diff --git a/click-buildtool.in b/click-buildtool.in index b259f4d01a..f76a58c2de 100644 --- a/click-buildtool.in +++ b/click-buildtool.in @@ -27,7 +27,6 @@ set_clickbuild () { prefix=@prefix@ set_clickbuild "$prefix" -LINUXMODULE_2_6=@LINUXMODULE_2_6@ gmake=@GMAKE@ verbose="" @@ -714,7 +713,7 @@ elem2make () { driver="" makevar="" date=`date` - linux26=x + linux=x bsdmake=0 while [ x"$1" != x ]; do case $1 in @@ -750,12 +749,12 @@ elem2make () { this_exclude=`echo "$1" | sed 's/^[^=]*=//'` for i in $this_exclude; do excludes=";/^$i"' \\$'"/d$excludes"; done shift 1;; - --l|--li|--lin|--linu|--linux|--linux2|--linux26) - linux26=1; shift 1;; + --l|--li|--lin|--linu|--linux) + linux=1; shift 1;; --b|--bs|--bsd) bsdmake=1; shift 1;; - --no-l|--no-li|--no-lin|--no-linu|--no-linux|--no-linux2|--no-linux26) - linux26=0; shift 1;; + --no-l|--no-li|--no-lin|--no-linu|--no-linux) + linux=0; shift 1;; -V|--verb|--verbo|--verbos|--verbose) verbose=1; shift 1;; -h|--h|--he|--hel|--help) @@ -770,7 +769,7 @@ Options: -t, --driver DRIVER Set target driver to DRIVER ('userlevel', 'linuxmodule', 'bsdmodule', 'ns', or 'tool'). -v, --make-variable N Use make variable N. - --linux26 Generate Linux 2.6-style makefile fragment. + --linux Generate Linux style makefile fragment. --bsd Generate BSD make compatible Makefile. -x, --exclude FILE Do not include FILE. -V, --verbose Print more information. @@ -791,7 +790,6 @@ EOF L=u elif test "$driver" = 'kernel' -o "$driver" = 'linuxmodule'; then L=k - test "$linux26" = x && linux26="$LINUXMODULE_2_6" elif test "$driver" = 'bsdmodule'; then L=b elif test "$driver" = 'ns' -o "$driver" = 'nsmodule'; then @@ -803,8 +801,8 @@ EOF exit 1 fi fi - if test "$linux26" = 1 -a "$bsdmake" = 1; then - echo "--linux26 and --bsd are mutually exclusive" 1>&2 + if test "$linux" = 1 -a "$bsdmake" = 1; then + echo "--linux and --bsd are mutually exclusive" 1>&2 exit 1 fi osuffix=".${L}o" @@ -828,7 +826,7 @@ EOF test -n "$libs" && libs=`echo "$libs" | tsort` # massage awk script based on Linux 2.6 or not - if test "$linux26" = 1; then + if test "$linux" = 1; then set_subdir_scriptlet=' if (dir != "" && substr(dir, 1, 1) == "/") subdirs[dirid] = dir; @@ -1264,7 +1262,6 @@ kversion_usage () { kversion () { gpl=0 - linux26=$LINUXMODULE_2_6 while [ x"$1" != x ]; do case $1 in --g|--gp|--gpl) diff --git a/config-linuxmodule.h.in b/config-linuxmodule.h.in index 3c959b87a9..14d465adfb 100644 --- a/config-linuxmodule.h.in +++ b/config-linuxmodule.h.in @@ -216,7 +216,7 @@ typedef unsigned long uintptr_t; #endif /* Define KBUILD symbols. */ -#if !defined(KBUILD_STR) && HAVE_LINUXMODULE_2_6 +#if !defined(KBUILD_STR) # define KBUILD_STR(s) #s # define KBUILD_BASENAME KBUILD_STR(click) # define KBUILD_MODNAME KBUILD_STR(click) diff --git a/configure b/configure index a5d009c80e..6323a66c83 100755 --- a/configure +++ b/configure @@ -9439,6 +9439,15 @@ if test "$linux_version.$linux_patchlevel" = 2.6 -o "$linux_version" = 3; then $as_echo "#define HAVE_LINUXMODULE_2_6 1" >>confdefs.h fi +if "$LINUXMODULE_2_6" = 0 ; then + as_fn_error $? " +========================================= + +Click no longer supports in-kernel compilation on Linux 2.4 kernels. +Try an older version of Click. + +=========================================" "$LINENO" 5 +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Click Linux kernel extensions" >&5 @@ -10769,11 +10778,9 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -10876,11 +10883,9 @@ if ${ac_cv_long_64_linuxmodule+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -10931,11 +10936,9 @@ if ${ac_cv_long_long_64_linuxmodule+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -10986,11 +10989,9 @@ if ${ac_cv_uintptr_t_linuxmodule+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11033,11 +11034,9 @@ $as_echo "#define HAVE_UINTPTR_T_LINUXMODULE 1" >>confdefs.h - ac_fn_cxx_check_decl "$LINENO" "atomic_cmpxchg" "ac_cv_have_decl_atomic_cmpxchg" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_cxx_check_decl "$LINENO" "atomic_cmpxchg" "ac_cv_have_decl_atomic_cmpxchg" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11067,11 +11066,9 @@ $as_echo "#define HAVE_LINUX_ATOMIC_CMPXCHG 1" >>confdefs.h fi - ac_fn_cxx_check_decl "$LINENO" "atomic_set_mask" "ac_cv_have_decl_atomic_set_mask" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_cxx_check_decl "$LINENO" "atomic_set_mask" "ac_cv_have_decl_atomic_set_mask" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11101,11 +11098,9 @@ $as_echo "#define HAVE_LINUX_ATOMIC_SET_MASK 1" >>confdefs.h fi - ac_fn_cxx_check_decl "$LINENO" "atomic_add_return" "ac_cv_have_decl_atomic_add_return" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_cxx_check_decl "$LINENO" "atomic_add_return" "ac_cv_have_decl_atomic_add_return" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11148,11 +11143,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11205,11 +11198,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11264,11 +11255,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11321,11 +11310,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11378,11 +11365,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11435,11 +11420,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11492,11 +11475,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11549,11 +11530,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11606,11 +11585,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11663,11 +11640,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11720,11 +11695,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11764,11 +11737,9 @@ $as_echo "#define HAVE_LINUX_POLLING 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "skb_dst_drop" "ac_cv_have_decl_skb_dst_drop" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "skb_dst_drop" "ac_cv_have_decl_skb_dst_drop" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11798,11 +11769,9 @@ $as_echo "#define HAVE_SKB_DST_DROP 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "skb_recycle" "ac_cv_have_decl_skb_recycle" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "skb_recycle" "ac_cv_have_decl_skb_recycle" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11848,11 +11817,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11894,11 +11861,9 @@ $as_echo "#define HAVE_CLICK_SKB_RECYCLE 1" >>confdefs.h CFLAGS="$save_cflags" - ac_fn_c_check_decl "$LINENO" "skb_linearize" "ac_cv_have_decl_skb_linearize" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "skb_linearize" "ac_cv_have_decl_skb_linearize" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11941,11 +11906,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -11991,11 +11954,9 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - ac_fn_c_check_decl "$LINENO" "net_enable_timestamp" "ac_cv_have_decl_net_enable_timestamp" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "net_enable_timestamp" "ac_cv_have_decl_net_enable_timestamp" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12026,11 +11987,9 @@ $as_echo "#define HAVE_NET_ENABLE_TIMESTAMP 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "netif_tx_lock" "ac_cv_have_decl_netif_tx_lock" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "netif_tx_lock" "ac_cv_have_decl_netif_tx_lock" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12061,11 +12020,9 @@ $as_echo "#define HAVE_NETIF_TX_LOCK 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "netdev_get_tx_queue" "ac_cv_have_decl_netdev_get_tx_queue" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "netdev_get_tx_queue" "ac_cv_have_decl_netdev_get_tx_queue" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12096,11 +12053,9 @@ $as_echo "#define HAVE_NETDEV_GET_TX_QUEUE 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "netif_tx_queue_frozen" "ac_cv_have_decl_netif_tx_queue_frozen" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "netif_tx_queue_frozen" "ac_cv_have_decl_netif_tx_queue_frozen" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12131,11 +12086,9 @@ $as_echo "#define HAVE_NETIF_TX_QUEUE_FROZEN 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "netdev_uses_dsa_tags" "ac_cv_have_decl_netdev_uses_dsa_tags" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "netdev_uses_dsa_tags" "ac_cv_have_decl_netdev_uses_dsa_tags" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12166,11 +12119,9 @@ $as_echo "#define HAVE_NETDEV_USES_DSA_TAGS 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "netdev_uses_trailer_tags" "ac_cv_have_decl_netdev_uses_trailer_tags" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "netdev_uses_trailer_tags" "ac_cv_have_decl_netdev_uses_trailer_tags" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12266,11 +12217,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif +#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete @@ -12310,11 +12259,9 @@ $as_echo "#define HAVE_LINUX_SUPER_BLOCK_S_D_OP 1" >>confdefs.h fi - ac_fn_c_check_decl "$LINENO" "d_make_root" "ac_cv_have_decl_d_make_root" "#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + ac_fn_c_check_decl "$LINENO" "d_make_root" "ac_cv_have_decl_d_make_root" "#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete diff --git a/configure.in b/configure.in index ad3cd97080..d2f847463c 100644 --- a/configure.in +++ b/configure.in @@ -715,6 +715,15 @@ if test "$linux_version.$linux_patchlevel" = 2.6 -o "$linux_version" = 3; then LINUXMODULE_2_6=1 AC_DEFINE([HAVE_LINUXMODULE_2_6], [1], [Define if the Click linuxmodule is compiled for a 2.6 or later kernel.]) fi +if [ "$LINUXMODULE_2_6" = 0 ]; then + AC_MSG_ERROR([ +========================================= + +Click no longer supports in-kernel compilation on Linux 2.4 kernels. +Try an older version of Click. + +=========================================]) +fi AC_SUBST(LINUXMODULE_2_6) AC_CACHE_CHECK(for Click Linux kernel extensions, ac_cv_click_kernel, @@ -1280,11 +1289,9 @@ fixincludes.pl execution failed. #endif " fi - AC_DEFUN([CLICK_LINUXMODULE_PROLOGUE], [[#if HAVE_LINUXMODULE_2_6 -# define KBUILD_STR(s) #s -# define KBUILD_BASENAME KBUILD_STR(click) -# define KBUILD_MODNAME KBUILD_STR(click) -#endif + AC_DEFUN([CLICK_LINUXMODULE_PROLOGUE], [[#define KBUILD_STR(s) #s +#define KBUILD_BASENAME KBUILD_STR(click) +#define KBUILD_MODNAME KBUILD_STR(click) #define new linux_new #define this linux_this #define delete linux_delete diff --git a/etc/debian-2.4.26-patch b/etc/debian-2.4.26-patch deleted file mode 100644 index 30675fdd6c..0000000000 --- a/etc/debian-2.4.26-patch +++ /dev/null @@ -1,3669 +0,0 @@ -diff -U 3 --recursive kernel-source-2.4.26/drivers/i2c/i2c-proc.c kernel-source-2.4.26_meshax/drivers/i2c/i2c-proc.c ---- kernel-source-2.4.26/drivers/i2c/i2c-proc.c Fri Feb 20 22:47:06 2004 -+++ kernel-source-2.4.26_meshax/drivers/i2c/i2c-proc.c Tue Oct 12 20:15:33 2004 -@@ -180,18 +180,19 @@ - - i2c_clients[id - 256] = client; - #ifdef DEBUG -- if (!new_header || !new_header->ctl_table || -- !new_header->ctl_table->child || -- !new_header->ctl_table->child->child || -- !new_header->ctl_table->child->child->de) { -+ if (!new_header || !new_header->ctl_table_member || -+ !new_header->ctl_table_member->child || -+ !new_header->ctl_table_member->child->child || -+ !new_header->ctl_table_member->child->child->de) { - printk - ("i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n"); - return id; - } - #endif /* DEBUG */ - i2c_inodes[id - 256] = -- new_header->ctl_table->child->child->de->low_ino; -- new_header->ctl_table->child->child->de->owner = controlling_mod; -+ new_header->ctl_table_member->child->child->de->low_ino; -+ new_header->ctl_table_member->child->child->de->owner = -+ controlling_mod; - - return id; - } -@@ -202,7 +203,7 @@ - char *temp; - id -= 256; - if (i2c_entries[id]) { -- table = i2c_entries[id]->ctl_table; -+ table = i2c_entries[id]->ctl_table_member; - unregister_sysctl_table(i2c_entries[id]); - /* 2-step kfree needed to keep gcc happy about const points */ - (const char *) temp = table[4].procname; -@@ -278,7 +279,7 @@ - for (i = 0; i < SENSORS_ENTRY_MAX; i++) - if (i2c_entries[i]) { - client_tbl = -- i2c_entries[i]->ctl_table->child->child; -+ i2c_entries[i]->ctl_table_member->child->child; - buflen = - sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name, - client_tbl->procname); -@@ -310,7 +311,7 @@ - i++) - if (i2c_entries[i]) { - client_tbl = -- i2c_entries[i]->ctl_table->child-> -+ i2c_entries[i]->ctl_table_member->child-> - child; - data.sysctl_id = client_tbl->ctl_name; - strcpy(data.name, client_tbl->procname); -@@ -853,7 +854,7 @@ - if (! - (i2c_proc_header = - register_sysctl_table(i2c_proc, 0))) return -ENOMEM; -- i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE; -+ i2c_proc_header->ctl_table_member->child->de->owner = THIS_MODULE; - i2c_initialized++; - return 0; - } -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/8139cp.c kernel-source-2.4.26_meshax/drivers/net/8139cp.c ---- kernel-source-2.4.26/drivers/net/8139cp.c Fri Feb 20 22:47:06 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/8139cp.c Tue Oct 12 20:23:22 2004 -@@ -472,7 +472,7 @@ - be16_to_cpu(desc->opts2 & 0xffff)); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb,skb->protocol,0); - } - - static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/aironet4500_proc.c kernel-source-2.4.26_meshax/drivers/net/aironet4500_proc.c ---- kernel-source-2.4.26/drivers/net/aironet4500_proc.c Sun Sep 30 15:26:06 2001 -+++ kernel-source-2.4.26_meshax/drivers/net/aironet4500_proc.c Tue Oct 12 20:16:57 2004 -@@ -452,7 +452,7 @@ - awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1; - awc_proc_priv[device_number].proc_table[group].mode = 0600; - awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(struct ctl_table) * (awc_rids[group].size +2), GFP_KERNEL); -- awc_proc_priv[device_number].proc_table[group].proc_handler = NULL; -+ awc_proc_priv[device_number].proc_table[group].proc_handler_member = NULL; - awc_proc_priv[device_number].proc_table[group].strategy = NULL; - awc_proc_priv[device_number].proc_table[group].de = NULL; - awc_proc_priv[device_number].proc_table[group].extra1 = NULL; -@@ -485,7 +485,7 @@ - else - awc_proc_priv[device_number].proc_table[group].child[rid].mode = 0600; - awc_proc_priv[device_number].proc_table[group].child[rid].child = NULL; -- awc_proc_priv[device_number].proc_table[group].child[rid].proc_handler = awc_proc_fun; -+ awc_proc_priv[device_number].proc_table[group].child[rid].proc_handler_member = awc_proc_fun; - awc_proc_priv[device_number].proc_table[group].child[rid].strategy = NULL; - awc_proc_priv[device_number].proc_table[group].child[rid].de = NULL; - awc_proc_priv[device_number].proc_table[group].child[rid].extra1 = (void *) &(((struct awc_private* )aironet4500_devices[device_number]->priv)->rid_dir[group]); -@@ -505,7 +505,7 @@ - awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1; - awc_proc_priv[device_number].proc_table[group].mode = 0600; - awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(awc_driver_level_ctable) , GFP_KERNEL); -- awc_proc_priv[device_number].proc_table[group].proc_handler = NULL; -+ awc_proc_priv[device_number].proc_table[group].proc_handler_member = NULL; - awc_proc_priv[device_number].proc_table[group].strategy = NULL; - awc_proc_priv[device_number].proc_table[group].de = NULL; - awc_proc_priv[device_number].proc_table[group].extra1 = NULL; -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/b44.c kernel-source-2.4.26_meshax/drivers/net/b44.c ---- kernel-source-2.4.26/drivers/net/b44.c Fri Nov 28 13:26:20 2003 -+++ kernel-source-2.4.26_meshax/drivers/net/b44.c Tue Oct 12 20:22:30 2004 -@@ -743,7 +743,7 @@ - } - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, bp->dev); -- netif_receive_skb(skb); -+ netif_receive_skb(skb,skb->protocol,0); - bp->dev->last_rx = jiffies; - received++; - budget--; -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/e1000/e1000_main.c kernel-source-2.4.26_meshax/drivers/net/e1000/e1000_main.c ---- kernel-source-2.4.26/drivers/net/e1000/e1000_main.c Wed Apr 14 09:05:30 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/e1000/e1000_main.c Tue Oct 12 20:24:10 2004 -@@ -2348,7 +2348,7 @@ - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); - } else { -- netif_receive_skb(skb); -+ netif_receive_skb(skb,skb->protocol,0); - } - #else /* CONFIG_E1000_NAPI */ - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/eepro100.c kernel-source-2.4.26_meshax/drivers/net/eepro100.c ---- kernel-source-2.4.26/drivers/net/eepro100.c Sat Aug 30 02:01:38 2003 -+++ kernel-source-2.4.26_meshax/drivers/net/eepro100.c Tue Oct 12 20:15:33 2004 -@@ -549,6 +549,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -880,6 +890,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1130,7 +1151,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* -@@ -1395,7 +1417,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1442,6 +1465,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1499,7 +1530,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1508,6 +1538,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1571,6 +1607,11 @@ - long ioaddr, boguscnt = max_interrupt_work; - unsigned short status; - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1599,13 +1640,15 @@ - break; - - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - - spin_lock(&sp->lock); - /* -@@ -1630,7 +1673,7 @@ - - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - speedo_tx_buffer_gc(dev); - if (sp->tx_full - && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -@@ -1748,6 +1791,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1764,6 +1813,12 @@ - - if (netif_msg_intr(sp)) - printk(KERN_DEBUG " In speedo_rx().\n"); -+ if (dev->polling) { -+ printk(KERN_ERR "%s: In speedo_rx() while polling.\n", -+ dev->name); -+ return 0; -+ } -+ - /* If we own the next entry, it's a new packet. Send it up. */ - while (sp->rx_ringp[entry] != NULL) { - int status; -@@ -2456,3 +2511,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (netif_msg_rx_err(sp)) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/gt64240eth.c kernel-source-2.4.26_meshax/drivers/net/gt64240eth.c ---- kernel-source-2.4.26/drivers/net/gt64240eth.c Fri Feb 20 22:47:06 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/gt64240eth.c Tue Oct 12 20:25:06 2004 -@@ -1520,7 +1520,7 @@ - /* NIC performed some checksum computation */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - #ifdef GT64240_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb,skb->protocol,0); - #else - netif_rx(skb); /* pass the packet to upper layers */ - #endif -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/mv64340_eth.c kernel-source-2.4.26_meshax/drivers/net/mv64340_eth.c ---- kernel-source-2.4.26/drivers/net/mv64340_eth.c Fri Feb 20 22:47:07 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/mv64340_eth.c Tue Oct 12 20:25:41 2004 -@@ -529,7 +529,7 @@ - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, dev); - #ifdef MV64340_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb,skb->protocol,0); - #else - netif_rx(skb); - #endif -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/tg3.c kernel-source-2.4.26_meshax/drivers/net/tg3.c ---- kernel-source-2.4.26/drivers/net/tg3.c Sat Apr 17 00:23:50 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/tg3.c Tue Oct 12 20:15:33 2004 -@@ -2302,7 +2302,7 @@ - desc->err_vlan & RXD_VLAN_MASK); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - tp->dev->last_rx = jiffies; - received++; -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/tulip/interrupt.c kernel-source-2.4.26_meshax/drivers/net/tulip/interrupt.c ---- kernel-source-2.4.26/drivers/net/tulip/interrupt.c Sat May 31 23:06:27 2003 -+++ kernel-source-2.4.26_meshax/drivers/net/tulip/interrupt.c Tue Oct 12 20:15:33 2004 -@@ -311,6 +311,10 @@ - #endif - } - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -320,7 +324,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -328,6 +331,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -341,14 +345,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -357,7 +380,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -425,16 +454,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -456,7 +486,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -547,7 +580,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -570,12 +605,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: -+} -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; - } -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/tulip/tulip_core.c kernel-source-2.4.26_meshax/drivers/net/tulip/tulip_core.c ---- kernel-source-2.4.26/drivers/net/tulip/tulip_core.c Wed Apr 14 09:05:30 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/tulip/tulip_core.c Tue Oct 12 20:15:33 2004 -@@ -268,6 +268,16 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); -+ - - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) -@@ -713,6 +723,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -748,13 +769,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -763,6 +784,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -825,8 +859,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -905,10 +943,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1729,6 +1771,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1937,3 +1990,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -diff -U 3 --recursive kernel-source-2.4.26/drivers/net/typhoon.c kernel-source-2.4.26_meshax/drivers/net/typhoon.c ---- kernel-source-2.4.26/drivers/net/typhoon.c Wed Apr 14 09:05:30 2004 -+++ kernel-source-2.4.26_meshax/drivers/net/typhoon.c Tue Oct 12 20:21:33 2004 -@@ -1729,7 +1729,7 @@ - vlan_hwaccel_receive_skb(new_skb, tp->vlgrp, - ntohl(rx->vlanTag) & 0xffff); - else -- netif_receive_skb(new_skb); -+ netif_receive_skb(new_skb,new_skb->protocol,0); - spin_unlock(&tp->state_lock); - - tp->dev->last_rx = jiffies; -diff -U 3 --recursive kernel-source-2.4.26/fs/proc/inode.c kernel-source-2.4.26_meshax/fs/proc/inode.c ---- kernel-source-2.4.26/fs/proc/inode.c Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/fs/proc/inode.c Tue Oct 12 20:15:33 2004 -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -diff -U 3 --recursive kernel-source-2.4.26/include/asm-alpha/core_tsunami.h kernel-source-2.4.26_meshax/include/asm-alpha/core_tsunami.h ---- kernel-source-2.4.26/include/asm-alpha/core_tsunami.h Fri Aug 2 20:39:45 2002 -+++ kernel-source-2.4.26_meshax/include/asm-alpha/core_tsunami.h Tue Oct 12 20:15:33 2004 -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-arm/mmu.h kernel-source-2.4.26_meshax/include/asm-arm/mmu.h ---- kernel-source-2.4.26/include/asm-arm/mmu.h Sat Aug 30 02:01:45 2003 -+++ kernel-source-2.4.26_meshax/include/asm-arm/mmu.h Tue Oct 12 20:15:33 2004 -@@ -4,6 +4,6 @@ - /* - * The ARM doesn't have a mmu context - */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -diff -U 3 --recursive kernel-source-2.4.26/include/asm-arm/proc-armo/pgalloc.h kernel-source-2.4.26_meshax/include/asm-arm/proc-armo/pgalloc.h ---- kernel-source-2.4.26/include/asm-arm/proc-armo/pgalloc.h Thu Apr 12 15:20:31 2001 -+++ kernel-source-2.4.26_meshax/include/asm-arm/proc-armo/pgalloc.h Tue Oct 12 20:15:33 2004 -@@ -20,7 +20,7 @@ - */ - static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) - { -- return kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ return (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - } - - /* -diff -U 3 --recursive kernel-source-2.4.26/include/asm-arm/proc-armv/pgalloc.h kernel-source-2.4.26_meshax/include/asm-arm/proc-armv/pgalloc.h ---- kernel-source-2.4.26/include/asm-arm/proc-armv/pgalloc.h Thu Apr 12 15:20:31 2001 -+++ kernel-source-2.4.26_meshax/include/asm-arm/proc-armv/pgalloc.h Tue Oct 12 20:15:33 2004 -@@ -22,7 +22,7 @@ - { - pte_t *pte; - -- pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ pte = (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - if (pte) - pte += PTRS_PER_PTE; - return pte; -diff -U 3 --recursive kernel-source-2.4.26/include/asm-arm/system.h kernel-source-2.4.26_meshax/include/asm-arm/system.h ---- kernel-source-2.4.26/include/asm-arm/system.h Sat Aug 30 02:01:46 2003 -+++ kernel-source-2.4.26_meshax/include/asm-arm/system.h Tue Oct 12 20:15:33 2004 -@@ -36,7 +36,7 @@ - - #define tas(ptr) (xchg((ptr),1)) - --extern asmlinkage void __backtrace(void); -+asmlinkage void __backtrace(void); - - /* - * Include processor dependent parts -diff -U 3 --recursive kernel-source-2.4.26/include/asm-cris/io.h kernel-source-2.4.26_meshax/include/asm-cris/io.h ---- kernel-source-2.4.26/include/asm-cris/io.h Sat Aug 30 02:01:46 2003 -+++ kernel-source-2.4.26_meshax/include/asm-cris/io.h Tue Oct 12 20:15:33 2004 -@@ -26,8 +26,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/desc.h kernel-source-2.4.26_meshax/include/asm-i386/desc.h ---- kernel-source-2.4.26/include/asm-i386/desc.h Fri Feb 20 22:47:16 2004 -+++ kernel-source-2.4.26_meshax/include/asm-i386/desc.h Tue Oct 12 20:15:33 2004 -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/highmem.h kernel-source-2.4.26_meshax/include/asm-i386/highmem.h ---- kernel-source-2.4.26/include/asm-i386/highmem.h Wed Apr 14 09:05:40 2004 -+++ kernel-source-2.4.26_meshax/include/asm-i386/highmem.h Tue Oct 12 20:15:33 2004 -@@ -94,7 +94,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -110,7 +110,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/pgtable.h kernel-source-2.4.26_meshax/include/asm-i386/pgtable.h ---- kernel-source-2.4.26/include/asm-i386/pgtable.h Thu Nov 28 18:53:15 2002 -+++ kernel-source-2.4.26_meshax/include/asm-i386/pgtable.h Tue Oct 12 20:15:33 2004 -@@ -43,7 +43,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/processor.h kernel-source-2.4.26_meshax/include/asm-i386/processor.h ---- kernel-source-2.4.26/include/asm-i386/processor.h Sun Feb 22 04:28:33 2004 -+++ kernel-source-2.4.26_meshax/include/asm-i386/processor.h Tue Oct 12 20:15:33 2004 -@@ -493,7 +493,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - static inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop" ::: "memory"); -+ __asm__ __volatile__("rep;nop" : : : "memory"); - } - - #define cpu_relax() rep_nop() -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/rwlock.h kernel-source-2.4.26_meshax/include/asm-i386/rwlock.h ---- kernel-source-2.4.26/include/asm-i386/rwlock.h Fri Aug 2 20:39:45 2002 -+++ kernel-source-2.4.26_meshax/include/asm-i386/rwlock.h Tue Oct 12 20:15:33 2004 -@@ -28,7 +28,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -58,7 +58,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/save_state.h kernel-source-2.4.26_meshax/include/asm-i386/save_state.h ---- kernel-source-2.4.26/include/asm-i386/save_state.h Sat Aug 30 02:01:46 2003 -+++ kernel-source-2.4.26_meshax/include/asm-i386/save_state.h Tue Oct 12 20:15:33 2004 -@@ -160,24 +160,24 @@ - * first restore %ds, so we can access our data properly - */ - asm volatile (".align 4"); -- asm volatile ("movw %0, %%ds" :: "r" ((u16)__KERNEL_DS)); -+ asm volatile ("movw %0, %%ds" : : "r" ((u16)__KERNEL_DS)); - - - /* - * control registers - */ -- asm volatile ("movl %0, %%cr4" :: "r" (saved_context.cr4)); -- asm volatile ("movl %0, %%cr3" :: "r" (saved_context.cr3)); -- asm volatile ("movl %0, %%cr2" :: "r" (saved_context.cr2)); -- asm volatile ("movl %0, %%cr0" :: "r" (saved_context.cr0)); -+ asm volatile ("movl %0, %%cr4" : : "r" (saved_context.cr4)); -+ asm volatile ("movl %0, %%cr3" : : "r" (saved_context.cr3)); -+ asm volatile ("movl %0, %%cr2" : : "r" (saved_context.cr2)); -+ asm volatile ("movl %0, %%cr0" : : "r" (saved_context.cr0)); - - /* - * segment registers - */ -- asm volatile ("movw %0, %%es" :: "r" (saved_context.es)); -- asm volatile ("movw %0, %%fs" :: "r" (saved_context.fs)); -- asm volatile ("movw %0, %%gs" :: "r" (saved_context.gs)); -- asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); -+ asm volatile ("movw %0, %%es" : : "r" (saved_context.es)); -+ asm volatile ("movw %0, %%fs" : : "r" (saved_context.fs)); -+ asm volatile ("movw %0, %%gs" : : "r" (saved_context.gs)); -+ asm volatile ("movw %0, %%ss" : : "r" (saved_context.ss)); - - /* - * the other general registers -@@ -188,21 +188,21 @@ - * bad since we don't have a stack set up when we enter, and we - * want to preserve the values on exit. So, we set them manually. - */ -- asm volatile ("movl %0, %%esp" :: "m" (saved_context.esp)); -- asm volatile ("movl %0, %%ebp" :: "m" (saved_context.ebp)); -- asm volatile ("movl %0, %%eax" :: "m" (saved_context.eax)); -- asm volatile ("movl %0, %%ebx" :: "m" (saved_context.ebx)); -- asm volatile ("movl %0, %%ecx" :: "m" (saved_context.ecx)); -- asm volatile ("movl %0, %%edx" :: "m" (saved_context.edx)); -- asm volatile ("movl %0, %%esi" :: "m" (saved_context.esi)); -- asm volatile ("movl %0, %%edi" :: "m" (saved_context.edi)); -+ asm volatile ("movl %0, %%esp" : : "m" (saved_context.esp)); -+ asm volatile ("movl %0, %%ebp" : : "m" (saved_context.ebp)); -+ asm volatile ("movl %0, %%eax" : : "m" (saved_context.eax)); -+ asm volatile ("movl %0, %%ebx" : : "m" (saved_context.ebx)); -+ asm volatile ("movl %0, %%ecx" : : "m" (saved_context.ecx)); -+ asm volatile ("movl %0, %%edx" : : "m" (saved_context.edx)); -+ asm volatile ("movl %0, %%esi" : : "m" (saved_context.esi)); -+ asm volatile ("movl %0, %%edi" : : "m" (saved_context.edi)); - - /* - * now restore the descriptor tables to their proper values - */ -- asm volatile ("lgdt (%0)" :: "m" (saved_context.gdt_limit)); -- asm volatile ("lidt (%0)" :: "m" (saved_context.idt_limit)); -- asm volatile ("lldt (%0)" :: "m" (saved_context.ldt)); -+ asm volatile ("lgdt (%0)" : : "m" (saved_context.gdt_limit)); -+ asm volatile ("lidt (%0)" : : "m" (saved_context.idt_limit)); -+ asm volatile ("lldt (%0)" : : "m" (saved_context.ldt)); - - fix_processor_context(); - do_fpu_end(); -diff -U 3 --recursive kernel-source-2.4.26/include/asm-i386/string.h kernel-source-2.4.26_meshax/include/asm-i386/string.h ---- kernel-source-2.4.26/include/asm-i386/string.h Fri Aug 10 21:13:47 2001 -+++ kernel-source-2.4.26_meshax/include/asm-i386/string.h Tue Oct 12 20:15:33 2004 -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/delay.h kernel-source-2.4.26_meshax/include/asm-ia64/delay.h ---- kernel-source-2.4.26/include/asm-ia64/delay.h Sat May 31 23:06:33 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/delay.h Tue Oct 12 20:15:33 2004 -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/intrinsics.h kernel-source-2.4.26_meshax/include/asm-ia64/intrinsics.h ---- kernel-source-2.4.26/include/asm-ia64/intrinsics.h Sat Aug 30 02:01:46 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/intrinsics.h Tue Oct 12 20:15:33 2004 -@@ -131,7 +131,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/io.h kernel-source-2.4.26_meshax/include/asm-ia64/io.h ---- kernel-source-2.4.26/include/asm-ia64/io.h Sat May 31 23:06:33 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/io.h Tue Oct 12 20:15:33 2004 -@@ -85,7 +85,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/pgalloc.h kernel-source-2.4.26_meshax/include/asm-ia64/pgalloc.h ---- kernel-source-2.4.26/include/asm-ia64/pgalloc.h Sat May 31 23:06:33 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/pgalloc.h Tue Oct 12 20:15:33 2004 -@@ -209,7 +209,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - else - vma->vm_mm->context = 0; - #endif -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/processor.h kernel-source-2.4.26_meshax/include/asm-ia64/processor.h ---- kernel-source-2.4.26/include/asm-ia64/processor.h Sat Apr 17 00:24:04 2004 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/processor.h Tue Oct 12 20:15:33 2004 -@@ -424,14 +424,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - /* Return TRUE if task T owns the fph partition of the CPU we're running on. */ -@@ -463,8 +463,8 @@ - extern void ia32_load_state (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -493,25 +493,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -525,7 +525,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -539,7 +539,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -554,7 +554,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -566,7 +566,7 @@ - ia64_clear_ic (void) - { - __u64 psr; -- asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) :: "memory"); -+ asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) : : "memory"); - return psr; - } - -@@ -576,7 +576,7 @@ - static inline void - ia64_set_psr (__u64 psr) - { -- asm volatile (";; mov psr.l=%0;; srlz.d" :: "r" (psr) : "memory"); -+ asm volatile (";; mov psr.l=%0;; srlz.d" : : "r" (psr) : "memory"); - } - - /* -@@ -588,14 +588,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -606,13 +606,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -623,16 +623,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -640,7 +640,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -655,20 +655,20 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #ifdef GAS_HAS_HINT_INSN - static inline void - ia64_hint_pause (void) - { -- asm volatile ("hint @pause" ::: "memory"); -+ asm volatile ("hint @pause" : : : "memory"); - } - - #define cpu_relax() ia64_hint_pause() -@@ -679,13 +679,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -700,7 +700,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -715,7 +715,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -780,7 +780,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -788,7 +788,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -803,7 +803,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -817,7 +817,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -834,7 +834,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -851,7 +851,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -868,7 +868,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -894,13 +894,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/sn/rw_mmr.h kernel-source-2.4.26_meshax/include/asm-ia64/sn/rw_mmr.h ---- kernel-source-2.4.26/include/asm-ia64/sn/rw_mmr.h Sat Aug 30 02:01:47 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/sn/rw_mmr.h Tue Oct 12 20:15:33 2004 -@@ -51,7 +51,7 @@ - "st8.rel [%0]=%1;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr), "r"(val) -+ : : "r"(mmr), "r"(val) - : "r2", "memory"); - } - -@@ -66,7 +66,7 @@ - "st8.rel [%2]=%3;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) -+ : : "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) - : "r2", "memory"); - } - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/sn/sn2/io.h kernel-source-2.4.26_meshax/include/asm-ia64/sn/sn2/io.h ---- kernel-source-2.4.26/include/asm-ia64/sn/sn2/io.h Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/sn/sn2/io.h Tue Oct 12 20:15:33 2004 -@@ -12,7 +12,7 @@ - extern void * sn_io_addr(unsigned long port) __attribute__ ((__const__)); /* Forward definition */ - extern void sn_mmiob(void); /* Forward definition */ - --#define __sn_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __sn_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - extern void sn_dma_flush(unsigned long); - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/spinlock.h kernel-source-2.4.26_meshax/include/asm-ia64/spinlock.h ---- kernel-source-2.4.26/include/asm-ia64/spinlock.h Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/spinlock.h Tue Oct 12 20:15:33 2004 -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -100,7 +100,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -165,7 +165,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ -+ : : "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ - } while(0) - - #define write_unlock(x) \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ia64/system.h kernel-source-2.4.26_meshax/include/asm-ia64/system.h ---- kernel-source-2.4.26/include/asm-ia64/system.h Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ia64/system.h Tue Oct 12 20:15:33 2004 -@@ -57,7 +57,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -82,7 +82,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -121,7 +121,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -133,7 +133,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -147,7 +147,7 @@ - __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (psr) :: "memory"); \ -+ : "=r" (psr) : : "memory"); \ - (x) = psr; \ - } while (0) - -@@ -171,25 +171,25 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_set(x) __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (x) :: "memory") -+ : "=r" (x) : : "memory") - # define local_irq_restore(x) __asm__ __volatile__ ("cmp.ne p6,p7=%0,r0;;" \ - "(p6) ssm psr.i;" \ - "(p7) rsm psr.i;;" \ - "srlz.d" \ -- :: "r"((x) & IA64_PSR_I) \ -+ : : "r"((x) & IA64_PSR_I) \ - : "p6", "p7", "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define __save_and_sti(flags) local_irq_set(flags) - #define save_and_cli(flags) __save_and_cli(flags) -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/fpu.h kernel-source-2.4.26_meshax/include/asm-mips/fpu.h ---- kernel-source-2.4.26/include/asm-mips/fpu.h Sat Aug 30 02:01:47 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips/fpu.h Tue Oct 12 20:15:33 2004 -@@ -22,8 +22,8 @@ - - struct sigcontext; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/irq.h kernel-source-2.4.26_meshax/include/asm-mips/irq.h ---- kernel-source-2.4.26/include/asm-mips/irq.h Sat Aug 30 02:01:48 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips/irq.h Tue Oct 12 20:15:33 2004 -@@ -30,7 +30,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/processor.h kernel-source-2.4.26_meshax/include/asm-mips/processor.h ---- kernel-source-2.4.26/include/asm-mips/processor.h Sun Feb 22 04:28:33 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips/processor.h Tue Oct 12 20:15:33 2004 -@@ -314,6 +314,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/system.h kernel-source-2.4.26_meshax/include/asm-mips/system.h ---- kernel-source-2.4.26/include/asm-mips/system.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips/system.h Tue Oct 12 20:15:33 2004 -@@ -260,7 +260,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/time.h kernel-source-2.4.26_meshax/include/asm-mips/time.h ---- kernel-source-2.4.26/include/asm-mips/time.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips/time.h Tue Oct 12 20:15:33 2004 -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips/watch.h kernel-source-2.4.26_meshax/include/asm-mips/watch.h ---- kernel-source-2.4.26/include/asm-mips/watch.h Sat Aug 30 02:01:48 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips/watch.h Tue Oct 12 20:15:33 2004 -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/fpu.h kernel-source-2.4.26_meshax/include/asm-mips64/fpu.h ---- kernel-source-2.4.26/include/asm-mips64/fpu.h Sat Aug 30 02:01:48 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/fpu.h Tue Oct 12 20:15:33 2004 -@@ -23,11 +23,11 @@ - struct sigcontext; - struct sigcontext32; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - --extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); --extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/irq.h kernel-source-2.4.26_meshax/include/asm-mips64/irq.h ---- kernel-source-2.4.26/include/asm-mips64/irq.h Sat Aug 30 02:01:48 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/irq.h Tue Oct 12 20:15:33 2004 -@@ -48,7 +48,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/processor.h kernel-source-2.4.26_meshax/include/asm-mips64/processor.h ---- kernel-source-2.4.26/include/asm-mips64/processor.h Sun Feb 22 04:28:34 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/processor.h Tue Oct 12 20:15:33 2004 -@@ -357,6 +357,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/system.h kernel-source-2.4.26_meshax/include/asm-mips64/system.h ---- kernel-source-2.4.26/include/asm-mips64/system.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/system.h Tue Oct 12 20:15:33 2004 -@@ -238,7 +238,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/time.h kernel-source-2.4.26_meshax/include/asm-mips64/time.h ---- kernel-source-2.4.26/include/asm-mips64/time.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/time.h Tue Oct 12 20:15:33 2004 -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -diff -U 3 --recursive kernel-source-2.4.26/include/asm-mips64/watch.h kernel-source-2.4.26_meshax/include/asm-mips64/watch.h ---- kernel-source-2.4.26/include/asm-mips64/watch.h Sat Aug 30 02:01:48 2003 -+++ kernel-source-2.4.26_meshax/include/asm-mips64/watch.h Tue Oct 12 20:15:33 2004 -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-parisc/system.h kernel-source-2.4.26_meshax/include/asm-parisc/system.h ---- kernel-source-2.4.26/include/asm-parisc/system.h Sat May 31 23:06:35 2003 -+++ kernel-source-2.4.26_meshax/include/asm-parisc/system.h Tue Oct 12 20:15:33 2004 -@@ -138,7 +138,7 @@ - ** The __asm__ op below simple prevents gcc/ld from reordering - ** instructions across the mb() "call". - */ --#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */ -+#define mb() __asm__ __volatile__("": : :"memory"); /* barrier() */ - #define rmb() mb() - #define wmb() mb() - #define smp_mb() mb() -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ppc64/delay.h kernel-source-2.4.26_meshax/include/asm-ppc64/delay.h ---- kernel-source-2.4.26/include/asm-ppc64/delay.h Sat May 31 23:06:36 2003 -+++ kernel-source-2.4.26_meshax/include/asm-ppc64/delay.h Tue Oct 12 20:15:33 2004 -@@ -19,7 +19,7 @@ - /* define these here to prevent circular dependencies */ - #define __HMT_low() asm volatile("or 1,1,1") - #define __HMT_medium() asm volatile("or 2,2,2") --#define __barrier() asm volatile("":::"memory") -+#define __barrier() asm volatile("": : :"memory") - - static inline unsigned long __get_tb(void) - { -diff -U 3 --recursive kernel-source-2.4.26/include/asm-ppc64/mmu_context.h kernel-source-2.4.26_meshax/include/asm-ppc64/mmu_context.h ---- kernel-source-2.4.26/include/asm-ppc64/mmu_context.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-ppc64/mmu_context.h Tue Oct 12 20:15:33 2004 -@@ -138,7 +138,7 @@ - "\tdssall\n" - "\tsync\n" - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) -- ::); -+ : :); - #endif - flush_stab(); - } -diff -U 3 --recursive kernel-source-2.4.26/include/asm-s390/uaccess.h kernel-source-2.4.26_meshax/include/asm-s390/uaccess.h ---- kernel-source-2.4.26/include/asm-s390/uaccess.h Fri Aug 2 20:39:45 2002 -+++ kernel-source-2.4.26_meshax/include/asm-s390/uaccess.h Tue Oct 12 20:15:33 2004 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4)); \ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -diff -U 3 --recursive kernel-source-2.4.26/include/asm-s390x/uaccess.h kernel-source-2.4.26_meshax/include/asm-s390x/uaccess.h ---- kernel-source-2.4.26/include/asm-s390x/uaccess.h Fri Aug 2 20:39:45 2002 -+++ kernel-source-2.4.26_meshax/include/asm-s390x/uaccess.h Tue Oct 12 20:15:33 2004 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -diff -U 3 --recursive kernel-source-2.4.26/include/asm-sparc/system.h kernel-source-2.4.26_meshax/include/asm-sparc/system.h ---- kernel-source-2.4.26/include/asm-sparc/system.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-sparc/system.h Tue Oct 12 20:15:33 2004 -@@ -295,9 +295,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - - #define nop() __asm__ __volatile__ ("nop"); - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-sparc64/system.h kernel-source-2.4.26_meshax/include/asm-sparc64/system.h ---- kernel-source-2.4.26/include/asm-sparc64/system.h Sat May 31 23:06:37 2003 -+++ kernel-source-2.4.26_meshax/include/asm-sparc64/system.h Tue Oct 12 20:15:33 2004 -@@ -121,9 +121,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/desc.h kernel-source-2.4.26_meshax/include/asm-x86_64/desc.h ---- kernel-source-2.4.26/include/asm-x86_64/desc.h Fri Feb 20 22:47:17 2004 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/desc.h Tue Oct 12 20:15:33 2004 -@@ -73,9 +73,9 @@ - #define __CPU_DESC_INDEX(x,field) \ - ((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + __GDT_HEAD_SIZE) - --#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss))); --#define __load_LDT(cpu) asm volatile("lldt %w0"::"r" (__CPU_DESC_INDEX(cpu, ldt))); --#define clear_LDT(n) asm volatile("lldt %w0"::"r" (0)) -+#define load_TR(cpu) asm volatile("ltr %w0": :"r" (__CPU_DESC_INDEX(cpu, tss))); -+#define __load_LDT(cpu) asm volatile("lldt %w0": :"r" (__CPU_DESC_INDEX(cpu, ldt))); -+#define clear_LDT(n) asm volatile("lldt %w0": :"r" (0)) - - extern struct gate_struct idt_table[]; - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/page.h kernel-source-2.4.26_meshax/include/asm-x86_64/page.h ---- kernel-source-2.4.26/include/asm-x86_64/page.h Sat Aug 30 02:01:49 2003 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/page.h Tue Oct 12 20:15:33 2004 -@@ -91,9 +91,9 @@ - char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */ - unsigned short line; - } __attribute__((packed)); --#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(KBUILD_BASENAME))) --#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(__FILE__))) - #define PAGE_BUG(page) BUG() - -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/pda.h kernel-source-2.4.26_meshax/include/asm-x86_64/pda.h ---- kernel-source-2.4.26/include/asm-x86_64/pda.h Sat Aug 30 02:01:49 2003 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/pda.h Tue Oct 12 20:15:33 2004 -@@ -41,9 +41,9 @@ - - #define pda_to_op(op,field,val) do { \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 4: asm volatile(op "l %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 8: asm volatile(op "q %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 2: asm volatile(op "w %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 4: asm volatile(op "l %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 8: asm volatile(op "q %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ - default: __bad_pda_field(); \ - } \ - } while (0) -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/pgtable.h kernel-source-2.4.26_meshax/include/asm-x86_64/pgtable.h ---- kernel-source-2.4.26/include/asm-x86_64/pgtable.h Wed Apr 14 09:05:40 2004 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/pgtable.h Tue Oct 12 20:15:33 2004 -@@ -49,7 +49,7 @@ - "movq %%cr3, %0; # flush TLB \n" \ - "movq %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/processor.h kernel-source-2.4.26_meshax/include/asm-x86_64/processor.h ---- kernel-source-2.4.26/include/asm-x86_64/processor.h Wed Apr 14 09:05:40 2004 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/processor.h Tue Oct 12 20:15:33 2004 -@@ -389,7 +389,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - extern inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop":::"memory"); -+ __asm__ __volatile__("rep;nop": : :"memory"); - } - - /* Avoid speculative execution by the CPU */ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/rwlock.h kernel-source-2.4.26_meshax/include/asm-x86_64/rwlock.h ---- kernel-source-2.4.26/include/asm-x86_64/rwlock.h Thu Nov 28 18:53:15 2002 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/rwlock.h Tue Oct 12 20:15:33 2004 -@@ -31,7 +31,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -44,7 +44,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile int *)rw))::"memory") -+ :"=m" (*((volatile int *)rw)): :"memory") - - #define __build_read_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -@@ -61,7 +61,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -@@ -74,7 +74,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile long *)rw))::"memory") -+ :"=m" (*((volatile long *)rw)): :"memory") - - #define __build_write_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/system.h kernel-source-2.4.26_meshax/include/asm-x86_64/system.h ---- kernel-source-2.4.26/include/asm-x86_64/system.h Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/system.h Tue Oct 12 20:15:33 2004 -@@ -248,9 +248,9 @@ - * but I'd also expect them to finally get their act together - * and add some real memory barriers if so. - */ --#define mb() asm volatile("mfence":::"memory") --#define rmb() asm volatile("lfence":::"memory") --#define wmb() asm volatile("sfence":::"memory") -+#define mb() asm volatile("mfence": : :"memory") -+#define rmb() asm volatile("lfence": : :"memory") -+#define wmb() asm volatile("sfence": : :"memory") - #define set_mb(var, value) do { xchg(&var, value); } while (0) - #define set_wmb(var, value) do { var = value; wmb(); } while (0) - -@@ -299,7 +299,7 @@ - #endif - - /* Default simics "magic" breakpoint */ --#define icebp() asm volatile("xchg %%bx,%%bx" ::: "ebx") -+#define icebp() asm volatile("xchg %%bx,%%bx" : : : "ebx") - - /* - * disable hlt during certain critical i/o operations -diff -U 3 --recursive kernel-source-2.4.26/include/asm-x86_64/uaccess.h kernel-source-2.4.26_meshax/include/asm-x86_64/uaccess.h ---- kernel-source-2.4.26/include/asm-x86_64/uaccess.h Wed Apr 14 09:05:40 2004 -+++ kernel-source-2.4.26_meshax/include/asm-x86_64/uaccess.h Tue Oct 12 20:15:33 2004 -@@ -284,13 +284,13 @@ - case 10: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2); - return ret; - case 16: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8); - return ret; - default: -diff -U 3 --recursive kernel-source-2.4.26/include/linux/atalk.h kernel-source-2.4.26_meshax/include/linux/atalk.h ---- kernel-source-2.4.26/include/linux/atalk.h Sat Nov 18 23:57:00 2000 -+++ kernel-source-2.4.26_meshax/include/linux/atalk.h Tue Oct 12 20:15:33 2004 -@@ -163,7 +163,7 @@ - - static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) - { -- return dev->atalk_ptr; -+ return (struct atalk_iface *) dev->atalk_ptr; - } - - extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/dqblk_v1.h kernel-source-2.4.26_meshax/include/linux/dqblk_v1.h ---- kernel-source-2.4.26/include/linux/dqblk_v1.h Sat Aug 30 02:01:49 2003 -+++ kernel-source-2.4.26_meshax/include/linux/dqblk_v1.h Tue Oct 12 20:15:33 2004 -@@ -12,7 +12,6 @@ - #define V1_DQF_RSQUASH 1 - - /* Special information about quotafile */ --struct v1_mem_dqinfo { --}; -+EMPTY_STRUCT_DECL(v1_mem_dqinfo); - - #endif /* _LINUX_DQBLK_V1_H */ -diff -U 3 --recursive kernel-source-2.4.26/include/linux/highmem.h kernel-source-2.4.26_meshax/include/linux/highmem.h ---- kernel-source-2.4.26/include/linux/highmem.h Sat Aug 30 02:01:49 2003 -+++ kernel-source-2.4.26_meshax/include/linux/highmem.h Tue Oct 12 20:15:33 2004 -@@ -17,7 +17,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -103,7 +103,7 @@ - - if (offset + size > PAGE_SIZE) - out_of_line_bug(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -114,8 +114,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/if_vlan.h kernel-source-2.4.26_meshax/include/linux/if_vlan.h ---- kernel-source-2.4.26/include/linux/if_vlan.h Wed Apr 14 09:05:40 2004 -+++ kernel-source-2.4.26_meshax/include/linux/if_vlan.h Tue Oct 12 20:15:33 2004 -@@ -184,7 +184,7 @@ - break; - }; - -- return (polling ? netif_receive_skb(skb) : netif_rx(skb)); -+ return (polling ? netif_receive_skb(skb, skb->protocol, 0) : netif_rx(skb)); - } - - static inline int vlan_hwaccel_rx(struct sk_buff *skb, -diff -U 3 --recursive kernel-source-2.4.26/include/linux/inetdevice.h kernel-source-2.4.26_meshax/include/linux/inetdevice.h ---- kernel-source-2.4.26/include/linux/inetdevice.h Fri Apr 16 20:10:28 2004 -+++ kernel-source-2.4.26_meshax/include/linux/inetdevice.h Tue Oct 12 20:15:33 2004 -@@ -142,7 +142,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/intermezzo_kml.h kernel-source-2.4.26_meshax/include/linux/intermezzo_kml.h ---- kernel-source-2.4.26/include/linux/intermezzo_kml.h Sun Nov 11 13:20:21 2001 -+++ kernel-source-2.4.26_meshax/include/linux/intermezzo_kml.h Tue Oct 12 20:15:33 2004 -@@ -70,8 +70,7 @@ - int gid; - }; - --struct kml_open { --}; -+EMPTY_STRUCT_DECL(kml_open); - - struct kml_mkdir { - char *path; -diff -U 3 --recursive kernel-source-2.4.26/include/linux/list.h kernel-source-2.4.26_meshax/include/linux/list.h ---- kernel-source-2.4.26/include/linux/list.h Fri Feb 20 22:47:18 2004 -+++ kernel-source-2.4.26_meshax/include/linux/list.h Tue Oct 12 20:15:33 2004 -@@ -91,8 +91,8 @@ - static inline void list_del(struct list_head *entry) - { - __list_del(entry->prev, entry->next); -- entry->next = (void *) 0; -- entry->prev = (void *) 0; -+ entry->next = (struct list_head *) 0; -+ entry->prev = (struct list_head *) 0; - } - - /** -diff -U 3 --recursive kernel-source-2.4.26/include/linux/mm.h kernel-source-2.4.26_meshax/include/linux/mm.h ---- kernel-source-2.4.26/include/linux/mm.h Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/include/linux/mm.h Tue Oct 12 20:15:33 2004 -@@ -589,7 +589,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/mtd/compatmac.h kernel-source-2.4.26_meshax/include/linux/mtd/compatmac.h ---- kernel-source-2.4.26/include/linux/mtd/compatmac.h Sat May 31 23:06:37 2003 -+++ kernel-source-2.4.26_meshax/include/linux/mtd/compatmac.h Tue Oct 12 20:15:33 2004 -@@ -133,8 +133,8 @@ - #endif /* !(__BIT_TYPES_DEFINED__) */ - - #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } -+ typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+ #define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - #else - typedef struct { int gcc_is_buggy; } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } -diff -U 3 --recursive kernel-source-2.4.26/include/linux/netdevice.h kernel-source-2.4.26_meshax/include/linux/netdevice.h ---- kernel-source-2.4.26/include/linux/netdevice.h Fri Apr 16 20:10:28 2004 -+++ kernel-source-2.4.26_meshax/include/linux/netdevice.h Tue Oct 12 20:15:33 2004 -@@ -457,6 +457,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - /* 2.6 compatibility */ -@@ -502,6 +542,9 @@ - extern void synchronize_net(void); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -@@ -615,7 +658,7 @@ - #define HAVE_NETIF_RX 1 - extern int netif_rx(struct sk_buff *skb); - #define HAVE_NETIF_RECEIVE_SKB 1 --extern int netif_receive_skb(struct sk_buff *skb); -+extern int netif_receive_skb(struct sk_buff *skb, unsigned short, int ignore_notifiers); - extern int dev_ioctl(unsigned int cmd, void *); - extern int dev_ethtool(struct ifreq *); - extern int dev_change_flags(struct net_device *, unsigned); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/netfilter_ipv4/ip_conntrack_irc.h kernel-source-2.4.26_meshax/include/linux/netfilter_ipv4/ip_conntrack_irc.h ---- kernel-source-2.4.26/include/linux/netfilter_ipv4/ip_conntrack_irc.h Thu Nov 28 18:53:15 2002 -+++ kernel-source-2.4.26_meshax/include/linux/netfilter_ipv4/ip_conntrack_irc.h Tue Oct 12 20:15:33 2004 -@@ -27,8 +27,7 @@ - }; - - /* This structure exists only once per master */ --struct ip_ct_irc_master { --}; -+EMPTY_STRUCT_DECL(ip_ct_irc_master); - - - #ifdef __KERNEL__ -diff -U 3 --recursive kernel-source-2.4.26/include/linux/nfsd/syscall.h kernel-source-2.4.26_meshax/include/linux/nfsd/syscall.h ---- kernel-source-2.4.26/include/linux/nfsd/syscall.h Sat Jun 24 00:31:05 2000 -+++ kernel-source-2.4.26_meshax/include/linux/nfsd/syscall.h Tue Oct 12 20:15:33 2004 -@@ -133,7 +133,7 @@ - * Kernel syscall implementation. - */ - #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) --extern asmlinkage long sys_nfsservctl(int, void *, void *); -+asmlinkage long sys_nfsservctl(int, void *, void *); - #else - #define sys_nfsservctl sys_ni_syscall - #endif -diff -U 3 --recursive kernel-source-2.4.26/include/linux/reiserfs_fs_sb.h kernel-source-2.4.26_meshax/include/linux/reiserfs_fs_sb.h ---- kernel-source-2.4.26/include/linux/reiserfs_fs_sb.h Sat Aug 30 02:01:49 2003 -+++ kernel-source-2.4.26_meshax/include/linux/reiserfs_fs_sb.h Tue Oct 12 20:15:33 2004 -@@ -352,8 +352,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -diff -U 3 --recursive kernel-source-2.4.26/include/linux/skbuff.h kernel-source-2.4.26_meshax/include/linux/skbuff.h ---- kernel-source-2.4.26/include/linux/skbuff.h Sat Apr 17 00:24:06 2004 -+++ kernel-source-2.4.26_meshax/include/linux/skbuff.h Tue Oct 12 20:15:33 2004 -@@ -128,19 +128,31 @@ - - struct net_device; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -- struct net_device *real_dev; /* For support of point to point protocols -- (e.g. 802.3ad) over bonding, we must save the -- physical device that got the packet before -- replacing skb->dev with the virtual device. */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -172,7 +184,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; - struct sec_path *sp; - - /* -@@ -183,23 +194,23 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -- unsigned int data_len; -- unsigned int csum; /* Checksum */ -- unsigned char local_df, -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ -- __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ -- unsigned short protocol; /* Packet protocol from driver. */ -- unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ -+ struct dst_entry *dst; - -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ struct net_device *real_dev; /* For support of point to point protocols -+ (e.g. 802.3ad) over bonding, we must save the -+ physical device that got the packet before -+ replacing skb->dev with the virtual device. */ -+ -+ -+ unsigned int data_len; -+ unsigned int csum; /* Checksum */ -+ unsigned char local_df; -+ __u32 priority; /* Packet queueing priority */ -+ unsigned short protocol; /* Packet protocol from driver. */ -+ unsigned short security; /* Security level of packet */ - - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER -@@ -238,6 +249,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -846,7 +859,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -874,7 +887,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -diff -U 3 --recursive kernel-source-2.4.26/include/linux/spinlock.h kernel-source-2.4.26_meshax/include/linux/spinlock.h ---- kernel-source-2.4.26/include/linux/spinlock.h Sun Feb 22 04:28:34 2004 -+++ kernel-source-2.4.26_meshax/include/linux/spinlock.h Tue Oct 12 20:15:33 2004 -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - #include - -@@ -72,13 +73,8 @@ - * - * Most gcc versions have a nasty bug with empty initializers. - */ --#if (__GNUC__ > 2) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -135,13 +131,8 @@ - * - * Most gcc versions have a nasty bug with empty initializers. - */ --#if (__GNUC__ > 2) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -diff -U 3 --recursive kernel-source-2.4.26/include/linux/swap.h kernel-source-2.4.26_meshax/include/linux/swap.h ---- kernel-source-2.4.26/include/linux/swap.h Fri Feb 20 22:47:18 2004 -+++ kernel-source-2.4.26_meshax/include/linux/swap.h Tue Oct 12 20:15:33 2004 -@@ -101,7 +101,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -diff -U 3 --recursive kernel-source-2.4.26/include/linux/sysctl.h kernel-source-2.4.26_meshax/include/linux/sysctl.h ---- kernel-source-2.4.26/include/linux/sysctl.h Sat Apr 17 00:24:06 2004 -+++ kernel-source-2.4.26_meshax/include/linux/sysctl.h Tue Oct 12 20:15:33 2004 -@@ -720,7 +720,7 @@ - - #ifdef __KERNEL__ - --extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+asmlinkage long sys_sysctl(struct __sysctl_args *); - extern void sysctl_init(void); - - typedef struct ctl_table ctl_table; -@@ -808,7 +808,7 @@ - int maxlen; - mode_t mode; - ctl_table *child; -- proc_handler *proc_handler; /* Callback for text formatting */ -+ proc_handler *proc_handler_member; /* Callback for text formatting */ - ctl_handler *strategy; /* Callback function for all r/w */ - struct proc_dir_entry *de; /* /proc control block */ - void *extra1; -@@ -819,7 +819,7 @@ - ctl_table trees. */ - struct ctl_table_header - { -- ctl_table *ctl_table; -+ ctl_table *ctl_table_member; - struct list_head ctl_entry; - }; - -diff -U 3 --recursive kernel-source-2.4.26/include/linux/types.h kernel-source-2.4.26_meshax/include/linux/types.h ---- kernel-source-2.4.26/include/linux/types.h Sat May 31 23:06:37 2003 -+++ kernel-source-2.4.26_meshax/include/linux/types.h Tue Oct 12 20:15:33 2004 -@@ -134,4 +134,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -diff -U 3 --recursive kernel-source-2.4.26/include/net/ax25.h kernel-source-2.4.26_meshax/include/net/ax25.h ---- kernel-source-2.4.26/include/net/ax25.h Thu Jan 4 17:51:20 2001 -+++ kernel-source-2.4.26_meshax/include/net/ax25.h Tue Oct 12 20:15:33 2004 -@@ -176,7 +176,7 @@ - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - ax25_digi *digipeat; -- ax25_dev *ax25_dev; -+ struct ax25_dev *ax25_dev; - unsigned char iamdigi; - unsigned char state, modulus, pidincl; - unsigned short vs, vr, va; -diff -U 3 --recursive kernel-source-2.4.26/include/net/checksum.h kernel-source-2.4.26_meshax/include/net/checksum.h ---- kernel-source-2.4.26/include/net/checksum.h Thu Jan 4 17:51:21 2001 -+++ kernel-source-2.4.26_meshax/include/net/checksum.h Tue Oct 12 20:15:33 2004 -@@ -111,7 +111,7 @@ - static __inline__ unsigned int csum_and_copy_to_user - (const char *src, char *dst, int len, unsigned int sum, int *err_ptr) - { -- sum = csum_partial(src, len, sum); -+ sum = csum_partial((const unsigned char *) src, len, sum); - - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len) == 0) -diff -U 3 --recursive kernel-source-2.4.26/include/net/route.h kernel-source-2.4.26_meshax/include/net/route.h ---- kernel-source-2.4.26/include/net/route.h Fri Apr 16 20:10:28 2004 -+++ kernel-source-2.4.26_meshax/include/net/route.h Tue Oct 12 20:15:33 2004 -@@ -146,16 +146,18 @@ - u32 src, u32 tos, int oif, u8 protocol, - u16 sport, u16 dport, struct sock *sk) - { -- struct flowi fl = { .oif = oif, -- .nl_u = { .ip4_u = { .daddr = dst, -- .saddr = src, -- .tos = tos } }, -- .proto = protocol, -- .uli_u = { .ports = -- { .sport = sport, -- .dport = dport } } }; -+ struct flowi fl; - - int err; -+ -+ fl.oif = oif; -+ fl.nl_u.ip4_u.daddr = dst; -+ fl.nl_u.ip4_u.saddr = src; -+ fl.nl_u.ip4_u.tos = tos; -+ fl.proto = protocol; -+ fl.uli_u.ports.sport = sport; -+ fl.uli_u.ports.dport = dport; -+ - if (!dst || !src) { - err = __ip_route_output_key(rp, &fl); - if (err) -diff -U 3 --recursive kernel-source-2.4.26/kernel/ksyms.c kernel-source-2.4.26_meshax/kernel/ksyms.c ---- kernel-source-2.4.26/kernel/ksyms.c Sun Feb 22 04:28:35 2004 -+++ kernel-source-2.4.26_meshax/kernel/ksyms.c Tue Oct 12 20:15:33 2004 -@@ -571,6 +571,8 @@ - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); - EXPORT_SYMBOL(__inode_dir_notify); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -diff -U 3 --recursive kernel-source-2.4.26/kernel/sysctl.c kernel-source-2.4.26_meshax/kernel/sysctl.c ---- kernel-source-2.4.26/kernel/sysctl.c Fri Nov 28 13:26:21 2003 -+++ kernel-source-2.4.26_meshax/kernel/sysctl.c Tue Oct 12 20:15:33 2004 -@@ -381,7 +381,7 @@ - list_entry(tmp, struct ctl_table_header, ctl_entry); - void *context = NULL; - int error = parse_table(name, nlen, oldval, oldlenp, -- newval, newlen, head->ctl_table, -+ newval, newlen, head->ctl_table_member, - &context); - if (context) - kfree(context); -@@ -543,7 +543,7 @@ - * child - a pointer to the child sysctl table if this entry is a directory, or - * %NULL. - * -- * proc_handler - the text handler routine (described below) -+ * proc_handler_th - the text handler routine (described below) - * - * strategy - the strategy routine (described below) - * -@@ -594,7 +594,7 @@ - tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL); - if (!tmp) - return NULL; -- tmp->ctl_table = table; -+ tmp->ctl_table_member = table; - INIT_LIST_HEAD(&tmp->ctl_entry); - if (insert_at_head) - list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); -@@ -617,7 +617,7 @@ - { - list_del(&header->ctl_entry); - #ifdef CONFIG_PROC_FS -- unregister_proc_table(header->ctl_table, proc_sys_root); -+ unregister_proc_table(header->ctl_table_member, proc_sys_root); - #endif - kfree(header); - } -@@ -640,7 +640,7 @@ - if (!table->procname) - continue; - /* Maybe we can't do anything with it... */ -- if (!table->proc_handler && !table->child) { -+ if (!table->proc_handler_member && !table->child) { - printk(KERN_WARNING "SYSCTL: Can't register %s\n", - table->procname); - continue; -@@ -650,7 +650,7 @@ - mode = table->mode; - - de = NULL; -- if (table->proc_handler) -+ if (table->proc_handler_member) - mode |= S_IFREG; - else { - mode |= S_IFDIR; -@@ -666,7 +666,7 @@ - if (!de) - continue; - de->data = (void *) table; -- if (table->proc_handler) { -+ if (table->proc_handler_member) { - de->proc_fops = &proc_sys_file_operations; - de->proc_iops = &proc_sys_inode_operations; - } -@@ -720,7 +720,7 @@ - if (!de || !de->data) - return -ENOTDIR; - table = (struct ctl_table *) de->data; -- if (!table || !table->proc_handler) -+ if (!table || !table->proc_handler_member) - return -ENOTDIR; - op = (write ? 002 : 004); - if (ctl_perm(table, op)) -@@ -732,7 +732,7 @@ - * FIXME: we need to pass on ppos to the handler. - */ - -- error = (*table->proc_handler) (table, write, file, buf, &res); -+ error = (*table->proc_handler_member) (table, write, file, buf, &res); - if (error) - return error; - return res; -diff -U 3 --recursive kernel-source-2.4.26/net/core/dev.c kernel-source-2.4.26_meshax/net/core/dev.c ---- kernel-source-2.4.26/net/core/dev.c Fri Apr 16 20:10:28 2004 -+++ kernel-source-2.4.26_meshax/net/core/dev.c Tue Oct 12 20:15:33 2004 -@@ -182,6 +182,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1432,6 +1435,22 @@ - } - - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1465,11 +1484,10 @@ - } - #endif /* CONFIG_NET_DIVERT */ - --int netif_receive_skb(struct sk_buff *skb) -+int netif_receive_skb(struct sk_buff *skb, unsigned short type, int notifier_data) - { - struct packet_type *ptype, *pt_prev; - int ret = NET_RX_DROP; -- unsigned short type; - - if (skb->stamp.tv_sec == 0) - do_gettimeofday(&skb->stamp); -@@ -1487,6 +1505,14 @@ - - skb->h.raw = skb->nh.raw = skb->data; - -+ /* Click: may want to steal the packet */ -+ if (notifier_data >= 0 -+ && notifier_call_chain(&net_in_chain, -+ notifier_data, -+ skb) & NOTIFY_STOP_MASK) { -+ return ret; -+ } -+ - pt_prev = NULL; - for (ptype = ptype_all; ptype; ptype = ptype->next) { - if (!ptype->dev || ptype->dev == skb->dev) { -@@ -1514,7 +1540,6 @@ - } - #endif - -- type = skb->protocol; - for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { - if (ptype->type == type && - (!ptype->dev || ptype->dev == skb->dev)) { -@@ -1567,7 +1592,7 @@ - - dev = skb->dev; - -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, skb_queue_len(&queue->input_pkt_queue)); - - dev_put(dev); - -diff -U 3 --recursive kernel-source-2.4.26/net/core/skbuff.c kernel-source-2.4.26_meshax/net/core/skbuff.c ---- kernel-source-2.4.26/net/core/skbuff.c Wed Sep 3 06:27:21 2003 -+++ kernel-source-2.4.26_meshax/net/core/skbuff.c Tue Oct 12 20:15:33 2004 -@@ -461,6 +461,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -diff -U 3 --recursive kernel-source-2.4.26/net/ipv4/arp.c kernel-source-2.4.26_meshax/net/ipv4/arp.c ---- kernel-source-2.4.26/net/ipv4/arp.c Fri Apr 16 20:10:28 2004 -+++ kernel-source-2.4.26_meshax/net/ipv4/arp.c Tue Oct 12 20:15:33 2004 -@@ -323,6 +323,7 @@ - { - u32 saddr = 0; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -360,8 +361,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -371,8 +372,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_ignore(struct in_device *in_dev, struct net_device *dev, -diff -U 3 --recursive kernel-source-2.4.26/net/ipv4/route.c kernel-source-2.4.26_meshax/net/ipv4/route.c ---- kernel-source-2.4.26/net/ipv4/route.c Sat Nov 29 04:53:54 2003 -+++ kernel-source-2.4.26_meshax/net/ipv4/route.c Tue Oct 12 20:15:33 2004 -@@ -2388,7 +2388,7 @@ - data: &flush_delay, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &ipv4_sysctl_rtcache_flush, -+ proc_handler_member: &ipv4_sysctl_rtcache_flush, - strategy: &ipv4_sysctl_rtcache_flush_strategy, - }, - { -@@ -2397,7 +2397,7 @@ - data: &ip_rt_min_delay, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2406,7 +2406,7 @@ - data: &ip_rt_max_delay, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2415,7 +2415,7 @@ - data: &ipv4_dst_ops.gc_thresh, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_MAX_SIZE, -@@ -2423,7 +2423,7 @@ - data: &ip_rt_max_size, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_GC_MIN_INTERVAL, -@@ -2431,7 +2431,7 @@ - data: &ip_rt_gc_min_interval, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2440,7 +2440,7 @@ - data: &ip_rt_gc_timeout, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2449,7 +2449,7 @@ - data: &ip_rt_gc_interval, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2458,7 +2458,7 @@ - data: &ip_rt_redirect_load, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_REDIRECT_NUMBER, -@@ -2466,7 +2466,7 @@ - data: &ip_rt_redirect_number, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_REDIRECT_SILENCE, -@@ -2474,7 +2474,7 @@ - data: &ip_rt_redirect_silence, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_ERROR_COST, -@@ -2482,7 +2482,7 @@ - data: &ip_rt_error_cost, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_ERROR_BURST, -@@ -2490,7 +2490,7 @@ - data: &ip_rt_error_burst, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_GC_ELASTICITY, -@@ -2498,7 +2498,7 @@ - data: &ip_rt_gc_elasticity, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_MTU_EXPIRES, -@@ -2506,7 +2506,7 @@ - data: &ip_rt_mtu_expires, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { -@@ -2515,7 +2515,7 @@ - data: &ip_rt_min_pmtu, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_MIN_ADVMSS, -@@ -2523,7 +2523,7 @@ - data: &ip_rt_min_advmss, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec, -+ proc_handler_member: &proc_dointvec, - }, - { - ctl_name: NET_IPV4_ROUTE_SECRET_INTERVAL, -@@ -2531,7 +2531,7 @@ - data: &ip_rt_secret_interval, - maxlen: sizeof(int), - mode: 0644, -- proc_handler: &proc_dointvec_jiffies, -+ proc_handler_member: &proc_dointvec_jiffies, - strategy: &sysctl_jiffies, - }, - { 0 } -diff -U 3 --recursive kernel-source-2.4.26/net/netsyms.c kernel-source-2.4.26_meshax/net/netsyms.c ---- kernel-source-2.4.26/net/netsyms.c Sat Apr 17 00:24:08 2004 -+++ kernel-source-2.4.26_meshax/net/netsyms.c Tue Oct 12 20:15:33 2004 -@@ -299,6 +299,11 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - -diff -U 3 --recursive kernel-source-2.4.26/net/sctp/sysctl.c kernel-source-2.4.26_meshax/net/sctp/sysctl.c ---- kernel-source-2.4.26/net/sctp/sysctl.c Wed Apr 14 09:05:41 2004 -+++ kernel-source-2.4.26_meshax/net/sctp/sysctl.c Tue Oct 12 20:19:55 2004 -@@ -54,7 +54,7 @@ - .data = &sctp_rto_initial, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -65,7 +65,7 @@ - .data = &sctp_rto_min, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -76,7 +76,7 @@ - .data = &sctp_rto_max, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -87,7 +87,7 @@ - .data = &sctp_valid_cookie_life, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -98,7 +98,7 @@ - .data = &sctp_max_burst, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS, -@@ -106,7 +106,7 @@ - .data = &sctp_max_retrans_association, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_PATH_MAX_RETRANS, -@@ -114,7 +114,7 @@ - .data = &sctp_max_retrans_path, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS, -@@ -122,7 +122,7 @@ - .data = &sctp_max_retrans_init, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_HB_INTERVAL, -@@ -130,7 +130,7 @@ - .data = &sctp_hb_interval, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -141,7 +141,7 @@ - .data = &sctp_cookie_preserve_enable, - .maxlen = sizeof(long), - .mode = 0644, -- .proc_handler = &proc_doulongvec_ms_jiffies_minmax, -+ .proc_handler_member = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max -@@ -152,7 +152,7 @@ - .data = &sctp_rto_alpha, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_RTO_BETA, -@@ -160,7 +160,7 @@ - .data = &sctp_rto_beta, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { - .ctl_name = NET_SCTP_ADDIP_ENABLE, -@@ -168,7 +168,7 @@ - .data = &sctp_addip_enable, - .maxlen = sizeof(int), - .mode = 0644, -- .proc_handler = &proc_dointvec -+ .proc_handler_member = &proc_dointvec - }, - { .ctl_name = 0 } - }; diff --git a/etc/linux-2.2.18-example-conf b/etc/linux-2.2.18-example-conf deleted file mode 100644 index d3c0b716da..0000000000 --- a/etc/linux-2.2.18-example-conf +++ /dev/null @@ -1,547 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Processor type and features -# -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -CONFIG_M686=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_TSC=y -CONFIG_X86_GOOD_APIC=y -# CONFIG_MICROCODE is not set -# CONFIG_X86_MSR is not set -# CONFIG_X86_CPUID is not set -CONFIG_1GB=y -# CONFIG_2GB is not set -CONFIG_MATH_EMULATION=y -CONFIG_MTRR=y -CONFIG_SMP=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_NET=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_QUIRKS=y -# CONFIG_PCI_OPTIMIZE is not set -CONFIG_PCI_OLD_PROC=y -# CONFIG_MCA is not set -# CONFIG_VISWS is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y -# CONFIG_BINFMT_JAVA is not set -# CONFIG_PARPORT is not set -# CONFIG_APM is not set -# CONFIG_TOSHIBA is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=y -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set -# CONFIG_BLK_DEV_CMD646 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_IDE_CHIPSETS is not set - -# -# Additional Block Devices -# -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=y -CONFIG_MD_STRIPED=y -CONFIG_MD_MIRRORING=y -CONFIG_MD_RAID5=y -CONFIG_MD_BOOT=y -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_XD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_PARIDE_PARPORT=y -CONFIG_PARIDE=m - -# -# Parallel IDE high-level drivers -# -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m - -# -# Parallel IDE protocol modules -# -# CONFIG_PARIDE_ATEN is not set -# CONFIG_PARIDE_BPCK is not set -# CONFIG_PARIDE_COMM is not set -# CONFIG_PARIDE_DSTR is not set -# CONFIG_PARIDE_FIT2 is not set -# CONFIG_PARIDE_FIT3 is not set -# CONFIG_PARIDE_EPAT is not set -# CONFIG_PARIDE_EPIA is not set -# CONFIG_PARIDE_FRIQ is not set -# CONFIG_PARIDE_FRPW is not set -# CONFIG_PARIDE_KBIC is not set -# CONFIG_PARIDE_KTTI is not set -# CONFIG_PARIDE_ON20 is not set -# CONFIG_PARIDE_ON26 is not set -CONFIG_BLK_CPQ_DA=m -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_HD is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y -# CONFIG_NETLINK_DEV is not set -# CONFIG_FIREWALL is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_RTNETLINK=y -CONFIG_NETLINK=y -# CONFIG_IP_MULTIPLE_TABLES is not set -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_TOS is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -# CONFIG_IP_ROUTE_LARGE_TABLES is not set -# CONFIG_IP_PNP is not set -CONFIG_IP_ROUTER=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -# CONFIG_INET_RARP is not set -CONFIG_SKB_LARGE=y -CONFIG_IPV6=m -# CONFIG_IPV6_EUI64 is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_LLC is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y -CONFIG_NET_SCH_CBQ=m -# CONFIG_NET_SCH_CSZ is not set -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -# CONFIG_NET_CLS is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=y -CONFIG_SCSI_AHA1542=y -CONFIG_SCSI_AHA1740=y -CONFIG_SCSI_AIC7XXX=y -# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set -CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 -# CONFIG_AIC7XXX_PROC_STATS is not set -CONFIG_AIC7XXX_RESET_DELAY=5 -CONFIG_SCSI_IPS=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -CONFIG_SCSI_GENERIC_NCR53C400=y -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -CONFIG_SCSI_INITIO=y -# CONFIG_SCSI_INIA100 is not set -CONFIG_SCSI_NCR53C406A=y -CONFIG_SCSI_SYM53C416=y -CONFIG_SCSI_SIM710=y -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_NCR53C8XX=y -CONFIG_SCSI_SYM53C8XX=y -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=20 -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_SEAGATE is not set -CONFIG_SCSI_DC390T=y -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -CONFIG_SCSI_DEBUG=m - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_SCSI is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_ETHERTAP is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -CONFIG_EL3=m -# CONFIG_3C515 is not set -CONFIG_VORTEX=m -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_RTL8139TOO is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_EISA=y -# CONFIG_PCNET32 is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -# CONFIG_DM9102 is not set -# CONFIG_DE4X5 is not set -CONFIG_DEC_ELCP=m -# CONFIG_DEC_ELCP_OLD is not set -# CONFIG_DGRS is not set -CONFIG_EEXPRESS_PRO100=m -# CONFIG_LNE390 is not set -# CONFIG_NE3210 is not set -CONFIG_NE2K_PCI=m -# CONFIG_TLAN is not set -CONFIG_VIA_RHINE=m -CONFIG_SIS900=m -# CONFIG_ES3210 is not set -CONFIG_EPIC100=m -# CONFIG_ZNET is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_HAMACHI is not set -CONFIG_YELLOWFIN=m -CONFIG_SK98LIN=m -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NET_RADIO is not set - -# -# Token ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set -# CONFIG_SEALEVEL_4021 is not set -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_LANMEDIA is not set -# CONFIG_COMX is not set -# CONFIG_HDLC is not set -# CONFIG_DLCI is not set -# CONFIG_XPEED is not set -# CONFIG_SBNI is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_MOUSE=y - -# -# Mice -# -# CONFIG_ATIXL_BUSMOUSE is not set -# CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=y -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Filesystems -# -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_EFS_FS is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -CONFIG_NFSD=m -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set - -# -# Partition Types -# -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_SMD_DISKLABEL is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_NLS is not set - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -# CONFIG_VIDEO_SELECT is not set -# CONFIG_MDA_CONSOLE is not set -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# Kernel hacking -# -# CONFIG_MAGIC_SYSRQ is not set diff --git a/etc/linux-2.2.18-patch b/etc/linux-2.2.18-patch deleted file mode 100644 index 1402ea7d2e..0000000000 --- a/etc/linux-2.2.18-patch +++ /dev/null @@ -1,3026 +0,0 @@ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/drivers/net/acenic.c ./drivers/net/acenic.c -*** ../linux-2.2.18-pure/drivers/net/acenic.c Sun Dec 10 16:49:42 2000 ---- ./drivers/net/acenic.c Sat May 4 23:29:49 2002 -*************** -*** 343,350 **** - * one running the interrupt handler just got the slab code hot in its - * cache. - */ -! #define RX_RING_SIZE 72 -! #define RX_MINI_SIZE 64 - #define RX_JUMBO_SIZE 48 - - #define RX_PANIC_STD_THRES 16 ---- 343,350 ---- - * one running the interrupt handler just got the slab code hot in its - * cache. - */ -! #define RX_RING_SIZE 128 -! #define RX_MINI_SIZE 128 - #define RX_JUMBO_SIZE 48 - - #define RX_PANIC_STD_THRES 16 -*************** -*** 376,385 **** - * on whether or not the user enables Jumbo frames. It's assumed that if - * Jumbo frames are enabled, the user wants optimal tuning for that case. - */ -! #define DEF_TX_COAL 400 /* 996 */ - #define DEF_TX_MAX_DESC 40 -! #define DEF_RX_COAL 120 /* 1000 */ -! #define DEF_RX_MAX_DESC 25 - #define DEF_TX_RATIO 21 /* 24 */ - - #define DEF_JUMBO_TX_COAL 20 ---- 376,385 ---- - * on whether or not the user enables Jumbo frames. It's assumed that if - * Jumbo frames are enabled, the user wants optimal tuning for that case. - */ -! #define DEF_TX_COAL 400 /* 996 */ - #define DEF_TX_MAX_DESC 40 -! #define DEF_RX_COAL 120 /* 1000 */ -! #define DEF_RX_MAX_DESC 25 - #define DEF_TX_RATIO 21 /* 24 */ - - #define DEF_JUMBO_TX_COAL 20 -*************** -*** 409,414 **** ---- 409,423 ---- - - static int probed __initdata = 0; - -+ /* Click - polling extension */ -+ static int ace_tx_queue(struct device *dev, struct sk_buff *skb); -+ static int ace_tx_start(struct device *dev); -+ static int ace_tx_eob(struct device *dev); -+ static int ace_rx_refill(struct device *dev, struct sk_buff **); -+ static struct sk_buff *ace_tx_clean(struct device *dev); -+ static struct sk_buff *ace_rx_poll(struct device *dev, int *want); -+ static int ace_poll_on(struct device *dev); -+ static int ace_poll_off(struct device *dev); - - #ifdef NEW_NETINIT - int __init acenic_probe (void) -*************** -*** 482,487 **** ---- 491,507 ---- - dev->set_mac_address = &ace_set_mac_addr; - dev->change_mtu = &ace_change_mtu; - -+ /* Click - polling extensions */ -+ dev->polling = 0; -+ dev->rx_poll = ace_rx_poll; -+ dev->rx_refill = ace_rx_refill; -+ dev->tx_clean = ace_tx_clean; -+ dev->tx_queue = ace_tx_queue; -+ dev->tx_start = ace_tx_start; -+ dev->tx_eob = ace_tx_eob; -+ dev->poll_off = ace_poll_off; -+ dev->poll_on = ace_poll_on; -+ - /* display version info if adapter is found */ - if (!version_disp) - { -*************** -*** 1592,1598 **** - skb = alloc_skb(ACE_STD_BUFSIZE, GFP_ATOMIC); - if (!skb) - break; -- - /* - * Make sure IP header starts on a fresh cache line. - */ ---- 1612,1617 ---- -*************** -*** 1862,1877 **** - return evtcsm; - } - -! -! static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) - { -! struct ace_private *ap = dev->priv; -! u32 idx; -! int mini_count = 0, std_count = 0; -! -! idx = rxretcsm; -! -! while (idx != rxretprd) { - struct ring_info *rip; - struct sk_buff *skb; - struct rx_desc *rxdesc, *retdesc; ---- 1881,1890 ---- - return evtcsm; - } - -! static struct sk_buff* -! ace_rx_get_skb(struct net_device *dev, u32 idx, int *mini_count, int *std_count) - { -! struct ace_private *ap = dev->priv; - struct ring_info *rip; - struct sk_buff *skb; - struct rx_desc *rxdesc, *retdesc; -*************** -*** 1895,1901 **** - rip = &ap->skb->rx_std_skbuff[skbidx]; - mapsize = ACE_STD_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_std_ring[skbidx]; -! std_count++; - break; - case BD_FLG_JUMBO: - rip = &ap->skb->rx_jumbo_skbuff[skbidx]; ---- 1908,1914 ---- - rip = &ap->skb->rx_std_skbuff[skbidx]; - mapsize = ACE_STD_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_std_ring[skbidx]; -! (*std_count)++; - break; - case BD_FLG_JUMBO: - rip = &ap->skb->rx_jumbo_skbuff[skbidx]; -*************** -*** 1907,1919 **** - rip = &ap->skb->rx_mini_skbuff[skbidx]; - mapsize = ACE_MINI_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_mini_ring[skbidx]; -! mini_count++; - break; - default: - printk(KERN_INFO "%s: unknown frame type (0x%02x) " - "returned by NIC\n", dev->name, - retdesc->flags); -! goto error; - } - - skb = rip->skb; ---- 1920,1932 ---- - rip = &ap->skb->rx_mini_skbuff[skbidx]; - mapsize = ACE_MINI_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_mini_ring[skbidx]; -! (*mini_count)++; - break; - default: - printk(KERN_INFO "%s: unknown frame type (0x%02x) " - "returned by NIC\n", dev->name, - retdesc->flags); -! return 0L; - } - - skb = rip->skb; -*************** -*** 1945,1955 **** - else - skb->ip_summed = CHECKSUM_NONE; - -- netif_rx(skb); /* send it up */ -- - ap->stats.rx_packets++; - ap->stats.rx_bytes += retdesc->size; - - idx = (idx + 1) % RX_RETURN_RING_ENTRIES; - } - ---- 1958,1986 ---- - else - skb->ip_summed = CHECKSUM_NONE; - - ap->stats.rx_packets++; - ap->stats.rx_bytes += retdesc->size; - -+ return skb; -+ } -+ -+ -+ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx; -+ int mini_count = 0, std_count = 0; -+ -+ idx = rxretcsm; -+ -+ while (idx != rxretprd) { -+ struct sk_buff *skb; -+ -+ skb = ace_rx_get_skb(dev, idx, &mini_count, &std_count); -+ if (skb == 0L) goto error; -+ -+ netif_rx(skb); /* send it up */ -+ - idx = (idx + 1) % RX_RETURN_RING_ENTRIES; - } - -*************** -*** 1974,1979 **** ---- 2005,2057 ---- - goto out; - } - -+ static void ace_service_tx(struct net_device *dev, int polling_ext) -+ { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ u32 txcsm, idx; -+ -+ ap = dev->priv; -+ regs = ap->regs; -+ -+ txcsm = *ap->tx_csm; -+ idx = ap->tx_ret_csm; -+ -+ do { -+ struct sk_buff *skb; -+ -+ skb = ap->skb->tx_skbuff[idx].skb; -+ if (skb) { -+ dma_addr_t mapping; -+ -+ mapping = ap->skb->tx_skbuff[idx].mapping; -+ -+ ap->stats.tx_packets++; -+ ap->stats.tx_bytes += skb->len; -+ pci_unmap_single(ap->pdev, mapping, skb->len, -+ PCI_DMA_TODEVICE); -+ dev_kfree_skb_irq(skb); -+ ap->skb->tx_skbuff[idx].skb = NULL; -+ } -+ -+ /* -+ * Question here is whether one should not skip -+ * these writes - I have never seen any errors -+ * caused by the NIC actually trying to access -+ * these incorrectly. -+ */ -+ #if (BITS_PER_LONG == 64) -+ writel(0, &ap->tx_ring[idx].addr.addrhi); -+ #endif -+ writel(0, &ap->tx_ring[idx].addr.addrlo); -+ writel(0, &ap->tx_ring[idx].flagsize); -+ -+ idx = (idx + 1) % TX_RING_ENTRIES; -+ } while (idx != txcsm); -+ } -+ -+ static unsigned long ace_poll_intr = 0; -+ static unsigned long ace_poll_evtintr = 0; - - static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) - { -*************** -*** 1987,1992 **** ---- 2065,2073 ---- - ap = dev->priv; - regs = ap->regs; - -+ if (dev->polling) -+ ace_poll_intr++; -+ - /* - * In case of PCI shared interrupts or spurious interrupts, - * we want to make sure it is actually our interrupt before -*************** -*** 2010,2022 **** - rxretprd = *ap->rx_ret_prd; - rxretcsm = ap->cur_rx; - -! if (rxretprd != rxretcsm) - ace_rx_int(dev, rxretprd, rxretcsm); - - txcsm = *ap->tx_csm; - idx = ap->tx_ret_csm; - -! if (txcsm != idx) { - do { - struct sk_buff *skb; - ---- 2091,2103 ---- - rxretprd = *ap->rx_ret_prd; - rxretcsm = ap->cur_rx; - -! if (rxretprd != rxretcsm && !dev->polling) - ace_rx_int(dev, rxretprd, rxretcsm); - - txcsm = *ap->tx_csm; - idx = ap->tx_ret_csm; - -! if (txcsm != idx && !dev->polling) { - do { - struct sk_buff *skb; - -*************** -*** 2092,2097 **** ---- 2173,2180 ---- - evtprd = *ap->evt_prd; - - if (evtcsm != evtprd) { -+ if (dev->polling) -+ ace_poll_evtintr++; - evtcsm = ace_handle_event(dev, evtcsm, evtprd); - writel(evtcsm, ®s->EvtCsm); - } -*************** -*** 2100,2106 **** - * This has to go last in the interrupt handler and run with - * the spin lock released ... what lock? - */ -! if (netif_running(dev)) { - int cur_size; - int run_bh = 0; - ---- 2183,2189 ---- - * This has to go last in the interrupt handler and run with - * the spin lock released ... what lock? - */ -! if (!dev->polling && netif_running(dev)) { - int cur_size; - int run_bh = 0; - -*************** -*** 2304,2317 **** - return 0; - } - -! -! static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; - unsigned long addr; -! u32 idx, flagsize; - - /* - * ARGH, there is just no pretty way to do this - */ ---- 2387,2428 ---- - return 0; - } - -! static int ace_queue_skb(struct sk_buff *skb, struct net_device *dev, u32 idx) - { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; - unsigned long addr; -! u32 flagsize; -! -! ap->skb->tx_skbuff[idx].skb = skb; -! ap->skb->tx_skbuff[idx].mapping = -! pci_map_single(ap->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); -! addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; -! #if (BITS_PER_LONG == 64) -! writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); -! #endif -! writel(addr & 0xffffffff, &ap->tx_ring[idx].addr.addrlo); -! flagsize = (skb->len << 16) | (BD_FLG_END) ; -! writel(flagsize, &ap->tx_ring[idx].flagsize); -! wmb(); -! idx = (idx + 1) % TX_RING_ENTRIES; -! -! ap->tx_prd = idx; -! ace_set_txprd(regs, ap, idx); -! return idx; -! } - -+ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx; -+ -+ /* polling extension: we have to use tbusy to prevent ace_start_xmit from -+ * colliding with ace_tx_queue */ -+ #if 1 -+ if (test_and_set_bit(0, &dev->tbusy)) -+ return 1; -+ #else - /* - * ARGH, there is just no pretty way to do this - */ -*************** -*** 2321,2326 **** ---- 2432,2438 ---- - #else - netif_stop_queue(dev); - #endif -+ #endif - - idx = ap->tx_prd; - -*************** -*** 2333,2354 **** - return 1; - } - -! ap->skb->tx_skbuff[idx].skb = skb; -! ap->skb->tx_skbuff[idx].mapping = -! pci_map_single(ap->pdev, skb->data, skb->len, -! PCI_DMA_TODEVICE); -! addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; -! #if (BITS_PER_LONG == 64) -! writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); -! #endif -! writel(addr & 0xffffffff, &ap->tx_ring[idx].addr.addrlo); -! flagsize = (skb->len << 16) | (BD_FLG_END) ; -! writel(flagsize, &ap->tx_ring[idx].flagsize); -! wmb(); -! idx = (idx + 1) % TX_RING_ENTRIES; -! -! ap->tx_prd = idx; -! ace_set_txprd(regs, ap, idx); - - /* - * tx_csm is set by the NIC whereas we set tx_ret_csm which ---- 2445,2451 ---- - return 1; - } - -! idx = ace_queue_skb(skb, dev, idx); - - /* - * tx_csm is set by the NIC whereas we set tx_ret_csm which -*************** -*** 3004,3012 **** - goto out; - } - -! - /* - * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" - * End: - */ ---- 3101,3513 ---- - goto out; - } - -! - /* - * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" - * End: - */ -+ -+ -+ /* -+ * Polling Extension -+ * -+ * tx_csm: NIC's tx consumer pointer. updated when NIC transmit a pkt. -+ * -+ * tx_ret_csm: driver's tx consumer pointer. the pkts between tx_ret_csm and -+ * tx_csm are transmitted packets that need to be cleaned up. -+ * -+ * TxPrd: tx producer register in shared memory, read by NIC. this is kept in -+ * sync with tx_prd. -+ * -+ * tx_prd: driver's tx producer pointer (i.e. the next free buf on tx ring). -+ * driver will queue pkts onto tx ring, starting from tx_prd until the idx on -+ * tx ring hits tx_ret_csm - 2. that is when the driver believes the tx ring -+ * is full. -+ * -+ * rx_ret_prd: NIC's rx producer pointer. when a pkt arrives at NIC, this -+ * producer is incremented. -+ * -+ * cur_rx: the next rx buffer the driver should read. the difference between -+ * cur_rx and rx_ret_prd are newly arrived pkts. -+ * -+ * rx processing with Tigon uses a return ring. there are three rx rings (std, -+ * mini, and jumbo) and one rx return ring. the rx_ret_prd pointer points to -+ * the return ring. on the return ring, a descriptor tells you which of the -+ * three rx rings contain the last pkt. there is a counter for each of the -+ * three rings. when a pkt is pulled off of a ring, the corresponding counter -+ * is incremented. this is important, because the number recorded by each -+ * counter is the number of buffer refilled onto each ring. -+ */ -+ -+ #define SELECTIVE_INTR 0 -+ -+ static int -+ ace_tx_queue(struct device *dev, struct sk_buff *skb) -+ { -+ struct ace_private *ap = dev->priv; -+ unsigned long addr; -+ u32 flagsize, idx; -+ -+ /* polling extension: we have to use tbusy to prevent -+ * ace_start_xmit from colliding with ace_tx_queue */ -+ if (test_and_set_bit(0, (void*)&dev->tbusy)) -+ return 1; -+ -+ idx = ap->tx_prd; -+ -+ /* hard_start_xmit and tx_clean collision detected */ -+ if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm) { -+ ap->tx_full = 1; -+ return 1; -+ } -+ -+ ap->skb->tx_skbuff[idx].skb = skb; -+ ap->skb->tx_skbuff[idx].mapping = -+ pci_map_single(ap->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); -+ addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; -+ #if (BITS_PER_LONG == 64) -+ writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); -+ #endif -+ writel(addr & 0xffffffff, &ap->tx_ring[idx].addr.addrlo); -+ flagsize = (skb->len << 16) | (BD_FLG_END) ; -+ writel(flagsize, &ap->tx_ring[idx].flagsize); -+ wmb(); -+ idx = (idx + 1) % TX_RING_ENTRIES; -+ ap->tx_prd = idx; -+ -+ if ((idx + 2) % TX_RING_ENTRIES == ap->tx_ret_csm) -+ ap->tx_full = 1; -+ else -+ clear_bit(0, (void*)&dev->tbusy); -+ -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ -+ static int -+ ace_tx_eob(struct device *dev) -+ { -+ struct ace_private *ap = dev->priv; -+ struct ace_regs *regs = ap->regs; -+ ace_set_txprd(regs, ap, ap->tx_prd); -+ return 0; -+ } -+ -+ static int -+ ace_tx_start(struct device *dev) -+ { -+ /* sorry pal, dunno how to do this... */ -+ return 1; -+ } -+ -+ static struct sk_buff* -+ ace_tx_clean(struct device *dev) -+ { -+ struct ace_private *ap = dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ u32 txcsm = *ap->tx_csm; -+ -+ skb_head = skb_last = NULL; -+ if (txcsm != ap->tx_ret_csm) { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ u32 txcsm, idx; -+ -+ ap = dev->priv; -+ regs = ap->regs; -+ -+ txcsm = *ap->tx_csm; -+ idx = ap->tx_ret_csm; -+ -+ do { -+ struct sk_buff *skb; -+ -+ skb = ap->skb->tx_skbuff[idx].skb; -+ if (skb) { -+ dma_addr_t mapping; -+ -+ mapping = ap->skb->tx_skbuff[idx].mapping; -+ -+ ap->stats.tx_packets++; -+ ap->stats.tx_bytes += skb->len; -+ pci_unmap_single(ap->pdev, mapping, skb->len, PCI_DMA_TODEVICE); -+ ap->skb->tx_skbuff[idx].skb = NULL; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+ /* -+ * Question here is whether one should not skip these -+ * writes - I have never seen any errors caused by the NIC -+ * actually trying to access these incorrectly. -+ */ -+ #if (BITS_PER_LONG == 64) -+ writel(0, &ap->tx_ring[idx].addr.addrhi); -+ #endif -+ writel(0, &ap->tx_ring[idx].addr.addrlo); -+ writel(0, &ap->tx_ring[idx].flagsize); -+ -+ idx = (idx + 1) % TX_RING_ENTRIES; -+ -+ } while (idx != txcsm); -+ -+ /* only clear the tbusy bit if tx_full is set, so we don't -+ * accidentally allow two start_xmit or tx_queue to go on w/o -+ * synchronization. if tx_full is set, then neither start_xmit -+ * nor tx_queue is executing, or one is executing but the -+ * producer pointer has already been updated. -+ */ -+ if (ap->tx_full) { -+ clear_bit(0, (void*)&ap->tx_full); -+ clear_bit(0, (void*)&dev->tbusy); -+ } -+ ap->tx_ret_csm = txcsm; -+ wmb(); -+ } -+ return skb_head; -+ } -+ -+ static int -+ ace_rx_refill(struct device *dev, struct sk_buff **skbs) -+ { -+ u32 evtcsm, evtprd; -+ struct ace_private *ap = dev->priv; -+ struct ace_regs *regs = ap->regs; -+ int cur_size = atomic_read(&ap->cur_rx_bufs); -+ struct sk_buff *skb_list; -+ -+ if (skbs == 0) -+ return (RX_RING_SIZE-atomic_read(&ap->cur_rx_bufs))+ -+ (RX_MINI_SIZE-atomic_read(&ap->cur_mini_bufs)); -+ skb_list = *skbs; -+ -+ if (!test_and_set_bit(0, &ap->std_refill_busy)) { -+ short nr_bufs = RX_RING_SIZE - cur_size; -+ short i = 0, idx; -+ idx = ap->rx_std_skbprd; -+ -+ for (; i < nr_bufs && skb_list; i++) { -+ struct sk_buff *skb; -+ struct rx_desc *rd; -+ dma_addr_t mapping; -+ -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ /* make sure IP header starts on a fresh cache line. */ -+ skb_reserve(skb, 2 + 16); -+ mapping = pci_map_single(ap->pdev, skb->data, -+ ACE_STD_BUFSIZE - (2 + 16), -+ PCI_DMA_FROMDEVICE); -+ ap->skb->rx_std_skbuff[idx].skb = skb; -+ ap->skb->rx_std_skbuff[idx].mapping = mapping; -+ rd = &ap->rx_std_ring[idx]; -+ set_aceaddr(&rd->addr, mapping); -+ rd->size = ACE_STD_MTU + ETH_HLEN + 4; -+ rd->idx = idx; -+ idx = (idx + 1) % RX_STD_RING_ENTRIES; -+ } -+ -+ atomic_add(i, &ap->cur_rx_bufs); -+ ap->rx_std_skbprd = idx; -+ -+ if (ACE_IS_TIGON_I(ap)) { -+ struct cmd cmd; -+ cmd.evt = C_SET_RX_PRD_IDX; -+ cmd.code = 0; -+ cmd.idx = ap->rx_std_skbprd; -+ ace_issue_cmd(regs, &cmd); -+ } else { -+ writel(idx, ®s->RxStdPrd); -+ wmb(); -+ } -+ clear_bit(0, &ap->std_refill_busy); -+ } -+ -+ if (ap->version >= 2 && !test_and_set_bit(0, &ap->mini_refill_busy)) { -+ short nr_bufs, i = 0, idx; -+ -+ cur_size = atomic_read(&ap->cur_mini_bufs); -+ nr_bufs = RX_MINI_SIZE - cur_size; -+ idx = ap->rx_mini_skbprd; -+ -+ for (; i < nr_bufs && skb_list; i++) { -+ struct sk_buff *skb; -+ struct rx_desc *rd; -+ dma_addr_t mapping; -+ -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ skb_reserve(skb, 2 + 16); -+ mapping = pci_map_single(ap->pdev, skb->data, -+ ACE_MINI_BUFSIZE - (2 + 16), -+ PCI_DMA_FROMDEVICE); -+ ap->skb->rx_mini_skbuff[idx].skb = skb; -+ ap->skb->rx_mini_skbuff[idx].mapping = mapping; -+ rd = &ap->rx_mini_ring[idx]; -+ set_aceaddr(&rd->addr, mapping); -+ rd->size = ACE_MINI_SIZE; -+ rd->idx = idx; -+ idx = (idx + 1) % RX_MINI_RING_ENTRIES; -+ } -+ -+ atomic_add(i, &ap->cur_mini_bufs); -+ ap->rx_mini_skbprd = idx; -+ -+ writel(idx, ®s->RxMiniPrd); -+ wmb(); -+ -+ clear_bit(0, &ap->mini_refill_busy); -+ } -+ -+ cur_size = atomic_read(&ap->cur_jumbo_bufs); -+ if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) && -+ !test_and_set_bit(0, &ap->jumbo_refill_busy)) -+ ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size); -+ -+ ap->bh_pending = 0; -+ -+ #if SELECTIVE_INTR -+ /* if this worked, we don't need to handle events */ -+ #else -+ /* handle events... since we can't selectively mask out rx and tx -+ * interrupts... -+ */ -+ evtcsm = readl(®s->EvtCsm); -+ evtprd = *ap->evt_prd; -+ -+ if (evtcsm != evtprd) { -+ evtcsm = ace_handle_event(dev, evtcsm, evtprd); -+ writel(evtcsm, ®s->EvtCsm); -+ } -+ #endif -+ -+ *skbs = skb_list; -+ return (RX_RING_SIZE-atomic_read(&ap->cur_rx_bufs))+ -+ (RX_MINI_SIZE-atomic_read(&ap->cur_mini_bufs)); -+ } -+ -+ static struct sk_buff * -+ ace_rx_poll(struct device *dev, int *want) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx, rxretprd; -+ int mini_count = 0, std_count = 0; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ rxretprd = *ap->rx_ret_prd; -+ idx = ap->cur_rx; -+ -+ while (idx != rxretprd && got < *want) { -+ struct sk_buff *skb; -+ -+ skb = ace_rx_get_skb(dev, idx, &mini_count, &std_count); -+ if (skb == 0L) goto error; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ -+ idx = (idx + 1) % RX_RETURN_RING_ENTRIES; -+ } -+ -+ atomic_sub(std_count, &ap->cur_rx_bufs); -+ if (!ACE_IS_TIGON_I(ap)) -+ atomic_sub(mini_count, &ap->cur_mini_bufs); -+ -+ out: -+ ap->cur_rx = idx; -+ *want = got; -+ return skb_head; -+ -+ error: -+ idx = rxretprd; -+ goto out; -+ } -+ -+ static int -+ ace_poll_on(struct device *dev) -+ { -+ if (!dev->polling) { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ struct net_device *d = (struct net_device*)dev; -+ u32 stat; -+ -+ ap = d->priv; -+ regs = ap->regs; -+ -+ #if SELECTIVE_INTR -+ /* okay, for some reason, below code segment did not turn off rx and -+ * tx interrupts... so we need to mask interrupts completely and -+ * depend on rx_refill to manage events. -+ */ -+ stat = readl(®s->ModeStat); -+ stat |= (ACE_DONT_RUPT_SENDS | ACE_DONT_RUPT_RECVS); -+ writel(stat, ®s->ModeStat); -+ #else -+ stat = readl(®s->HostCtrl); -+ stat |= MASK_INTS; -+ writel(stat, ®s->HostCtrl); -+ #endif -+ dev->polling = 2; -+ } -+ return 0; -+ } -+ -+ static int -+ ace_poll_off(struct device *dev) -+ { -+ if (dev->polling) { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ struct net_device *d = (struct net_device*)dev; -+ u32 stat; -+ -+ ap = d->priv; -+ regs = ap->regs; -+ -+ #if SELECTIVE_INTR -+ stat = readl(®s->ModeStat); -+ stat &= ~(ACE_DONT_RUPT_SENDS | ACE_DONT_RUPT_RECVS); -+ writel(stat, ®s->ModeStat); -+ #else -+ stat = readl(®s->HostCtrl); -+ stat &= ~MASK_INTS; -+ writel(stat, ®s->HostCtrl); -+ #endif -+ dev->polling = 0; -+ -+ printk("ace polling interrupt summary: %ld %ld\n", -+ ace_poll_intr, ace_poll_evtintr); -+ ace_poll_intr = ace_poll_evtintr = 0; -+ } -+ return 0; -+ } -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/drivers/net/acenic.h ./drivers/net/acenic.h -*** ../linux-2.2.18-pure/drivers/net/acenic.h Sun Dec 10 16:49:42 2000 ---- ./drivers/net/acenic.h Sat May 4 23:29:49 2002 -*************** -*** 251,256 **** ---- 251,259 ---- - #define ACE_WARN 0x08 - #define ACE_BYTE_SWAP_DMA 0x10 - #define ACE_NO_JUMBO_FRAG 0x200 -+ #define ACE_DONT_RUPT_EVENTS 0x1000 -+ #define ACE_DONT_RUPT_SENDS 0x2000 -+ #define ACE_DONT_RUPT_RECVS 0x4000 - #define ACE_FATAL 0x40000000 - - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/drivers/net/eepro100.c ./drivers/net/eepro100.c -*** ../linux-2.2.18-pure/drivers/net/eepro100.c Sun Dec 10 16:49:42 2000 ---- ./drivers/net/eepro100.c Sat May 4 23:29:48 2002 -*************** -*** 49,62 **** - static const char *version = - "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" - "eepro100.c: $Revision: 1.20.2.10 $ 2000/05/31 Modified by Andrey V. Savochkin and others\n" -! "eepro100.c: VA Linux custom, Dragan Stancevic 2000/11/15\n"; - - /* A few user-configurable values that apply to all boards. - First set is undocumented and spelled per Intel recommendations. */ - -! static int congenb = 0; /* Enable congestion control in the DP83840. */ -! static int txfifo = 0; /* Tx FIFO threshold in 4 byte units, 0-15 */ -! static int rxfifo = 0xF; /* Rx FIFO threshold, default 32 bytes. */ - /* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ - static int txdmacount = 128; - static int rxdmacount = 0; ---- 49,69 ---- - static const char *version = - "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" - "eepro100.c: $Revision: 1.20.2.10 $ 2000/05/31 Modified by Andrey V. Savochkin and others\n" -! "eepro100.c: VA Linux custom, Dragan Stancevic 2000/11/15\n" -! "eepro100.c: MIT click polling extensions\n"; -! - - /* A few user-configurable values that apply to all boards. - First set is undocumented and spelled per Intel recommendations. */ - -! /* -! * benjie: i am setting txfifo to 8 and rxfifo to 8 as they are in the -! * 2.4.9 linux kernel -! */ -! static int congenb = 0; /* Enable congestion control in the DP83840. */ -! static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ -! static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ -! - /* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ - static int txdmacount = 128; - static int rxdmacount = 0; -*************** -*** 587,592 **** ---- 594,609 ---- - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+ /* device polling stuff */ -+ static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+ static int speedo_tx_eob(struct net_device *dev); -+ static int speedo_tx_start(struct net_device *dev); -+ static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+ static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+ static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+ static int speedo_poll_on(struct net_device *dev); -+ static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -*************** -*** 751,756 **** ---- 768,774 ---- - This takes less than 10usec and will easily finish before the next - action. */ - outl(PortReset, ioaddr + SCBPort); -+ inl(ioaddr + SCBPort); - /* Honor PortReset timing. */ - udelay(10); - -*************** -*** 778,784 **** - /* The self-test results must be paragraph aligned. */ - s32 str[6], *volatile self_test_results; - int boguscnt = 16000; /* Timeout for set-test. */ -! if (eeprom[3] & 0x03) - printk(KERN_INFO " Receiver lock-up bug exists -- enabling" - " work-around.\n"); - printk(KERN_INFO " Board assembly %4.4x%2.2x-%3.3d, Physical" ---- 796,802 ---- - /* The self-test results must be paragraph aligned. */ - s32 str[6], *volatile self_test_results; - int boguscnt = 16000; /* Timeout for set-test. */ -! if ((eeprom[3] & 0x03) != 0x03) - printk(KERN_INFO " Receiver lock-up bug exists -- enabling" - " work-around.\n"); - printk(KERN_INFO " Board assembly %4.4x%2.2x-%3.3d, Physical" -*************** -*** 839,844 **** ---- 857,863 ---- - #endif /* kernel_bloat */ - - outl(PortReset, ioaddr + SCBPort); -+ inl(ioaddr + SCBPort); - /* Honor PortReset timing. */ - udelay(10); - -*************** -*** 889,894 **** ---- 908,924 ---- - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return dev; - } - -*************** -*** 1062,1067 **** ---- 1092,1100 ---- - /* Set the segment registers to '0'. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(0, ioaddr + SCBPointer); -+ /* impose a delay to avoid a bug */ -+ inl(ioaddr + SCBPointer); -+ udelay(10); - outb(RxAddrLoad, ioaddr + SCBCmd); - wait_for_cmd_done(ioaddr + SCBCmd); - outb(CUCmdBase, ioaddr + SCBCmd); -*************** -*** 1106,1112 **** - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -! outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); - } - - /* Media monitoring and control. */ ---- 1139,1146 ---- - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -! outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -! (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* Media monitoring and control. */ -*************** -*** 1313,1319 **** - dev->name); - outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -! outw(CUStart, ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else ---- 1347,1354 ---- - dev->name); - outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -! outw(CUStart | (dev->polling ? SCBMaskAll : 0), -! ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -*************** -*** 1360,1365 **** ---- 1395,1408 ---- - long ioaddr = dev->base_addr; - int entry; - -+ #if 0 -+ if (dev->polling > 0) { -+ printk(KERN_ERR "%s: start_xmit while polling\n", -+ dev->name); -+ return 1; -+ } -+ #endif -+ - #if ! defined(HAS_NETIF_QUEUE) - if (test_bit(0, (void*)&dev->tbusy) != 0) { - int tickssofar = jiffies - dev->trans_start; -*************** -*** 1372,1378 **** - command atomic. --SAW */ - spin_lock_irqsave(&sp->lock, flags); - wait_for_cmd_done(ioaddr + SCBCmd); -! outw(SCBTriggerIntr, ioaddr + SCBCmd); - spin_unlock_irqrestore(&sp->lock, flags); - return 1; - } ---- 1415,1422 ---- - command atomic. --SAW */ - spin_lock_irqsave(&sp->lock, flags); - wait_for_cmd_done(ioaddr + SCBCmd); -! outw(SCBTriggerIntr | ((dev->polling>0) ? SCBMaskAll : 0), -! ioaddr + SCBCmd); - spin_unlock_irqrestore(&sp->lock, flags); - return 1; - } -*************** -*** 1383,1389 **** - - { /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; -- - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ ---- 1427,1432 ---- -*************** -*** 1431,1437 **** - } - - dev->trans_start = jiffies; -- - return 0; - } - ---- 1474,1479 ---- -*************** -*** 1440,1445 **** ---- 1482,1493 ---- - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -*************** -*** 1505,1510 **** ---- 1553,1561 ---- - } - #endif - -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -*************** -*** 1534,1543 **** - break; - - /* Always check if all rx buffers are allocated. --SAW */ -! speedo_refill_rx_buffers(dev, 0); - -! if ((status & 0x5000) || /* Packet received, or Rx error. */ -! (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - ---- 1585,1596 ---- - break; - - /* Always check if all rx buffers are allocated. --SAW */ -! if (!dev->polling) -! speedo_refill_rx_buffers(dev, 0); - -! if (!dev->polling && -! ((status & 0x5000) || /* Packet received, or Rx error. */ -! (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - -*************** -*** 1607,1613 **** - } - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -! if (status & 0xA400) { - spin_lock(&sp->lock); - speedo_tx_buffer_gc(dev); - if (sp->tx_full ---- 1660,1666 ---- - } - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -! if (!dev->polling && (status & 0xA400)) { - spin_lock(&sp->lock); - speedo_tx_buffer_gc(dev); - if (sp->tx_full -*************** -*** 1716,1721 **** ---- 1769,1780 ---- - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -*************** -*** 1730,1735 **** ---- 1789,1800 ---- - int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; - int alloc_ok = 1; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: in speedo_rx() while polling\n", -+ dev->name); -+ return 0; -+ } -+ - if (speedo_debug > 4) - printk(KERN_DEBUG " In speedo_rx().\n"); - /* If we own the next entry, it's a new packet. Send it up. */ -*************** -*** 2213,2215 **** ---- 2278,2649 ---- - * tab-width: 4 - * End: - */ -+ -+ /* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+ static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ sp->rx_ringp[entry] = (struct RxFD *) skb->tail; -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ -+ rxf = sp->rx_ringp[entry]; -+ rxf->rx_buf_addr = (uint32_t)0xffffffff; -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+ } -+ -+ static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ /* If the packet hasn't been received, bail out. */ -+ if ((status & RxComplete) == 0) -+ break; -+ -+ /* If we've already received too many packets, bail out. */ -+ if (got == *want || --rx_work_limit < 0) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+ } -+ -+ static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ long ioaddr = dev->base_addr; -+ int entry; -+ unsigned flags; -+ -+ #if ! defined(HAS_NETIF_QUEUE) -+ if (test_bit(0, (void*)&dev->tbusy) != 0) { -+ int tickssofar = jiffies - dev->trans_start; -+ if (tickssofar < TX_TIMEOUT - 2) -+ return 1; -+ if (tickssofar < TX_TIMEOUT) { -+ /* Reap sent packets from the full Tx queue. */ -+ unsigned long flags; -+ /* Take a spinlock to make wait_for_cmd_done and -+ * sending the command atomic. --SAW -+ */ -+ spin_lock_irqsave(&sp->lock, flags); -+ wait_for_cmd_done(ioaddr + SCBCmd); -+ outw(SCBTriggerIntr | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ speedo_tx_timeout(dev); -+ return 1; -+ } -+ #endif -+ -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ spin_unlock_irqrestore(&sp->lock, flags); -+ sp->tx_full = 1; -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].link = -+ virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); -+ sp->tx_ring[entry].tx_desc_addr = -+ virt_to_le32desc(&sp->tx_ring[entry].tx_buf_addr0); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32desc(skb->data); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ -+ /* Trigger the command unit resume. */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+ } -+ -+ static int speedo_tx_eob(struct net_device *dev) -+ { -+ /* Start the DMA going again */ -+ #if 1 -+ #if 0 // benjie -+ wait_for_cmd_done(ioaddr + SCBCmd); -+ #endif -+ outb(CUResume, dev->base_addr + SCBCmd); -+ #endif -+ return 0; -+ } -+ -+ static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ -+ static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (speedo_debug > 2) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (speedo_debug > 1) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+ } -+ -+ static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+ } -+ -+ static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+ } -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/drivers/net/tulip.c ./drivers/net/tulip.c -*** ../linux-2.2.18-pure/drivers/net/tulip.c Sun Dec 10 16:49:42 2000 ---- ./drivers/net/tulip.c Sat May 4 23:29:49 2002 -*************** -*** 26,34 **** - - /* A few user-configurable values. */ - -- /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -- static int max_interrupt_work = 25; -- - #define MAX_UNITS 8 - /* Used to pass the full-duplex flag, etc. */ - static int full_duplex[MAX_UNITS] = {0, }; ---- 26,31 ---- -*************** -*** 149,158 **** - - #define RUN_AT(x) (jiffies + (x)) - -- #if (LINUX_VERSION_CODE >= 0x20100) -- static char kernel_version[] = UTS_RELEASE; -- #endif -- - #if LINUX_VERSION_CODE < 0x20123 - #define hard_smp_processor_id() smp_processor_id() - #define test_and_set_bit(val, addr) set_bit(val, addr) ---- 146,151 ---- -*************** -*** 497,511 **** - }; - - struct tulip_private { -! char devname[8]; /* Used only for kernel debugging. */ -! const char *product_name; -! struct device *next_module; - struct tulip_rx_desc rx_ring[RX_RING_SIZE]; - struct tulip_tx_desc tx_ring[TX_RING_SIZE]; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; -! /* The addresses of receive-in-place skbuffs. */ -! struct sk_buff* rx_skbuff[RX_RING_SIZE]; - char *rx_buffs; /* Address of temporary Rx buffers. */ - u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ - int chip_id; ---- 490,510 ---- - }; - - struct tulip_private { -! unsigned int cur_rx, dirty_rx; -! unsigned int rx_reserved[6]; - struct tulip_rx_desc rx_ring[RX_RING_SIZE]; -+ /* The addresses of receive-in-place skbuffs. */ -+ struct sk_buff* rx_skbuff[RX_RING_SIZE]; -+ -+ unsigned int cur_tx, dirty_tx; -+ unsigned int tx_reserved[6]; - struct tulip_tx_desc tx_ring[TX_RING_SIZE]; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; -! -! char devname[8]; /* Used only for kernel debugging. */ -! const char *product_name; -! struct device *next_module; - char *rx_buffs; /* Address of temporary Rx buffers. */ - u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ - int chip_id; -*************** -*** 514,521 **** - struct net_device_stats stats; - struct timer_list timer; /* Media selection timer. */ - int interrupt; /* In-interrupt flag. */ -- unsigned int cur_rx, cur_tx; /* The next free ring entry */ -- unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - unsigned int tx_full:1; /* The Tx queue is full. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int full_duplex_lock:1; ---- 513,518 ---- -*************** -*** 568,573 **** ---- 565,580 ---- - #endif - static void set_rx_mode(struct device *dev); - -+ /* device polling stuff */ -+ static int tulip_tx_queue(struct device *dev, struct sk_buff *skb); -+ static int tulip_tx_eob(struct device *dev); -+ static int tulip_tx_start(struct device *dev); -+ static int tulip_rx_refill(struct device *dev, struct sk_buff **); -+ static struct sk_buff *tulip_tx_clean(struct device *dev); -+ static struct sk_buff *tulip_rx_poll(struct device *dev, int *want); -+ static int tulip_poll_on(struct device *dev); -+ static int tulip_poll_off(struct device *dev); -+ - - - /* A list of all installed Tulip devices. */ -*************** -*** 815,820 **** ---- 822,838 ---- - - dev->base_addr = ioaddr; - dev->irq = irq; -+ -+ /* Click - polling extensions */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_off = tulip_poll_off; -+ dev->poll_on = tulip_poll_on; - - tp->pci_bus = pci_bus; - tp->pci_devfn = pci_devfn; -*************** -*** 2540,2561 **** - tp->tx_ring[i-1].buffer2 = virt_to_le32desc(&tp->tx_ring[0]); - } - - static int - tulip_start_xmit(struct sk_buff *skb, struct device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - u32 flag; - -- /* Block a timer-based transmit from overlapping. This could better be -- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -! if (jiffies - dev->trans_start < TX_TIMEOUT) -! return 1; -! tulip_tx_timeout(dev); - return 1; - } -! - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - ---- 2558,2593 ---- - tp->tx_ring[i-1].buffer2 = virt_to_le32desc(&tp->tx_ring[0]); - } - -+ /* start the tulip transmit process by doing an outb */ -+ static int -+ tulip_tx_start(struct device *dev) -+ { -+ if (dev->polling <= 0) -+ /* Trigger an immediate transmit demand. */ -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ - static int - tulip_start_xmit(struct sk_buff *skb, struct device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - u32 flag; -+ -+ #if 0 -+ if (dev->polling > 0) { -+ printk("tulip_start_xmit when interrupt is off\n"); -+ } -+ #endif - - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -! if (jiffies - dev->trans_start >= TX_TIMEOUT) -! tulip_tx_timeout(dev); - return 1; - } -! - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - -*************** -*** 2579,2594 **** - flag = 0xe0000000 | DESC_RING_WRAP; - - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - tp->cur_tx++; -! if ( ! tp->tx_full) -! clear_bit(0, (void*)&dev->tbusy); - -! dev->trans_start = jiffies; -! /* Trigger an immediate transmit demand. */ -! outl(0, dev->base_addr + CSR1); - -! return 0; - } - - /* The interrupt handler does all of the Rx thread work and cleans up ---- 2611,2642 ---- - flag = 0xe0000000 | DESC_RING_WRAP; - - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* new linux memory barrier thingie */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - tp->cur_tx++; -! -! tulip_tx_start(dev); -! -! if (!tp->tx_full) -! clear_bit(0, (void*)&dev->tbusy); -! -! return 0; -! } - -! /* polling extension - intr stats */ -! void (*tulip_interrupt_hook)(struct device *, unsigned); - -! static __inline__ unsigned long long -! tulip_get_cycles(void) -! { -! unsigned long low, high; -! unsigned long long x; -! __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -! x = high; -! x <<= 32; -! x |= low; -! return(x); - } - - /* The interrupt handler does all of the Rx thread work and cleans up -*************** -*** 2600,2612 **** - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; - int maxrx = RX_RING_SIZE; - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - - #if defined(__i386__) && defined(SMP_CHECK) - if (test_and_set_bit(0, (void*)&dev->interrupt)) { ---- 2648,2660 ---- - long ioaddr = dev->base_addr; - int csr5; - int entry; - int rx = 0; - int tx = 0; - int oi = 0; - int maxrx = RX_RING_SIZE; - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; -+ int first_time = 1; - - #if defined(__i386__) && defined(SMP_CHECK) - if (test_and_set_bit(0, (void*)&dev->interrupt)) { -*************** -*** 2628,2649 **** - - do { - csr5 = inl(ioaddr + CSR5); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -! if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) -! break; -! -! if (csr5 & (RxIntr | RxNoBuf)) { -! rx += tulip_rx(dev); -! tulip_refill_rx(dev); - } - -! if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { - unsigned int dirty_tx; - - for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; ---- 2676,2714 ---- - - do { - csr5 = inl(ioaddr + CSR5); -+ -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) goto out; -+ if (first_time) goto out; -+ else break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook. */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr))==0) goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -! if ((csr5 & (RxIntr | RxNoBuf)) && !dev->polling) { -! rx += tulip_rx(dev); -! tulip_refill_rx(dev); - } - -! if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) -! && !dev->polling) { -! /* part of following code duplicated at the end -! * in tulip_tx_clean for the polling driver, changes -! * here should propagate to there as well */ - unsigned int dirty_tx; - - for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; -*************** -*** 2708,2721 **** - } - - tp->dirty_tx = dirty_tx; -! if (csr5 & TxDied) { -! if (tulip_debug > 2) -! printk(KERN_WARNING "%s: The transmitter stopped." -! " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -! dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -! outl(tp->csr6 | 0x0002, ioaddr + CSR6); -! outl(tp->csr6 | 0x2002, ioaddr + CSR6); -! } - } - - /* Log errors. */ ---- 2773,2787 ---- - } - - tp->dirty_tx = dirty_tx; -! } -! -! if (csr5 & TxDied) { -! if (tulip_debug > 2) -! printk(KERN_WARNING "%s: The transmitter stopped." -! " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -! dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -! outl(tp->csr6 | 0x0002, ioaddr + CSR6); -! outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - - /* Log errors. */ -*************** -*** 2734,2741 **** - outl(0, ioaddr + CSR1); - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ - tp->stats.rx_errors++; -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { ---- 2800,2810 ---- - outl(0, ioaddr + CSR1); - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -+ unsigned csr8status = inl(ioaddr+CSR8); -+ unsigned fifostatus = csr8status>>17; - tp->stats.rx_errors++; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; - outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { -*************** -*** 2775,2781 **** - } - } while (1); - -! tulip_refill_rx(dev); - - /* check if we card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; ---- 2844,2852 ---- - } - } while (1); - -! if (!dev->polling) { -! tulip_refill_rx(dev); -! } - - /* check if we card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -*************** -*** 2793,2806 **** ---- 2864,2880 ---- - } - } - -+ #if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+ #endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+ out: - #if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); - #else -*************** -*** 2946,2953 **** - if (tp->chip_id == DC21040) - outl(0x00000004, ioaddr + CSR13); - -! if (inl(ioaddr + CSR6) != 0xffffffff) -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - - del_timer(&tp->timer); - ---- 3020,3031 ---- - if (tp->chip_id == DC21040) - outl(0x00000004, ioaddr + CSR13); - -! if (inl(ioaddr + CSR6) != 0xffffffff) { -! unsigned csr8status = inl(ioaddr+CSR8); -! unsigned fifostatus = csr8status>>17; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; -! } - - del_timer(&tp->timer); - -*************** -*** 2990,2998 **** - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - -! if (dev->start) -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -! - return &tp->stats; - } - ---- 3068,3081 ---- - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - -! if (dev->start) { -! unsigned csr8status = inl(ioaddr+CSR8); -! unsigned fifostatus = csr8status>>17; -! unsigned missed = csr8status & 0x1ffff; -! tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; -! } - return &tp->stats; - } - -*************** -*** 3189,3195 **** - /* Same setup recently queued, we need not add it. */ - } else { - unsigned long flags; -! unsigned int entry; - - save_flags(flags); cli(); - entry = tp->cur_tx++ % TX_RING_SIZE; ---- 3272,3278 ---- - /* Same setup recently queued, we need not add it. */ - } else { - unsigned long flags; -! unsigned int entry, dummy = 0; - - save_flags(flags); cli(); - entry = tp->cur_tx++ % TX_RING_SIZE; -*************** -*** 3200,3206 **** ---- 3283,3294 ---- - tp->tx_ring[entry].length = - (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0; - tp->tx_ring[entry].buffer1 = 0; -+ #if 1 -+ /* race with chip, set DescOwned later */ -+ dummy = entry; -+ #else - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ #endif - entry = tp->cur_tx++ % TX_RING_SIZE; - } - -*************** -*** 3215,3220 **** ---- 3303,3312 ---- - set_bit(0, (void*)&dev->tbusy); - tp->tx_full = 1; - } -+ #if 1 -+ if (dummy >= 0) -+ tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); -+ #endif - restore_flags(flags); - /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); -*************** -*** 3359,3361 **** ---- 3451,3735 ---- - * tab-width: 4 - * End: - */ -+ -+ -+ /* -+ * Polling Extension -+ * -+ * Most of the following functions are verbatim, or very similar to, code from -+ * the interrupt routines. They are cleaned up and tuned for polling. -+ * -+ * Very minimal synchronization occurs: most polling functions are suppose to -+ * be used in polling mode, under which case the interrupt handler is -+ * disallowed from touching the rx and tx ring. Callers of polling functions -+ * are expected to synchronize calls to these functions themselves. -+ * -+ * dev->tbusy was used by Linux's original tulip driver to synchronize the -+ * send pkt routine (tulip_start_xmit) and timer based send. I am using it -+ * also to synchronize tx queueing. -+ */ -+ -+ /* demand polling */ -+ /* #define DEMAND_POLLTX 1 */ -+ -+ int -+ tulip_rx_refill(struct device *dev, struct sk_buff **skbs) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == 0) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ /* Refill the Rx ring buffers. */ -+ for (; (tp->cur_rx-tp->dirty_rx) > 0 && skb_list != 0L; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_skbuff[entry] == NULL) { -+ struct sk_buff *skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ tp->rx_skbuff[entry] = skb; -+ skb->dev = dev; /* mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = virt_to_le32desc(skb->tail); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if (skb_list == 0) -+ *skbs = 0; -+ else -+ *skbs = skb_list; -+ return tp->cur_rx - tp->dirty_rx; -+ } -+ -+ static struct sk_buff * -+ tulip_rx_poll(struct device *dev, int *want) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while (! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned " "multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_skbuff[entry]; -+ int p; -+ tp->rx_skbuff[entry] = NULL; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; -+ } -+ -+ -+ static int -+ tulip_poll_on(struct device *dev) -+ { -+ long ioaddr = dev->base_addr; -+ int csr7; -+ #ifdef DEMAND_POLLTX -+ int csr0; -+ #endif -+ if (!dev->polling) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr+CSR7); -+ #ifdef DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr+CSR0); -+ #endif -+ dev->polling = 2; -+ } -+ return 0; -+ } -+ -+ static int -+ tulip_poll_off(struct device *dev) -+ { -+ long ioaddr = dev->base_addr; -+ int csr7; -+ #ifdef DEMAND_POLLTX -+ int csr0; -+ #endif -+ if (dev->polling > 0) { -+ #ifdef DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr+CSR0); -+ #endif -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr+CSR7); -+ dev->polling = 0; -+ } -+ return 0; -+ } -+ -+ static int -+ tulip_tx_queue(struct device *dev, struct sk_buff *skb) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ -+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -+ /* printk("tulip_tx_queue: reject because tbusy\n"); */ -+ return 1; -+ } -+ -+ /* Caution: the write order is important here, set the base address -+ * with the "ownership" bits last. */ -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_skbuff[entry] = skb; -+ tp->tx_ring[entry].buffer1 = virt_to_le32desc(skb->data); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) -+ tp->tx_full = 0; -+ else -+ /* Leave room for set_rx_mode() to fill entries. */ -+ tp->tx_full = 1; -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* new linux memory barrier thingie */ -+ wmb(); -+ /* Pass ownership to the chip. */ -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ tp->cur_tx++; -+ -+ #if 0 /* use eob interface instead */ -+ #ifndef DEMAND_POLLTX -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ #endif -+ #endif -+ if (!tp->tx_full) -+ clear_bit(0, (void*)&dev->tbusy); -+ -+ return 0; -+ } -+ -+ /* clean up tx dma ring */ -+ static struct sk_buff* -+ tulip_tx_clean(struct device *dev) -+ { -+ struct sk_buff *skb_head, *skb_last; -+ struct tulip_private *tp; -+ unsigned int dirty_tx; -+ tp = (struct tulip_private *)dev->priv; -+ skb_head = skb_last = 0; -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) break; /* It still hasn't been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_skbuff[entry] == NULL) continue; -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ skb = tp->tx_skbuff[entry]; -+ tp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+ if (tp->tx_full && dev->tbusy && tp->cur_tx-dirty_tx < TX_RING_SIZE-2) { -+ /* The ring is no longer full, clear tbusy. */ -+ tp->tx_full = 0; -+ clear_bit(0, (void*)&dev->tbusy); -+ } -+ -+ tp->dirty_tx = dirty_tx; -+ // ret = tp->cur_tx - tp->dirty_tx; -+ return skb_head; -+ } -+ -+ static int tulip_tx_eob(struct device *dev) -+ { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/fs/proc/inode.c ./fs/proc/inode.c -*** ../linux-2.2.18-pure/fs/proc/inode.c Mon Sep 4 10:39:27 2000 ---- ./fs/proc/inode.c Sat May 4 23:29:48 2002 -*************** -*** 265,270 **** ---- 265,275 ---- - if (inode->i_sb != sb) - printk("proc_get_inode: inode fubar\n"); - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/fs/super.c ./fs/super.c -*** ../linux-2.2.18-pure/fs/super.c Sun Dec 10 16:49:44 2000 ---- ./fs/super.c Sat May 4 23:30:27 2002 -*************** -*** 565,570 **** ---- 565,571 ---- - s->s_dev = dev; - s->s_flags = flags; - s->s_dirt = 0; -+ s->s_type = type; - sema_init(&s->s_vfs_rename_sem,1); - sema_init(&s->s_nfsd_free_path_sem,1); - /* N.B. Should lock superblock now ... */ -*************** -*** 572,578 **** - goto out_fail; - s->s_dev = dev; /* N.B. why do this again?? */ - s->s_rd_only = 0; -- s->s_type = type; - out: - return s; - ---- 573,578 ---- -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/include/linux/netdevice.h ./include/linux/netdevice.h -*** ../linux-2.2.18-pure/include/linux/netdevice.h Sun Dec 10 16:49:44 2000 ---- ./include/linux/netdevice.h Sat May 4 23:29:47 2002 -*************** -*** 324,329 **** ---- 324,370 ---- - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct device *); -+ int (*poll_off)(struct device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct device*, int *want); -+ /* -+ * refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct device *); - }; - - -*************** -*** 361,366 **** ---- 402,410 ---- - extern int unregister_netdevice(struct device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+ extern int register_net_in(struct notifier_block *nb); /* Click */ -+ extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+ extern void ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct device *dev_get_by_index(int ifindex); - extern int dev_restart(struct device *dev); -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/include/linux/signal.h ./include/linux/signal.h -*** ../linux-2.2.18-pure/include/linux/signal.h Tue May 11 10:35:43 1999 ---- ./include/linux/signal.h Sat May 4 23:29:47 2002 -*************** -*** 189,195 **** - memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = 0; -! case 1: - } - } - ---- 189,195 ---- - memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = 0; -! case 1: ; - } - } - -*************** -*** 201,207 **** - memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = -1; -! case 1: - } - } - ---- 201,207 ---- - memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = -1; -! case 1: ; - } - } - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/include/linux/skbuff.h ./include/linux/skbuff.h -*** ../linux-2.2.18-pure/include/linux/skbuff.h Thu May 13 10:33:17 1999 ---- ./include/linux/skbuff.h Sat May 4 23:29:47 2002 -*************** -*** 36,49 **** - for using debugging */ - }; - - struct sk_buff { - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - struct sk_buff_head * list; /* List we are on */ -! struct sock *sk; /* Socket we are owned by */ -! struct timeval stamp; /* Time we arrived */ - struct device *dev; /* Device we arrived on/are leaving by */ -! - /* Transport layer header */ - union - { ---- 36,65 ---- - for using debugging */ - }; - -+ /* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+ #define PACKET_CLEAN 128 /* Is packet clean? */ -+ #define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+ /* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - struct sk_buff_head * list; /* List we are on */ -! unsigned int len; /* Length of actual data */ -! unsigned char *data; /* Data head pointer */ -! unsigned char *tail; /* Tail pointer */ - struct device *dev; /* Device we arrived on/are leaving by */ -! unsigned char is_clone, /* We are a clone */ -! cloned, /* head may be cloned (check refcnt to be sure). */ -! pkt_type, /* Packet class */ -! ip_summed; /* Driver fed us an IP checksum */ -! atomic_t users; /* User count - see datagram.c,tcp.c */ -! unsigned int truesize; /* Buffer size */ -! unsigned char *head; /* Head of buffer */ -! unsigned char *end; /* End pointer */ - /* Transport layer header */ - union - { -*************** -*** 72,101 **** - struct ethhdr *ethernet; - unsigned char *raw; - } mac; - - struct dst_entry *dst; - -! char cb[48]; -! -! unsigned int len; /* Length of actual data */ -! unsigned int csum; /* Checksum */ - volatile char used; /* Data moved to user and not MSG_PEEK */ -! unsigned char is_clone, /* We are a clone */ -! cloned, /* head may be cloned (check refcnt to be sure). */ -! pkt_type, /* Packet class */ -! pkt_bridged, /* Tracker for bridging */ -! ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ -- -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -- void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_IP_FIREWALL - __u32 fwmark; /* Label made by fwchains, used by pktsched */ - #endif ---- 88,107 ---- - struct ethhdr *ethernet; - unsigned char *raw; - } mac; -+ -+ char cb[48]; - - struct dst_entry *dst; - -! void (*destructor)(struct sk_buff *); /* Destruct function */ -! struct sock *sk; /* Socket we are owned by */ -! struct timeval stamp; /* Time we arrived */ - volatile char used; /* Data moved to user and not MSG_PEEK */ -! unsigned char pkt_bridged; /* Tracker for bridging */ -! unsigned int csum; /* Checksum */ - __u32 priority; /* Packet queueing priority */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ - #ifdef CONFIG_IP_FIREWALL - __u32 fwmark; /* Label made by fwchains, used by pktsched */ - #endif -*************** -*** 145,150 **** ---- 151,158 ---- - extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list); - extern struct sk_buff * alloc_skb(unsigned int size, int priority); - extern struct sk_buff * dev_alloc_skb(unsigned int size); -+ extern void skb_recycled_init(struct sk_buff *buf); -+ extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority); -*************** -*** 491,497 **** - return skb->data; - } - -! extern __inline__ char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - return skb->data+=len; ---- 499,505 ---- - return skb->data; - } - -! extern __inline__ unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - return skb->data+=len; -*************** -*** 551,560 **** - extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length) - { - struct sk_buff *skb; - -! skb = alloc_skb(length+16, GFP_ATOMIC); - if (skb) -! skb_reserve(skb,16); - return skb; - } - ---- 559,573 ---- - extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length) - { - struct sk_buff *skb; -+ #if 0 -+ #define SKB_RESERVE_LENGTH 32 -+ #else -+ #define SKB_RESERVE_LENGTH 16 -+ #endif - -! skb = alloc_skb(length+SKB_RESERVE_LENGTH, GFP_ATOMIC); - if (skb) -! skb_reserve(skb,SKB_RESERVE_LENGTH); - return skb; - } - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/include/net/neighbour.h ./include/net/neighbour.h -*** ../linux-2.2.18-pure/include/net/neighbour.h Tue May 11 10:36:38 1999 ---- ./include/net/neighbour.h Sat May 4 23:29:47 2002 -*************** -*** 50,55 **** ---- 50,56 ---- - #define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) - #define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE) - -+ struct neighbour; - struct neigh_parms - { - struct neigh_parms *next; -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/kernel/ksyms.c ./kernel/ksyms.c -*** ../linux-2.2.18-pure/kernel/ksyms.c Sun Dec 10 16:49:44 2000 ---- ./kernel/ksyms.c Sat May 4 23:31:20 2002 -*************** -*** 342,347 **** ---- 342,348 ---- - - /* process management */ - EXPORT_SYMBOL(__wake_up); -+ EXPORT_SYMBOL(wake_up_process); - EXPORT_SYMBOL(sleep_on); - EXPORT_SYMBOL(sleep_on_timeout); - EXPORT_SYMBOL(interruptible_sleep_on); -*************** -*** 415,420 **** ---- 416,425 ---- - EXPORT_SYMBOL(__down_trylock); - EXPORT_SYMBOL(__up); - EXPORT_SYMBOL(brw_page); -+ EXPORT_SYMBOL(inuse_filps); -+ EXPORT_SYMBOL(super_blocks); -+ extern spinlock_t inode_lock; -+ EXPORT_SYMBOL(inode_lock); - - /* all busmice */ - EXPORT_SYMBOL(add_mouse_randomness); -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/net/core/dev.c ./net/core/dev.c -*** ../linux-2.2.18-pure/net/core/dev.c Sun Dec 10 16:49:44 2000 ---- ./net/core/dev.c Sat May 4 23:29:48 2002 -*************** -*** 154,159 **** ---- 154,162 ---- - - static struct notifier_block *netdev_chain=NULL; - -+ /* input packet handlers -- might steal packets from net_bh(). for Click. */ -+ static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the bottom half handler. -*************** -*** 335,340 **** ---- 338,345 ---- - kfree(dev); - return NULL; - } -+ /* by default, no polling support */ -+ dev->poll_on = dev->poll_off = 0; - return dev; - } - -*************** -*** 516,521 **** ---- 521,542 ---- - } - - /* -+ * Allow Click modules to ask to intercept input packets. -+ * Must add these to ../netsyms.c -+ */ -+ int -+ register_net_in(struct notifier_block *nb) -+ { -+ return(notifier_chain_register(&net_in_chain, nb)); -+ } -+ -+ int -+ unregister_net_in(struct notifier_block *nb) -+ { -+ return(notifier_chain_unregister(&net_in_chain, nb)); -+ } -+ -+ /* - * Support routine. Sends outgoing frames to any network - * taps currently in use. - */ -*************** -*** 852,857 **** ---- 873,958 ---- - } - #endif /* CONFIG_NET_DIVERT */ - -+ -+ /* -+ * Hand a packet to the ordinary Linux protocol stack. -+ * Broke this out from net_bh() so that Click can call it. -+ * Always frees the skb one way or another. -+ * -+ * skb->pkt_type needs to be set to PACKET_{BROADCAST,MULTICAST,OTHERHOST} -+ * maybe skb->mac.raw must point to ether header. -+ * skb->protocol must be set to a htons(ETHERTYPE_?). -+ * skb->data must point to the ethernet payload (e.g. the IP header). -+ * skb->nh.raw must point to the ethernet payload also. -+ */ -+ void -+ ptype_dispatch(struct sk_buff *skb, unsigned short type) -+ { -+ struct packet_type *ptype; -+ struct packet_type *pt_prev; -+ -+ /* -+ * We got a packet ID. Now loop over the "known protocols" -+ * list. There are two lists. The ptype_all list of taps (normally empty) -+ * and the main protocol list which is hashed perfectly for normal protocols. -+ */ -+ -+ pt_prev = NULL; -+ for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) -+ { -+ if (!ptype->dev || ptype->dev == skb->dev) { -+ if(pt_prev) -+ { -+ struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); -+ if(skb2) -+ pt_prev->func(skb2,skb->dev, pt_prev); -+ } -+ pt_prev=ptype; -+ } -+ } -+ -+ for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) -+ { -+ if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev)) -+ { -+ /* -+ * We already have a match queued. Deliver -+ * to it and then remember the new match -+ */ -+ if(pt_prev) -+ { -+ struct sk_buff *skb2; -+ -+ skb2=skb_clone(skb, GFP_ATOMIC); -+ -+ /* -+ * Kick the protocol handler. This should be fast -+ * and efficient code. -+ */ -+ -+ if(skb2) -+ pt_prev->func(skb2, skb->dev, pt_prev); -+ } -+ /* Remember the current last to do */ -+ pt_prev=ptype; -+ } -+ } /* End of protocol list loop */ -+ -+ /* -+ * Is there a last item to send to ? -+ */ -+ -+ if(pt_prev) -+ pt_prev->func(skb, skb->dev, pt_prev); -+ /* -+ * Has an unknown packet has been received ? -+ */ -+ -+ else { -+ kfree_skb(skb); -+ } -+ } -+ - /* - * When we are called the queue is ready to grab, the interrupts are - * on and hardware can interrupt and queue to the receive queue as we -*************** -*** 862,869 **** - - void net_bh(void) - { -- struct packet_type *ptype; -- struct packet_type *pt_prev; - unsigned short type; - unsigned long start_time = jiffies; - #ifdef CONFIG_CPU_IS_SLOW ---- 963,968 ---- -*************** -*** 979,1044 **** - handle_bridge(skb, type); - #endif - -! /* -! * We got a packet ID. Now loop over the "known protocols" -! * list. There are two lists. The ptype_all list of taps (normally empty) -! * and the main protocol list which is hashed perfectly for normal protocols. -! */ -! -! pt_prev = NULL; -! for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) -! { -! if (!ptype->dev || ptype->dev == skb->dev) { -! if(pt_prev) -! { -! struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); -! if(skb2) -! pt_prev->func(skb2,skb->dev, pt_prev); -! } -! pt_prev=ptype; -! } -! } -! -! for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) -! { -! if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev)) -! { -! /* -! * We already have a match queued. Deliver -! * to it and then remember the new match -! */ -! if(pt_prev) -! { -! struct sk_buff *skb2; - -- skb2=skb_clone(skb, GFP_ATOMIC); - -! /* -! * Kick the protocol handler. This should be fast -! * and efficient code. -! */ - -- if(skb2) -- pt_prev->func(skb2, skb->dev, pt_prev); -- } -- /* Remember the current last to do */ -- pt_prev=ptype; -- } -- } /* End of protocol list loop */ - -- /* -- * Is there a last item to send to ? -- */ - -- if(pt_prev) -- pt_prev->func(skb, skb->dev, pt_prev); -- /* -- * Has an unknown packet has been received ? -- */ -- -- else { -- kfree_skb(skb); -- } - } /* End of queue loop */ - - /* ---- 1078,1096 ---- - handle_bridge(skb, type); - #endif - -! /* does Click want to steal this packet? */ -! if(notifier_call_chain(&net_in_chain, skb_queue_len(&backlog), skb) & NOTIFY_STOP_MASK) -! continue; - - -! /* -! * Ordinary Linux dispatch based on packet type. -! * Moved into a function so Click can call it. -! */ -! ptype_dispatch(skb, type); - - - - } /* End of queue loop */ - - /* -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/net/core/skbuff.c ./net/core/skbuff.c -*** ../linux-2.2.18-pure/net/core/skbuff.c Sun Mar 7 10:12:18 1999 ---- ./net/core/skbuff.c Sat May 4 23:29:48 2002 -*************** -*** 257,262 **** ---- 257,300 ---- - return n; - } - -+ -+ /* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+ struct sk_buff *skb_recycle(struct sk_buff *skb) -+ { -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ dst_release(skb->dst); -+ if (skb->destructor) -+ skb->destructor(skb); -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || atomic_dec_and_test(skb_datarefp(skb))) { -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->is_clone = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(skb_datarefp(skb), 1); -+ -+ return skb; -+ } -+ -+ kmem_cache_free(skbuff_head_cache, skb); -+ atomic_dec(&net_skbcount); -+ } -+ -+ return 0; -+ } -+ -+ - /* - * This is slower, and copies the whole data area - */ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.18-pure/net/netsyms.c ./net/netsyms.c -*** ../linux-2.2.18-pure/net/netsyms.c Sun Dec 10 16:49:44 2000 ---- ./net/netsyms.c Sat May 4 23:29:48 2002 -*************** -*** 464,469 **** ---- 464,476 ---- - EXPORT_SYMBOL(unregister_inetaddr_notifier); - #endif - -+ /* Click */ -+ EXPORT_SYMBOL(register_net_in); -+ EXPORT_SYMBOL(unregister_net_in); -+ EXPORT_SYMBOL(ptype_dispatch); -+ struct inet_protocol *inet_get_protocol(unsigned char prot); -+ EXPORT_SYMBOL(inet_get_protocol); -+ - /* support for loadable net drivers */ - #ifdef CONFIG_NET - EXPORT_SYMBOL(loopback_dev); -*************** -*** 487,492 **** ---- 494,500 ---- - EXPORT_SYMBOL(eth_copy_and_sum); - EXPORT_SYMBOL(alloc_skb); - EXPORT_SYMBOL(__kfree_skb); -+ EXPORT_SYMBOL(skb_recycle); - EXPORT_SYMBOL(skb_clone); - EXPORT_SYMBOL(skb_copy); - EXPORT_SYMBOL(netif_rx); diff --git a/etc/linux-2.2.19-patch b/etc/linux-2.2.19-patch deleted file mode 100644 index b592599ab3..0000000000 --- a/etc/linux-2.2.19-patch +++ /dev/null @@ -1,2849 +0,0 @@ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/drivers/net/acenic.c ./drivers/net/acenic.c -*** ../linux-2.2.19-pure/drivers/net/acenic.c Sun Mar 25 08:31:20 2001 ---- ./drivers/net/acenic.c Sat May 4 23:13:01 2002 -*************** -*** 409,414 **** ---- 409,477 ---- - - static int probed __initdata = 0; - -+ /* Click - polling extension */ -+ static int ace_tx_queue(struct device *dev, struct sk_buff *skb); -+ static int ace_tx_start(struct device *dev); -+ static int ace_tx_eob(struct device *dev); -+ static int ace_rx_refill(struct device *dev, struct sk_buff **); -+ static struct sk_buff *ace_tx_clean(struct device *dev); -+ static struct sk_buff *ace_rx_poll(struct device *dev, int *want); -+ static int ace_poll_on(struct device *dev); -+ static int ace_poll_off(struct device *dev); -+ -+ /* -+ * only recycle normal size pkts... no jumbo frames. -+ * set to 0 if don't want to do recycle. -+ */ -+ #define SKB_RECYCLED 256 -+ -+ unsigned acenic_recycled_skb_size = 0; -+ static int acenic_recycled_skb_cnt = 0; -+ static unsigned long acenic_recycle_skb_lock = 0; -+ static struct sk_buff *acenic_recycled_skbs[SKB_RECYCLED]; -+ -+ /* WARNING: these functions are not reentrant! */ -+ static inline struct sk_buff* -+ acenic_get_recycled_skb(void) -+ { -+ struct sk_buff* skb = 0; -+ if (acenic_recycled_skb_cnt > 0) { -+ while (test_and_set_bit(0, (void*)&acenic_recycle_skb_lock)) { -+ while(acenic_recycle_skb_lock) -+ asm volatile("" ::: "memory"); -+ } -+ if (acenic_recycled_skb_cnt > 0) { -+ acenic_recycled_skb_cnt--; -+ skb = acenic_recycled_skbs[acenic_recycled_skb_cnt]; -+ } -+ clear_bit(0, (void*)&acenic_recycle_skb_lock); -+ } -+ return skb; -+ } -+ -+ /* tries to recycle an skb. if not successful, the skb passed in is freed */ -+ static inline void -+ acenic_recycle_or_free_skb(struct sk_buff *skb) -+ { -+ if (skb->truesize == acenic_recycled_skb_size) { -+ if (acenic_recycled_skb_cnt < SKB_RECYCLED) { -+ while (test_and_set_bit(0, (void*)&acenic_recycle_skb_lock)) { -+ while(acenic_recycle_skb_lock) -+ asm volatile("" ::: "memory"); -+ } -+ if (acenic_recycled_skb_cnt < SKB_RECYCLED) { -+ if (skb_recycle(skb)) { -+ acenic_recycled_skbs[acenic_recycled_skb_cnt] = skb; -+ acenic_recycled_skb_cnt++; -+ } -+ skb = 0; -+ } -+ clear_bit(0, (void*)&acenic_recycle_skb_lock); -+ } -+ } -+ if (skb != 0) dev_kfree_skb(skb); -+ } -+ - - #ifdef NEW_NETINIT - int __init acenic_probe (void) -*************** -*** 482,487 **** ---- 545,561 ---- - dev->set_mac_address = &ace_set_mac_addr; - dev->change_mtu = &ace_change_mtu; - -+ /* Click - polling extensions */ -+ dev->polling = 0; -+ dev->rx_poll = ace_rx_poll; -+ dev->rx_refill = ace_rx_refill; -+ dev->tx_clean = ace_tx_clean; -+ dev->tx_queue = ace_tx_queue; -+ dev->tx_start = ace_tx_start; -+ dev->tx_eob = ace_tx_eob; -+ dev->poll_off = ace_poll_off; -+ dev->poll_on = ace_poll_on; -+ - /* display version info if adapter is found */ - if (!version_disp) - { -*************** -*** 1579,1584 **** ---- 1653,1659 ---- - { - struct ace_regs *regs; - short i, idx; -+ extern unsigned acenic_recycled_skb_size; - - regs = ap->regs; - -*************** -*** 1589,1597 **** - struct rx_desc *rd; - dma_addr_t mapping; - -! skb = alloc_skb(ACE_STD_BUFSIZE, GFP_ATOMIC); - if (!skb) - break; - - /* - * Make sure IP header starts on a fresh cache line. ---- 1664,1677 ---- - struct rx_desc *rd; - dma_addr_t mapping; - -! if (acenic_recycled_skb_size == 0 || -! (skb = acenic_get_recycled_skb()) == 0L) -! skb = alloc_skb(ACE_STD_BUFSIZE, GFP_ATOMIC); - if (!skb) - break; -+ /* Click: save the size of the skb we need for the std rx ring. */ -+ if (acenic_recycled_skb_size == 0) -+ acenic_recycled_skb_size = skb->truesize; - - /* - * Make sure IP header starts on a fresh cache line. -*************** -*** 1862,1877 **** - return evtcsm; - } - -! -! static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) - { -! struct ace_private *ap = dev->priv; -! u32 idx; -! int mini_count = 0, std_count = 0; -! -! idx = rxretcsm; -! -! while (idx != rxretprd) { - struct ring_info *rip; - struct sk_buff *skb; - struct rx_desc *rxdesc, *retdesc; ---- 1942,1951 ---- - return evtcsm; - } - -! static struct sk_buff* -! ace_rx_get_skb(struct net_device *dev, u32 idx, int *mini_count, int *std_count) - { -! struct ace_private *ap = dev->priv; - struct ring_info *rip; - struct sk_buff *skb; - struct rx_desc *rxdesc, *retdesc; -*************** -*** 1895,1901 **** - rip = &ap->skb->rx_std_skbuff[skbidx]; - mapsize = ACE_STD_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_std_ring[skbidx]; -! std_count++; - break; - case BD_FLG_JUMBO: - rip = &ap->skb->rx_jumbo_skbuff[skbidx]; ---- 1969,1975 ---- - rip = &ap->skb->rx_std_skbuff[skbidx]; - mapsize = ACE_STD_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_std_ring[skbidx]; -! (*std_count)++; - break; - case BD_FLG_JUMBO: - rip = &ap->skb->rx_jumbo_skbuff[skbidx]; -*************** -*** 1907,1919 **** - rip = &ap->skb->rx_mini_skbuff[skbidx]; - mapsize = ACE_MINI_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_mini_ring[skbidx]; -! mini_count++; - break; - default: - printk(KERN_INFO "%s: unknown frame type (0x%02x) " - "returned by NIC\n", dev->name, - retdesc->flags); -! goto error; - } - - skb = rip->skb; ---- 1981,1993 ---- - rip = &ap->skb->rx_mini_skbuff[skbidx]; - mapsize = ACE_MINI_BUFSIZE - (2 + 16); - rxdesc = &ap->rx_mini_ring[skbidx]; -! (*mini_count)++; - break; - default: - printk(KERN_INFO "%s: unknown frame type (0x%02x) " - "returned by NIC\n", dev->name, - retdesc->flags); -! return 0L; - } - - skb = rip->skb; -*************** -*** 1945,1955 **** - else - skb->ip_summed = CHECKSUM_NONE; - -- netif_rx(skb); /* send it up */ -- - ap->stats.rx_packets++; - ap->stats.rx_bytes += retdesc->size; - - idx = (idx + 1) % RX_RETURN_RING_ENTRIES; - } - ---- 2019,2047 ---- - else - skb->ip_summed = CHECKSUM_NONE; - - ap->stats.rx_packets++; - ap->stats.rx_bytes += retdesc->size; - -+ return skb; -+ } -+ -+ -+ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx; -+ int mini_count = 0, std_count = 0; -+ -+ idx = rxretcsm; -+ -+ while (idx != rxretprd) { -+ struct sk_buff *skb; -+ -+ skb = ace_rx_get_skb(dev, idx, &mini_count, &std_count); -+ if (skb == 0L) goto error; -+ -+ netif_rx(skb); /* send it up */ -+ - idx = (idx + 1) % RX_RETURN_RING_ENTRIES; - } - -*************** -*** 1974,1979 **** ---- 2066,2123 ---- - goto out; - } - -+ static void ace_service_tx(struct net_device *dev, int polling_ext) -+ { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ u32 txcsm, idx; -+ -+ ap = dev->priv; -+ regs = ap->regs; -+ -+ txcsm = *ap->tx_csm; -+ idx = ap->tx_ret_csm; -+ -+ do { -+ struct sk_buff *skb; -+ -+ skb = ap->skb->tx_skbuff[idx].skb; -+ if (skb) { -+ dma_addr_t mapping; -+ -+ mapping = ap->skb->tx_skbuff[idx].mapping; -+ -+ ap->stats.tx_packets++; -+ ap->stats.tx_bytes += skb->len; -+ pci_unmap_single(ap->pdev, mapping, skb->len, -+ PCI_DMA_TODEVICE); -+ if (!polling_ext) { -+ dev_kfree_skb_irq(skb); -+ } else { -+ acenic_recycle_or_free_skb(skb); -+ } -+ -+ ap->skb->tx_skbuff[idx].skb = NULL; -+ } -+ -+ /* -+ * Question here is whether one should not skip -+ * these writes - I have never seen any errors -+ * caused by the NIC actually trying to access -+ * these incorrectly. -+ */ -+ #if (BITS_PER_LONG == 64) -+ writel(0, &ap->tx_ring[idx].addr.addrhi); -+ #endif -+ writel(0, &ap->tx_ring[idx].addr.addrlo); -+ writel(0, &ap->tx_ring[idx].flagsize); -+ -+ idx = (idx + 1) % TX_RING_ENTRIES; -+ } while (idx != txcsm); -+ } -+ -+ static unsigned long ace_poll_intr = 0; -+ static unsigned long ace_poll_evtintr = 0; - - static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) - { -*************** -*** 1995,2000 **** ---- 2139,2147 ---- - if (!(readl(®s->HostCtrl) & IN_INT)) - return; - -+ if (dev->polling) -+ ace_poll_intr++; -+ - /* - * Tell the card not to generate interrupts while we are in here. - */ -*************** -*** 2010,2022 **** - rxretprd = *ap->rx_ret_prd; - rxretcsm = ap->cur_rx; - -! if (rxretprd != rxretcsm) - ace_rx_int(dev, rxretprd, rxretcsm); - - txcsm = *ap->tx_csm; - idx = ap->tx_ret_csm; - -! if (txcsm != idx) { - do { - struct sk_buff *skb; - ---- 2157,2169 ---- - rxretprd = *ap->rx_ret_prd; - rxretcsm = ap->cur_rx; - -! if (rxretprd != rxretcsm && !dev->polling) - ace_rx_int(dev, rxretprd, rxretcsm); - - txcsm = *ap->tx_csm; - idx = ap->tx_ret_csm; - -! if (txcsm != idx && !dev->polling) { - do { - struct sk_buff *skb; - -*************** -*** 2092,2097 **** ---- 2239,2246 ---- - evtprd = *ap->evt_prd; - - if (evtcsm != evtprd) { -+ if (dev->polling) -+ ace_poll_evtintr++; - evtcsm = ace_handle_event(dev, evtcsm, evtprd); - writel(evtcsm, ®s->EvtCsm); - } -*************** -*** 2100,2106 **** - * This has to go last in the interrupt handler and run with - * the spin lock released ... what lock? - */ -! if (netif_running(dev)) { - int cur_size; - int run_bh = 0; - ---- 2249,2255 ---- - * This has to go last in the interrupt handler and run with - * the spin lock released ... what lock? - */ -! if (!dev->polling && netif_running(dev)) { - int cur_size; - int run_bh = 0; - -*************** -*** 2304,2317 **** - return 0; - } - -! -! static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; - unsigned long addr; -! u32 idx, flagsize; - - /* - * ARGH, there is just no pretty way to do this - */ ---- 2453,2495 ---- - return 0; - } - -! static int ace_queue_skb(struct sk_buff *skb, struct net_device *dev, u32 idx) - { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; - unsigned long addr; -! u32 flagsize; -! -! ap->skb->tx_skbuff[idx].skb = skb; -! ap->skb->tx_skbuff[idx].mapping = -! pci_map_single(ap->pdev, skb->data, skb->len, -! PCI_DMA_TODEVICE); -! addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; -! #if (BITS_PER_LONG == 64) -! writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); -! #endif -! writel(addr & 0xffffffff, &ap->tx_ring[idx].addr.addrlo); -! flagsize = (skb->len << 16) | (BD_FLG_END) ; -! writel(flagsize, &ap->tx_ring[idx].flagsize); -! wmb(); -! idx = (idx + 1) % TX_RING_ENTRIES; -! -! ap->tx_prd = idx; -! ace_set_txprd(regs, ap, idx); -! return idx; -! } -! -! static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) -! { -! struct ace_private *ap = dev->priv; -! u32 idx; - -+ /* polling extension: we have to use tbusy to prevent ace_start_xmit from -+ * colliding with ace_tx_queue */ -+ #if 1 -+ if (test_and_set_bit(0, &dev->tbusy)) -+ return 1; -+ #else - /* - * ARGH, there is just no pretty way to do this - */ -*************** -*** 2321,2326 **** ---- 2499,2505 ---- - #else - netif_stop_queue(dev); - #endif -+ #endif - - idx = ap->tx_prd; - -*************** -*** 2333,2354 **** - return 1; - } - -! ap->skb->tx_skbuff[idx].skb = skb; -! ap->skb->tx_skbuff[idx].mapping = -! pci_map_single(ap->pdev, skb->data, skb->len, -! PCI_DMA_TODEVICE); -! addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; -! #if (BITS_PER_LONG == 64) -! writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); -! #endif -! writel(addr & 0xffffffff, &ap->tx_ring[idx].addr.addrlo); -! flagsize = (skb->len << 16) | (BD_FLG_END) ; -! writel(flagsize, &ap->tx_ring[idx].flagsize); -! wmb(); -! idx = (idx + 1) % TX_RING_ENTRIES; -! -! ap->tx_prd = idx; -! ace_set_txprd(regs, ap, idx); - - /* - * tx_csm is set by the NIC whereas we set tx_ret_csm which ---- 2512,2518 ---- - return 1; - } - -! idx = ace_queue_skb(skb, dev, idx); - - /* - * tx_csm is set by the NIC whereas we set tx_ret_csm which -*************** -*** 3004,3012 **** - goto out; - } - -! - /* - * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" - * End: - */ ---- 3168,3437 ---- - goto out; - } - -! - /* - * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" - * End: - */ -+ -+ -+ /* -+ * Polling Extension -+ * -+ * tx_csm: NIC's tx consumer pointer. updated when NIC transmit a pkt. -+ * -+ * tx_ret_csm: driver's tx consumer pointer. the pkts between tx_ret_csm and -+ * tx_csm are transmitted packets that need to be cleaned up. -+ * -+ * TxPrd: tx producer register in shared memory, read by NIC. this is kept in -+ * sync with tx_prd. -+ * -+ * tx_prd: driver's tx producer pointer (i.e. the next free buf on tx ring). -+ * driver will queue pkts onto tx ring, starting from tx_prd until the idx on -+ * tx ring hits tx_ret_csm - 2. that is when the driver believes the tx ring -+ * is full. -+ * -+ * rx_ret_prd: NIC's rx producer pointer. when a pkt arrives at NIC, this -+ * producer is incremented. -+ * -+ * cur_rx: the next rx buffer the driver should read. the difference between -+ * cur_rx and rx_ret_prd are newly arrived pkts. -+ * -+ * rx processing with Tigon uses a return ring. there are three rx rings (std, -+ * mini, and jumbo) and one rx return ring. the rx_ret_prd pointer points to -+ * the return ring. on the return ring, a descriptor tells you which of the -+ * three rx rings contain the last pkt. there is a counter for each of the -+ * three rings. when a pkt is pulled off of a ring, the corresponding counter -+ * is incremented. this is important, because the number recorded by each -+ * counter is the number of buffer refilled onto each ring. -+ */ -+ -+ // #define SELECTIVE_INTR 1 -+ -+ static int -+ ace_tx_queue(struct device *dev, struct sk_buff *skb) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx; -+ -+ /* polling extension: we have to use tbusy to prevent ace_start_xmit from -+ * colliding with ace_tx_queue */ -+ if (test_and_set_bit(0, (void*)&dev->tbusy)) -+ return 1; -+ -+ idx = ap->tx_prd; -+ -+ /* hard_start_xmit and tx_clean collision detected */ -+ if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm) { -+ ap->tx_full = 1; -+ return 1; -+ } -+ -+ idx = ace_queue_skb(skb, dev, idx); -+ -+ if ((idx + 2) % TX_RING_ENTRIES == ap->tx_ret_csm) { -+ ap->tx_full = 1; -+ } else { -+ clear_bit(0, (void*)&dev->tbusy); -+ } -+ -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ -+ static int -+ ace_tx_start(struct device *dev) -+ { -+ /* sorry pal, dunno how to do this... */ -+ return 1; -+ } -+ -+ static struct sk_buff* -+ ace_tx_clean(struct device *dev) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 txcsm = *ap->tx_csm; -+ -+ if (txcsm != ap->tx_ret_csm) { -+ ace_service_tx(dev, 1); -+ -+ /* only clear the tbusy bit if tx_full is set, so we don't -+ * accidentally allow two start_xmit or tx_queue to go on w/o -+ * synchronization. if tx_full is set, then neither start_xmit nor -+ * tx_queue is executing, or one is executing but the producer pointer -+ * has already been updated. -+ */ -+ if (ap->tx_full) { -+ clear_bit(0, (void*)&ap->tx_full); -+ clear_bit(0, (void*)&dev->tbusy); -+ } -+ ap->tx_ret_csm = txcsm; -+ wmb(); -+ } -+ #if 0 -+ if (ap->tx_prd < ap->tx_ret_csm) -+ return ap->tx_prd + TX_RING_ENTRIES - ap->tx_ret_csm; -+ else -+ return ap->tx_prd - ap->tx_ret_csm; -+ #endif -+ return 0; -+ } -+ -+ static int -+ ace_rx_refill(struct device *dev, struct sk_buff **skb_list) -+ { -+ u32 evtcsm, evtprd; -+ struct ace_private *ap = dev->priv; -+ struct ace_regs *regs = ap->regs; -+ -+ /* this seems like what we wanted: while it does clear the bh_pending bit -+ * for ace, but bh_pending is only set when rx rings need to be filled, so -+ * we should be fine. -+ * -+ * ace_bh return type is void, so we always return 0, even if ace_bh says -+ * there are no more memory to refill the rings... I guess that is really -+ * a fatalistic condition anyways... -+ */ -+ ace_bh(dev); -+ -+ #ifndef SELECTIVE_INTR -+ /* handle events... since we can't selectively mask out rx and tx -+ * interrupts... -+ */ -+ evtcsm = readl(®s->EvtCsm); -+ evtprd = *ap->evt_prd; -+ -+ if (evtcsm != evtprd) { -+ evtcsm = ace_handle_event(dev, evtcsm, evtprd); -+ writel(evtcsm, ®s->EvtCsm); -+ } -+ #endif -+ return 0; -+ } -+ -+ static struct sk_buff * -+ ace_rx_poll(struct device *dev, int *want) -+ { -+ struct ace_private *ap = dev->priv; -+ u32 idx, rxretprd; -+ int mini_count = 0, std_count = 0; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ rxretprd = *ap->rx_ret_prd; -+ idx = ap->cur_rx; -+ -+ while (idx != rxretprd && got < *want) { -+ struct sk_buff *skb; -+ -+ skb = ace_rx_get_skb(dev, idx, &mini_count, &std_count); -+ if (skb == 0L) goto error; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ -+ idx = (idx + 1) % RX_RETURN_RING_ENTRIES; -+ } -+ -+ atomic_sub(std_count, &ap->cur_rx_bufs); -+ if (!ACE_IS_TIGON_I(ap)) -+ atomic_sub(mini_count, &ap->cur_mini_bufs); -+ -+ out: -+ /* -+ * According to the documentation RxRetCsm is obsolete with -+ * the 12.3.x Firmware - my Tigon I NICs seem to disagree! -+ */ -+ if (ACE_IS_TIGON_I(ap)) { -+ struct ace_regs *regs = ap->regs; -+ writel(idx, ®s->RxRetCsm); -+ } -+ ap->cur_rx = idx; -+ -+ *want = got; -+ return skb_head; -+ -+ error: -+ idx = rxretprd; -+ goto out; -+ } -+ -+ static int -+ ace_poll_on(struct device *dev) -+ { -+ if (!dev->polling) { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ struct net_device *d = (struct net_device*)dev; -+ u32 stat; -+ -+ ap = d->priv; -+ regs = ap->regs; -+ -+ #ifdef SELECTIVE_INTR -+ /* okay, for some reason, below code segment did not turn off rx and -+ * tx interrupts... so we need to mask interrupts completely and -+ * depend on rx_refill to manage events. -+ */ -+ stat = readl(®s->ModeStat); -+ stat |= (ACE_DONT_RUPT_SENDS | ACE_DONT_RUPT_RECVS); -+ writel(stat, ®s->ModeStat); -+ #else -+ stat = readl(®s->HostCtrl); -+ stat |= MASK_INTS; -+ writel(stat, ®s->HostCtrl); -+ #endif -+ dev->polling = 2; -+ } -+ return 0; -+ } -+ -+ static int -+ ace_poll_off(struct device *dev) -+ { -+ if (dev->polling) { -+ struct ace_private *ap; -+ struct ace_regs *regs; -+ struct net_device *d = (struct net_device*)dev; -+ u32 stat; -+ -+ ap = d->priv; -+ regs = ap->regs; -+ -+ #ifdef SELECTIVE_INTR -+ stat = readl(®s->ModeStat); -+ stat &= ~(ACE_DONT_RUPT_SENDS | ACE_DONT_RUPT_RECVS); -+ writel(stat, ®s->ModeStat); -+ #else -+ stat = readl(®s->HostCtrl); -+ stat &= ~MASK_INTS; -+ writel(stat, ®s->HostCtrl); -+ #endif -+ dev->polling = 0; -+ -+ printk("ace polling interrupt summary: %ld %ld\n", -+ ace_poll_intr, ace_poll_evtintr); -+ ace_poll_intr = ace_poll_evtintr = 0; -+ } -+ return 0; -+ } -+ -+ static int ace_tx_eob(struct device *dev) -+ { -+ return 0; -+ } -+ -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/drivers/net/acenic.h ./drivers/net/acenic.h -*** ../linux-2.2.19-pure/drivers/net/acenic.h Sun Mar 25 08:31:20 2001 ---- ./drivers/net/acenic.h Sat May 4 23:13:01 2002 -*************** -*** 251,256 **** ---- 251,259 ---- - #define ACE_WARN 0x08 - #define ACE_BYTE_SWAP_DMA 0x10 - #define ACE_NO_JUMBO_FRAG 0x200 -+ #define ACE_DONT_RUPT_EVENTS 0x1000 -+ #define ACE_DONT_RUPT_SENDS 0x2000 -+ #define ACE_DONT_RUPT_RECVS 0x4000 - #define ACE_FATAL 0x40000000 - - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/drivers/net/eepro100.c ./drivers/net/eepro100.c -*** ../linux-2.2.19-pure/drivers/net/eepro100.c Sun Mar 25 08:37:34 2001 ---- ./drivers/net/eepro100.c Sat May 4 23:13:01 2002 -*************** -*** 49,62 **** - static const char *version = - "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" - "eepro100.c: $Revision: 1.20.2.10 $ 2000/05/31 Modified by Andrey V. Savochkin and others\n" -! "eepro100.c: VA Linux custom, Dragan Stancevic 2000/11/15\n"; - - /* A few user-configurable values that apply to all boards. - First set is undocumented and spelled per Intel recommendations. */ - -! static int congenb = 0; /* Enable congestion control in the DP83840. */ -! static int txfifo = 0; /* Tx FIFO threshold in 4 byte units, 0-15 */ -! static int rxfifo = 0xF; /* Rx FIFO threshold, default 32 bytes. */ - /* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ - static int txdmacount = 128; - static int rxdmacount = 0; ---- 49,69 ---- - static const char *version = - "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" - "eepro100.c: $Revision: 1.20.2.10 $ 2000/05/31 Modified by Andrey V. Savochkin and others\n" -! "eepro100.c: VA Linux custom, Dragan Stancevic 2000/11/15\n" -! "eepro100.c: MIT click polling extensions\n"; -! - - /* A few user-configurable values that apply to all boards. - First set is undocumented and spelled per Intel recommendations. */ - -! /* -! * benjie: i am setting txfifo to 8 and rxfifo to 8 as they are in the -! * 2.4.9 linux kernel -! */ -! static int congenb = 0; /* Enable congestion control in the DP83840. */ -! static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ -! static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ -! - /* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ - static int txdmacount = 128; - static int rxdmacount = 0; -*************** -*** 587,592 **** ---- 594,609 ---- - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+ /* device polling stuff */ -+ static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+ static int speedo_tx_eob(struct net_device *dev); -+ static int speedo_tx_start(struct net_device *dev); -+ static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+ static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+ static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+ static int speedo_poll_on(struct net_device *dev); -+ static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -*************** -*** 891,896 **** ---- 908,924 ---- - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return dev; - } - -*************** -*** 1111,1117 **** - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -! outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); - } - - /* Media monitoring and control. */ ---- 1139,1146 ---- - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -! outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -! (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* Media monitoring and control. */ -*************** -*** 1318,1324 **** - dev->name); - outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -! outw(CUStart, ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else ---- 1347,1354 ---- - dev->name); - outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -! outw(CUStart | (dev->polling ? SCBMaskAll : 0), -! ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -*************** -*** 1365,1370 **** ---- 1395,1408 ---- - long ioaddr = dev->base_addr; - int entry; - -+ #if 0 -+ if (dev->polling > 0) { -+ printk(KERN_ERR "%s: start_xmit while polling\n", -+ dev->name); -+ return 1; -+ } -+ #endif -+ - #if ! defined(HAS_NETIF_QUEUE) - if (test_bit(0, (void*)&dev->tbusy) != 0) { - int tickssofar = jiffies - dev->trans_start; -*************** -*** 1377,1383 **** - command atomic. --SAW */ - spin_lock_irqsave(&sp->lock, flags); - wait_for_cmd_done(ioaddr + SCBCmd); -! outw(SCBTriggerIntr, ioaddr + SCBCmd); - spin_unlock_irqrestore(&sp->lock, flags); - return 1; - } ---- 1415,1422 ---- - command atomic. --SAW */ - spin_lock_irqsave(&sp->lock, flags); - wait_for_cmd_done(ioaddr + SCBCmd); -! outw(SCBTriggerIntr | ((dev->polling>0) ? SCBMaskAll : 0), -! ioaddr + SCBCmd); - spin_unlock_irqrestore(&sp->lock, flags); - return 1; - } -*************** -*** 1388,1394 **** - - { /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; -- - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ ---- 1427,1432 ---- -*************** -*** 1436,1442 **** - } - - dev->trans_start = jiffies; -- - return 0; - } - ---- 1474,1479 ---- -*************** -*** 1445,1450 **** ---- 1482,1493 ---- - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -*************** -*** 1510,1515 **** ---- 1553,1561 ---- - } - #endif - -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -*************** -*** 1539,1548 **** - break; - - /* Always check if all rx buffers are allocated. --SAW */ -! speedo_refill_rx_buffers(dev, 0); - -! if ((status & 0x5000) || /* Packet received, or Rx error. */ -! (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - ---- 1585,1596 ---- - break; - - /* Always check if all rx buffers are allocated. --SAW */ -! if (!dev->polling) -! speedo_refill_rx_buffers(dev, 0); - -! if (!dev->polling && -! ((status & 0x5000) || /* Packet received, or Rx error. */ -! (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - -*************** -*** 1612,1618 **** - } - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -! if (status & 0xA400) { - spin_lock(&sp->lock); - speedo_tx_buffer_gc(dev); - if (sp->tx_full ---- 1660,1666 ---- - } - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -! if (!dev->polling && (status & 0xA400)) { - spin_lock(&sp->lock); - speedo_tx_buffer_gc(dev); - if (sp->tx_full -*************** -*** 1721,1726 **** ---- 1769,1780 ---- - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -*************** -*** 1735,1740 **** ---- 1789,1800 ---- - int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; - int alloc_ok = 1; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: in speedo_rx() while polling\n", -+ dev->name); -+ return 0; -+ } -+ - if (speedo_debug > 4) - printk(KERN_DEBUG " In speedo_rx().\n"); - /* If we own the next entry, it's a new packet. Send it up. */ -*************** -*** 2218,2220 **** ---- 2278,2649 ---- - * tab-width: 4 - * End: - */ -+ -+ /* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+ static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ sp->rx_ringp[entry] = (struct RxFD *) skb->tail; -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ -+ rxf = sp->rx_ringp[entry]; -+ rxf->rx_buf_addr = (uint32_t)0xffffffff; -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+ } -+ -+ static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ /* If the packet hasn't been received, bail out. */ -+ if ((status & RxComplete) == 0) -+ break; -+ -+ /* If we've already received too many packets, bail out. */ -+ if (got == *want || --rx_work_limit < 0) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+ } -+ -+ static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ long ioaddr = dev->base_addr; -+ int entry; -+ unsigned flags; -+ -+ #if ! defined(HAS_NETIF_QUEUE) -+ if (test_bit(0, (void*)&dev->tbusy) != 0) { -+ int tickssofar = jiffies - dev->trans_start; -+ if (tickssofar < TX_TIMEOUT - 2) -+ return 1; -+ if (tickssofar < TX_TIMEOUT) { -+ /* Reap sent packets from the full Tx queue. */ -+ unsigned long flags; -+ /* Take a spinlock to make wait_for_cmd_done and -+ * sending the command atomic. --SAW -+ */ -+ spin_lock_irqsave(&sp->lock, flags); -+ wait_for_cmd_done(ioaddr + SCBCmd); -+ outw(SCBTriggerIntr | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ speedo_tx_timeout(dev); -+ return 1; -+ } -+ #endif -+ -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ spin_unlock_irqrestore(&sp->lock, flags); -+ sp->tx_full = 1; -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].link = -+ virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); -+ sp->tx_ring[entry].tx_desc_addr = -+ virt_to_le32desc(&sp->tx_ring[entry].tx_buf_addr0); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32desc(skb->data); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ -+ /* Trigger the command unit resume. */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+ } -+ -+ static int speedo_tx_eob(struct net_device *dev) -+ { -+ /* Start the DMA going again */ -+ #if 1 -+ #if 0 // benjie -+ wait_for_cmd_done(ioaddr + SCBCmd); -+ #endif -+ outb(CUResume, dev->base_addr + SCBCmd); -+ #endif -+ return 0; -+ } -+ -+ static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ -+ static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (speedo_debug > 2) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (speedo_debug > 1) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+ } -+ -+ static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+ } -+ -+ static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+ } -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/drivers/net/tulip.c ./drivers/net/tulip.c -*** ../linux-2.2.19-pure/drivers/net/tulip.c Sun Mar 25 08:37:35 2001 ---- ./drivers/net/tulip.c Sat May 4 23:13:01 2002 -*************** -*** 495,509 **** - }; - - struct tulip_private { -! char devname[8]; /* Used only for kernel debugging. */ -! const char *product_name; -! struct device *next_module; - struct tulip_rx_desc rx_ring[RX_RING_SIZE]; - struct tulip_tx_desc tx_ring[TX_RING_SIZE]; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; -! /* The addresses of receive-in-place skbuffs. */ -! struct sk_buff* rx_skbuff[RX_RING_SIZE]; - char *rx_buffs; /* Address of temporary Rx buffers. */ - u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ - int chip_id; ---- 495,515 ---- - }; - - struct tulip_private { -! unsigned int cur_rx, dirty_rx; -! unsigned int rx_reserved[6]; - struct tulip_rx_desc rx_ring[RX_RING_SIZE]; -+ /* The addresses of receive-in-place skbuffs. */ -+ struct sk_buff* rx_skbuff[RX_RING_SIZE]; -+ -+ unsigned int cur_tx, dirty_tx; -+ unsigned int tx_reserved[6]; - struct tulip_tx_desc tx_ring[TX_RING_SIZE]; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; -! -! char devname[8]; /* Used only for kernel debugging. */ -! const char *product_name; -! struct device *next_module; - char *rx_buffs; /* Address of temporary Rx buffers. */ - u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */ - int chip_id; -*************** -*** 512,519 **** - struct net_device_stats stats; - struct timer_list timer; /* Media selection timer. */ - int interrupt; /* In-interrupt flag. */ -- unsigned int cur_rx, cur_tx; /* The next free ring entry */ -- unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - unsigned int tx_full:1; /* The Tx queue is full. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int full_duplex_lock:1; ---- 518,523 ---- -*************** -*** 566,571 **** ---- 570,585 ---- - #endif - static void set_rx_mode(struct device *dev); - -+ /* device polling stuff */ -+ static int tulip_tx_queue(struct device *dev, struct sk_buff *skb); -+ static int tulip_tx_eob(struct device *dev); -+ static int tulip_tx_start(struct device *dev); -+ static int tulip_rx_refill(struct device *dev, struct sk_buff **); -+ static struct sk_buff *tulip_tx_clean(struct device *dev); -+ static struct sk_buff *tulip_rx_poll(struct device *dev, int *want); -+ static int tulip_poll_on(struct device *dev); -+ static int tulip_poll_off(struct device *dev); -+ - - - /* A list of all installed Tulip devices. */ -*************** -*** 813,818 **** ---- 827,843 ---- - - dev->base_addr = ioaddr; - dev->irq = irq; -+ -+ /* Click - polling extensions */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_off = tulip_poll_off; -+ dev->poll_on = tulip_poll_on; - - tp->pci_bus = pci_bus; - tp->pci_devfn = pci_devfn; -*************** -*** 2539,2560 **** - tp->tx_ring[i-1].buffer2 = virt_to_le32desc(&tp->tx_ring[0]); - } - - static int - tulip_start_xmit(struct sk_buff *skb, struct device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - u32 flag; - -- /* Block a timer-based transmit from overlapping. This could better be -- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -! if (jiffies - dev->trans_start < TX_TIMEOUT) -! return 1; -! tulip_tx_timeout(dev); - return 1; - } -! - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - ---- 2564,2599 ---- - tp->tx_ring[i-1].buffer2 = virt_to_le32desc(&tp->tx_ring[0]); - } - -+ /* start the tulip transmit process by doing an outb */ -+ static int -+ tulip_tx_start(struct device *dev) -+ { -+ if (dev->polling <= 0) -+ /* Trigger an immediate transmit demand. */ -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+ } -+ - static int - tulip_start_xmit(struct sk_buff *skb, struct device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int entry; - u32 flag; -+ -+ #if 0 -+ if (dev->polling > 0) { -+ printk("tulip_start_xmit when interrupt is off\n"); -+ } -+ #endif - - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -! if (jiffies - dev->trans_start >= TX_TIMEOUT) -! tulip_tx_timeout(dev); - return 1; - } -! - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - -*************** -*** 2578,2593 **** - flag = 0xe0000000 | DESC_RING_WRAP; - - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - tp->cur_tx++; -! if ( ! tp->tx_full) -! clear_bit(0, (void*)&dev->tbusy); - -! dev->trans_start = jiffies; -! /* Trigger an immediate transmit demand. */ -! outl(0, dev->base_addr + CSR1); - -! return 0; - } - - /* The interrupt handler does all of the Rx thread work and cleans up ---- 2617,2648 ---- - flag = 0xe0000000 | DESC_RING_WRAP; - - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* new linux memory barrier thingie */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - tp->cur_tx++; -! -! tulip_tx_start(dev); -! -! if (!tp->tx_full) -! clear_bit(0, (void*)&dev->tbusy); -! -! return 0; -! } - -! /* polling extension - intr stats */ -! void (*tulip_interrupt_hook)(struct device *, unsigned); - -! static __inline__ unsigned long long -! tulip_get_cycles(void) -! { -! unsigned long low, high; -! unsigned long long x; -! __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -! x = high; -! x <<= 32; -! x |= low; -! return(x); - } - - /* The interrupt handler does all of the Rx thread work and cleans up -*************** -*** 2599,2611 **** - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; - int maxrx = RX_RING_SIZE; - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - - #if defined(__i386__) && defined(SMP_CHECK) - if (test_and_set_bit(0, (void*)&dev->interrupt)) { ---- 2654,2666 ---- - long ioaddr = dev->base_addr; - int csr5; - int entry; - int rx = 0; - int tx = 0; - int oi = 0; - int maxrx = RX_RING_SIZE; - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; -+ int first_time = 1; - - #if defined(__i386__) && defined(SMP_CHECK) - if (test_and_set_bit(0, (void*)&dev->interrupt)) { -*************** -*** 2627,2648 **** - - do { - csr5 = inl(ioaddr + CSR5); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -! if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) -! break; -! -! if (csr5 & (RxIntr | RxNoBuf)) { -! rx += tulip_rx(dev); -! tulip_refill_rx(dev); - } - -! if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { - unsigned int dirty_tx; - - for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; ---- 2682,2720 ---- - - do { - csr5 = inl(ioaddr + CSR5); -+ -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) goto out; -+ if (first_time) goto out; -+ else break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook. */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr))==0) goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -! if ((csr5 & (RxIntr | RxNoBuf)) && !dev->polling) { -! rx += tulip_rx(dev); -! tulip_refill_rx(dev); - } - -! if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) -! && !dev->polling) { -! /* part of following code duplicated at the end -! * in tulip_tx_clean for the polling driver, changes -! * here should propagate to there as well */ - unsigned int dirty_tx; - - for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; -*************** -*** 2707,2720 **** - } - - tp->dirty_tx = dirty_tx; -! if (csr5 & TxDied) { -! if (tulip_debug > 2) -! printk(KERN_WARNING "%s: The transmitter stopped." -! " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -! dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -! outl(tp->csr6 | 0x0002, ioaddr + CSR6); -! outl(tp->csr6 | 0x2002, ioaddr + CSR6); -! } - } - - /* Log errors. */ ---- 2779,2793 ---- - } - - tp->dirty_tx = dirty_tx; -! } -! -! if (csr5 & TxDied) { -! if (tulip_debug > 2) -! printk(KERN_WARNING "%s: The transmitter stopped." -! " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -! dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -! outl(tp->csr6 | 0x0002, ioaddr + CSR6); -! outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - - /* Log errors. */ -*************** -*** 2733,2740 **** - outl(0, ioaddr + CSR1); - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ - tp->stats.rx_errors++; -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { ---- 2806,2816 ---- - outl(0, ioaddr + CSR1); - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -+ unsigned csr8status = inl(ioaddr+CSR8); -+ unsigned fifostatus = csr8status>>17; - tp->stats.rx_errors++; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; - outl(tp->csr6 | 0x2002, ioaddr + CSR6); - } - if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { -*************** -*** 2774,2780 **** - } - } while (1); - -! tulip_refill_rx(dev); - - /* check if we card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; ---- 2850,2858 ---- - } - } while (1); - -! if (!dev->polling) { -! tulip_refill_rx(dev); -! } - - /* check if we card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -*************** -*** 2792,2805 **** ---- 2870,2886 ---- - } - } - -+ #if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+ #endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+ out: - #if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); - #else -*************** -*** 2945,2952 **** - if (tp->chip_id == DC21040) - outl(0x00000004, ioaddr + CSR13); - -! if (inl(ioaddr + CSR6) != 0xffffffff) -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - - del_timer(&tp->timer); - ---- 3026,3037 ---- - if (tp->chip_id == DC21040) - outl(0x00000004, ioaddr + CSR13); - -! if (inl(ioaddr + CSR6) != 0xffffffff) { -! unsigned csr8status = inl(ioaddr+CSR8); -! unsigned fifostatus = csr8status>>17; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; -! } - - del_timer(&tp->timer); - -*************** -*** 2989,2997 **** - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - -! if (dev->start) -! tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -! - return &tp->stats; - } - ---- 3074,3087 ---- - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - -! if (dev->start) { -! unsigned csr8status = inl(ioaddr+CSR8); -! unsigned fifostatus = csr8status>>17; -! unsigned missed = csr8status & 0x1ffff; -! tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; -! tp->stats.rx_missed_errors += csr8status&0xffff; -! tp->stats.rx_fifo_errors += fifostatus&0x7ff; -! } - return &tp->stats; - } - -*************** -*** 3190,3196 **** - /* Same setup recently queued, we need not add it. */ - } else { - unsigned long flags; -! unsigned int entry; - - save_flags(flags); cli(); - entry = tp->cur_tx++ % TX_RING_SIZE; ---- 3280,3286 ---- - /* Same setup recently queued, we need not add it. */ - } else { - unsigned long flags; -! unsigned int entry, dummy = 0; - - save_flags(flags); cli(); - entry = tp->cur_tx++ % TX_RING_SIZE; -*************** -*** 3201,3207 **** ---- 3291,3302 ---- - tp->tx_ring[entry].length = - (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0; - tp->tx_ring[entry].buffer1 = 0; -+ #if 1 -+ /* race with chip, set DescOwned later */ -+ dummy = entry; -+ #else - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ #endif - entry = tp->cur_tx++ % TX_RING_SIZE; - } - -*************** -*** 3216,3221 **** ---- 3311,3320 ---- - set_bit(0, (void*)&dev->tbusy); - tp->tx_full = 1; - } -+ #if 1 -+ if (dummy >= 0) -+ tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); -+ #endif - restore_flags(flags); - /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); -*************** -*** 3360,3362 **** ---- 3459,3739 ---- - * tab-width: 4 - * End: - */ -+ -+ -+ /* -+ * Polling Extension -+ * -+ * Most of the following functions are verbatim, or very similar to, code from -+ * the interrupt routines. They are cleaned up and tuned for polling. -+ * -+ * Very minimal synchronization occurs: most polling functions are suppose to -+ * be used in polling mode, under which case the interrupt handler is -+ * disallowed from touching the rx and tx ring. Callers of polling functions -+ * are expected to synchronize calls to these functions themselves. -+ * -+ * dev->tbusy was used by Linux's original tulip driver to synchronize the -+ * send pkt routine (tulip_start_xmit) and timer based send. I am using it -+ * also to synchronize tx queueing. -+ */ -+ -+ /* demand polling */ -+ #define DEMAND_POLLTX 1 -+ -+ int -+ tulip_rx_refill(struct device *dev, struct sk_buff **skbs) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == 0) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ /* Refill the Rx ring buffers. */ -+ for (; (tp->cur_rx-tp->dirty_rx) > 0 && skb_list != 0L; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_skbuff[entry] == NULL) { -+ struct sk_buff *skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ tp->rx_skbuff[entry] = skb; -+ skb->dev = dev; /* mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = virt_to_le32desc(skb->tail); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if (skb_list == 0) -+ *skbs = 0; -+ else -+ *skbs = skb_list; -+ return tp->cur_rx - tp->dirty_rx; -+ } -+ -+ static struct sk_buff * -+ tulip_rx_poll(struct device *dev, int *want) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while (! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned " "multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_skbuff[entry]; -+ int p; -+ tp->rx_skbuff[entry] = NULL; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; -+ } -+ -+ -+ static int -+ tulip_poll_on(struct device *dev) -+ { -+ long ioaddr = dev->base_addr; -+ int csr7; -+ #ifdef DEMAND_POLLTX -+ int csr0; -+ #endif -+ if (!dev->polling) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr+CSR7); -+ #ifdef DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr+CSR0); -+ #endif -+ dev->polling = 2; -+ } -+ return 0; -+ } -+ -+ static int -+ tulip_poll_off(struct device *dev) -+ { -+ long ioaddr = dev->base_addr; -+ int csr7; -+ #ifdef DEMAND_POLLTX -+ int csr0; -+ #endif -+ if (dev->polling > 0) { -+ #ifdef DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr+CSR0); -+ #endif -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr+CSR7); -+ dev->polling = 0; -+ } -+ return 0; -+ } -+ -+ static int -+ tulip_tx_queue(struct device *dev, struct sk_buff *skb) -+ { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ -+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { -+ /* printk("tulip_tx_queue: reject because tbusy\n"); */ -+ return 1; -+ } -+ -+ /* Caution: the write order is important here, set the base address -+ * with the "ownership" bits last. */ -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_skbuff[entry] = skb; -+ tp->tx_ring[entry].buffer1 = virt_to_le32desc(skb->data); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) -+ tp->tx_full = 0; -+ else -+ /* Leave room for set_rx_mode() to fill entries. */ -+ tp->tx_full = 1; -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* new linux memory barrier thingie */ -+ wmb(); -+ /* Pass ownership to the chip. */ -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ tp->cur_tx++; -+ -+ #ifndef DEMAND_POLLTX -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ #endif -+ if (!tp->tx_full) -+ clear_bit(0, (void*)&dev->tbusy); -+ -+ return 0; -+ } -+ -+ /* clean up tx dma ring */ -+ static struct sk_buff* -+ tulip_tx_clean(struct device *dev) -+ { -+ struct sk_buff *skb_head, *skb_last; -+ struct tulip_private *tp; -+ unsigned int dirty_tx; -+ tp = (struct tulip_private *)dev->priv; -+ skb_head = skb_last = 0; -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) break; /* It still hasn't been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_skbuff[entry] == NULL) continue; -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ skb = tp->tx_skbuff[entry]; -+ tp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+ if (tp->tx_full && dev->tbusy && tp->cur_tx-dirty_tx < TX_RING_SIZE-2) { -+ /* The ring is no longer full, clear tbusy. */ -+ tp->tx_full = 0; -+ clear_bit(0, (void*)&dev->tbusy); -+ } -+ -+ tp->dirty_tx = dirty_tx; -+ // ret = tp->cur_tx - tp->dirty_tx; -+ return skb_head; -+ } -+ -+ static int tulip_tx_eob(struct device *dev) -+ { -+ return 0; -+ } -+ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/fs/proc/inode.c ./fs/proc/inode.c -*** ../linux-2.2.19-pure/fs/proc/inode.c Sun Mar 25 08:30:58 2001 ---- ./fs/proc/inode.c Sat May 4 23:13:01 2002 -*************** -*** 265,270 **** ---- 265,275 ---- - if (inode->i_sb != sb) - printk("proc_get_inode: inode fubar\n"); - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/fs/super.c ./fs/super.c -*** ../linux-2.2.19-pure/fs/super.c Sun Mar 25 08:30:58 2001 ---- ./fs/super.c Sat May 4 23:17:23 2002 -*************** -*** 565,570 **** ---- 565,571 ---- - s->s_dev = dev; - s->s_flags = flags; - s->s_dirt = 0; -+ s->s_type = type; - sema_init(&s->s_vfs_rename_sem,1); - sema_init(&s->s_nfsd_free_path_sem,1); - /* N.B. Should lock superblock now ... */ -*************** -*** 572,578 **** - goto out_fail; - s->s_dev = dev; /* N.B. why do this again?? */ - s->s_rd_only = 0; -- s->s_type = type; - out: - return s; - ---- 573,578 ---- -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/include/linux/netdevice.h ./include/linux/netdevice.h -*** ../linux-2.2.19-pure/include/linux/netdevice.h Sun Mar 25 08:31:03 2001 ---- ./include/linux/netdevice.h Sat May 4 23:13:01 2002 -*************** -*** 324,329 **** ---- 324,370 ---- - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct device *); -+ int (*poll_off)(struct device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct device*, int *want); -+ /* -+ * refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct device *); - }; - - -*************** -*** 361,366 **** ---- 402,410 ---- - extern int unregister_netdevice(struct device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+ extern int register_net_in(struct notifier_block *nb); /* Click */ -+ extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+ extern void ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct device *dev_get_by_index(int ifindex); - extern int dev_restart(struct device *dev); -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/include/linux/signal.h ./include/linux/signal.h -*** ../linux-2.2.19-pure/include/linux/signal.h Sun Mar 25 08:31:03 2001 ---- ./include/linux/signal.h Sat May 4 23:13:01 2002 -*************** -*** 189,195 **** - memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = 0; -! case 1: - } - } - ---- 189,195 ---- - memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = 0; -! case 1: ; - } - } - -*************** -*** 201,207 **** - memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = -1; -! case 1: - } - } - ---- 201,207 ---- - memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1)); - break; - case 2: set->sig[1] = -1; -! case 1: ; - } - } - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/include/linux/skbuff.h ./include/linux/skbuff.h -*** ../linux-2.2.19-pure/include/linux/skbuff.h Sun Mar 25 08:31:03 2001 ---- ./include/linux/skbuff.h Sat May 4 23:13:01 2002 -*************** -*** 36,49 **** - for using debugging */ - }; - - struct sk_buff { - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - struct sk_buff_head * list; /* List we are on */ -! struct sock *sk; /* Socket we are owned by */ -! struct timeval stamp; /* Time we arrived */ - struct device *dev; /* Device we arrived on/are leaving by */ -! - /* Transport layer header */ - union - { ---- 36,65 ---- - for using debugging */ - }; - -+ /* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+ #define PACKET_CLEAN 128 /* Is packet clean? */ -+ #define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+ /* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - struct sk_buff_head * list; /* List we are on */ -! unsigned int len; /* Length of actual data */ -! unsigned char *data; /* Data head pointer */ -! unsigned char *tail; /* Tail pointer */ - struct device *dev; /* Device we arrived on/are leaving by */ -! unsigned char is_clone, /* We are a clone */ -! cloned, /* head may be cloned (check refcnt to be sure). */ -! pkt_type, /* Packet class */ -! ip_summed; /* Driver fed us an IP checksum */ -! atomic_t users; /* User count - see datagram.c,tcp.c */ -! unsigned int truesize; /* Buffer size */ -! unsigned char *head; /* Head of buffer */ -! unsigned char *end; /* End pointer */ - /* Transport layer header */ - union - { -*************** -*** 72,101 **** - struct ethhdr *ethernet; - unsigned char *raw; - } mac; - - struct dst_entry *dst; - -! char cb[48]; -! -! unsigned int len; /* Length of actual data */ -! unsigned int csum; /* Checksum */ - volatile char used; /* Data moved to user and not MSG_PEEK */ -! unsigned char is_clone, /* We are a clone */ -! cloned, /* head may be cloned (check refcnt to be sure). */ -! pkt_type, /* Packet class */ -! pkt_bridged, /* Tracker for bridging */ -! ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ -- -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -- void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_IP_FIREWALL - __u32 fwmark; /* Label made by fwchains, used by pktsched */ - #endif ---- 88,107 ---- - struct ethhdr *ethernet; - unsigned char *raw; - } mac; -+ -+ char cb[48]; - - struct dst_entry *dst; - -! void (*destructor)(struct sk_buff *); /* Destruct function */ -! struct sock *sk; /* Socket we are owned by */ -! struct timeval stamp; /* Time we arrived */ - volatile char used; /* Data moved to user and not MSG_PEEK */ -! unsigned char pkt_bridged; /* Tracker for bridging */ -! unsigned int csum; /* Checksum */ - __u32 priority; /* Packet queueing priority */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ - #ifdef CONFIG_IP_FIREWALL - __u32 fwmark; /* Label made by fwchains, used by pktsched */ - #endif -*************** -*** 145,150 **** ---- 151,158 ---- - extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list); - extern struct sk_buff * alloc_skb(unsigned int size, int priority); - extern struct sk_buff * dev_alloc_skb(unsigned int size); -+ extern void skb_recycled_init(struct sk_buff *buf); -+ extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority); -*************** -*** 491,497 **** - return skb->data; - } - -! extern __inline__ char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - return skb->data+=len; ---- 499,505 ---- - return skb->data; - } - -! extern __inline__ unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - return skb->data+=len; -*************** -*** 551,560 **** - extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length) - { - struct sk_buff *skb; - -! skb = alloc_skb(length+16, GFP_ATOMIC); - if (skb) -! skb_reserve(skb,16); - return skb; - } - ---- 559,573 ---- - extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length) - { - struct sk_buff *skb; -+ #if 0 -+ #define SKB_RESERVE_LENGTH 32 -+ #else -+ #define SKB_RESERVE_LENGTH 16 -+ #endif - -! skb = alloc_skb(length+SKB_RESERVE_LENGTH, GFP_ATOMIC); - if (skb) -! skb_reserve(skb,SKB_RESERVE_LENGTH); - return skb; - } - -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/include/net/neighbour.h ./include/net/neighbour.h -*** ../linux-2.2.19-pure/include/net/neighbour.h Sun Mar 25 08:31:08 2001 ---- ./include/net/neighbour.h Sat May 4 23:13:01 2002 -*************** -*** 50,55 **** ---- 50,56 ---- - #define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) - #define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE) - -+ struct neighbour; - struct neigh_parms - { - struct neigh_parms *next; -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/kernel/ksyms.c ./kernel/ksyms.c -*** ../linux-2.2.19-pure/kernel/ksyms.c Sun Mar 25 08:31:02 2001 ---- ./kernel/ksyms.c Sat May 4 23:17:42 2002 -*************** -*** 342,347 **** ---- 342,348 ---- - - /* process management */ - EXPORT_SYMBOL(__wake_up); -+ EXPORT_SYMBOL(wake_up_process); - EXPORT_SYMBOL(sleep_on); - EXPORT_SYMBOL(sleep_on_timeout); - EXPORT_SYMBOL(interruptible_sleep_on); -*************** -*** 415,420 **** ---- 416,425 ---- - EXPORT_SYMBOL(__down_trylock); - EXPORT_SYMBOL(__up); - EXPORT_SYMBOL(brw_page); -+ EXPORT_SYMBOL(inuse_filps); -+ EXPORT_SYMBOL(super_blocks); -+ extern spinlock_t inode_lock; -+ EXPORT_SYMBOL(inode_lock); - - /* all busmice */ - EXPORT_SYMBOL(add_mouse_randomness); -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/net/core/dev.c ./net/core/dev.c -*** ../linux-2.2.19-pure/net/core/dev.c Sun Mar 25 08:37:41 2001 ---- ./net/core/dev.c Sat May 4 23:13:01 2002 -*************** -*** 154,159 **** ---- 154,162 ---- - - static struct notifier_block *netdev_chain=NULL; - -+ /* input packet handlers -- might steal packets from net_bh(). for Click. */ -+ static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the bottom half handler. -*************** -*** 335,340 **** ---- 338,345 ---- - kfree(dev); - return NULL; - } -+ /* by default, no polling support */ -+ dev->poll_on = dev->poll_off = 0; - return dev; - } - -*************** -*** 516,521 **** ---- 521,542 ---- - } - - /* -+ * Allow Click modules to ask to intercept input packets. -+ * Must add these to ../netsyms.c -+ */ -+ int -+ register_net_in(struct notifier_block *nb) -+ { -+ return(notifier_chain_register(&net_in_chain, nb)); -+ } -+ -+ int -+ unregister_net_in(struct notifier_block *nb) -+ { -+ return(notifier_chain_unregister(&net_in_chain, nb)); -+ } -+ -+ /* - * Support routine. Sends outgoing frames to any network - * taps currently in use. - */ -*************** -*** 852,857 **** ---- 873,958 ---- - } - #endif /* CONFIG_NET_DIVERT */ - -+ -+ /* -+ * Hand a packet to the ordinary Linux protocol stack. -+ * Broke this out from net_bh() so that Click can call it. -+ * Always frees the skb one way or another. -+ * -+ * skb->pkt_type needs to be set to PACKET_{BROADCAST,MULTICAST,OTHERHOST} -+ * maybe skb->mac.raw must point to ether header. -+ * skb->protocol must be set to a htons(ETHERTYPE_?). -+ * skb->data must point to the ethernet payload (e.g. the IP header). -+ * skb->nh.raw must point to the ethernet payload also. -+ */ -+ void -+ ptype_dispatch(struct sk_buff *skb, unsigned short type) -+ { -+ struct packet_type *ptype; -+ struct packet_type *pt_prev; -+ -+ /* -+ * We got a packet ID. Now loop over the "known protocols" -+ * list. There are two lists. The ptype_all list of taps (normally empty) -+ * and the main protocol list which is hashed perfectly for normal protocols. -+ */ -+ -+ pt_prev = NULL; -+ for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) -+ { -+ if (!ptype->dev || ptype->dev == skb->dev) { -+ if(pt_prev) -+ { -+ struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); -+ if(skb2) -+ pt_prev->func(skb2,skb->dev, pt_prev); -+ } -+ pt_prev=ptype; -+ } -+ } -+ -+ for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) -+ { -+ if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev)) -+ { -+ /* -+ * We already have a match queued. Deliver -+ * to it and then remember the new match -+ */ -+ if(pt_prev) -+ { -+ struct sk_buff *skb2; -+ -+ skb2=skb_clone(skb, GFP_ATOMIC); -+ -+ /* -+ * Kick the protocol handler. This should be fast -+ * and efficient code. -+ */ -+ -+ if(skb2) -+ pt_prev->func(skb2, skb->dev, pt_prev); -+ } -+ /* Remember the current last to do */ -+ pt_prev=ptype; -+ } -+ } /* End of protocol list loop */ -+ -+ /* -+ * Is there a last item to send to ? -+ */ -+ -+ if(pt_prev) -+ pt_prev->func(skb, skb->dev, pt_prev); -+ /* -+ * Has an unknown packet has been received ? -+ */ -+ -+ else { -+ kfree_skb(skb); -+ } -+ } -+ - /* - * When we are called the queue is ready to grab, the interrupts are - * on and hardware can interrupt and queue to the receive queue as we -*************** -*** 862,869 **** - - void net_bh(void) - { -- struct packet_type *ptype; -- struct packet_type *pt_prev; - unsigned short type; - unsigned long start_time = jiffies; - #ifdef CONFIG_CPU_IS_SLOW ---- 963,968 ---- -*************** -*** 979,1044 **** - handle_bridge(skb, type); - #endif - -! /* -! * We got a packet ID. Now loop over the "known protocols" -! * list. There are two lists. The ptype_all list of taps (normally empty) -! * and the main protocol list which is hashed perfectly for normal protocols. -! */ -! -! pt_prev = NULL; -! for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) -! { -! if (!ptype->dev || ptype->dev == skb->dev) { -! if(pt_prev) -! { -! struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); -! if(skb2) -! pt_prev->func(skb2,skb->dev, pt_prev); -! } -! pt_prev=ptype; -! } -! } -! -! for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) -! { -! if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev)) -! { -! /* -! * We already have a match queued. Deliver -! * to it and then remember the new match -! */ -! if(pt_prev) -! { -! struct sk_buff *skb2; - -- skb2=skb_clone(skb, GFP_ATOMIC); - -! /* -! * Kick the protocol handler. This should be fast -! * and efficient code. -! */ - -- if(skb2) -- pt_prev->func(skb2, skb->dev, pt_prev); -- } -- /* Remember the current last to do */ -- pt_prev=ptype; -- } -- } /* End of protocol list loop */ - -- /* -- * Is there a last item to send to ? -- */ - -- if(pt_prev) -- pt_prev->func(skb, skb->dev, pt_prev); -- /* -- * Has an unknown packet has been received ? -- */ -- -- else { -- kfree_skb(skb); -- } - } /* End of queue loop */ - - /* ---- 1078,1096 ---- - handle_bridge(skb, type); - #endif - -! /* does Click want to steal this packet? */ -! if(notifier_call_chain(&net_in_chain, skb_queue_len(&backlog), skb) & NOTIFY_STOP_MASK) -! continue; - - -! /* -! * Ordinary Linux dispatch based on packet type. -! * Moved into a function so Click can call it. -! */ -! ptype_dispatch(skb, type); - - - - } /* End of queue loop */ - - /* -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/net/core/skbuff.c ./net/core/skbuff.c -*** ../linux-2.2.19-pure/net/core/skbuff.c Sun Mar 25 08:31:12 2001 ---- ./net/core/skbuff.c Sat May 4 23:13:01 2002 -*************** -*** 257,262 **** ---- 257,300 ---- - return n; - } - -+ -+ /* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+ struct sk_buff *skb_recycle(struct sk_buff *skb) -+ { -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ dst_release(skb->dst); -+ if (skb->destructor) -+ skb->destructor(skb); -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || atomic_dec_and_test(skb_datarefp(skb))) { -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->is_clone = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(skb_datarefp(skb), 1); -+ -+ return skb; -+ } -+ -+ kmem_cache_free(skbuff_head_cache, skb); -+ atomic_dec(&net_skbcount); -+ } -+ -+ return 0; -+ } -+ -+ - /* - * This is slower, and copies the whole data area - */ -diff -r -c --exclude=*.o --exclude=*.flags ../linux-2.2.19-pure/net/netsyms.c ./net/netsyms.c -*** ../linux-2.2.19-pure/net/netsyms.c Sun Mar 25 08:37:41 2001 ---- ./net/netsyms.c Sat May 4 23:13:01 2002 -*************** -*** 464,469 **** ---- 464,476 ---- - EXPORT_SYMBOL(unregister_inetaddr_notifier); - #endif - -+ /* Click */ -+ EXPORT_SYMBOL(register_net_in); -+ EXPORT_SYMBOL(unregister_net_in); -+ EXPORT_SYMBOL(ptype_dispatch); -+ struct inet_protocol *inet_get_protocol(unsigned char prot); -+ EXPORT_SYMBOL(inet_get_protocol); -+ - /* support for loadable net drivers */ - #ifdef CONFIG_NET - EXPORT_SYMBOL(loopback_dev); -*************** -*** 487,492 **** ---- 494,500 ---- - EXPORT_SYMBOL(eth_copy_and_sum); - EXPORT_SYMBOL(alloc_skb); - EXPORT_SYMBOL(__kfree_skb); -+ EXPORT_SYMBOL(skb_recycle); - EXPORT_SYMBOL(skb_clone); - EXPORT_SYMBOL(skb_copy); - EXPORT_SYMBOL(netif_rx); diff --git a/etc/linux-2.4.18-patch b/etc/linux-2.4.18-patch deleted file mode 100644 index ab28c35a86..0000000000 --- a/etc/linux-2.4.18-patch +++ /dev/null @@ -1,2542 +0,0 @@ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/drivers/net/eepro100.c ./drivers/net/eepro100.c ---- ../x/linux-2.4.18-pure/drivers/net/eepro100.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./drivers/net/eepro100.c 2002-05-26 23:41:38.000000000 -0700 -@@ -549,6 +549,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -843,6 +853,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1071,7 +1092,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* Media monitoring and control. */ -@@ -1298,7 +1320,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1345,6 +1368,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1401,7 +1432,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1410,6 +1440,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1480,6 +1516,11 @@ - } - #endif - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1508,10 +1549,12 @@ - break; - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - -@@ -1581,7 +1624,7 @@ - } - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - spin_lock(&sp->lock); - speedo_tx_buffer_gc(dev); - if (sp->tx_full -@@ -1697,6 +1740,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1710,6 +1759,12 @@ - int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; - int alloc_ok = 1; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: in speedo_rx() while polling\n", -+ dev->name); -+ return 0; -+ } -+ - if (speedo_debug > 4) - printk(KERN_DEBUG " In speedo_rx().\n"); - /* If we own the next entry, it's a new packet. Send it up. */ -@@ -2340,3 +2395,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (speedo_debug > 2) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev->base_addr + SCBCmd); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (speedo_debug > 2) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (speedo_debug > 1) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/drivers/net/tulip/interrupt.c ./drivers/net/tulip/interrupt.c ---- ../x/linux-2.4.18-pure/drivers/net/tulip/interrupt.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./drivers/net/tulip/interrupt.c 2002-05-26 23:34:57.000000000 -0700 -@@ -292,6 +292,10 @@ - } - - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -301,7 +305,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -309,6 +312,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -319,14 +323,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -335,7 +358,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -403,16 +432,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -434,7 +464,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -525,7 +558,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -548,12 +583,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: -+} -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; - } -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/drivers/net/tulip/tulip_core.c ./drivers/net/tulip/tulip_core.c ---- ../x/linux-2.4.18-pure/drivers/net/tulip/tulip_core.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./drivers/net/tulip/tulip_core.c 2002-05-26 23:34:57.000000000 -0700 -@@ -251,6 +251,16 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); -+ - - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) -@@ -696,6 +706,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -731,13 +752,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -746,6 +767,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -808,8 +842,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -888,10 +926,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1714,6 +1756,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1922,3 +1975,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/fs/proc/inode.c ./fs/proc/inode.c ---- ../x/linux-2.4.18-pure/fs/proc/inode.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./fs/proc/inode.c 2002-05-26 23:34:57.000000000 -0700 -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-alpha/core_tsunami.h ./include/asm-alpha/core_tsunami.h ---- ../x/linux-2.4.18-pure/include/asm-alpha/core_tsunami.h 2001-11-09 13:45:35.000000000 -0800 -+++ ./include/asm-alpha/core_tsunami.h 2002-11-21 12:19:53.000000000 -0800 -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-arm/mmu.h ./include/asm-arm/mmu.h ---- ../x/linux-2.4.18-pure/include/asm-arm/mmu.h 2000-12-29 14:07:23.000000000 -0800 -+++ ./include/asm-arm/mmu.h 2003-02-07 17:04:09.000000000 -0800 -@@ -2,6 +2,6 @@ - #define __ARM_MMU_H - - /* The ARM doesn't have a mmu context */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-cris/io.h ./include/asm-cris/io.h ---- ../x/linux-2.4.18-pure/include/asm-cris/io.h 2001-10-08 11:43:54.000000000 -0700 -+++ ./include/asm-cris/io.h 2003-02-10 10:37:59.000000000 -0800 -@@ -24,8 +24,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-i386/desc.h ./include/asm-i386/desc.h ---- ../x/linux-2.4.18-pure/include/asm-i386/desc.h 2001-07-26 13:40:32.000000000 -0700 -+++ ./include/asm-i386/desc.h 2003-02-10 10:37:54.000000000 -0800 -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-i386/highmem.h ./include/asm-i386/highmem.h ---- ../x/linux-2.4.18-pure/include/asm-i386/highmem.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/asm-i386/highmem.h 2003-02-10 10:38:26.000000000 -0800 -@@ -91,7 +91,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -107,7 +107,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-i386/pgtable.h ./include/asm-i386/pgtable.h ---- ../x/linux-2.4.18-pure/include/asm-i386/pgtable.h 2001-11-22 11:46:19.000000000 -0800 -+++ ./include/asm-i386/pgtable.h 2003-02-10 10:38:26.000000000 -0800 -@@ -42,7 +42,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-i386/rwlock.h ./include/asm-i386/rwlock.h ---- ../x/linux-2.4.18-pure/include/asm-i386/rwlock.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/asm-i386/rwlock.h 2002-05-26 23:39:49.000000000 -0700 -@@ -33,7 +33,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - ".subsection 0\n" \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -69,7 +69,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - ".subsection 0\n" \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-i386/string.h ./include/asm-i386/string.h ---- ../x/linux-2.4.18-pure/include/asm-i386/string.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/asm-i386/string.h 2003-02-10 10:38:26.000000000 -0800 -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/delay.h ./include/asm-ia64/delay.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/delay.h 2001-04-05 12:51:47.000000000 -0700 -+++ ./include/asm-ia64/delay.h 2003-02-10 10:37:59.000000000 -0800 -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/io.h ./include/asm-ia64/io.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/io.h 2001-11-09 14:26:17.000000000 -0800 -+++ ./include/asm-ia64/io.h 2003-02-10 10:37:59.000000000 -0800 -@@ -67,7 +67,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/pgalloc.h ./include/asm-ia64/pgalloc.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/pgalloc.h 2001-11-09 14:26:17.000000000 -0800 -+++ ./include/asm-ia64/pgalloc.h 2003-02-10 10:37:58.000000000 -0800 -@@ -193,7 +193,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - #endif - } - -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/processor.h ./include/asm-ia64/processor.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/processor.h 2001-11-09 14:26:17.000000000 -0800 -+++ ./include/asm-ia64/processor.h 2003-02-10 10:37:58.000000000 -0800 -@@ -504,14 +504,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - -@@ -547,8 +547,8 @@ - extern void ia64_load_pm_regs (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -577,25 +577,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -609,7 +609,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -623,7 +623,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -638,7 +638,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -648,7 +648,7 @@ - */ - #define ia64_clear_ic(flags) \ - asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" \ -- : "=r"(flags) :: "memory"); -+ : "=r"(flags) : : "memory"); - - /* - * Insert a translation into an instruction and/or data translation -@@ -659,14 +659,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -677,13 +677,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -694,16 +694,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -711,7 +711,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -726,13 +726,13 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #define cpu_relax() do { } while (0) -@@ -741,13 +741,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -762,7 +762,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -777,7 +777,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -845,7 +845,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - /* -@@ -856,7 +856,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -871,7 +871,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -885,7 +885,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -902,7 +902,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -919,7 +919,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -936,7 +936,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -962,13 +962,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/spinlock.h ./include/asm-ia64/spinlock.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/spinlock.h 2001-11-09 14:26:17.000000000 -0800 -+++ ./include/asm-ia64/spinlock.h 2003-02-10 10:37:58.000000000 -0800 -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -93,7 +93,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -156,7 +156,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "r2", "r29", "memory"); \ -+ : : "r"(rw) : "r2", "r29", "memory"); \ - } while(0) - - /* -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-ia64/system.h ./include/asm-ia64/system.h ---- ../x/linux-2.4.18-pure/include/asm-ia64/system.h 2001-12-21 09:42:03.000000000 -0800 -+++ ./include/asm-ia64/system.h 2003-02-10 10:37:57.000000000 -0800 -@@ -62,7 +62,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -87,7 +87,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -124,7 +124,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & (1UL << 14)) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -136,7 +136,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & (1UL << 14)) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -158,17 +158,17 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_restore(x) __asm__ __volatile__ (";; mov psr.l=%0;; srlz.d" \ -- :: "r" (x) : "memory") -+ : : "r" (x) : "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define save_and_cli(flags) __save_and_cli(flags) - #define __sti() local_irq_enable () -@@ -301,7 +301,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-mips/processor.h ./include/asm-mips/processor.h ---- ../x/linux-2.4.18-pure/include/asm-mips/processor.h 2001-10-05 12:11:05.000000000 -0700 -+++ ./include/asm-mips/processor.h 2003-02-10 10:37:57.000000000 -0800 -@@ -276,6 +276,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-mips64/processor.h ./include/asm-mips64/processor.h ---- ../x/linux-2.4.18-pure/include/asm-mips64/processor.h 2001-10-05 12:11:05.000000000 -0700 -+++ ./include/asm-mips64/processor.h 2003-02-10 10:37:57.000000000 -0800 -@@ -307,6 +307,6 @@ - * functions. We avoid the overhead of a function call by forcing the - * compiler to save the return address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-parisc/system.h ./include/asm-parisc/system.h ---- ../x/linux-2.4.18-pure/include/asm-parisc/system.h 2000-12-06 11:46:39.000000000 -0800 -+++ ./include/asm-parisc/system.h 2003-02-10 10:37:56.000000000 -0800 -@@ -56,9 +56,9 @@ - * uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h - * hasn't yet been included yet so it fails, thus repeating the macro here. - */ --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - /* interrupt control */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-s390/uaccess.h ./include/asm-s390/uaccess.h ---- ../x/linux-2.4.18-pure/include/asm-s390/uaccess.h 2002-02-25 11:38:13.000000000 -0800 -+++ ./include/asm-s390/uaccess.h 2003-02-10 10:37:56.000000000 -0800 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->thread.fs) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" (x.acc4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" (x.acc4)); \ - current->thread.fs = (x);}) - - #define segment_eq(a,b) ((a).acc4 == (b).acc4) -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-s390x/uaccess.h ./include/asm-s390x/uaccess.h ---- ../x/linux-2.4.18-pure/include/asm-s390x/uaccess.h 2002-02-25 11:38:13.000000000 -0800 -+++ ./include/asm-s390x/uaccess.h 2003-02-10 10:37:55.000000000 -0800 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-sparc/system.h ./include/asm-sparc/system.h ---- ../x/linux-2.4.18-pure/include/asm-sparc/system.h 2001-10-30 15:08:11.000000000 -0800 -+++ ./include/asm-sparc/system.h 2003-02-10 10:37:55.000000000 -0800 -@@ -280,9 +280,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - - #define nop() __asm__ __volatile__ ("nop"); - -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/asm-sparc64/system.h ./include/asm-sparc64/system.h ---- ../x/linux-2.4.18-pure/include/asm-sparc64/system.h 2001-12-21 09:42:03.000000000 -0800 -+++ ./include/asm-sparc64/system.h 2003-02-10 10:37:54.000000000 -0800 -@@ -110,9 +110,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/highmem.h ./include/linux/highmem.h ---- ../x/linux-2.4.18-pure/include/linux/highmem.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/highmem.h 2003-02-10 10:38:26.000000000 -0800 -@@ -18,7 +18,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -65,7 +65,7 @@ - - if (offset + size > PAGE_SIZE) - BUG(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -76,8 +76,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/inetdevice.h ./include/linux/inetdevice.h ---- ../x/linux-2.4.18-pure/include/linux/inetdevice.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/inetdevice.h 2002-05-26 23:34:57.000000000 -0700 -@@ -122,7 +122,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/mm.h ./include/linux/mm.h ---- ../x/linux-2.4.18-pure/include/linux/mm.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/mm.h 2003-02-10 10:38:26.000000000 -0800 -@@ -509,7 +509,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/netdevice.h ./include/linux/netdevice.h ---- ../x/linux-2.4.18-pure/include/linux/netdevice.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/netdevice.h 2003-01-13 15:17:30.000000000 -0800 -@@ -415,6 +415,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - -@@ -453,6 +493,9 @@ - extern int unregister_netdevice(struct net_device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/reiserfs_fs_sb.h ./include/linux/reiserfs_fs_sb.h ---- ../x/linux-2.4.18-pure/include/linux/reiserfs_fs_sb.h 2002-02-25 11:38:13.000000000 -0800 -+++ ./include/linux/reiserfs_fs_sb.h 2003-02-10 10:38:26.000000000 -0800 -@@ -378,8 +378,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/skbuff.h ./include/linux/skbuff.h ---- ../x/linux-2.4.18-pure/include/linux/skbuff.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/skbuff.h 2003-02-10 10:38:51.000000000 -0800 -@@ -126,15 +126,31 @@ - skb_frag_t frags[MAX_SKB_FRAGS]; - }; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -165,8 +181,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; -- - /* - * This is the control buffer. It is free to use for every - * layer. Please put your private variables there. If you -@@ -175,23 +189,17 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -+ struct dst_entry *dst; -+ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ - unsigned int data_len; - unsigned int csum; /* Checksum */ -- unsigned char __unused, /* Dead field, may be reused */ -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ -- -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ - - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER -@@ -233,6 +241,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -822,7 +832,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -850,7 +860,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/spinlock.h ./include/linux/spinlock.h ---- ../x/linux-2.4.18-pure/include/linux/spinlock.h 2001-11-22 11:46:19.000000000 -0800 -+++ ./include/linux/spinlock.h 2003-02-10 10:38:26.000000000 -0800 -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - /* - * These are the generic versions of the spinlocks and read-write -@@ -53,13 +54,8 @@ - * - * Most gcc versions have a nasty bug with empty initializers. - */ --#if (__GNUC__ > 2) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -116,13 +112,8 @@ - * - * Most gcc versions have a nasty bug with empty initializers. - */ --#if (__GNUC__ > 2) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/swap.h ./include/linux/swap.h ---- ../x/linux-2.4.18-pure/include/linux/swap.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/linux/swap.h 2003-02-10 10:38:26.000000000 -0800 -@@ -98,7 +98,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/linux/types.h ./include/linux/types.h ---- ../x/linux-2.4.18-pure/include/linux/types.h 2001-11-22 11:46:18.000000000 -0800 -+++ ./include/linux/types.h 2003-02-10 10:07:37.000000000 -0800 -@@ -127,4 +127,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/include/net/route.h ./include/net/route.h ---- ../x/linux-2.4.18-pure/include/net/route.h 2002-06-08 23:28:47.000000000 -0700 -+++ ./include/net/route.h 2003-01-13 15:18:46.000000000 -0800 -@@ -136,7 +136,13 @@ - static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) - { -+#ifdef __cplusplus -+ struct rt_key key = { daddr, saddr }; -+ key.oif = oif; -+ key.tos = tos; -+#else - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; -+#endif - - return ip_route_output_key(rp, &key); - } -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/kernel/ksyms.c ./kernel/ksyms.c ---- ../x/linux-2.4.18-pure/kernel/ksyms.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./kernel/ksyms.c 2002-11-21 13:08:53.000000000 -0800 -@@ -516,6 +516,8 @@ - EXPORT_SYMBOL(is_bad_inode); - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/net/core/dev.c ./net/core/dev.c ---- ../x/linux-2.4.18-pure/net/core/dev.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./net/core/dev.c 2002-05-26 23:34:57.000000000 -0700 -@@ -181,6 +181,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1383,6 +1386,22 @@ - br_write_unlock_bh(BR_NETPROTO_LOCK); - } - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1416,6 +1435,86 @@ - #endif /* CONFIG_NET_DIVERT */ - - -+/* -+ * Click: Hand a packet to the ordinary Linux protocol stack. -+ * Broke this out from net_tx_action so that Click can call it. -+ * Always frees the skb one way or another. -+ * -+ * skb->pkt_type needs to be set to PACKET_{BROADCAST,MULTICAST,OTHERHOST} -+ * maybe skb->mac.raw must point to ether header. -+ * skb->protocol must be set to a htons(ETHERTYPE_?). -+ * skb->data must point to the ethernet payload (e.g. the IP header). -+ * skb->nh.raw must point to the ethernet payload also. -+ * -+ * Returns 1 if caller should skip bugdet, etc. -+ */ -+int ptype_dispatch(struct sk_buff *skb, unsigned short type) -+{ -+ struct packet_type *ptype, *pt_prev; -+ -+ pt_prev = NULL; -+ for (ptype = ptype_all; ptype; ptype = ptype->next) { -+ if (!ptype->dev || ptype->dev == skb->dev) { -+ if (pt_prev) { -+ if (!pt_prev->data) { -+ deliver_to_old_ones(pt_prev, skb, 0); -+ } else { -+ atomic_inc(&skb->users); -+ pt_prev->func(skb, -+ skb->dev, -+ pt_prev); -+ } -+ } -+ pt_prev = ptype; -+ } -+ } -+ -+ /* Click: exit if sniffers only */ -+ if (type == 0xFFFF) -+ goto done; -+ -+#ifdef CONFIG_NET_DIVERT -+ if (skb->dev->divert && skb->dev->divert->divert) -+ handle_diverter(skb); -+#endif /* CONFIG_NET_DIVERT */ -+ -+ -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ if (skb->dev->br_port != NULL && -+ br_handle_frame_hook != NULL) { -+ handle_bridge(skb, pt_prev); -+ return 1; -+ } -+#endif -+ -+ for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { -+ if (ptype->type == type && -+ (!ptype->dev || ptype->dev == skb->dev)) { -+ if (pt_prev) { -+ if (!pt_prev->data) -+ deliver_to_old_ones(pt_prev, skb, 0); -+ else { -+ atomic_inc(&skb->users); -+ pt_prev->func(skb, -+ skb->dev, -+ pt_prev); -+ } -+ } -+ pt_prev = ptype; -+ } -+ } -+ -+done: -+ if (pt_prev) { -+ if (!pt_prev->data) -+ deliver_to_old_ones(pt_prev, skb, 1); -+ else -+ pt_prev->func(skb, skb->dev, pt_prev); -+ } else -+ kfree_skb(skb); -+ return 0; -+} -+ - static void net_rx_action(struct softirq_action *h) - { - int this_cpu = smp_processor_id(); -@@ -1428,6 +1527,7 @@ - for (;;) { - struct sk_buff *skb; - struct net_device *rx_dev; -+ int backlog; - - local_irq_disable(); - skb = __skb_dequeue(&queue->input_pkt_queue); -@@ -1449,66 +1549,19 @@ - } - #endif - skb->h.raw = skb->nh.raw = skb->data; -- { -- struct packet_type *ptype, *pt_prev; -- unsigned short type = skb->protocol; -- -- pt_prev = NULL; -- for (ptype = ptype_all; ptype; ptype = ptype->next) { -- if (!ptype->dev || ptype->dev == skb->dev) { -- if (pt_prev) { -- if (!pt_prev->data) { -- deliver_to_old_ones(pt_prev, skb, 0); -- } else { -- atomic_inc(&skb->users); -- pt_prev->func(skb, -- skb->dev, -- pt_prev); -- } -- } -- pt_prev = ptype; -- } -- } - --#ifdef CONFIG_NET_DIVERT -- if (skb->dev->divert && skb->dev->divert->divert) -- handle_diverter(skb); --#endif /* CONFIG_NET_DIVERT */ -- -- --#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -- if (skb->dev->br_port != NULL && -- br_handle_frame_hook != NULL) { -- handle_bridge(skb, pt_prev); -- dev_put(rx_dev); -- continue; -- } --#endif -- -- for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { -- if (ptype->type == type && -- (!ptype->dev || ptype->dev == skb->dev)) { -- if (pt_prev) { -- if (!pt_prev->data) -- deliver_to_old_ones(pt_prev, skb, 0); -- else { -- atomic_inc(&skb->users); -- pt_prev->func(skb, -- skb->dev, -- pt_prev); -- } -- } -- pt_prev = ptype; -- } -- } -+ /* Click: may want to steal the packet */ -+ if (notifier_call_chain(&net_in_chain, -+ skb_queue_len(&queue->input_pkt_queue), -+ skb) & NOTIFY_STOP_MASK) { -+ dev_put(rx_dev); -+ continue; -+ } - -- if (pt_prev) { -- if (!pt_prev->data) -- deliver_to_old_ones(pt_prev, skb, 1); -- else -- pt_prev->func(skb, skb->dev, pt_prev); -- } else -- kfree_skb(skb); -+ /* Click: dispatch based on protocol type */ -+ if (ptype_dispatch(skb, skb->protocol)) { -+ dev_put(rx_dev); -+ continue; - } - - dev_put(rx_dev); -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/net/core/skbuff.c ./net/core/skbuff.c ---- ../x/linux-2.4.18-pure/net/core/skbuff.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./net/core/skbuff.c 2002-05-26 23:34:57.000000000 -0700 -@@ -443,6 +443,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/net/ipv4/arp.c ./net/ipv4/arp.c ---- ../x/linux-2.4.18-pure/net/ipv4/arp.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./net/ipv4/arp.c 2002-05-26 23:34:57.000000000 -0700 -@@ -318,6 +318,7 @@ - { - u32 saddr; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -330,8 +331,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -341,8 +342,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) -diff -ru --exclude=.depend --exclude='*.o' --exclude='*.orig' --exclude='*.flags' ../x/linux-2.4.18-pure/net/netsyms.c ./net/netsyms.c ---- ../x/linux-2.4.18-pure/net/netsyms.c 2002-06-08 23:28:47.000000000 -0700 -+++ ./net/netsyms.c 2003-02-09 22:25:32.000000000 -0800 -@@ -277,6 +277,12 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(ptype_dispatch); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - diff --git a/etc/linux-2.4.20-patch b/etc/linux-2.4.20-patch deleted file mode 100644 index 25bb1595be..0000000000 --- a/etc/linux-2.4.20-patch +++ /dev/null @@ -1,2896 +0,0 @@ -Index: include/asm-mips/sibyte/64bit.h -=================================================================== ---- include/asm-mips/sibyte/64bit.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips/sibyte/64bit.h (working copy) -@@ -51,7 +51,7 @@ - " or $1, $1, $2 \n" - " sd $1, (%2)\n" - ".set pop\n" -- ::"r" (high), "r" (low), "r" (addr) -+ : :"r" (high), "r" (low), "r" (addr) - :"$1", "$2"); - __restore_flags(flags); - } -Index: include/asm-mips/processor.h -=================================================================== ---- include/asm-mips/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips/processor.h (working copy) -@@ -256,6 +256,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips/system.h -=================================================================== ---- include/asm-mips/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips/system.h (working copy) -@@ -243,17 +243,17 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - #endif /* !__ASSEMBLY__ */ - - #define prepare_to_switch() do { } while(0) - - struct task_struct; - --extern asmlinkage void lazy_fpu_switch(void *); --extern asmlinkage void init_fpu(void); --extern asmlinkage void save_fp(struct task_struct *); --extern asmlinkage void restore_fp(struct task_struct *); -+asmlinkage void lazy_fpu_switch(void *); -+asmlinkage void init_fpu(void); -+asmlinkage void save_fp(struct task_struct *); -+asmlinkage void restore_fp(struct task_struct *); - - #define switch_to(prev,next,last) \ - do { \ -Index: include/asm-mips/watch.h -=================================================================== ---- include/asm-mips/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips/watch.h (working copy) -@@ -20,9 +20,9 @@ - - extern char watch_available; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (watch_available) \ -Index: include/linux/netfilter_ipv4/ip_conntrack_irc.h -=================================================================== ---- include/linux/netfilter_ipv4/ip_conntrack_irc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/netfilter_ipv4/ip_conntrack_irc.h (working copy) -@@ -27,8 +27,7 @@ - }; - - /* This structure exists only once per master */ --struct ip_ct_irc_master { --}; -+EMPTY_STRUCT_DECL(ip_ct_irc_master); - - - #ifdef __KERNEL__ -Index: include/linux/list.h -=================================================================== ---- include/linux/list.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/list.h (working copy) -@@ -91,8 +91,8 @@ - static inline void list_del(struct list_head *entry) - { - __list_del(entry->prev, entry->next); -- entry->next = (void *) 0; -- entry->prev = (void *) 0; -+ entry->next = (struct list_head *) 0; -+ entry->prev = (struct list_head *) 0; - } - - /** -Index: include/linux/sysctl.h -=================================================================== ---- include/linux/sysctl.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/sysctl.h (working copy) -@@ -631,7 +631,7 @@ - - #ifdef __KERNEL__ - --extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+asmlinkage long sys_sysctl(struct __sysctl_args *); - extern void sysctl_init(void); - - typedef struct ctl_table ctl_table; -Index: include/linux/spinlock.h -=================================================================== ---- include/linux/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/spinlock.h (working copy) -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - /* - * These are the generic versions of the spinlocks and read-write -@@ -71,13 +72,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 95) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -135,13 +131,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -Index: include/linux/netdevice.h -=================================================================== ---- include/linux/netdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/netdevice.h (working copy) -@@ -438,6 +438,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - -@@ -476,6 +516,9 @@ - extern int unregister_netdevice(struct net_device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -@@ -589,7 +632,7 @@ - #define HAVE_NETIF_RX 1 - extern int netif_rx(struct sk_buff *skb); - #define HAVE_NETIF_RECEIVE_SKB 1 --extern int netif_receive_skb(struct sk_buff *skb); -+extern int netif_receive_skb(struct sk_buff *skb, unsigned short, int ignore_notifiers); - extern int dev_ioctl(unsigned int cmd, void *); - extern int dev_change_flags(struct net_device *, unsigned); - extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); -Index: include/linux/intermezzo_kml.h -=================================================================== ---- include/linux/intermezzo_kml.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/intermezzo_kml.h (working copy) -@@ -70,8 +70,7 @@ - int gid; - }; - --struct kml_open { --}; -+EMPTY_STRUCT_DECL(kml_open); - - struct kml_mkdir { - char *path; -Index: include/linux/skbuff.h -=================================================================== ---- include/linux/skbuff.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/skbuff.h (working copy) -@@ -126,15 +126,31 @@ - skb_frag_t frags[MAX_SKB_FRAGS]; - }; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -165,8 +181,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; -- - /* - * This is the control buffer. It is free to use for every - * layer. Please put your private variables there. If you -@@ -175,24 +189,18 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -+ struct dst_entry *dst; -+ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ - unsigned int data_len; - unsigned int csum; /* Checksum */ -- unsigned char __unused, /* Dead field, may be reused */ -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ - -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -- - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER - /* Can be used for communication between hooks. */ -@@ -233,6 +241,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -822,7 +832,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -850,7 +860,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -Index: include/linux/atalk.h -=================================================================== ---- include/linux/atalk.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/atalk.h (working copy) -@@ -163,7 +163,7 @@ - - static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) - { -- return dev->atalk_ptr; -+ return (struct atalk_iface *) dev->atalk_ptr; - } - - extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); -Index: include/linux/types.h -=================================================================== ---- include/linux/types.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/types.h (working copy) -@@ -127,4 +127,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -Index: include/linux/inetdevice.h -=================================================================== ---- include/linux/inetdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/inetdevice.h (working copy) -@@ -124,7 +124,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -Index: include/linux/if_vlan.h -=================================================================== ---- include/linux/if_vlan.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/if_vlan.h (working copy) -@@ -183,7 +183,7 @@ - break; - }; - -- return (polling ? netif_receive_skb(skb) : netif_rx(skb)); -+ return (polling ? netif_receive_skb(skb, skb->protocol, 0) : netif_rx(skb)); - } - - static inline int vlan_hwaccel_rx(struct sk_buff *skb, -Index: include/linux/nfsd/syscall.h -=================================================================== ---- include/linux/nfsd/syscall.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/nfsd/syscall.h (working copy) -@@ -133,7 +133,7 @@ - * Kernel syscall implementation. - */ - #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) --extern asmlinkage long sys_nfsservctl(int, void *, void *); -+asmlinkage long sys_nfsservctl(int, void *, void *); - #else - #define sys_nfsservctl sys_ni_syscall - #endif -Index: include/linux/highmem.h -=================================================================== ---- include/linux/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/highmem.h (working copy) -@@ -17,7 +17,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -102,7 +102,7 @@ - - if (offset + size > PAGE_SIZE) - out_of_line_bug(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -113,8 +113,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -Index: include/linux/mm.h -=================================================================== ---- include/linux/mm.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/mm.h (working copy) -@@ -576,7 +576,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -Index: include/linux/reiserfs_fs_sb.h -=================================================================== ---- include/linux/reiserfs_fs_sb.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/reiserfs_fs_sb.h (working copy) -@@ -405,8 +405,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -Index: include/linux/swap.h -=================================================================== ---- include/linux/swap.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/linux/swap.h (working copy) -@@ -100,7 +100,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -Index: include/asm-mips64/sibyte/64bit.h -=================================================================== ---- include/asm-mips64/sibyte/64bit.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips64/sibyte/64bit.h (working copy) -@@ -51,7 +51,7 @@ - " or $1, $1, $2 \n" - " sd $1, (%2)\n" - ".set pop\n" -- ::"r" (high), "r" (low), "r" (addr) -+ : :"r" (high), "r" (low), "r" (addr) - :"$1", "$2"); - __restore_flags(flags); - } -Index: include/asm-mips64/processor.h -=================================================================== ---- include/asm-mips64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips64/processor.h (working copy) -@@ -307,6 +307,6 @@ - * functions. We avoid the overhead of a function call by forcing the - * compiler to save the return address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips64/system.h -=================================================================== ---- include/asm-mips64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips64/system.h (working copy) -@@ -216,16 +216,16 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - - struct task_struct; - --extern asmlinkage void lazy_fpu_switch(void *, void *); --extern asmlinkage void init_fpu(void); --extern asmlinkage void save_fp(struct task_struct *); --extern asmlinkage void restore_fp(struct task_struct *); -+asmlinkage void lazy_fpu_switch(void *, void *); -+asmlinkage void init_fpu(void); -+asmlinkage void save_fp(struct task_struct *); -+asmlinkage void restore_fp(struct task_struct *); - - #ifdef CONFIG_SMP - #define SWITCH_DO_LAZY_FPU \ -Index: include/asm-mips64/watch.h -=================================================================== ---- include/asm-mips64/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-mips64/watch.h (working copy) -@@ -20,9 +20,9 @@ - - extern char watch_available; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (watch_available) \ -Index: include/asm-ia64/delay.h -=================================================================== ---- include/asm-ia64/delay.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/delay.h (working copy) -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -Index: include/asm-ia64/io.h -=================================================================== ---- include/asm-ia64/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/io.h (working copy) -@@ -67,7 +67,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -Index: include/asm-ia64/processor.h -=================================================================== ---- include/asm-ia64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/processor.h (working copy) -@@ -414,14 +414,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - -@@ -448,8 +448,8 @@ - extern void ia32_load_state (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -478,25 +478,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -510,7 +510,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -524,7 +524,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -539,7 +539,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -551,7 +551,7 @@ - ia64_clear_ic (void) - { - __u64 psr; -- asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) :: "memory"); -+ asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) : : "memory"); - return psr; - } - -@@ -561,7 +561,7 @@ - static inline void - ia64_set_psr (__u64 psr) - { -- asm volatile (";; mov psr.l=%0;; srlz.d" :: "r" (psr) : "memory"); -+ asm volatile (";; mov psr.l=%0;; srlz.d" : : "r" (psr) : "memory"); - } - - /* -@@ -573,14 +573,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -591,13 +591,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -608,16 +608,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -625,7 +625,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -640,13 +640,13 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #define cpu_relax() do { } while (0) -@@ -655,13 +655,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -676,7 +676,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -691,7 +691,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -759,7 +759,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - /* -@@ -770,7 +770,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -785,7 +785,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -799,7 +799,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -816,7 +816,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -833,7 +833,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -850,7 +850,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -876,13 +876,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -Index: include/asm-ia64/spinlock.h -=================================================================== ---- include/asm-ia64/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/spinlock.h (working copy) -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -93,7 +93,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -156,7 +156,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ -+ : : "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ - } while(0) - - #define write_unlock(x) \ -Index: include/asm-ia64/system.h -=================================================================== ---- include/asm-ia64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/system.h (working copy) -@@ -57,7 +57,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -82,7 +82,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -121,7 +121,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & (1UL << 14)) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -133,7 +133,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & (1UL << 14)) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -160,21 +160,21 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_restore(x) __asm__ __volatile__ ("cmp.ne p6,p7=%0,r0;;" \ - "(p6) ssm psr.i;" \ - "(p7) rsm psr.i;;" \ - "srlz.d" \ -- :: "r"((x) & IA64_PSR_I) \ -+ : : "r"((x) & IA64_PSR_I) \ - : "p6", "p7", "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define save_and_cli(flags) __save_and_cli(flags) - #define __sti() local_irq_enable () -@@ -307,7 +307,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -Index: include/asm-ia64/pgalloc.h -=================================================================== ---- include/asm-ia64/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-ia64/pgalloc.h (working copy) -@@ -194,7 +194,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - else - vma->vm_mm->context = 0; - #endif -Index: include/asm-sparc/system.h -=================================================================== ---- include/asm-sparc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-sparc/system.h (working copy) -@@ -280,9 +280,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - - #define nop() __asm__ __volatile__ ("nop"); - -Index: include/net/route.h -=================================================================== ---- include/net/route.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/net/route.h (working copy) -@@ -140,7 +140,13 @@ - static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) - { -+#ifdef __cplusplus -+ struct rt_key key = { daddr, saddr }; -+ key.oif = oif; -+ key.tos = tos; -+#else - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; -+#endif - - return ip_route_output_key(rp, &key); - } -Index: include/net/checksum.h -=================================================================== ---- include/net/checksum.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/net/checksum.h (working copy) -@@ -111,7 +111,7 @@ - static __inline__ unsigned int csum_and_copy_to_user - (const char *src, char *dst, int len, unsigned int sum, int *err_ptr) - { -- sum = csum_partial(src, len, sum); -+ sum = csum_partial((const unsigned char *) src, len, sum); - - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len) == 0) -Index: include/net/ax25.h -=================================================================== ---- include/net/ax25.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/net/ax25.h (working copy) -@@ -176,7 +176,7 @@ - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - ax25_digi *digipeat; -- ax25_dev *ax25_dev; -+ struct ax25_dev *ax25_dev; - unsigned char iamdigi; - unsigned char state, modulus, pidincl; - unsigned short vs, vr, va; -Index: include/asm-arm/mmu.h -=================================================================== ---- include/asm-arm/mmu.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-arm/mmu.h (working copy) -@@ -2,6 +2,6 @@ - #define __ARM_MMU_H - - /* The ARM doesn't have a mmu context */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -Index: include/asm-arm/system.h -=================================================================== ---- include/asm-arm/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-arm/system.h (working copy) -@@ -29,7 +29,7 @@ - - #define tas(ptr) (xchg((ptr),1)) - --extern asmlinkage void __backtrace(void); -+asmlinkage void __backtrace(void); - - /* - * Include processor dependent parts -Index: include/asm-arm/proc-armo/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armo/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-arm/proc-armo/pgalloc.h (working copy) -@@ -20,7 +20,7 @@ - */ - static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) - { -- return kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ return (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - } - - /* -Index: include/asm-arm/proc-armv/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armv/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-arm/proc-armv/pgalloc.h (working copy) -@@ -22,7 +22,7 @@ - { - pte_t *pte; - -- pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ pte = (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - if (pte) - pte += PTRS_PER_PTE; - return pte; -Index: include/asm-parisc/system.h -=================================================================== ---- include/asm-parisc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-parisc/system.h (working copy) -@@ -145,7 +145,7 @@ - ** The __asm__ op below simple prevents gcc/ld from reordering - ** instructions across the mb() "call". - */ --#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */ -+#define mb() __asm__ __volatile__("": : :"memory"); /* barrier() */ - #define rmb() mb() - #define wmb() mb() - #define smp_mb() mb() -Index: include/asm-sparc64/system.h -=================================================================== ---- include/asm-sparc64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-sparc64/system.h (working copy) -@@ -110,9 +110,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -Index: include/asm-alpha/core_tsunami.h -=================================================================== ---- include/asm-alpha/core_tsunami.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-alpha/core_tsunami.h (working copy) -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -Index: include/asm-s390x/uaccess.h -=================================================================== ---- include/asm-s390x/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-s390x/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-i386/pgtable.h -=================================================================== ---- include/asm-i386/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-i386/pgtable.h (working copy) -@@ -43,7 +43,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-i386/rwlock.h -=================================================================== ---- include/asm-i386/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-i386/rwlock.h (working copy) -@@ -28,7 +28,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -58,7 +58,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -Index: include/asm-i386/string.h -=================================================================== ---- include/asm-i386/string.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-i386/string.h (working copy) -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -Index: include/asm-i386/desc.h -=================================================================== ---- include/asm-i386/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-i386/desc.h (working copy) -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -Index: include/asm-i386/highmem.h -=================================================================== ---- include/asm-i386/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-i386/highmem.h (working copy) -@@ -91,7 +91,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -107,7 +107,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -Index: include/asm-s390/uaccess.h -=================================================================== ---- include/asm-s390/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-s390/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4)); \ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-x86_64/pgtable.h -=================================================================== ---- include/asm-x86_64/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/pgtable.h (working copy) -@@ -49,7 +49,7 @@ - "movq %%cr3, %0; # flush TLB \n" \ - "movq %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-x86_64/rwlock.h -=================================================================== ---- include/asm-x86_64/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/rwlock.h (working copy) -@@ -31,7 +31,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -44,7 +44,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile int *)rw))::"memory") -+ :"=m" (*((volatile int *)rw)): :"memory") - - #define __build_read_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -@@ -61,7 +61,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -@@ -74,7 +74,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile long *)rw))::"memory") -+ :"=m" (*((volatile long *)rw)): :"memory") - - #define __build_write_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -Index: include/asm-x86_64/pda.h -=================================================================== ---- include/asm-x86_64/pda.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/pda.h (working copy) -@@ -47,9 +47,9 @@ - - #define pda_to_op(op,field,val) do { \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %0,%%gs:" __STR2(pda_ ## field) ::"r" (val):"memory"); break; \ -- case 4: asm volatile(op "l %0,%%gs:" __STR2(pda_ ## field) ::"r" (val):"memory"); break; \ -- case 8: asm volatile(op "q %0,%%gs:" __STR2(pda_ ## field) ::"r" (val):"memory"); break; \ -+ case 2: asm volatile(op "w %0,%%gs:" __STR2(pda_ ## field) : :"r" (val):"memory"); break; \ -+ case 4: asm volatile(op "l %0,%%gs:" __STR2(pda_ ## field) : :"r" (val):"memory"); break; \ -+ case 8: asm volatile(op "q %0,%%gs:" __STR2(pda_ ## field) : :"r" (val):"memory"); break; \ - default: __bad_pda_field(); \ - } \ - } while (0) -@@ -58,9 +58,9 @@ - #define pda_from_op(op,field) ({ \ - typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__)::"memory"); break; \ -- case 4: asm volatile(op "l %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__)::"memory"); break; \ -- case 8: asm volatile(op "q %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__)::"memory"); break; \ -+ case 2: asm volatile(op "w %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__): :"memory"); break; \ -+ case 4: asm volatile(op "l %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__): :"memory"); break; \ -+ case 8: asm volatile(op "q %%gs:" __STR2(pda_ ## field) ",%0":"=r" (ret__): :"memory"); break; \ - default: __bad_pda_field(); \ - } \ - ret__; }) -Index: include/asm-x86_64/page.h -=================================================================== ---- include/asm-x86_64/page.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/page.h (working copy) -@@ -85,9 +85,9 @@ - char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */ - unsigned short line; - } __attribute__((packed)); --#define BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" :: "i"(__LINE__), \ -+#define BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" : : "i"(__LINE__), \ - "i" (__stringify(KBUILD_BASENAME))) --#define HEADER_BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" :: "i"(__LINE__), \ -+#define HEADER_BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" : : "i"(__LINE__), \ - "i" (__stringify(__FILE__))) - #define PAGE_BUG(page) BUG() - -Index: include/asm-x86_64/desc.h -=================================================================== ---- include/asm-x86_64/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/desc.h (working copy) -@@ -73,9 +73,9 @@ - #define __CPU_DESC_INDEX(x,field) \ - ((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + __GDT_HEAD_SIZE) - --#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss))); --#define __load_LDT(cpu) asm volatile("lldt %w0"::"r" (__CPU_DESC_INDEX(cpu, ldt))); --#define clear_LDT(n) asm volatile("lldt %w0"::"r" (0)) -+#define load_TR(cpu) asm volatile("ltr %w0": :"r" (__CPU_DESC_INDEX(cpu, tss))); -+#define __load_LDT(cpu) asm volatile("lldt %w0": :"r" (__CPU_DESC_INDEX(cpu, ldt))); -+#define clear_LDT(n) asm volatile("lldt %w0": :"r" (0)) - - extern struct gate_struct idt_table[]; - -Index: include/asm-x86_64/system.h -=================================================================== ---- include/asm-x86_64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-x86_64/system.h (working copy) -@@ -230,9 +230,9 @@ - * but I'd also expect them to finally get their act together - * and add some real memory barriers if so. - */ --#define mb() asm volatile("mfence":::"memory") --#define rmb() asm volatile("lfence":::"memory") --#define wmb() asm volatile("sfence":::"memory") -+#define mb() asm volatile("mfence": : :"memory") -+#define rmb() asm volatile("lfence": : :"memory") -+#define wmb() asm volatile("sfence": : :"memory") - #define set_mb(var, value) do { xchg(&var, value); } while (0) - #define set_wmb(var, value) do { var = value; wmb(); } while (0) - -@@ -273,7 +273,7 @@ - #endif - - /* Default simics "magic" breakpoint */ --#define icebp() asm volatile("xchg %%bx,%%bx" ::: "ebx") -+#define icebp() asm volatile("xchg %%bx,%%bx" : : : "ebx") - - /* - * disable hlt during certain critical i/o operations -Index: include/asm-cris/io.h -=================================================================== ---- include/asm-cris/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ include/asm-cris/io.h (working copy) -@@ -24,8 +24,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -Index: kernel/ksyms.c -=================================================================== ---- kernel/ksyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ kernel/ksyms.c (working copy) -@@ -533,6 +533,8 @@ - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); - EXPORT_SYMBOL(__inode_dir_notify); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -Index: net/netsyms.c -=================================================================== ---- net/netsyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ net/netsyms.c (working copy) -@@ -277,6 +277,11 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - -Index: net/core/dev.c -=================================================================== ---- net/core/dev.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ net/core/dev.c (working copy) -@@ -182,6 +182,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1379,6 +1382,22 @@ - } - - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1412,11 +1431,10 @@ - } - #endif /* CONFIG_NET_DIVERT */ - --int netif_receive_skb(struct sk_buff *skb) -+int netif_receive_skb(struct sk_buff *skb, unsigned short type, int notifier_data) - { - struct packet_type *ptype, *pt_prev; - int ret = NET_RX_DROP; -- unsigned short type = skb->protocol; - - if (skb->stamp.tv_sec == 0) - do_gettimeofday(&skb->stamp); -@@ -1434,6 +1452,14 @@ - - skb->h.raw = skb->nh.raw = skb->data; - -+ /* Click: may want to steal the packet */ -+ if (notifier_data >= 0 -+ && notifier_call_chain(&net_in_chain, -+ notifier_data, -+ skb) & NOTIFY_STOP_MASK) { -+ return ret; -+ } -+ - pt_prev = NULL; - for (ptype = ptype_all; ptype; ptype = ptype->next) { - if (!ptype->dev || ptype->dev == skb->dev) { -@@ -1513,7 +1539,7 @@ - - dev = skb->dev; - -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, skb_queue_len(&queue->input_pkt_queue)); - - dev_put(dev); - -Index: net/core/skbuff.c -=================================================================== ---- net/core/skbuff.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ net/core/skbuff.c (working copy) -@@ -443,6 +443,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -Index: net/ipv4/arp.c -=================================================================== ---- net/ipv4/arp.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ net/ipv4/arp.c (working copy) -@@ -318,6 +318,7 @@ - { - u32 saddr; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -330,8 +331,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -341,8 +342,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) -Index: fs/proc/inode.c -=================================================================== ---- fs/proc/inode.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ fs/proc/inode.c (working copy) -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -Index: drivers/net/tulip/tulip_core.c -=================================================================== ---- drivers/net/tulip/tulip_core.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ drivers/net/tulip/tulip_core.c (working copy) -@@ -264,7 +264,17 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); - -+ - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) - { -@@ -709,6 +719,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -744,13 +765,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -759,6 +780,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -821,8 +855,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -901,10 +939,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1722,6 +1764,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1930,3 +1983,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -Index: drivers/net/tulip/interrupt.c -=================================================================== ---- drivers/net/tulip/interrupt.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ drivers/net/tulip/interrupt.c (working copy) -@@ -311,6 +311,10 @@ - #endif - } - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -320,7 +324,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -328,6 +331,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -341,14 +345,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -357,7 +380,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -425,16 +454,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -456,7 +486,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -547,7 +580,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -570,12 +605,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: - } -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; -+} -Index: drivers/net/tg3.c -=================================================================== ---- drivers/net/tg3.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ drivers/net/tg3.c (working copy) -@@ -2016,7 +2016,7 @@ - desc->err_vlan & RXD_VLAN_MASK); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - tp->dev->last_rx = jiffies; - received++; -Index: drivers/net/eepro100.c -=================================================================== ---- drivers/net/eepro100.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.20) (revision 23) -+++ drivers/net/eepro100.c (working copy) -@@ -544,6 +544,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -874,6 +884,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1125,7 +1146,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* -@@ -1390,7 +1412,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1437,6 +1460,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1494,7 +1525,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1503,6 +1533,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1566,6 +1602,11 @@ - long ioaddr, boguscnt = max_interrupt_work; - unsigned short status; - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1594,13 +1635,15 @@ - break; - - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - - spin_lock(&sp->lock); - /* -@@ -1625,7 +1668,7 @@ - - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - speedo_tx_buffer_gc(dev); - if (sp->tx_full - && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -@@ -1743,6 +1786,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1759,6 +1808,12 @@ - - if (netif_msg_intr(sp)) - printk(KERN_DEBUG " In speedo_rx().\n"); -+ if (dev->polling) { -+ printk(KERN_ERR "%s: In speedo_rx() while polling.\n", -+ dev->name); -+ return 0; -+ } -+ - /* If we own the next entry, it's a new packet. Send it up. */ - while (sp->rx_ringp[entry] != NULL) { - int status; -@@ -2449,3 +2504,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (netif_msg_rx_err(sp)) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ diff --git a/etc/linux-2.4.20-wifi-patch b/etc/linux-2.4.20-wifi-patch deleted file mode 100644 index c23445e894..0000000000 --- a/etc/linux-2.4.20-wifi-patch +++ /dev/null @@ -1,20366 +0,0 @@ - -Index: include/linux/packet_anno.h ---- include/linux/packet_anno.h.orig 2003-08-12 14:10:54.000000000 -0400 -+++ include/linux/packet_anno.h 2003-07-21 02:00:58.000000000 -0400 -@@ -0,0 +1,73 @@ -+#ifndef PACKET_ANNO_H -+#define PACKET_ANNO_H -+/* -+ * Click packet annotations. -+ */ -+ -+#include -+ -+enum { ADDR_ANNO_SIZE = 16 }; -+ -+enum { USER_ANNO_SIZE = 24, -+ USER_ANNO_US_SIZE = 12, -+ USER_ANNO_S_SIZE = 12, -+ USER_ANNO_U_SIZE = 6, -+ USER_ANNO_I_SIZE = 6 }; -+ -+// Anno must fit in sk_buff's char cb[48]. -+struct Anno { -+ union { -+ uint8_t c[ADDR_ANNO_SIZE]; -+ uint32_t ip4; -+ } addr; -+ -+ union { -+ uint8_t c[USER_ANNO_SIZE]; -+ uint16_t us[USER_ANNO_US_SIZE]; -+ int16_t s[USER_ANNO_S_SIZE]; -+ uint32_t u[USER_ANNO_U_SIZE]; -+ int32_t i[USER_ANNO_I_SIZE]; -+ } user; -+ uint64_t perfctr; -+}; -+ -+ -+struct Anno *anno(struct sk_buff *skb) {return (struct Anno *) skb->cb; } -+ -+ -+uint8_t user_anno_c(struct sk_buff *skb, int i) { return anno(skb)->user.c[i]; } -+void set_user_anno_c(struct sk_buff *skb, int i, uint8_t v) { anno(skb)->user.c[i] = v; } -+uint16_t user_anno_us(struct sk_buff *skb, int i) { return anno(skb)->user.us[i]; } -+void set_user_anno_us(struct sk_buff *skb, int i, uint16_t v) { anno(skb)->user.us[i] = v; } -+int16_t user_anno_s(struct sk_buff *skb, int i) { return anno(skb)->user.us[i]; } -+void set_user_anno_s(struct sk_buff *skb, int i, int16_t v) { anno(skb)->user.s[i] = v; } -+uint32_t user_anno_u(struct sk_buff *skb, int i) { return anno(skb)->user.u[i]; } -+void set_user_anno_u(struct sk_buff *skb, int i, uint32_t v) { anno(skb)->user.u[i] = v; } -+int32_t user_anno_i(struct sk_buff *skb, int i) { return anno(skb)->user.i[i]; } -+void set_user_anno_i(struct sk_buff *skb, int i, int32_t v) { anno(skb)->user.i[i] = v; } -+ -+ -+ -+#define WIFI_FROM_CLICK(p) (user_anno_c(p, 9) == 0xaa) -+#define SET_WIFI_FROM_CLICK(p) (set_user_anno_c(p, 9, (0xaa))) -+ -+#define WIFI_TX_SUCCESS_ANNO(p) (user_anno_c(p, 10)) -+#define SET_WIFI_TX_SUCCESS_ANNO(p, v) (set_user_anno_c(p, 10, (v))) -+ -+#define WIFI_TX_POWER_ANNO(p) (user_anno_c(p, 11)) -+#define SET_WIFI_TX_POWER_ANNO(p, v) (set_user_anno_c(p, 11, (v))) -+ -+#define WIFI_RATE_ANNO(p) (user_anno_c(p, 12)) -+#define SET_WIFI_RATE_ANNO(p, v) (set_user_anno_c(p, 12, (v))) -+ -+#define WIFI_RETRIES_ANNO(p) (user_anno_c(p, 13)) -+#define SET_WIFI_RETRIES_ANNO(p, v) (set_user_anno_c(p, 13, (v))) -+ -+#define WIFI_SIGNAL_ANNO(p) (user_anno_c(p, 14)) -+#define SET_WIFI_SIGNAL_ANNO(p, v) (set_user_anno_c(p, 14, (v))) -+ -+#define WIFI_NOISE_ANNO(p) (user_anno_c(p, 15)) -+#define SET_WIFI_NOISE_ANNO(p, v) (set_user_anno_c(p, 15, (v))) -+ -+ -+#endif /* PACKET_ANNO_H */ - -Index: include/linux/click_wifi.h ---- include/linux/click_wifi.h.orig 2003-08-12 14:10:32.000000000 -0400 -+++ include/linux/click_wifi.h 2003-08-08 22:39:41.000000000 -0400 -@@ -0,0 +1,27 @@ -+#ifndef CLICK_WIFI_H -+#define CLICK_WIFI_H -+ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif /* __cplusplus */ -+ -+ -+/* begin click callbacks */ -+typedef int (*tx_ev_cb)(struct sk_buff *, void *arg); -+typedef int (*rx_fcserr_cb)(struct sk_buff *, void *arg); -+ -+extern int register_click_wifi_tx_cb (tx_ev_cb cb, void *arg); -+extern void click_wifi_tx_ev(struct sk_buff *skb); -+ -+extern int register_click_wifi_rx_fcserr_cb(rx_fcserr_cb cb, void *arg); -+extern void click_wifi_rx_fcserr(struct sk_buff *skb); -+/* end click callbacks */ -+ -+ -+#ifdef __cplusplus -+} -+#endif /* __cplusplus */ -+ -+ -+#endif /* CLICK_WIFI_H */ - -Index: drivers/net/wireless/click_wifi.c ---- drivers/net/wireless/click_wifi.c.orig 2003-08-12 14:11:22.000000000 -0400 -+++ drivers/net/wireless/click_wifi.c 2003-08-12 15:33:21.000000000 -0400 -@@ -0,0 +1,99 @@ -+#include -+#include -+#include /* Not needed ??? */ -+#include /* Not needed ??? */ -+#include /* off_t */ -+ -+/* support for callbacks for transmission feedback --------------------------------------------- */ -+ -+tx_ev_cb click_cb; -+void *click_arg; -+ -+int -+register_click_wifi_tx_cb (tx_ev_cb cb, void *arg) -+{ -+ if (cb) { -+ printk (KERN_WARNING "click_wifi: registering tx callback %ld\n", (long)(cb)); -+ } else { -+ printk (KERN_WARNING "click_wifi: unregistering tx callback\n"); -+ } -+ -+ click_cb = cb; -+ click_arg = arg; -+ return 0; -+} -+ -+void -+click_wifi_tx_ev(struct sk_buff *skb) -+{ -+ if (click_cb != NULL) { -+ click_cb (skb, click_arg); -+ } else { -+ dev_kfree_skb(skb); -+ } -+} -+ -+ -+/* support for callbacks for receiving broken frames --------------------------------------------- */ -+ -+rx_fcserr_cb click_rx_fcserr_cb; -+void * click_rx_fcserr_arg; -+ -+int -+register_click_wifi_rx_fcserr_cb(rx_fcserr_cb cb, void *arg) -+{ -+ if (cb) { -+ printk (KERN_WARNING "click_wifi: registering callback for receiving broken frames %ld\n", (long)(cb)); -+ } else { -+ printk (KERN_WARNING "click_wifi: unregistering broken frame rx callback\n"); -+ } -+ -+ click_rx_fcserr_cb = cb; -+ click_rx_fcserr_arg = arg; -+ return 0; -+} -+ -+void click_wifi_rx_fcserr(struct sk_buff *skb) -+{ -+ if (click_rx_fcserr_cb != NULL) { -+ click_rx_fcserr_cb(skb, click_rx_fcserr_arg); -+ } else { -+ dev_kfree_skb(skb); -+ } -+} -+ -+/* init stuff */ -+ -+static int -+__init click_wifi_init(void) -+{ -+ click_cb = NULL; -+ click_arg = NULL; -+ -+ click_rx_fcserr_cb = NULL; -+ click_rx_fcserr_arg = NULL; -+ -+ return 0; -+} -+ -+static void -+__exit click_wifi_exit(void) -+{ -+ click_cb = NULL; -+ click_arg = NULL; -+ -+ click_rx_fcserr_cb = NULL; -+ click_rx_fcserr_arg = NULL; -+} -+EXPORT_SYMBOL(click_wifi_tx_ev); -+EXPORT_SYMBOL(register_click_wifi_tx_cb); -+ -+EXPORT_SYMBOL(click_wifi_rx_fcserr); -+EXPORT_SYMBOL(register_click_wifi_rx_fcserr_cb); -+ -+module_init(click_wifi_init); -+module_exit(click_wifi_exit); -+ -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("Dual BSD/GPL"); -+#endif - -Index: drivers/net/wireless/airo.h ---- drivers/net/wireless/airo.h.orig 2003-08-12 15:07:01.000000000 -0400 -+++ drivers/net/wireless/airo.h 2003-06-09 13:30:25.000000000 -0400 -@@ -0,0 +1,270 @@ -+/* This is a really ugly header file! The objective is to keep airo.c as -+ * close as possible to what's in the 2.4 kernel. Basically we want to -+ * support the use of airo.c with the latest pcmcia-cs and the 2.0 and 2.2 -+ * stable kernels. Basically we end up with ugly hacks to insert code into -+ * airo.c without having to put ifdefs into airo.c. -+ */ -+#if LINUX_VERSION_CODE < 0x20400 -+#define __devinitdata -+#define __devinit -+ -+#ifdef CONFIG_PCI -+#define PCI_ANY_ID 0 -+struct pci_device_id { -+ unsigned short vendor; -+ unsigned short id; -+ unsigned short fill1; -+ unsigned short fill2; -+}; -+ -+struct pci_driver { -+ char *name; -+ struct pci_device_id *id_table; -+ int(*probe)(struct pci_dev *, const struct pci_device_id *); -+ void(*remove)(struct pci_dev *); -+}; -+#endif -+ -+#define driver_data sysdata -+ -+#define MODULE_DEVICE_TABLE(x,y) -+ -+#define del_timer_sync(x) del_timer(x) -+ -+#define alloc_etherdev(x) init_etherdev(0, x) -+/* init_etherdev does it... */ -+#define register_netdev(x) 0 -+ -+/* Before 2.4 this was a void function, so we gotta fake it if we are -+ compiling with an older kernel. */ -+static inline int bogo_request_region(unsigned long x, unsigned long y, -+ const char *z) { -+ request_region(x, y, z); -+ return 1; -+} -+ -+#define request_region(x,y,z) bogo_request_region(x,y,z) -+ -+#define SET_MODULE_OWNER(x) -+ -+#define proc_root_driver &proc_root -+ -+static int airo_pci_probe(struct pci_dev *a, const struct pci_device_id *b) -+{return 0;} -+static void airo_pci_remove(struct pci_dev *c) {} -+ -+#define set_current_state(x) current->state = x -+ -+#if LINUX_VERSION_CODE < 0x20200 -+#include -+#define get_user_bogus(x,y) ((x) = get_fs_byte(y))&0 -+#undef get_user -+#define get_user(x,y) get_user_bogus(x,y) -+#define pci_module_init(k) (int)k&0; \ -+{\ -+ int j;\ -+ unsigned char bus, fun;\ -+\ -+ for( j = 0; j < 4; j++ ) { \ -+ unsigned char irq;\ -+ unsigned int io;\ -+ if (pcibios_find_device(card_ids[i].vendor, card_ids[i].id, j, \ -+ &bus, &fun ) != PCIBIOS_SUCCESSFUL ) \ -+ break;\ -+ pcibios_read_config_byte(bus, fun, PCI_INTERRUPT_LINE, &irq);\ -+ pcibios_read_config_dword(bus, fun, PCI_BASE_ADDRESS_2, &io);\ -+ io &= PCI_BASE_ADDRESS_IO_MASK;\ -+ init_airo_card( irq, io, 0 );\ -+ }\ -+} -+#define MODULE_PARM_DESC(x,y) -+ -+/* We don't support SMP on 2.0, so we just stub out the spinlocks */ -+#define spinlock_t int -+#define spin_lock_irqsave(x,y) y=1 -+#define spin_unlock_irqrestore(x,y) y=1 -+#define SPIN_LOCK_UNLOCKED 1 -+ -+static void schedule_timeout(long to) { -+ current->timeout = to + jiffies; -+ schedule(); -+ current->timeout = 0; -+} -+ -+static inline void dev_kfree_skb_bogus(struct sk_buff *skb) { -+ dev_kfree_skb(skb, FREE_WRITE); -+} -+ -+#define dev_kfree_skb(x) dev_kfree_skb_bogus(x) -+static int in_interrupt(void) { return 0; } -+static inline int timer_pending(struct timer_list *ti) {return (int)ti->next;} -+ -+#define capable(x) suser() -+ -+/* Ah it's magical! There was a big change of the signatures of these -+ callbacks between 2.0 and 2.2. */ -+typedef struct file_operations file_operations_t; -+#define file_operations bogus_file_operations -+struct file_operations { -+ file_operations_t real_ops; -+ struct inode_operations i_ops; -+ int (*open)( struct inode *inode, struct file *file ); -+ ssize_t (*read)(struct file *file, char *buffer, -+ size_t len, loff_t *offset); -+ ssize_t (*write)(struct file *file, const char *buffer, -+ size_t len, loff_t *offset ); -+ int (*release)(struct inode *inode, struct file *file ); -+}; -+ -+static int open_redirect( struct inode *inode, struct file *file ) { -+ return ((struct file_operations*)file->f_op)->open(inode, file); -+} -+static int read_redirect( struct inode *inode, struct file *file, -+ char *buffer, int len ) { -+ return ((struct file_operations*)file->f_op)-> -+ read(file, buffer, len, &file->f_pos); -+} -+static int write_redirect( struct inode *inode, struct file *file, -+ const char *buffer, int len ) { -+ return ((struct file_operations*)file->f_op)-> -+ write(file, buffer, len, &file->f_pos); -+} -+static void release_redirect( struct inode *inode, struct file *file ) { -+ ((struct file_operations*)file->f_op)->release(inode, file); -+} -+ -+static inline int check_match(int len, const char *name, -+ struct proc_dir_entry *pde) -+{ -+ if (len != pde->namelen) return 0; -+ return !memcmp(pde->name, name, len); -+} -+ -+static struct proc_dir_entry *my_proc_lookup(struct proc_dir_entry *parent, -+ const char *name) -+{ -+ struct proc_dir_entry *pde = parent->subdir; -+ int len = strlen(name); -+ while(pde) { -+ if (pde->low_ino && check_match(len, name, pde)) return pde; -+ pde = pde->next; -+ } -+ return 0; -+} -+static void remove_proc_entry(const char *name, struct proc_dir_entry *parent) -+{ -+ struct proc_dir_entry *pde = my_proc_lookup(parent, name); -+ if (!pde) return; -+ proc_unregister(parent, pde->low_ino); -+ kfree(pde); -+} -+ -+static struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, -+ struct proc_dir_entry *parent) -+{ -+ struct proc_dir_entry *pde = my_proc_lookup(parent, name); -+ int flen = strlen(name); -+ if (!pde) { -+ pde = (struct proc_dir_entry *)kmalloc(sizeof(*pde)+flen+1, -+ GFP_KERNEL); -+ if (!pde) return 0; -+ memset(pde, 0, sizeof(*pde)); -+ pde->name = (const char*)&pde[1]; -+ strcpy((char*)pde->name, name); -+ pde->namelen = flen; -+ proc_register_dynamic(parent, pde); -+ } -+ pde->mode = mode; -+ pde->nlink = S_ISDIR(mode) ? 2 : 1; -+ if (S_ISDIR(mode)) { -+ pde->ops = proc_net.ops; -+ } -+ return pde; -+} -+ -+static inline int put_user_bogus(char c, char *ptr) { -+ put_user(c, ptr); -+ return 0; -+} -+#include -+static inline void mdelay(long x) { udelay(x*1000); } -+#undef put_user -+#define put_user(x,y) put_user_bogus(x,y) -+static void my_setproc_ops(struct proc_dir_entry *pde, -+ struct file_operations *fops) -+{ -+ memset(&fops->i_ops, 0, sizeof(fops->i_ops)); -+ pde->ops = &fops->i_ops; -+ fops->i_ops.default_file_ops = (file_operations_t*)fops; -+ fops->real_ops.open = open_redirect; -+ fops->real_ops.read = read_redirect; -+ fops->real_ops.write = write_redirect; -+ fops->real_ops.release = release_redirect; -+} -+ -+#define SETPROC_OPS(entry, fops) my_setproc_ops(entry, &fops) -+ -+#else -+/* Here are the 2.2 specific hacks */ -+#define pci_module_init(k) \ -+ 0; \ -+ for( i = 0; card_ids[i].vendor; i++ ) { \ -+ struct pci_dev *dev = 0; \ -+ while((dev=pci_find_device(card_ids[i].vendor, card_ids[i].id,\ -+ dev))) { \ -+ init_airo_card( dev->irq, \ -+ dev->base_address[2] & \ -+ PCI_BASE_ADDRESS_IO_MASK, 0 \ -+ ); \ -+ } \ -+ } -+#define SETPROC_OPS(entry, fops) (entry)->ops = &(inode_##fops) -+ -+static struct file_operations proc_statsdelta_ops; -+static struct inode_operations inode_proc_statsdelta_ops = { -+ &proc_statsdelta_ops}; -+ -+static struct file_operations proc_stats_ops; -+static struct inode_operations inode_proc_stats_ops = { -+ &proc_stats_ops}; -+ -+static struct file_operations proc_status_ops; -+static struct inode_operations inode_proc_status_ops = { -+ &proc_status_ops}; -+ -+static struct file_operations proc_SSID_ops; -+static struct inode_operations inode_proc_SSID_ops = { -+ &proc_SSID_ops}; -+ -+static struct file_operations proc_APList_ops; -+static struct inode_operations inode_proc_APList_ops = { -+ &proc_APList_ops}; -+ -+static struct file_operations proc_BSSList_ops; -+static struct inode_operations inode_proc_BSSList_ops = { -+ &proc_BSSList_ops}; -+ -+static struct file_operations proc_config_ops; -+static struct inode_operations inode_proc_config_ops = { -+ &proc_config_ops}; -+ -+static struct file_operations proc_wepkey_ops; -+static struct inode_operations inode_proc_wepkey_ops = { -+ &proc_wepkey_ops}; -+#endif -+#endif -+ -+#ifndef ARPHRD_IEEE80211 -+#define ARPHRD_IEEE80211 801 -+#endif -+ -+#if LINUX_VERSION_CODE <= 0x20409 -+#ifdef min -+#undef min -+#endif -+#define min(x,y) (((x)<(y))?x:y) -+#endif -+ -+#ifndef MODULE_LICENSE -+#define MODULE_LICENSE(x) -+#endif - -Index: drivers/net/wireless/airo.c ---- drivers/net/wireless/airo.c.orig 2003-08-12 14:28:03.000000000 -0400 -+++ drivers/net/wireless/airo.c 2003-08-12 15:40:51.000000000 -0400 -@@ -44,7 +44,12 @@ - #include - #include - #include -+#include -+#include - #include -+#include "airo.h" -+ -+#define WEXT_USECHANNELS /* grid */ - - #ifdef CONFIG_PCI - static struct pci_device_id card_ids[] __devinitdata = { -@@ -71,6 +76,11 @@ - /* Include Wireless Extension definition and check version - Jean II */ - #include - #define WIRELESS_SPY // enable iwspy support -+#if WIRELESS_EXT < 9 -+#warning "Wireless extension v9 or newer required - please upgrade your kernel" -+#undef WIRELESS_EXT -+#undef WIRELESS_SPY -+#endif - #if WIRELESS_EXT > 12 - #include // New driver API - #endif /* WIRELESS_EXT > 12 */ -@@ -86,7 +96,7 @@ - aes.h, aestab.h and mic.h files from the CVS at - http://sf.net/projects/airo-linux/ Put the files in the same directory - as airo.c and compile normally */ --#undef MICSUPPORT -+/* #define MICSUPPORT */ - - /* Hack to do some power saving */ - #define POWER_ON_DOWN -@@ -635,7 +645,7 @@ - u8 mac[ETH_ALEN]; - u16 mode; - u16 errorCode; -- u16 sigQuality; -+ u16 curSignalStrength; - u16 SSIDlen; - char SSID[32]; - char apName[16]; -@@ -654,9 +664,38 @@ - u16 currentXmitRate; - u16 apDevExtensions; - u16 normalizedSignalStrength; -- u16 _reserved1; -+ u16 shortPreamble; - u8 apIP[4]; -- u16 _reserved[7]; -+ u8 noisePercent; /* Noise percent in last second */ -+ u8 noisedBm; /* Noise dBm in last second */ -+ u8 noiseAvePercent; /* Noise percent in last minute */ -+ u8 noiseAvedBm; /* Noise dBm in last minute */ -+ u8 noiseMaxPercent; /* Highest noise percent in last minute */ -+ u8 noiseMaxdBm; /* Highest noise dbm in last minute */ -+ u16 load; -+ u8 carrier[4]; -+ u16 assocStatus; -+#define STAT_NOPACKETS 0 -+#define STAT_NOCARRIERSET 10 -+#define STAT_GOTCARRIERSET 11 -+#define STAT_WRONGSSID 20 -+#define STAT_BADCHANNEL 25 -+#define STAT_BADBITRATES 30 -+#define STAT_BADPRIVACY 35 -+#define STAT_APFOUND 40 -+#define STAT_APREJECTED 50 -+#define STAT_AUTHENTICATING 60 -+#define STAT_DEAUTHENTICATED 61 -+#define STAT_AUTHTIMEOUT 62 -+#define STAT_ASSOCIATING 70 -+#define STAT_DEASSOCIATED 71 -+#define STAT_ASSOCTIMEOUT 72 -+#define STAT_NOTAIROAP 73 -+#define STAT_ASSOCIATED 80 -+#define STAT_LEAPING 90 -+#define STAT_LEAPFAILED 91 -+#define STAT_LEAPTIMEDOUT 92 -+#define STAT_LEAPCOMPLETE 93 - } StatusRid; - - typedef struct { -@@ -921,7 +960,7 @@ - #endif /* WIRELESS_EXT > 12 */ - #endif /* WIRELESS_EXT */ - --static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)"; -+static const char version[] = "$Revision: 1.1 $"; - - struct airo_info; - -@@ -929,8 +968,8 @@ - static void OUT4500( struct airo_info *, u16 register, u16 value ); - static unsigned short IN4500( struct airo_info *, u16 register ); - static u16 setup_card(struct airo_info*, u8 *mac); --static int enable_MAC( struct airo_info *ai, Resp *rsp ); --static void disable_MAC(struct airo_info *ai); -+static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ); -+static void disable_MAC(struct airo_info *ai, int lock); - static void enable_interrupts(struct airo_info*); - static void disable_interrupts(struct airo_info*); - static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); -@@ -944,11 +983,11 @@ - static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen, - int whichbap); - static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd); --static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len); -+static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock); - static int PC4500_writerid(struct airo_info*, u16 rid, const void -- *pBuf, int len); -+ *pBuf, int len, int lock); - static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, -- int len ); -+ int len, int dummy ); - static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw); - static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket); - static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket); -@@ -979,6 +1018,7 @@ - use the high bit to mark wether it is in use. */ - #define MAX_FIDS 6 - int fids[MAX_FIDS]; -+ struct sk_buff *txskb[MAX_FIDS]; - int registered; - ConfigRid config; - int need_commit; // Need to set config -@@ -992,7 +1032,6 @@ - #define FLAG_PROMISC IFF_PROMISC /* 0x100 - include/linux/if.h */ - #define FLAG_RADIO_OFF 0x02 /* User disabling of MAC */ - #define FLAG_RADIO_DOWN 0x08 /* ifup/ifdown disabling of MAC */ --#define FLAG_LOCKED 2 /* 0x04 - use as a bit offset */ - #define FLAG_FLASHING 0x10 - #define FLAG_ADHOC 0x01 /* Needed by MIC */ - #define FLAG_MIC_CAPABLE 0x20 -@@ -1005,6 +1044,7 @@ - tdsRssiEntry *rssi; - struct semaphore sem; - struct task_struct *task; -+ struct tq_struct stats_task; - struct tq_struct promisc_task; - struct { - struct sk_buff *skb; -@@ -1042,6 +1082,8 @@ - #include "mic.h" - #endif - -+ -+ - static int readBSSListRid(struct airo_info *ai, int first, - BSSListRid *list) { - int rc; -@@ -1062,7 +1104,7 @@ - ai->task = NULL; - } - rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, -- list, sizeof(*list)); -+ list, sizeof(*list), 1); - - list->len = le16_to_cpu(list->len); - list->index = le16_to_cpu(list->index); -@@ -1077,7 +1119,7 @@ - - static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) { - int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, -- wkr, sizeof(*wkr)); -+ wkr, sizeof(*wkr), 1); - - wkr->len = le16_to_cpu(wkr->len); - wkr->kindex = le16_to_cpu(wkr->kindex); -@@ -1086,17 +1128,17 @@ - } - /* In the writeXXXRid routines we copy the rids so that we don't screwup - * the originals when we endian them... */ --static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) { -+static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) { - int rc; - WepKeyRid wkr = *pwkr; - - wkr.len = cpu_to_le16(wkr.len); - wkr.kindex = cpu_to_le16(wkr.kindex); - wkr.klen = cpu_to_le16(wkr.klen); -- rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr)); -+ rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); - if (perm) { -- rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr)); -+ rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) { - printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); - } -@@ -1106,7 +1148,7 @@ - - static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { - int i; -- int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr)); -+ int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); - - ssidr->len = le16_to_cpu(ssidr->len); - for(i = 0; i < 3; i++) { -@@ -1123,10 +1165,10 @@ - for(i = 0; i < 3; i++) { - ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len); - } -- rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr)); -+ rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), 1); - return rc; - } --static int readConfigRid(struct airo_info*ai) { -+static int readConfigRid(struct airo_info*ai, int lock) { - int rc; - u16 *s; - ConfigRid cfg; -@@ -1134,7 +1176,7 @@ - if (ai->config.len) - return SUCCESS; - -- rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg)); -+ rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock); - if (rc != SUCCESS) - return rc; - -@@ -1163,7 +1205,7 @@ - } - } - } --static int writeConfigRid(struct airo_info*ai) { -+static int writeConfigRid(struct airo_info*ai, int lock) { - u16 *s; - ConfigRid cfgr; - -@@ -1190,33 +1232,34 @@ - for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++) - *s = cpu_to_le16(*s); - -- return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr)); -+ return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); - } - static int readStatusRid(struct airo_info*ai, StatusRid *statr) { -- int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr)); -+ int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), 1); - u16 *s; - - statr->len = le16_to_cpu(statr->len); - for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s); - -- for(s = &statr->beaconPeriod; s <= &statr->_reserved[9]; s++) -+ for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++) - *s = le16_to_cpu(*s); -- -+ statr->load = le16_to_cpu(statr->load); -+ statr->assocStatus = le16_to_cpu(statr->assocStatus); - return rc; - } - static int readAPListRid(struct airo_info*ai, APListRid *aplr) { -- int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr)); -+ int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); - aplr->len = le16_to_cpu(aplr->len); - return rc; - } - static int writeAPListRid(struct airo_info*ai, APListRid *aplr) { - int rc; - aplr->len = cpu_to_le16(aplr->len); -- rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr)); -+ rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); - return rc; - } - static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) { -- int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr)); -+ int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), 1); - u16 *s; - - capr->len = le16_to_cpu(capr->len); -@@ -1227,8 +1270,8 @@ - *s = le16_to_cpu(*s); - return rc; - } --static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid) { -- int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr)); -+static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) { -+ int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); - u32 *i; - - sr->len = le16_to_cpu(sr->len); -@@ -1248,8 +1291,8 @@ - * is open (to pipeline changes and speed-up card setup). If - * those changes are not yet commited, do it now - Jean II */ - if(info->need_commit) { -- disable_MAC(info); -- writeConfigRid(info); -+ disable_MAC(info, 1); -+ writeConfigRid(info, 1); - } - - if (info->wifidev != dev) { -@@ -1257,14 +1300,19 @@ - info->flags &= ~FLAG_RADIO_DOWN; - enable_interrupts(info); - } -- enable_MAC(info, &rsp); -+ enable_MAC(info, &rsp, 1); - - netif_start_queue(dev); -+#if LINUX_VERSION_CODE < 0x020400 -+ MOD_INC_USE_COUNT; -+ netif_mark_up(dev); -+#endif - return 0; - } - - static void get_tx_error(struct airo_info *ai, u32 fid) - { -+#if LINUX_VERSION_CODE > 0x20200 - u16 status; - - if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) == SUCCESS) { -@@ -1310,6 +1358,7 @@ - } - #endif /* WIRELESS_EXT > 13 */ - } -+#endif - } - - static void airo_do_xmit(struct net_device *dev) { -@@ -1332,17 +1381,24 @@ - - i = 0; - if ( status == SUCCESS ) { -- dev->trans_start = jiffies; -- for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); -+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); -+ priv->txskb[fid] = skb2; -+ -+ dev->trans_start = jiffies; -+ for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); - } else { - priv->fids[fid] &= 0xffff; -+#if LINUX_VERSION_CODE > 0x20200 - priv->stats.tx_window_errors++; -+#endif - } -+ -+ dev_kfree_skb(skb); -+ - if (i < MAX_FIDS / 2) - netif_wake_queue(dev); - else - netif_stop_queue(dev); -- dev_kfree_skb(skb); - } - - static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { -@@ -1360,7 +1416,9 @@ - for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); - - if ( i == MAX_FIDS / 2 ) { -+#if LINUX_VERSION_CODE > 0x20200 - priv->stats.tx_fifo_errors++; -+#endif - dev_kfree_skb(skb); - } else { - /* check min length*/ -@@ -1394,17 +1452,22 @@ - - i = MAX_FIDS / 2; - if ( status == SUCCESS ) { -- dev->trans_start = jiffies; -- for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); -+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); -+ priv->txskb[fid] = skb2; -+ -+ dev->trans_start = jiffies; -+ for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); - } else { - priv->fids[fid] &= 0xffff; - priv->stats.tx_window_errors++; - } -+ -+ dev_kfree_skb(skb); -+ - if (i < MAX_FIDS) - netif_wake_queue(dev); - else - netif_stop_queue(dev); -- dev_kfree_skb(skb); - } - - static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { -@@ -1436,29 +1499,47 @@ - return 0; - } - --struct net_device_stats *airo_get_stats(struct net_device *dev) --{ -- struct airo_info *local = dev->priv; -+static void airo_read_stats(struct airo_info *ai) { - StatsRid stats_rid; - u32 *vals = stats_rid.vals; - -- /* Get stats out of the card */ -- readStatsRid(local, &stats_rid, RID_STATS); -+ if (down_trylock(&ai->sem) == 0) { -+ readStatsRid(ai, &stats_rid, RID_STATS, 0); -+ up(&ai->sem); -+ -+ ai->stats.rx_packets = vals[43] + vals[44] + vals[45]; -+ ai->stats.tx_packets = vals[39] + vals[40] + vals[41]; -+ ai->stats.rx_bytes = vals[92]; -+ ai->stats.tx_bytes = vals[91]; -+ ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; -+ ai->stats.tx_errors = vals[42] -+#if LINUX_VERSION_CODE > 0x20200 -+ + ai->stats.tx_fifo_errors -+#endif -+ ; -+ ai->stats.multicast = vals[43]; -+ ai->stats.collisions = vals[89]; -+ -+#if LINUX_VERSION_CODE > 0x20200 -+ /* detailed rx_errors: */ -+ ai->stats.rx_length_errors = vals[3]; -+ ai->stats.rx_crc_errors = vals[4]; -+ ai->stats.rx_frame_errors = vals[2]; -+ ai->stats.rx_fifo_errors = vals[0]; -+#endif -+ } else { -+ ai->stats_task.routine = (void (*)(void *))airo_read_stats; -+ ai->stats_task.data = (void *)ai; -+ schedule_task(&ai->stats_task); -+ } -+} -+ -+struct net_device_stats *airo_get_stats(struct net_device *dev) -+{ -+ struct airo_info *local = dev->priv; - -- local->stats.rx_packets = vals[43] + vals[44] + vals[45]; -- local->stats.tx_packets = vals[39] + vals[40] + vals[41]; -- local->stats.rx_bytes = vals[92]; -- local->stats.tx_bytes = vals[91]; -- local->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; -- local->stats.tx_errors = vals[42] + local->stats.tx_fifo_errors; -- local->stats.multicast = vals[43]; -- local->stats.collisions = vals[89]; -- -- /* detailed rx_errors: */ -- local->stats.rx_length_errors = vals[3]; -- local->stats.rx_crc_errors = vals[4]; -- local->stats.rx_frame_errors = vals[2]; -- local->stats.rx_fifo_errors = vals[0]; -+ /* Get stats out of the card if available */ -+ airo_read_stats(local); - - return &local->stats; - } -@@ -1513,9 +1594,9 @@ - - memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); - ai->need_commit = 1; -- disable_MAC(ai); -- writeConfigRid (ai); -- enable_MAC(ai, &rsp); -+ disable_MAC(ai, 1); -+ writeConfigRid (ai, 1); -+ enable_MAC(ai, &rsp, 1); - memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); - if (ai->wifidev) - memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len); -@@ -1535,6 +1616,10 @@ - struct airo_info *ai = dev->priv; - - netif_stop_queue(dev); -+#if LINUX_VERSION_CODE < 0x020400 -+ MOD_DEC_USE_COUNT; -+ netif_mark_down(dev); -+#endif - - if (ai->wifidev != dev) { - #ifdef POWER_ON_DOWN -@@ -1544,7 +1629,7 @@ - * stack (i.e. the network stack won't try to broadcast - * anything on the interface and routes are gone. Jean II */ - ai->flags |= FLAG_RADIO_DOWN; -- disable_MAC(ai); -+ disable_MAC(ai, 1); - #endif - disable_interrupts( ai ); - } -@@ -1725,7 +1810,8 @@ - ai->wifidev = init_wifidev(ai, dev); - - ai->registered = 1; -- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", -+ printk( KERN_INFO "airo: (Grid hacks: MAX_SPY=%d) MAC enabled %s %x:%x:%x:%x:%x:%x\n", -+ IW_MAX_SPY, - dev->name, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] ); -@@ -1768,6 +1854,9 @@ - int i; - struct airo_info *ai = dev->priv; - -+ -+ if (down_interruptible(&ai->sem)) -+ return -1; - waitbusy (ai); - OUT4500(ai,COMMAND,CMD_SOFTRESET); - set_current_state (TASK_UNINTERRUPTIBLE); -@@ -1777,9 +1866,10 @@ - schedule_timeout (HZ/5); - if ( setup_card(ai, dev->dev_addr ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); -+ up(&ai->sem); - return -1; - } else { -- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", -+ printk( KERN_INFO "airo: MAC enabled (Grid hacks) %s %x:%x:%x:%x:%x:%x\n", - dev->name, - dev->dev_addr[0], - dev->dev_addr[1], -@@ -1794,6 +1884,7 @@ - } - enable_interrupts( ai ); - netif_wake_queue(dev); -+ up(&ai->sem); - return 0; - } - -@@ -1806,9 +1897,7 @@ - StatusRid status_rid; - - if (down_trylock(&ai->sem) == 0) { -- __set_bit(FLAG_LOCKED, &ai->flags); -- PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid)); -- clear_bit(FLAG_LOCKED, &ai->flags); -+ PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); - up(&ai->sem); - wrqu.data.length = 0; - wrqu.data.flags = 0; -@@ -1829,9 +1918,7 @@ - MICRid mic_rid; - - if (down_trylock(&ai->sem) == 0) { -- __set_bit(FLAG_LOCKED, &ai->flags); -- PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid)); -- clear_bit(FLAG_LOCKED, &ai->flags); -+ PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); - up(&ai->sem); - #ifdef MICSUPPORT - micinit (ai, &mic_rid); -@@ -1869,7 +1956,8 @@ - - if ( status & EV_MIC ) { - OUT4500( apriv, EVACK, EV_MIC ); -- airo_read_mic( apriv ); -+ if (apriv->flags & FLAG_MIC_CAPABLE) -+ airo_read_mic( apriv ); - } - if ( status & EV_LINK ) { - #if WIRELESS_EXT > 13 -@@ -1966,7 +2054,7 @@ - #pragma pack() - u16 gap; - u16 tmpbuf[4]; -- u16 *buffer; -+ u16 *buffer = NULL; - - fid = IN4500( apriv, RXFID ); - -@@ -2078,7 +2166,7 @@ - if (apriv->rssi) - apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; - else -- apriv->spy_stat[i].level = (hdr.rssi[1] + 321) / 2; -+ apriv->spy_stat[i].level = (hdr.rssi[1]) + 0x100 - 100; - apriv->spy_stat[i].noise = 0; - apriv->spy_stat[i].updated = 3; - break; -@@ -2116,17 +2204,41 @@ - if ( ( apriv->fids[i] & 0xffff ) == fid ) { - len = apriv->fids[i] >> 16; - index = i; -- /* Set up to be used again */ -- apriv->fids[i] &= 0xffff; - } - } - if (index != -1) { -- netif_wake_queue(dev); -+ -+ { -+ /* click callbacks */ -+ char res[16]; -+ if (bap_setup(apriv, apriv->fids[index] & 0xffff, 0x0, BAP0) == SUCCESS) { -+ bap_read(apriv, (u16 *)res, 16, BAP0); // get result header including retry counters, etc. -+ // printk (KERN_WARNING "airo: tx retry counters: %d %d\n", -+ // le16_to_cpu(ctrs) >> 8, le16_to_cpu(ctrs) & 0xff); -+ int success = !((unsigned char) res[0x04] & (0x02 || 0x04)); -+ int rate = ((unsigned char) res[0x08]); -+ int short_retries = ((unsigned char) res[0x0C]); -+ //int long_retries = ((unsigned char) res[0x0D]); -+ struct sk_buff *skbfoo = apriv->txskb[index]; -+ apriv->txskb[index] = NULL; -+ -+ SET_WIFI_TX_SUCCESS_ANNO(skbfoo, success); -+ SET_WIFI_RATE_ANNO(skbfoo, rate); -+ SET_WIFI_RETRIES_ANNO(skbfoo, short_retries); -+ click_wifi_tx_ev(skbfoo); -+ } -+ } -+ -+#if LINUX_VERSION_CODE > 0x20200 - if (status & EV_TXEXC) - get_tx_error(apriv, index); -- } -- OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); -- if (index==-1) { -+#endif -+ OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); -+ /* Set up to be used again */ -+ apriv->fids[index] &= 0xffff; -+ netif_wake_queue(dev); -+ } else { -+ OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); - printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); - } - } -@@ -2172,7 +2284,7 @@ - return rc; - } - --static int enable_MAC( struct airo_info *ai, Resp *rsp ) { -+static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { - int rc; - Cmd cmd; - -@@ -2185,7 +2297,7 @@ - if (ai->flags & (FLAG_RADIO_OFF|FLAG_RADIO_DOWN)) return SUCCESS; - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = MAC_ENABLE; -- if (test_bit(FLAG_LOCKED, &ai->flags) != 0) -+ if (!lock) - return issuecommand(ai, &cmd, rsp); - - if (down_interruptible(&ai->sem)) -@@ -2195,13 +2307,13 @@ - return rc; - } - --static void disable_MAC( struct airo_info *ai ) { -+static void disable_MAC( struct airo_info *ai, int lock ) { - Cmd cmd; - Resp rsp; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = MAC_DISABLE; // disable in case already enabled -- if (test_bit(FLAG_LOCKED, &ai->flags) != 0) { -+ if (!lock) { - issuecommand(ai, &cmd, &rsp); - return; - } -@@ -2279,18 +2391,19 @@ - CapabilityRid cap_rid; - - // general configuration (read/modify/write) -- status = readConfigRid(ai); -+ status = readConfigRid(ai, 1); - if ( status != SUCCESS ) return ERROR; - - status = readCapabilityRid(ai, &cap_rid); - if ( status != SUCCESS ) return ERROR; - -- status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid)); -+ status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),1); - if ( status == SUCCESS ) { - if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) - memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); - } - else { -+ printk( KERN_WARNING "airo: unable to read RSSI map\n"); - if (ai->rssi) { - kfree(ai->rssi); - ai->rssi = NULL; -@@ -2349,14 +2462,14 @@ - } - } - -- status = writeConfigRid(ai); -+ status = writeConfigRid(ai, 1); - if ( status != SUCCESS ) return ERROR; - - /* Set up the SSID list */ - status = writeSsidRid(ai, &mySsid); - if ( status != SUCCESS ) return ERROR; - -- status = enable_MAC(ai, &rsp); -+ status = enable_MAC(ai, &rsp, 1); - if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { - printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); - return ERROR; -@@ -2571,13 +2684,12 @@ - - /* Note, that we are using BAP1 which is also used by transmit, so - * we must get a lock. */ --static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len) -+static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, int lock) - { -- u16 status, dolock = 0; -+ u16 status; - int rc = SUCCESS; - -- if (test_bit(FLAG_LOCKED, &ai->flags) == 0) { -- dolock = 1; -+ if (lock) { - if (down_interruptible(&ai->sem)) - return ERROR; - } -@@ -2605,7 +2717,7 @@ - // read remainder of the rid - rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1); - done: -- if (dolock) -+ if (lock) - up(&ai->sem); - return rc; - } -@@ -2613,13 +2725,14 @@ - /* Note, that we are using BAP1 which is also used by transmit, so - * make sure this isnt called when a transmit is happening */ - static int PC4500_writerid(struct airo_info *ai, u16 rid, -- const void *pBuf, int len) -+ const void *pBuf, int len, int lock) - { -- u16 status, dolock = 0; -+ u16 status; - int rc = SUCCESS; - -- if (test_bit(FLAG_LOCKED, &ai->flags) == 0) { -- dolock = 1; -+ *(u16*)pBuf = cpu_to_le16((u16)len); -+ -+ if (lock) { - if (down_interruptible(&ai->sem)) - return ERROR; - } -@@ -2637,7 +2750,7 @@ - // ---now commit the rid data - rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS); - done: -- if (dolock) -+ if (lock) - up(&ai->sem); - return rc; - } -@@ -2656,11 +2769,11 @@ - if (down_interruptible(&ai->sem)) - return ERROR; - if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { -- txFid = 0; -+ txFid = ERROR; - goto done; - } - if ( (rsp.status & 0xFF00) != 0) { -- txFid = 0; -+ txFid = ERROR; - goto done; - } - /* wait for the allocate event/indication -@@ -2707,7 +2820,7 @@ - - len >>= 16; - -- if (len < ETH_ALEN * 2) { -+ if (len <= ETH_ALEN * 2) { - printk( KERN_WARNING "Short packet %d\n", len ); - return ERROR; - } -@@ -3094,7 +3207,7 @@ - "Signal Quality: %d\n" - "SSID: %-.*s\n" - "AP: %-.16s\n" -- "Freq: %d\n" -+ "Freq: %d (%d)\n" - "BitRate: %dmbs\n" - "Driver Version: %s\n" - "Device: %s\nManufacturer: %s\nFirmware Version: %s\n" -@@ -3108,6 +3221,7 @@ - status_rid.SSID, - status_rid.apName, - (int)status_rid.channel, -+ (int)status_rid.channelSet, - (int)status_rid.currentXmitRate/2, - version, - cap_rid.prodName, -@@ -3158,7 +3272,7 @@ - return -ENOMEM; - } - -- readStatsRid(apriv, &stats, rid); -+ readStatsRid(apriv, &stats, rid, 1); - - j = 0; - for(i=0; (int)statsLabels[i]!=-1 && -@@ -3204,7 +3318,7 @@ - - if ( !data->writelen ) return; - -- readConfigRid(ai); -+ readConfigRid(ai, 1); - - line = data->wbuffer; - while( line[0] ) { -@@ -3390,7 +3504,7 @@ - while( line[0] && line[0] != '\n' ) line++; - if ( line[0] ) line++; - } -- disable_MAC(ai); -+ disable_MAC(ai, 1); - if (need_reset) { - APListRid APList_rid; - SsidRid SSID_rid; -@@ -3398,12 +3512,12 @@ - readAPListRid(ai, &APList_rid); - readSsidRid(ai, &SSID_rid); - reset_airo_card(dev); -- disable_MAC(ai); -+ disable_MAC(ai, 1); - writeSsidRid(ai, &SSID_rid); - writeAPListRid(ai, &APList_rid); - } -- writeConfigRid(ai); -- enable_MAC(ai, &rsp); -+ writeConfigRid(ai, 1); -+ enable_MAC(ai, &rsp, 1); - if (need_reset) - airo_set_promisc(ai); - } -@@ -3443,7 +3557,7 @@ - data->maxwritelen = 2048; - data->on_close = proc_config_on_close; - -- readConfigRid(ai); -+ readConfigRid(ai, 1); - - i = sprintf( data->rbuffer, - "Mode: %s\n" -@@ -3535,9 +3649,9 @@ - offset < data->writelen ) offset++; - offset++; - } -- disable_MAC(ai); -+ disable_MAC(ai, 1); - writeSsidRid(ai, &SSID_rid); -- enable_MAC(ai, &rsp); -+ enable_MAC(ai, &rsp, 1); - } - - inline static u8 hexVal(char c) { -@@ -3576,20 +3690,20 @@ - } - } - } -- disable_MAC(ai); -+ disable_MAC(ai, 1); - writeAPListRid(ai, &APList_rid); -- enable_MAC(ai, &rsp); -+ enable_MAC(ai, &rsp, 1); - } - - /* This function wraps PC4500_writerid with a MAC disable */ - static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, -- int len ) { -+ int len, int dummy ) { - int rc; - Resp rsp; - -- disable_MAC(ai); -- rc = PC4500_writerid(ai, rid, rid_data, len); -- enable_MAC(ai, &rsp); -+ disable_MAC(ai, 1); -+ rc = PC4500_writerid(ai, rid, rid_data, len, 1); -+ enable_MAC(ai, &rsp, 1); - return rc; - } - -@@ -3617,7 +3731,7 @@ - } - - static int set_wep_key(struct airo_info *ai, u16 index, -- const char *key, u16 keylen, int perm ) { -+ const char *key, u16 keylen, int perm, int lock ) { - static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; - WepKeyRid wkr; - -@@ -3639,7 +3753,7 @@ - printk(KERN_INFO "Setting key %d\n", index); - } - -- writeWepKeyRid(ai, &wkr, perm); -+ writeWepKeyRid(ai, &wkr, perm, lock); - return 0; - } - -@@ -3662,7 +3776,7 @@ - (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { - index = data->wbuffer[0] - '0'; - if (data->wbuffer[1] == '\n') { -- set_wep_key(ai, index, 0, 0, 1); -+ set_wep_key(ai, index, 0, 0, 1, 1); - return; - } - j = 2; -@@ -3681,7 +3795,7 @@ - break; - } - } -- set_wep_key(ai, index, key, i/3, 1); -+ set_wep_key(ai, index, key, i/3, 1, 1); - } - - static int proc_wepkey_open( struct inode *inode, struct file *file ) { -@@ -3937,10 +4051,9 @@ - add_timer(&apriv->timer); - return; - } -- __set_bit(FLAG_LOCKED, &apriv->flags); - -- readConfigRid(apriv); -- disable_MAC(apriv); -+ readConfigRid(apriv, 0); -+ disable_MAC(apriv, 0); - switch(apriv->config.authType) { - case AUTH_ENCRYPT: - /* So drop to OPEN */ -@@ -3948,13 +4061,13 @@ - break; - case AUTH_SHAREDKEY: - if (apriv->keyindex < auto_wep) { -- set_wep_key(apriv, apriv->keyindex, 0, 0, 0); -+ set_wep_key(apriv, apriv->keyindex, 0, 0, 0, 0); - apriv->config.authType = AUTH_SHAREDKEY; - apriv->keyindex++; - } else { - /* Drop to ENCRYPT */ - apriv->keyindex = 0; -- set_wep_key(apriv, apriv->defindex, 0, 0, 0); -+ set_wep_key(apriv, apriv->defindex, 0, 0, 0, 0); - apriv->config.authType = AUTH_ENCRYPT; - } - break; -@@ -3962,9 +4075,8 @@ - apriv->config.authType = AUTH_SHAREDKEY; - } - apriv->need_commit = 1; -- writeConfigRid(apriv); -- enable_MAC(apriv, &rsp); -- clear_bit(FLAG_LOCKED, &apriv->flags); -+ writeConfigRid(apriv, 0); -+ enable_MAC(apriv, &rsp, 0); - up(&apriv->sem); - - /* Schedule check to see if the change worked */ -@@ -4003,11 +4115,16 @@ - } - - #ifdef CONFIG_PCI -+#if (LINUX_VERSION_CODE >= 0x20400) - static int __devinit airo_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *pent) - { - struct net_device *dev; - -+ if (pci_enable_device(pdev)) -+ return -ENODEV; -+ pci_set_master(pdev); -+ - dev = init_airo_card(pdev->irq, pdev->resource[2].start, 0); - if (!dev) - return -ENODEV; -@@ -4021,6 +4138,7 @@ - stop_airo_card(pci_get_drvdata(pdev), 1); - } - #endif -+#endif - - static int __init airo_init_module( void ) - { -@@ -4140,15 +4258,17 @@ - struct airo_info *local = dev->priv; - StatusRid status_rid; /* Card status info */ - -- readStatusRid(local, &status_rid); -+ if ((local->config.opmode & 0xFF) == MODE_STA_ESS) -+ status_rid.channel = local->config.channelSet; -+ else -+ readStatusRid(local, &status_rid); - -- /* Will return zero in infrastructure mode */ - #ifdef WEXT_USECHANNELS -- fwrq->m = ((int)status_rid.channel) + 1; -+ fwrq->m = ((int)status_rid.channelSet) + 1; - fwrq->e = 0; - #else - { -- int f = (int)status_rid.channel; -+ int f = (int)status_rid.channelSet; - fwrq->m = frequency_list[f] * 100000; - fwrq->e = 1; - } -@@ -4196,9 +4316,9 @@ - SSID_rid.ssids[index].len = dwrq->length - 1; - } - /* Write it to the card */ -- disable_MAC(local); -+ disable_MAC(local, 1); - writeSsidRid(local, &SSID_rid); -- enable_MAC(local, &rsp); -+ enable_MAC(local, &rsp, 1); - - return 0; - } -@@ -4260,9 +4380,9 @@ - memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = sizeof(APList_rid); - memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); -- disable_MAC(local); -+ disable_MAC(local, 1); - writeAPListRid(local, &APList_rid); -- enable_MAC(local, &rsp); -+ enable_MAC(local, &rsp, 1); - } - return 0; - } -@@ -4618,7 +4738,7 @@ - /* Copy the key in the driver */ - memcpy(key.key, extra, dwrq->length); - /* Send the key to the card */ -- set_wep_key(local, index, key.key, key.len, 1); -+ set_wep_key(local, index, key.key, key.len, 1, 1); - } - /* WE specify that if a valid key is set, encryption - * should be enabled (user may turn it off later) -@@ -4632,7 +4752,7 @@ - /* Do we want to just set the transmit key index ? */ - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) { -- set_wep_key(local, index, 0, 0, 1); -+ set_wep_key(local, index, 0, 0, 1, 1); - } else - /* Don't complain if only change the mode */ - if(!dwrq->flags & IW_ENCODE_MODE) { -@@ -4699,6 +4819,7 @@ - return 0; - } - -+#if WIRELESS_EXT > 9 - /*------------------------------------------------------------------*/ - /* - * Wireless Handler : set Tx-Power -@@ -4752,7 +4873,9 @@ - - return 0; - } -+#endif /* WIRELESS_EXT > 9 */ - -+#if WIRELESS_EXT > 10 - /*------------------------------------------------------------------*/ - /* - * Wireless Handler : set Retry limits -@@ -4818,6 +4941,7 @@ - - return 0; - } -+#endif /* WIRELESS_EXT > 10 */ - - /*------------------------------------------------------------------*/ - /* -@@ -4852,8 +4976,8 @@ - range->num_frequency = k; - - /* Hum... Should put the right values there */ -- range->max_qual.qual = 10; -- range->max_qual.level = 0x100 - 120; /* -120 dBm */ -+ range->max_qual.qual = 0xFF; -+ range->max_qual.level = 0; - range->max_qual.noise = 0; - range->sensitivity = 65535; - -@@ -4891,6 +5015,7 @@ - range->num_encoding_sizes = 0; - range->max_encoding_tokens = 0; - } -+#if WIRELESS_EXT > 9 - range->min_pmp = 0; - range->max_pmp = 5000000; /* 5 secs */ - range->min_pmt = 0; -@@ -4907,6 +5032,8 @@ - } - range->num_txpower = i; - range->txpower_capa = IW_TXPOW_MWATT; -+#endif /* WIRELESS_EXT > 9 */ -+#if WIRELESS_EXT > 10 - range->we_version_source = 12; - range->we_version_compiled = WIRELESS_EXT; - range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; -@@ -4916,6 +5043,8 @@ - range->max_retry = 65535; - range->min_r_time = 1024; - range->max_r_time = 65535 * 1024; -+#endif /* WIRELESS_EXT > 10 */ -+#if WIRELESS_EXT > 11 - /* Experimental measurements - boundary 11/5.5 Mb/s */ - /* Note : with or without the (local->rssi), results - * are somewhat different. - Jean II */ -@@ -4925,6 +5054,7 @@ - else - range->avg_qual.level = 176; /* -80 dBm */ - range->avg_qual.noise = 0; -+#endif /* WIRELESS_EXT > 11 */ - - return 0; - } -@@ -5277,7 +5407,7 @@ - * consequences are begnign. So I don't bother fixing it - Javier */ - - /* Try to read the first entry of the scan result */ -- rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList)); -+ rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1); - if((rc) || (BSSList.index == 0xffff)) { - /* Client error, no scan results... - * The caller need to restart the scan. */ -@@ -5293,7 +5423,7 @@ - - /* Read next entry */ - rc = PC4500_readrid(ai, RID_BSSLISTNEXT, -- &BSSList, sizeof(BSSList)); -+ &BSSList, sizeof(BSSList), 1); - } - /* Length of data */ - dwrq->length = (current_ev - extra); -@@ -5315,22 +5445,35 @@ - { - struct airo_info *local = dev->priv; - struct sockaddr *address = (struct sockaddr *) extra; -+ int idx = 0; - - /* Disable spy while we copy the addresses. - * As we don't disable interrupts, we need to do this to avoid races */ - local->spy_number = 0; - - if (dwrq->length > 0) { -- int i; -+ int i, j, dup; - - /* Copy addresses */ -- for (i = 0; i < dwrq->length; i++) -- memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN); -+ for (i = 0; i < dwrq->length; i++) { -+ dup = 0; -+ for (j = 0; j < i; j++) { -+ if (memcmp(local->spy_address[j], address[i].sa_data, ETH_ALEN) == 0) { -+ dup = 1; -+ /* printk ("tried to add duplicate MAC to spy list\n"); */ -+ break; -+ } -+ } -+ if (! dup) { -+ memcpy(local->spy_address[idx], address[i].sa_data, ETH_ALEN); -+ idx++; -+ } -+ } - /* Reset stats */ - memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); - } - /* Enable addresses */ -- local->spy_number = dwrq->length; -+ local->spy_number = idx; - - return 0; - } -@@ -5383,9 +5526,9 @@ - - /* Some of the "SET" function may have modified some of the - * parameters. It's now time to commit them in the card */ -- disable_MAC(local); -- writeConfigRid(local); -- enable_MAC(local, &rsp); -+ disable_MAC(local, 1); -+ writeConfigRid(local, 1); -+ enable_MAC(local, &rsp, 1); - - return 0; - } -@@ -5668,19 +5811,23 @@ - } - break; - -+#if WIRELESS_EXT > 9 - case SIOCGIWTXPOW: // Get the current Tx-Power - rc=airo_get_txpow(dev, NULL, &(wrq->u.txpower), NULL); - break; - case SIOCSIWTXPOW: - rc=airo_set_txpow(dev, NULL, &(wrq->u.txpower), NULL); - break; -+#endif /* WIRELESS_EXT > 9 */ - -+#if WIRELESS_EXT > 10 - case SIOCSIWRETRY: - rc=airo_set_retry(dev, NULL, &(wrq->u.retry), NULL); - break; - case SIOCGIWRETRY: - rc=airo_get_retry(dev, NULL, &(wrq->u.retry), NULL); - break; -+#endif /* WIRELESS_EXT > 10 */ - - case SIOCGIWRANGE: // Get range of parameters - { -@@ -5869,33 +6016,39 @@ - - /* Get stats out of the card */ - readStatusRid(local, &status_rid); -- readStatsRid(local, &stats_rid, RID_STATS); -+ readStatsRid(local, &stats_rid, RID_STATS, 1); - - /* The status */ -- local->wstats.status = status_rid.mode; -+ local->wstats.status = le16_to_cpu(status_rid.mode); - - /* Signal quality and co. But where is the noise level ??? */ -- local->wstats.qual.qual = status_rid.signalQuality; -+ local->wstats.qual.qual = le16_to_cpu(status_rid.signalQuality); - if (local->rssi) -- local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; -- else -- local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; -- local->wstats.qual.noise = 0; -+ local->wstats.qual.level = 0x100 - local->rssi[le16_to_cpu(status_rid.curSignalStrength)].rssidBm; -+ else { -+ local->wstats.qual.level = le16_to_cpu(status_rid.curSignalStrength) + 0x100 - 100; -+ } -+ local->wstats.qual.noise = 0x100 - status_rid.noiseAvedBm; - local->wstats.qual.updated = 3; - - /* Packets discarded in the wireless adapter due to wireless - * specific problems */ - local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */ - local->wstats.discard.code = vals[6];/* RxWepErr */ -+#if WIRELESS_EXT > 11 - local->wstats.discard.fragment = vals[30]; - local->wstats.discard.retries = vals[10]; - local->wstats.discard.misc = vals[1] + vals[32]; - local->wstats.miss.beacon = vals[34]; -+#else /* WIRELESS_EXT > 11 */ -+ local->wstats.discard.misc = vals[1] + vals[30] + vals[32]; -+#endif /* WIRELESS_EXT > 11 */ - return &local->wstats; - } - #endif /* WIRELESS_EXT */ - - #ifdef CISCO_EXT -+#define RIDS_SIZE 2048 - /* - * This just translates from driver IOCTL codes to the command codes to - * feed to the radio's host interface. Things can be added/deleted -@@ -5904,7 +6057,7 @@ - */ - static int readrids(struct net_device *dev, aironet_ioctl *comp) { - unsigned short ridcode; -- unsigned char iobuf[2048]; -+ unsigned char *iobuf; - struct airo_info *ai = dev->priv; - - if (ai->flags & FLAG_FLASHING) -@@ -5913,7 +6066,7 @@ - switch(comp->command) - { - case AIROGCAP: ridcode = RID_CAPABILITIES; break; -- case AIROGCFG: writeConfigRid (ai); -+ case AIROGCFG: writeConfigRid (ai, 1); - ridcode = RID_CONFIG; break; - case AIROGSLIST: ridcode = RID_SSID; break; - case AIROGVLIST: ridcode = RID_APLIST; break; -@@ -5942,15 +6095,21 @@ - break; - } - -- PC4500_readrid(ai,ridcode,iobuf,sizeof(iobuf)); -+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ -+ PC4500_readrid(ai,ridcode,iobuf,RIDS_SIZE, 1); - /* get the count of bytes in the rid docs say 1st 2 bytes is it. - * then return it to the user - * 9/22/2000 Honor user given length - */ - - if (copy_to_user(comp->data, iobuf, -- min((int)comp->len, (int)sizeof(iobuf)))) -+ min((int)comp->len, (int)RIDS_SIZE))) { -+ kfree (iobuf); - return -EFAULT; -+ } -+ kfree (iobuf); - return 0; - } - -@@ -5962,8 +6121,8 @@ - struct airo_info *ai = dev->priv; - int ridcode, enabled; - Resp rsp; -- static int (* writer)(struct airo_info *, u16 rid, const void *, int); -- unsigned char iobuf[2048]; -+ static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); -+ unsigned char *iobuf; - - /* Only super-user can write RIDs */ - if (!capable(CAP_NET_ADMIN)) -@@ -5992,7 +6151,7 @@ - * same with MAC off - */ - case AIROPMACON: -- if (enable_MAC(ai, &rsp) != 0) -+ if (enable_MAC(ai, &rsp, 1) != 0) - return -EIO; - return 0; - -@@ -6001,7 +6160,7 @@ - * as disable_MAC. it's probably so short the compiler does not gen one. - */ - case AIROPMACOFF: -- disable_MAC(ai); -+ disable_MAC(ai, 1); - return 0; - - /* This command merely clears the counts does not actually store any data -@@ -6009,25 +6168,36 @@ - * writerid routines. - */ - case AIROPSTCLR: -- PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,sizeof(iobuf)); -+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ -+ PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDS_SIZE, 1); - - enabled = ai->micstats.enabled; - memset(&ai->micstats,0,sizeof(ai->micstats)); - ai->micstats.enabled = enabled; - - if (copy_to_user(comp->data, iobuf, -- min((int)comp->len, (int)sizeof(iobuf)))) -+ min((int)comp->len, (int)RIDS_SIZE))) { -+ kfree (iobuf); - return -EFAULT; -+ } -+ kfree (iobuf); - return 0; - - default: - return -EOPNOTSUPP; /* Blarg! */ - } -- if(comp->len > sizeof(iobuf)) -+ if(comp->len > RIDS_SIZE) - return -EINVAL; - -- if (copy_from_user(iobuf,comp->data,comp->len)) -+ if ((iobuf = kmalloc(RIDS_SIZE, GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(iobuf,comp->data,comp->len)) { -+ kfree (iobuf); - return -EFAULT; -+ } - - if (comp->command == AIROPCFG) { - ConfigRid *cfg = (ConfigRid *)iobuf; -@@ -6041,8 +6211,11 @@ - ai->flags &= ~FLAG_ADHOC; - } - -- if((*writer)(ai, ridcode, iobuf,comp->len)) -+ if((*writer)(ai, ridcode, iobuf,comp->len,1)) { -+ kfree (iobuf); - return -EIO; -+ } -+ kfree (iobuf); - return 0; - } - -@@ -6121,7 +6294,7 @@ - */ - - int cmdreset(struct airo_info *ai) { -- disable_MAC(ai); -+ disable_MAC(ai, 1); - - if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang before RESET\n"); - -Index: drivers/net/wireless/Makefile ---- drivers/net/wireless/Makefile.orig 2003-08-12 14:09:58.000000000 -0400 -+++ drivers/net/wireless/Makefile 2003-08-12 14:26:55.000000000 -0400 -@@ -12,7 +12,10 @@ - obj- := - - # Things that need to export symbols --export-objs := airo.o orinoco.o hermes.o -+export-objs := airo.o orinoco.o hermes.o hostap.o hostap_crypt.o -+export-objs += click_wifi.o -+ -+obj-m += click_wifi.o - - obj-$(CONFIG_HERMES) += orinoco.o hermes.o - obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o -@@ -23,4 +26,9 @@ - obj-$(CONFIG_AIRO) += airo.o - obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o - -+obj-$(CONFIG_HOSTAP) += hostap.o hostap_crypt.o hostap_crypt_wep.o -+obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o -+obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o -+obj-$(CONFIG_HOSTAP_PCI) += hostap_pci.o -+ - include $(TOPDIR)/Rules.make - -Index: drivers/net/wireless/Config.in ---- drivers/net/wireless/Config.in.orig 2003-08-12 14:43:39.000000000 -0400 -+++ drivers/net/wireless/Config.in 2003-06-09 13:30:25.000000000 -0400 -@@ -7,6 +7,7 @@ - fi - - tristate ' Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)' CONFIG_HERMES -+tristate ' Host AP support for Prism2/2.5/3 IEEE 802.11b' CONFIG_HOSTAP - - if [ "$CONFIG_ALL_PPC" = "y" ]; then - dep_tristate ' Apple Airport support (built-in)' CONFIG_APPLE_AIRPORT $CONFIG_HERMES -@@ -15,6 +16,9 @@ - if [ "$CONFIG_PCI" = "y" ]; then - dep_tristate ' Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)' CONFIG_PLX_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL - dep_tristate ' Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)' CONFIG_PCI_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL -+ dep_tristate ' Host AP driver for Prism2/2.5/3 in PLX9052 based PCI adaptors' CONFIG_HOSTAP_PLX $CONFIG_HOSTAP -+ dep_tristate ' Host AP driver for Prism2.5 PCI adaptors' CONFIG_HOSTAP_PCI $CONFIG_HOSTAP -+ - fi - - # If Pcmcia is compiled in, offer Pcmcia cards... -@@ -22,6 +26,7 @@ - comment 'Wireless Pcmcia cards support' - - dep_tristate ' Hermes PCMCIA card support' CONFIG_PCMCIA_HERMES $CONFIG_HERMES -+ dep_tristate ' Host AP driver for Prism2/2.5/3 PC Cards' CONFIG_HOSTAP_CS $CONFIG_HOSTAP $CONFIG_PCMCIA - tristate ' Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards' CONFIG_AIRO_CS - fi - - -Index: drivers/net/wireless/hostap_ap.c ---- drivers/net/wireless/hostap_ap.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_ap.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,3309 @@ -+/* -+ * Intersil Prism2 driver with Host AP (software access point) support -+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen -+ * -+ * Copyright (c) 2002-2003, Jouni Malinen -+ * -+ * This file is to be included into hostap.c when S/W AP functionality is -+ * compiled. -+ * -+ * AP: FIX: -+ * - if unicast Class 2 (assoc,reassoc,disassoc) frame received from -+ * unauthenticated STA, send deauth. frame (8802.11: 5.5) -+ * - if unicast Class 3 (data with to/from DS,deauth,pspoll) frame received -+ * from authenticated, but unassoc STA, send disassoc frame (8802.11: 5.5) -+ * - if unicast Class 3 received from unauthenticated STA, send deauth. frame -+ * (8802.11: 5.5) -+ */ -+ -+static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL, -+ DEF_INTS }; -+MODULE_PARM(other_ap_policy, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(other_ap_policy, "Other AP beacon monitoring policy (0-3)"); -+ -+static int ap_max_inactivity[MAX_PARM_DEVICES] = { AP_MAX_INACTIVITY / HZ, -+ DEF_INTS }; -+MODULE_PARM(ap_max_inactivity, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(ap_max_inactivity, "AP timeout (in seconds) for station " -+ "inactivity"); -+ -+static int ap_bridge_packets[MAX_PARM_DEVICES] = { 1, DEF_INTS }; -+MODULE_PARM(ap_bridge_packets, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(ap_bridge_packets, "Bridge packets directly between " -+ "stations"); -+ -+static int autom_ap_wds[MAX_PARM_DEVICES] = { 0, DEF_INTS }; -+MODULE_PARM(autom_ap_wds, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs " -+ "automatically"); -+ -+ -+static void prism2_ap_update_sq(struct sta_info *sta, -+ struct hfa384x_rx_frame *rxdesc); -+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta); -+static void hostap_event_expired_sta(struct net_device *dev, -+ struct sta_info *sta); -+static void handle_add_proc_queue(void *data); -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+static void handle_add_wds_queue(void *data); -+static void prism2_send_mgmt(struct net_device *dev, -+ int type, int subtype, char *body, -+ int body_len, int txevent, u8 *addr, -+ u16 tx_cb_idx); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+static int ap_debug_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ struct ap_data *ap = (struct ap_data *) data; -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+ p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast); -+ p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast); -+ p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ); -+ p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets); -+ p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack); -+ p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds); -+ p += sprintf(p, "auth_algs=%u\n", ap->auth_algs); -+ -+ return (p - page); -+} -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ -+ -+static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta) -+{ -+ sta->hnext = ap->sta_hash[STA_HASH(sta->addr)]; -+ ap->sta_hash[STA_HASH(sta->addr)] = sta; -+} -+ -+static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta) -+{ -+ struct sta_info *s; -+ -+ s = ap->sta_hash[STA_HASH(sta->addr)]; -+ if (s == NULL) return; -+ if (memcmp(s->addr, sta->addr, 6) == 0) { -+ ap->sta_hash[STA_HASH(sta->addr)] = s->hnext; -+ return; -+ } -+ -+ while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, 6) != 0) -+ s = s->hnext; -+ if (s->hnext != NULL) -+ s->hnext = s->hnext->hnext; -+ else -+ printk("AP: could not remove STA " MACSTR " from hash table\n", -+ MAC2STR(sta->addr)); -+} -+ -+static void ap_free_sta(struct ap_data *ap, struct sta_info *sta) -+{ -+ struct sk_buff *skb; -+ -+ if (sta->ap && sta->local) -+ hostap_event_expired_sta(sta->local->dev, sta); -+ -+ if (ap->proc != NULL) { -+ char name[20]; -+ sprintf(name, MACSTR, MAC2STR(sta->addr)); -+ remove_proc_entry(name, ap->proc); -+ } -+ -+ if (sta->crypt) { -+ sta->crypt->ops->deinit(sta->crypt->priv); -+ kfree(sta->crypt); -+ sta->crypt = NULL; -+ } -+ -+ while ((skb = skb_dequeue(&sta->tx_buf)) != NULL) -+ dev_kfree_skb(skb); -+ -+ ap->num_sta--; -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (sta->aid > 0) -+ ap->sta_aid[sta->aid - 1] = NULL; -+ -+ if (!sta->ap && sta->u.sta.challenge) -+ kfree(sta->u.sta.challenge); -+ del_timer(&sta->timer); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ kfree(sta); -+} -+ -+ -+struct set_tim_data { -+ struct list_head list; -+ int aid; -+ int set; -+}; -+ -+static void hostap_set_tim(local_info_t *local, int aid, int set) -+{ -+ struct list_head *ptr; -+ struct set_tim_data *new_entry; -+ -+ new_entry = (struct set_tim_data *) -+ kmalloc(sizeof(*new_entry), GFP_ATOMIC); -+ if (new_entry == NULL) { -+ printk(KERN_DEBUG "%s: hostap_set_tim: kmalloc failed\n", -+ local->dev->name); -+ return; -+ } -+ memset(new_entry, 0, sizeof(*new_entry)); -+ new_entry->aid = aid; -+ new_entry->set = set; -+ -+ spin_lock_bh(&local->ap->set_tim_lock); -+ for (ptr = local->ap->set_tim_list.next; -+ ptr != &local->ap->set_tim_list; -+ ptr = ptr->next) { -+ struct set_tim_data *entry = (struct set_tim_data *) ptr; -+ if (entry->aid == aid) { -+ PDEBUG(DEBUG_PS2, "%s: hostap_set_tim: aid=%d " -+ "set=%d ==> %d\n", -+ local->dev->name, aid, entry->set, set); -+ entry->set = set; -+ kfree(new_entry); -+ new_entry = NULL; -+ break; -+ } -+ } -+ if (new_entry) -+ list_add_tail(&new_entry->list, &local->ap->set_tim_list); -+ spin_unlock_bh(&local->ap->set_tim_lock); -+ -+ PRISM2_SCHEDULE_TASK(&local->ap->set_tim_queue); -+} -+ -+ -+static void handle_set_tim_queue(void *data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct set_tim_data *entry; -+ u16 val; -+ -+ for (;;) { -+ entry = NULL; -+ spin_lock_bh(&local->ap->set_tim_lock); -+ if (!list_empty(&local->ap->set_tim_list)) { -+ entry = list_entry(local->ap->set_tim_list.next, -+ struct set_tim_data, list); -+ list_del(&entry->list); -+ } -+ spin_unlock_bh(&local->ap->set_tim_lock); -+ if (!entry) -+ break; -+ -+ PDEBUG(DEBUG_PS2, "%s: hostap_set_tim_queue: aid=%d set=%d\n", -+ local->dev->name, entry->aid, entry->set); -+ -+ val = entry->aid; -+ if (entry->set) -+ val |= 0x8000; -+ if (hostap_set_word(local->dev, HFA384X_RID_CNFTIMCTRL, val)) { -+ printk(KERN_DEBUG "%s: set_tim failed (aid=%d " -+ "set=%d)\n", -+ local->dev->name, entry->aid, entry->set); -+ } -+ -+ kfree(entry); -+ } -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+static void hostap_event_new_sta(struct net_device *dev, struct sta_info *sta) -+{ -+#if WIRELESS_EXT >= 15 -+ union iwreq_data wrqu; -+ memset(&wrqu, 0, sizeof(wrqu)); -+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN); -+ wrqu.addr.sa_family = ARPHRD_ETHER; -+ wireless_send_event(dev, IWEVREGISTERED, &wrqu, NULL); -+#endif /* WIRELESS_EXT >= 15 */ -+} -+ -+ -+static void hostap_event_expired_sta(struct net_device *dev, -+ struct sta_info *sta) -+{ -+#if WIRELESS_EXT >= 15 -+ union iwreq_data wrqu; -+ memset(&wrqu, 0, sizeof(wrqu)); -+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN); -+ wrqu.addr.sa_family = ARPHRD_ETHER; -+ wireless_send_event(dev, IWEVEXPIRED, &wrqu, NULL); -+#endif /* WIRELESS_EXT >= 15 */ -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ -+static void ap_handle_timer(unsigned long data) -+{ -+ struct sta_info *sta = (struct sta_info *) data; -+ local_info_t *local; -+ struct ap_data *ap; -+ unsigned long next_time = 0; -+ int was_assoc; -+ -+ if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) { -+ PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n"); -+ return; -+ } -+ -+ local = sta->local; -+ ap = local->ap; -+ was_assoc = sta->flags & WLAN_STA_ASSOC; -+ -+ if (atomic_read(&sta->users) != 0) -+ next_time = jiffies + HZ; -+ else if ((sta->flags & WLAN_STA_PERM) && !(sta->flags & WLAN_STA_AUTH)) -+ next_time = jiffies + ap->max_inactivity; -+ -+ if (sta->last_rx + ap->max_inactivity > jiffies) { -+ /* station activity detected; reset timeout state */ -+ sta->timeout_next = STA_NULLFUNC; -+ next_time = sta->last_rx + ap->max_inactivity; -+ } else if (sta->timeout_next == STA_DISASSOC && sta->txexc == 0) { -+ /* data nullfunc frame poll did not produce TX errors; assume -+ * station ACKed it */ -+ sta->timeout_next = STA_NULLFUNC; -+ next_time = jiffies + ap->max_inactivity; -+ } -+ -+ if (next_time) { -+ sta->timer.expires = next_time; -+ add_timer(&sta->timer); -+ return; -+ } -+ -+ if (sta->ap) -+ sta->timeout_next = STA_DEAUTH; -+ -+ if (sta->timeout_next == STA_DEAUTH && !(sta->flags & WLAN_STA_PERM)) { -+ spin_lock(&ap->sta_table_lock); -+ ap_sta_hash_del(ap, sta); -+ list_del(&sta->list); -+ spin_unlock(&ap->sta_table_lock); -+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); -+ } else if (sta->timeout_next == STA_DISASSOC) -+ sta->flags &= ~WLAN_STA_ASSOC; -+ -+ if (was_assoc && !(sta->flags & WLAN_STA_ASSOC) && !sta->ap) -+ hostap_event_expired_sta(local->dev, sta); -+ -+ if (sta->timeout_next == STA_DEAUTH && sta->aid > 0 && -+ !skb_queue_empty(&sta->tx_buf)) { -+ hostap_set_tim(local, sta->aid, 0); -+ sta->flags &= ~WLAN_STA_TIM; -+ } -+ -+ if (sta->ap) { -+ if (ap->autom_ap_wds) { -+ PDEBUG(DEBUG_AP, "%s: removing automatic WDS " -+ "connection to AP " MACSTR "\n", -+ local->dev->name, MAC2STR(sta->addr)); -+ prism2_wds_del(local, sta->addr, 0, 1); -+ } -+ } else if (sta->timeout_next == STA_NULLFUNC) { -+ /* send data frame to poll STA and check whether this frame -+ * is ACKed */ -+ sta->txexc = 0; -+ /* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but -+ * it is apparently not retried so TX Exc events are not -+ * received for it */ -+ prism2_send_mgmt(local->dev, WLAN_FC_TYPE_DATA, -+ WLAN_FC_STYPE_DATA, NULL, 0, 1, -+ sta->addr, 0); -+ } else { -+ int deauth = sta->timeout_next == STA_DEAUTH; -+ u16 resp; -+ PDEBUG(DEBUG_AP, "%s: sending %s info to STA " MACSTR -+ "(last=%lu, jiffies=%lu)\n", -+ local->dev->name, -+ deauth ? "deauthentication" : "disassociation", -+ MAC2STR(sta->addr), sta->last_rx, jiffies); -+ -+ resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID : -+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); -+ prism2_send_mgmt(local->dev, WLAN_FC_TYPE_MGMT, -+ (deauth ? WLAN_FC_STYPE_DEAUTH : -+ WLAN_FC_STYPE_DISASSOC), -+ (char *) &resp, 2, 1, sta->addr, 0); -+ } -+ -+ if (sta->timeout_next == STA_DEAUTH) { -+ if (sta->flags & WLAN_STA_PERM) { -+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " would have been " -+ "removed, but it has 'perm' flag\n", -+ local->dev->name, MAC2STR(sta->addr)); -+ } else -+ ap_free_sta(ap, sta); -+ return; -+ } -+ -+ if (sta->timeout_next == STA_NULLFUNC) { -+ sta->timeout_next = STA_DISASSOC; -+ sta->timer.expires = jiffies + AP_DISASSOC_DELAY; -+ } else { -+ sta->timeout_next = STA_DEAUTH; -+ sta->timer.expires = jiffies + AP_DEAUTH_DELAY; -+ } -+ -+ add_timer(&sta->timer); -+} -+ -+ -+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap, -+ int resend) -+{ -+ u8 addr[ETH_ALEN]; -+ u16 resp; -+ int i; -+ -+ PDEBUG(DEBUG_AP, "%s: Deauthenticate all stations\n", dev->name); -+ memset(addr, 0xff, ETH_ALEN); -+ -+ resp = __constant_cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); -+ -+ /* deauth message sent; try to resend it few times; the message is -+ * broadcast, so it may be delayed until next DTIM; there is not much -+ * else we can do at this point since the driver is going to be shut -+ * down */ -+ for (i = 0; i < 5; i++) { -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH, -+ (char *) &resp, 2, 1, addr, 0); -+ -+ if (!resend || ap->num_sta <= 0) -+ return; -+ -+ mdelay(50); -+ } -+} -+ -+ -+static int ap_control_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ struct ap_data *ap = (struct ap_data *) data; -+ char *policy_txt; -+ struct list_head *ptr; -+ struct mac_entry *entry; -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+ switch (ap->mac_restrictions.policy) { -+ case MAC_POLICY_OPEN: -+ policy_txt = "open"; -+ break; -+ case MAC_POLICY_ALLOW: -+ policy_txt = "allow"; -+ break; -+ case MAC_POLICY_DENY: -+ policy_txt = "deny"; -+ break; -+ default: -+ policy_txt = "unknown"; -+ break; -+ }; -+ p += sprintf(p, "MAC policy: %s\n", policy_txt); -+ p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); -+ p += sprintf(p, "MAC list:\n"); -+ spin_lock_bh(&ap->mac_restrictions.lock); -+ for (ptr = ap->mac_restrictions.mac_list.next; -+ ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) { -+ if (p - page > PAGE_SIZE - 80) { -+ p += sprintf(p, "All entries did not fit one page.\n"); -+ break; -+ } -+ -+ entry = list_entry(ptr, struct mac_entry, list); -+ p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr)); -+ } -+ spin_unlock_bh(&ap->mac_restrictions.lock); -+ -+ return (p - page); -+} -+ -+ -+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions, -+ u8 *mac) -+{ -+ struct mac_entry *entry; -+ -+ entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL); -+ if (entry == NULL) -+ return -1; -+ -+ memcpy(entry->addr, mac, 6); -+ -+ spin_lock_bh(&mac_restrictions->lock); -+ list_add_tail(&entry->list, &mac_restrictions->mac_list); -+ mac_restrictions->entries++; -+ spin_unlock_bh(&mac_restrictions->lock); -+ -+ return 0; -+} -+ -+ -+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions, -+ u8 *mac) -+{ -+ struct list_head *ptr; -+ struct mac_entry *entry; -+ -+ spin_lock_bh(&mac_restrictions->lock); -+ for (ptr = mac_restrictions->mac_list.next; -+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) { -+ entry = list_entry(ptr, struct mac_entry, list); -+ -+ if (memcmp(entry->addr, mac, 6) == 0) { -+ list_del(ptr); -+ kfree(entry); -+ mac_restrictions->entries--; -+ spin_unlock_bh(&mac_restrictions->lock); -+ return 0; -+ } -+ } -+ spin_unlock_bh(&mac_restrictions->lock); -+ return -1; -+} -+ -+ -+static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, -+ u8 *mac) -+{ -+ struct list_head *ptr; -+ struct mac_entry *entry; -+ int found = 0; -+ -+ if (mac_restrictions->policy == MAC_POLICY_OPEN) -+ return 0; -+ -+ spin_lock_bh(&mac_restrictions->lock); -+ for (ptr = mac_restrictions->mac_list.next; -+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) { -+ entry = list_entry(ptr, struct mac_entry, list); -+ -+ if (memcmp(entry->addr, mac, 6) == 0) { -+ found = 1; -+ break; -+ } -+ } -+ spin_unlock_bh(&mac_restrictions->lock); -+ -+ if (mac_restrictions->policy == MAC_POLICY_ALLOW) -+ return !found; -+ else -+ return found; -+} -+ -+ -+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions) -+{ -+ struct list_head *ptr, *n; -+ struct mac_entry *entry; -+ -+ if (mac_restrictions->entries == 0) -+ return; -+ -+ spin_lock_bh(&mac_restrictions->lock); -+ for (ptr = mac_restrictions->mac_list.next, n = ptr->next; -+ ptr != &mac_restrictions->mac_list; -+ ptr = n, n = ptr->next) { -+ entry = list_entry(ptr, struct mac_entry, list); -+ list_del(ptr); -+ kfree(entry); -+ } -+ mac_restrictions->entries = 0; -+ spin_unlock_bh(&mac_restrictions->lock); -+} -+ -+ -+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, -+ u8 *mac) -+{ -+ struct sta_info *sta; -+ u16 resp; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, mac); -+ if (sta) { -+ ap_sta_hash_del(ap, sta); -+ list_del(&sta->list); -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (!sta) -+ return -EINVAL; -+ -+ resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH, -+ (char *) &resp, 2, 1, sta->addr, 0); -+ -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) -+ hostap_event_expired_sta(dev, sta); -+ -+ ap_free_sta(ap, sta); -+ -+ return 0; -+} -+ -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+static void ap_control_kickall(struct ap_data *ap) -+{ -+ struct list_head *ptr, *n; -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list; -+ ptr = n, n = ptr->next) { -+ sta = list_entry(ptr, struct sta_info, list); -+ ap_sta_hash_del(ap, sta); -+ list_del(&sta->list); -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) -+ hostap_event_expired_sta(sta->local->dev, sta); -+ ap_free_sta(ap, sta); -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ -+#define PROC_LIMIT (PAGE_SIZE - 80) -+ -+static int prism2_ap_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ struct ap_data *ap = (struct ap_data *) data; -+ struct list_head *ptr; -+ int i; -+ -+ if (off > PROC_LIMIT) { -+ *eof = 1; -+ return 0; -+ } -+ -+ p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); -+ spin_lock_bh(&ap->sta_table_lock); -+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ -+ if (!sta->ap) -+ continue; -+ -+ p += sprintf(p, MACSTR " %d %d %d %d '", MAC2STR(sta->addr), -+ sta->u.ap.channel, sta->last_rx_signal, -+ sta->last_rx_silence, sta->last_rx_rate); -+ for (i = 0; i < sta->u.ap.ssid_len; i++) -+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && -+ sta->u.ap.ssid[i] < 127) ? -+ "%c" : "<%02x>"), -+ sta->u.ap.ssid[i]); -+ p += sprintf(p, "'"); -+ if (sta->capability & WLAN_CAPABILITY_ESS) -+ p += sprintf(p, " [ESS]"); -+ if (sta->capability & WLAN_CAPABILITY_IBSS) -+ p += sprintf(p, " [IBSS]"); -+ if (sta->capability & WLAN_CAPABILITY_PRIVACY) -+ p += sprintf(p, " [WEP]"); -+ p += sprintf(p, "\n"); -+ -+ if ((p - page) > PROC_LIMIT) { -+ printk(KERN_DEBUG "hostap: ap proc did not fit\n"); -+ break; -+ } -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if ((p - page) <= off) { -+ *eof = 1; -+ return 0; -+ } -+ -+ *start = page + off; -+ -+ return (p - page - off); -+} -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+void hostap_check_sta_fw_version(struct ap_data *ap, int major, int minor, -+ int variant) -+{ -+ if (!ap) -+ return; -+ -+ if (major == 0 && minor == 8 && variant == 0) { -+ PDEBUG(DEBUG_AP, "Using data::nullfunc ACK workaround - " -+ "firmware upgrade recommended\n"); -+ ap->nullfunc_ack = 1; -+ } else -+ ap->nullfunc_ack = 0; -+ -+ if (major == 1 && minor == 4 && variant == 2) { -+ printk(KERN_WARNING "%s: Warning: secondary station firmware " -+ "version 1.4.2 does not seem to work in Host AP mode\n", -+ ap->local->dev->name); -+ } -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data) -+{ -+ struct ap_data *ap = data; -+ u16 fc; -+ struct hostap_ieee80211_hdr *hdr; -+ -+ if (!ap->local->hostapd || !ap->local->apdev) { -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ hdr = (struct hostap_ieee80211_hdr *) skb->data; -+ fc = le16_to_cpu(hdr->frame_control); -+ -+ /* Pass the TX callback frame to the hostapd; use 802.11 header version -+ * 1 to indicate failure (no ACK) and 2 success (frame ACKed) */ -+ -+ fc &= ~WLAN_FC_PVER; -+ fc |= ok ? BIT(1) : BIT(0); -+ hdr->frame_control = cpu_to_le16(fc); -+ -+ skb->dev = ap->local->apdev; -+ skb_pull(skb, hostap_80211_get_hdrlen(fc)); -+ skb->pkt_type = PACKET_OTHERHOST; -+ skb->protocol = __constant_htons(ETH_P_802_2); -+ memset(skb->cb, 0, sizeof(skb->cb)); -+ netif_rx(skb); -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data) -+{ -+ struct ap_data *ap = data; -+ struct net_device *dev = ap->local->dev; -+ struct hostap_ieee80211_hdr *hdr; -+ u16 fc, *pos, auth_alg, auth_transaction, status; -+ struct sta_info *sta = NULL; -+ char *txt = NULL; -+ -+ if (ap->local->hostapd) { -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ hdr = (struct hostap_ieee80211_hdr *) skb->data; -+ fc = le16_to_cpu(hdr->frame_control); -+ if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || -+ WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_AUTH || -+ skb->len < 24 + 6) { -+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid " -+ "frame\n", dev->name); -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ if (!ok) { -+ txt = "frame was not ACKed"; -+ goto done; -+ } -+ -+ spin_lock(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, hdr->addr1); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&ap->sta_table_lock); -+ -+ if (!sta) { -+ txt = "STA not found"; -+ goto done; -+ } -+ -+ pos = (u16 *) (skb->data + 24); -+ auth_alg = le16_to_cpu(*pos++); -+ auth_transaction = le16_to_cpu(*pos++); -+ status = le16_to_cpu(*pos++); -+ if (status == WLAN_STATUS_SUCCESS && -+ ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || -+ (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { -+ txt = "STA authenticated"; -+ sta->flags |= WLAN_STA_AUTH; -+ sta->last_auth = jiffies; -+ } else if (status != WLAN_STATUS_SUCCESS) -+ txt = "authentication failed"; -+ -+ done: -+ if (sta) -+ atomic_dec(&sta->users); -+ if (txt) { -+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth_cb - %s\n", -+ dev->name, MAC2STR(hdr->addr1), txt); -+ } -+ dev_kfree_skb(skb); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) -+{ -+ struct ap_data *ap = data; -+ struct net_device *dev = ap->local->dev; -+ struct hostap_ieee80211_hdr *hdr; -+ u16 fc, *pos, status; -+ struct sta_info *sta = NULL; -+ char *txt = NULL; -+ -+ if (ap->local->hostapd) { -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ hdr = (struct hostap_ieee80211_hdr *) skb->data; -+ fc = le16_to_cpu(hdr->frame_control); -+ if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || -+ (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ASSOC_RESP && -+ WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_REASSOC_RESP) || -+ skb->len < 24 + 4) { -+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid " -+ "frame\n", dev->name); -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ if (!ok) { -+ txt = "frame was not ACKed"; -+ goto done; -+ } -+ -+ spin_lock(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, hdr->addr1); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&ap->sta_table_lock); -+ -+ if (!sta) { -+ txt = "STA not found"; -+ goto done; -+ } -+ -+ pos = (u16 *) (skb->data + 24); -+ pos++; -+ status = le16_to_cpu(*pos++); -+ if (status == WLAN_STATUS_SUCCESS) { -+ if (!(sta->flags & WLAN_STA_ASSOC)) -+ hostap_event_new_sta(dev, sta); -+ txt = "STA associated"; -+ sta->flags |= WLAN_STA_ASSOC; -+ sta->last_assoc = jiffies; -+ } else -+ txt = "association failed"; -+ -+ done: -+ if (sta) -+ atomic_dec(&sta->users); -+ if (txt) { -+ PDEBUG(DEBUG_AP, "%s: " MACSTR " assoc_cb - %s\n", -+ dev->name, MAC2STR(hdr->addr1), txt); -+ } -+ dev_kfree_skb(skb); -+} -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+void hostap_init_data(local_info_t *local) -+{ -+ struct ap_data *ap = local->ap; -+ -+ if (ap == NULL) { -+ printk(KERN_WARNING "hostap_init_data: ap == NULL\n"); -+ return; -+ } -+ memset(ap, 0, sizeof(struct ap_data)); -+ ap->local = local; -+ -+ ap->ap_policy = GET_INT_PARM(other_ap_policy, local->card_idx); -+ ap->proc = local->proc; -+ ap->bridge_packets = GET_INT_PARM(ap_bridge_packets, local->card_idx); -+ ap->max_inactivity = -+ GET_INT_PARM(ap_max_inactivity, local->card_idx) * HZ; -+ ap->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY; -+ ap->autom_ap_wds = GET_INT_PARM(autom_ap_wds, local->card_idx); -+ -+ spin_lock_init(&ap->sta_table_lock); -+ INIT_LIST_HEAD(&ap->sta_list); -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ if (ap->proc != NULL) { -+ create_proc_read_entry("ap_debug", 0, ap->proc, -+ ap_debug_proc_read, ap); -+ } -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ -+ /* Initialize task queue structure for AP management */ -+ HOSTAP_QUEUE_INIT(&local->ap->set_tim_queue, handle_set_tim_queue, -+ local); -+ INIT_LIST_HEAD(&ap->set_tim_list); -+ spin_lock_init(&ap->set_tim_lock); -+ -+ HOSTAP_QUEUE_INIT(&local->ap->add_sta_proc_queue, -+ handle_add_proc_queue, ap); -+ -+ ap->tx_callback_idx = -+ hostap_tx_callback_register(local, hostap_ap_tx_cb, ap); -+ if (ap->tx_callback_idx == 0) -+ printk(KERN_WARNING "%s: failed to register TX callback for " -+ "AP\n", local->dev->name); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ HOSTAP_QUEUE_INIT(&local->ap->add_wds_queue, -+ handle_add_wds_queue, local); -+ -+ ap->tx_callback_auth = -+ hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap); -+ ap->tx_callback_assoc = -+ hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap); -+ if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0) -+ printk(KERN_WARNING "%s: failed to register TX callback for " -+ "AP\n", local->dev->name); -+ -+ spin_lock_init(&ap->mac_restrictions.lock); -+ INIT_LIST_HEAD(&ap->mac_restrictions.mac_list); -+ if (ap->proc != NULL) { -+ create_proc_read_entry("ap_control", 0, ap->proc, -+ ap_control_proc_read, ap); -+ } -+ -+ create_proc_read_entry("ap", 0, ap->proc, -+ prism2_ap_proc_read, ap); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ ap->initialized = 1; -+} -+ -+void hostap_free_data(struct ap_data *ap) -+{ -+ struct list_head *ptr, *n; -+ -+ if (ap == NULL || !ap->initialized) { -+ printk(KERN_DEBUG "hostap_free_data: ap has not yet been " -+ "initialized - skip resource freeing\n"); -+ return; -+ } -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (ap->crypt) -+ ap->crypt->deinit(ap->crypt_priv); -+ ap->crypt = ap->crypt_priv = NULL; -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ ptr = ap->sta_list.next; -+ while (ptr != NULL && ptr != &ap->sta_list) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ ptr = ptr->next; -+ ap_sta_hash_del(ap, sta); -+ list_del(&sta->list); -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) -+ hostap_event_expired_sta(sta->local->dev, sta); -+ ap_free_sta(ap, sta); -+ } -+ -+ for (ptr = ap->set_tim_list.next, n = ptr->next; -+ ptr != &ap->set_tim_list; ptr = n, n = ptr->next) { -+ struct set_tim_data *entry; -+ entry = list_entry(ptr, struct set_tim_data, list); -+ list_del(&entry->list); -+ kfree(entry); -+ } -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ if (ap->proc != NULL) { -+ remove_proc_entry("ap_debug", ap->proc); -+ } -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (ap->proc != NULL) { -+ remove_proc_entry("ap", ap->proc); -+ remove_proc_entry("ap_control", ap->proc); -+ } -+ ap_control_flush_macs(&ap->mac_restrictions); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ ap->initialized = 0; -+} -+ -+ -+/* caller should have mutex for AP STA list handling */ -+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta) -+{ -+ struct sta_info *s; -+ -+ s = ap->sta_hash[STA_HASH(sta)]; -+ while (s != NULL && memcmp(s->addr, sta, 6) != 0) -+ s = s->hnext; -+ return s; -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ -+/* Called from timer handler and from scheduled AP queue handlers */ -+static void prism2_send_mgmt(struct net_device *dev, -+ int type, int subtype, char *body, -+ int body_len, int txevent, u8 *addr, -+ u16 tx_cb_idx) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct hfa384x_tx_frame *txdesc; -+ u16 fc, tx_control; -+ struct sk_buff *skb; -+ -+ if (!(dev->flags & IFF_UP)) { -+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt - device is not UP - " -+ "cannot send frame\n", dev->name); -+ return; -+ } -+ -+ skb = dev_alloc_skb(sizeof(*txdesc) + body_len); -+ if (skb == NULL) { -+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt failed to allocate " -+ "skb\n", dev->name); -+ return; -+ } -+ -+ txdesc = (struct hfa384x_tx_frame *) skb_put(skb, sizeof(*txdesc)); -+ if (body) -+ memcpy(skb_put(skb, body_len), body, body_len); -+ -+ memset(txdesc, 0, sizeof(*txdesc)); -+ /* FIX: set tx_rate if f/w does not know how to do it */ -+ tx_control = txevent ? local->tx_control : HFA384X_TX_CTRL_802_11; -+ if (tx_cb_idx) -+ tx_control |= HFA384X_TX_CTRL_TX_OK; -+ txdesc->sw_support = cpu_to_le16(tx_cb_idx); -+ txdesc->tx_control = cpu_to_le16(tx_control); -+ txdesc->data_len = cpu_to_le16(body_len); -+ -+ fc = (type << 2) | (subtype << 4); -+ -+ memcpy(txdesc->addr1, addr, ETH_ALEN); /* DA / RA */ -+ if (type == WLAN_FC_TYPE_DATA) { -+ fc |= WLAN_FC_FROMDS; -+ memcpy(txdesc->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */ -+ memcpy(txdesc->addr3, dev->dev_addr, ETH_ALEN); /* SA */ -+ } else if (type == WLAN_FC_TYPE_CTRL) { -+ /* control:ACK does not have addr2 or addr3 */ -+ memset(txdesc->addr2, 0, ETH_ALEN); -+ memset(txdesc->addr3, 0, ETH_ALEN); -+ } else { -+ memcpy(txdesc->addr2, dev->dev_addr, ETH_ALEN); /* SA */ -+ memcpy(txdesc->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */ -+ } -+ -+ txdesc->frame_control = cpu_to_le16(fc); -+ -+ /* FIX: is it OK to call dev_queue_xmit() here? This can be called in -+ * interrupt context, but not in hard interrupt (like prism2_rx() that -+ * required bridge_list. If needed, bridge_list could be used also here -+ * when prism2_send_mgmt is called in interrupt context. */ -+ -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ skb->dev = dev; -+ skb->mac.raw = skb->nh.raw = skb->data; -+ dev_queue_xmit(skb); -+} -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+static int prism2_sta_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ struct sta_info *sta = (struct sta_info *) data; -+ int i; -+ -+ /* FIX: possible race condition.. the STA data could have just expired, -+ * but proc entry was still here so that the read could have started; -+ * some locking should be done here.. */ -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+ p += sprintf(p, "%s=" MACSTR "\nusers=%d\naid=%d\n" -+ "flags=0x%04x%s%s%s%s%s%s\n" -+ "capability=0x%02x\nlisten_interval=%d\nsupported_rates=", -+ sta->ap ? "AP" : "STA", -+ MAC2STR(sta->addr), atomic_read(&sta->users), sta->aid, -+ sta->flags, -+ sta->flags & WLAN_STA_AUTH ? " AUTH" : "", -+ sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "", -+ sta->flags & WLAN_STA_PS ? " PS" : "", -+ sta->flags & WLAN_STA_TIM ? " TIM" : "", -+ sta->flags & WLAN_STA_PERM ? " PERM" : "", -+ sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "", -+ sta->capability, sta->listen_interval); -+ /* supported_rates: 500 kbit/s units with msb ignored */ -+ for (i = 0; i < sizeof(sta->supported_rates); i++) -+ if (sta->supported_rates[i] != 0) -+ p += sprintf(p, "%d%sMbps ", -+ (sta->supported_rates[i] & 0x7f) / 2, -+ sta->supported_rates[i] & 1 ? ".5" : ""); -+ p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n" -+ "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n" -+ "tx_packets=%lu\n" -+ "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n" -+ "last_rx: silence=%d signal=%d rate=%d flow=%d\n" -+ "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n" -+ "tx[11M]=%d\n" -+ "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n" -+ "txexc=%d\n", -+ jiffies, sta->last_auth, sta->last_assoc, sta->last_rx, -+ sta->last_tx, -+ sta->rx_packets, sta->tx_packets, sta->rx_bytes, -+ sta->tx_bytes, skb_queue_len(&sta->tx_buf), -+ sta->last_rx_silence, -+ sta->last_rx_signal, sta->last_rx_rate, -+ sta->last_rx_flow, -+ sta->tx_rate, sta->tx_count[0], sta->tx_count[1], -+ sta->tx_count[2], sta->tx_count[3], sta->rx_count[0], -+ sta->rx_count[1], sta->rx_count[2], sta->rx_count[3], -+ sta->txexc); -+ if (sta->crypt && sta->crypt->ops) -+ p += sprintf(p, "crypt=%s\n", sta->crypt->ops->name); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (sta->ap) { -+ if (sta->u.ap.channel >= 0) -+ p += sprintf(p, "channel=%d\n", sta->u.ap.channel); -+ p += sprintf(p, "ssid="); -+ for (i = 0; i < sta->u.ap.ssid_len; i++) -+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && -+ sta->u.ap.ssid[i] < 127) ? -+ "%c" : "<%02x>"), -+ sta->u.ap.ssid[i]); -+ p += sprintf(p, "\n"); -+ } -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ return (p - page); -+} -+ -+ -+static void handle_add_proc_queue(void *data) -+{ -+ struct ap_data *ap = (struct ap_data *) data; -+ struct sta_info *sta; -+ char name[20]; -+ struct add_sta_proc_data *entry, *prev; -+ -+ entry = ap->add_sta_proc_entries; -+ ap->add_sta_proc_entries = NULL; -+ -+ while (entry) { -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, entry->addr); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (sta) { -+ sprintf(name, MACSTR, MAC2STR(sta->addr)); -+ sta->proc = create_proc_read_entry( -+ name, 0, ap->proc, -+ prism2_sta_proc_read, sta); -+ -+ atomic_dec(&sta->users); -+ } -+ -+ prev = entry; -+ entry = entry->next; -+ kfree(prev); -+ } -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr) -+{ -+ struct sta_info *sta; -+ -+ sta = (struct sta_info *) -+ kmalloc(sizeof(struct sta_info), GFP_ATOMIC); -+ if (sta == NULL) { -+ PDEBUG(DEBUG_AP, "AP: kmalloc failed\n"); -+ return NULL; -+ } -+ -+ /* initialize STA info data */ -+ memset(sta, 0, sizeof(struct sta_info)); -+ sta->local = ap->local; -+ skb_queue_head_init(&sta->tx_buf); -+ memcpy(sta->addr, addr, ETH_ALEN); -+ -+ atomic_inc(&sta->users); -+ spin_lock_bh(&ap->sta_table_lock); -+ list_add(&sta->list, &ap->sta_list); -+ ap->num_sta++; -+ ap_sta_hash_add(ap, sta); -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (ap->proc) { -+ struct add_sta_proc_data *entry; -+ /* schedule a non-interrupt context process to add a procfs -+ * entry for the STA since procfs code use GFP_KERNEL */ -+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (entry) { -+ memcpy(entry->addr, sta->addr, ETH_ALEN); -+ entry->next = ap->add_sta_proc_entries; -+ ap->add_sta_proc_entries = entry; -+ PRISM2_SCHEDULE_TASK(&ap->add_sta_proc_queue); -+ } else -+ printk(KERN_DEBUG "Failed to add STA proc data\n"); -+ } -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ init_timer(&sta->timer); -+ sta->timer.expires = jiffies + ap->max_inactivity; -+ sta->timer.data = (unsigned long) sta; -+ sta->timer.function = ap_handle_timer; -+ if (!ap->local->hostapd) -+ add_timer(&sta->timer); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ return sta; -+} -+ -+ -+static int ap_tx_rate_ok(int rateidx, struct sta_info *sta, -+ local_info_t *local) -+{ -+ if (rateidx > sta->tx_max_rate || -+ !(sta->tx_supp_rates & (1 << rateidx))) -+ return 0; -+ -+ if (local->tx_rate_control != 0 && -+ !(local->tx_rate_control & (1 << rateidx))) -+ return 0; -+ -+ return 1; -+} -+ -+ -+static void prism2_check_tx_rates(struct sta_info *sta) -+{ -+ int i; -+ -+ sta->tx_supp_rates = 0; -+ for (i = 0; i < sizeof(sta->supported_rates); i++) { -+ if ((sta->supported_rates[i] & 0x7f) == 2) -+ sta->tx_supp_rates |= WLAN_RATE_1M; -+ if ((sta->supported_rates[i] & 0x7f) == 4) -+ sta->tx_supp_rates |= WLAN_RATE_2M; -+ if ((sta->supported_rates[i] & 0x7f) == 11) -+ sta->tx_supp_rates |= WLAN_RATE_5M5; -+ if ((sta->supported_rates[i] & 0x7f) == 22) -+ sta->tx_supp_rates |= WLAN_RATE_11M; -+ } -+ sta->tx_max_rate = sta->tx_rate = sta->tx_rate_idx = 0; -+ if (sta->tx_supp_rates & WLAN_RATE_1M) { -+ sta->tx_max_rate = 0; -+ if (ap_tx_rate_ok(0, sta, sta->local)) { -+ sta->tx_rate = 10; -+ sta->tx_rate_idx = 0; -+ } -+ } -+ if (sta->tx_supp_rates & WLAN_RATE_2M) { -+ sta->tx_max_rate = 1; -+ if (ap_tx_rate_ok(1, sta, sta->local)) { -+ sta->tx_rate = 20; -+ sta->tx_rate_idx = 1; -+ } -+ } -+ if (sta->tx_supp_rates & WLAN_RATE_5M5) { -+ sta->tx_max_rate = 2; -+ if (ap_tx_rate_ok(2, sta, sta->local)) { -+ sta->tx_rate = 55; -+ sta->tx_rate_idx = 2; -+ } -+ } -+ if (sta->tx_supp_rates & WLAN_RATE_11M) { -+ sta->tx_max_rate = 3; -+ if (ap_tx_rate_ok(3, sta, sta->local)) { -+ sta->tx_rate = 110; -+ sta->tx_rate_idx = 3; -+ } -+ } -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ -+static void ap_crypt_init(struct ap_data *ap) -+{ -+ ap->crypt = hostap_get_crypto_ops("WEP"); -+ -+ if (ap->crypt) { -+ if (ap->crypt->init) { -+ ap->crypt_priv = ap->crypt->init(); -+ if (ap->crypt_priv == NULL) -+ ap->crypt = NULL; -+ else { -+ u8 key[WEP_KEY_LEN]; -+ get_random_bytes(key, WEP_KEY_LEN); -+ ap->crypt->set_key(0, key, WEP_KEY_LEN, -+ ap->crypt_priv); -+ } -+ } -+ } -+ -+ if (ap->crypt == NULL) { -+ printk(KERN_WARNING "AP could not initialize WEP: load module " -+ "hostap_crypt_wep.o\n"); -+ } -+} -+ -+ -+/* Generate challenge data for shared key authentication. IEEE 802.11 specifies -+ * that WEP algorithm is used for generating challange. This should be unique, -+ * but otherwise there is not really need for randomness etc. Initialize WEP -+ * with pseudo random key and then use increasing IV to get unique challenge -+ * streams. -+ * -+ * Called only as a scheduled task for pending AP frames. -+ */ -+static char * ap_auth_make_challenge(struct ap_data *ap) -+{ -+ char *tmpbuf; -+ int olen; -+ -+ if (ap->crypt == NULL) { -+ ap_crypt_init(ap); -+ if (ap->crypt == NULL) -+ return NULL; -+ } -+ -+ tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN + -+ ap->crypt->extra_prefix_len + -+ ap->crypt->extra_postfix_len, -+ GFP_ATOMIC); -+ if (tmpbuf == NULL) { -+ PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n"); -+ return NULL; -+ } -+ memset(tmpbuf, 0, WLAN_AUTH_CHALLENGE_LEN + -+ ap->crypt->extra_prefix_len + ap->crypt->extra_postfix_len); -+ olen = ap->crypt->encrypt(tmpbuf, WLAN_AUTH_CHALLENGE_LEN, -+ ap->crypt_priv); -+ if (olen < 0) { -+ kfree(tmpbuf); -+ return NULL; -+ } -+ memmove(tmpbuf, tmpbuf + 4, WLAN_AUTH_CHALLENGE_LEN); -+ return tmpbuf; -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_authen(local_info_t *local, struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ struct ap_data *ap = local->ap; -+ char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL; -+ int len, olen; -+ u16 auth_alg, auth_transaction, status_code, *pos; -+ u16 resp = WLAN_STATUS_SUCCESS, fc; -+ struct sta_info *sta = NULL; -+ struct prism2_crypt_data *crypt; -+ char *txt = ""; -+ -+ len = __le16_to_cpu(rxdesc->data_len); -+ -+ fc = le16_to_cpu(rxdesc->frame_control); -+ -+ if (len < 6) { -+ PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload " -+ "(len=%d) from " MACSTR "\n", dev->name, len, -+ MAC2STR(rxdesc->addr2)); -+ return; -+ } -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ -+ if (sta && sta->crypt) -+ crypt = sta->crypt; -+ else -+ crypt = local->crypt; -+ -+ if (crypt && local->host_decrypt && (fc & WLAN_FC_ISWEP)) { -+ atomic_inc(&crypt->refcnt); -+ olen = crypt->ops->decrypt((u8 *) (rxdesc + 1), len, -+ crypt->priv); -+ atomic_dec(&crypt->refcnt); -+ if (olen < 0) { -+ if (sta) -+ atomic_dec(&sta->users); -+ PDEBUG(DEBUG_AP, "%s: handle_authen: auth frame from " -+ "STA " MACSTR " could not be decrypted\n", -+ dev->name, MAC2STR(rxdesc->addr2)); -+ return; -+ } -+ if (olen < 6) { -+ PDEBUG(DEBUG_AP, "%s: handle_authen - too short " -+ "payload (len=%d, decrypted len=%d) from " -+ MACSTR "\n", -+ dev->name, len, olen, MAC2STR(rxdesc->addr2)); -+ return; -+ } -+ len = olen; -+ } -+ -+ pos = (u16 *) (rxdesc + 1); -+ auth_alg = __le16_to_cpu(*pos); -+ pos++; -+ auth_transaction = __le16_to_cpu(*pos); -+ pos++; -+ status_code = __le16_to_cpu(*pos); -+ pos++; -+ -+ if (ap_control_mac_deny(&ap->mac_restrictions, rxdesc->addr2)) { -+ txt = "authentication denied"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ -+ if (((ap->auth_algs & PRISM2_AUTH_OPEN) && -+ auth_alg == WLAN_AUTH_OPEN) || -+ ((ap->auth_algs & PRISM2_AUTH_SHARED_KEY) && -+ crypt && auth_alg == WLAN_AUTH_SHARED_KEY)) { -+ } else { -+ txt = "unsupported algorithm"; -+ resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; -+ goto fail; -+ } -+ -+ if (len >= 8) { -+ u8 *u = (u8 *) pos; -+ if (*u == WLAN_EID_CHALLENGE) { -+ if (*(u + 1) != WLAN_AUTH_CHALLENGE_LEN) { -+ txt = "invalid challenge len"; -+ resp = WLAN_STATUS_CHALLENGE_FAIL; -+ goto fail; -+ } -+ if (len - 8 < WLAN_AUTH_CHALLENGE_LEN) { -+ txt = "challenge underflow"; -+ resp = WLAN_STATUS_CHALLENGE_FAIL; -+ goto fail; -+ } -+ challenge = (char *) (u + 2); -+ } -+ } -+ -+ if (sta && sta->ap) { -+ if (jiffies > sta->u.ap.last_beacon + -+ (10 * sta->listen_interval * HZ) / 1024) { -+ PDEBUG(DEBUG_AP, "%s: no beacons received for a while," -+ " assuming AP " MACSTR " is now STA\n", -+ dev->name, MAC2STR(sta->addr)); -+ sta->ap = 0; -+ sta->flags = 0; -+ sta->u.sta.challenge = NULL; -+ } else { -+ txt = "AP trying to authenticate?"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ } -+ -+ if ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) || -+ (auth_alg == WLAN_AUTH_SHARED_KEY && -+ (auth_transaction == 1 || -+ (auth_transaction == 3 && sta != NULL && -+ sta->u.sta.challenge != NULL)))) { -+ } else { -+ txt = "unknown authentication transaction number"; -+ resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; -+ goto fail; -+ } -+ -+ if (sta == NULL) { -+ txt = "new STA"; -+ -+ if (local->ap->num_sta >= MAX_STA_COUNT) { -+ /* FIX: might try to remove some old STAs first? */ -+ txt = "no more room for new STAs"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ -+ sta = ap_add_sta(local->ap, rxdesc->addr2); -+ if (sta == NULL) { -+ txt = "ap_add_sta failed"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ } -+ -+ prism2_ap_update_sq(sta, rxdesc); -+ -+ switch (auth_alg) { -+ case WLAN_AUTH_OPEN: -+ txt = "authOK"; -+ /* STA will be authenticated, if it ACKs authentication frame -+ */ -+ break; -+ -+ case WLAN_AUTH_SHARED_KEY: -+ if (auth_transaction == 1) { -+ if (sta->u.sta.challenge == NULL) { -+ sta->u.sta.challenge = -+ ap_auth_make_challenge(local->ap); -+ if (sta->u.sta.challenge == NULL) { -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ } -+ } else { -+ if (sta->u.sta.challenge == NULL || -+ challenge == NULL || -+ memcmp(sta->u.sta.challenge, challenge, -+ WLAN_AUTH_CHALLENGE_LEN) != 0 || -+ !(fc & WLAN_FC_ISWEP)) { -+ txt = "challenge response incorrect"; -+ resp = WLAN_STATUS_CHALLENGE_FAIL; -+ goto fail; -+ } -+ -+ txt = "challenge OK - authOK"; -+ /* STA will be authenticated, if it ACKs authentication -+ * frame */ -+ kfree(sta->u.sta.challenge); -+ sta->u.sta.challenge = NULL; -+ } -+ break; -+ } -+ -+ fail: -+ pos = (u16 *) body; -+ *pos = cpu_to_le16(auth_alg); -+ pos++; -+ *pos = cpu_to_le16(auth_transaction + 1); -+ pos++; -+ *pos = cpu_to_le16(resp); /* status_code */ -+ pos++; -+ olen = 6; -+ -+ if (resp == WLAN_STATUS_SUCCESS && sta != NULL && -+ sta->u.sta.challenge != NULL && -+ auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 1) { -+ u8 *tmp = (u8 *) pos; -+ *tmp++ = WLAN_EID_CHALLENGE; -+ *tmp++ = WLAN_AUTH_CHALLENGE_LEN; -+ pos++; -+ memcpy(pos, sta->u.sta.challenge, WLAN_AUTH_CHALLENGE_LEN); -+ olen += 2 + WLAN_AUTH_CHALLENGE_LEN; -+ } -+ -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_AUTH, -+ body, olen, 1, rxdesc->addr2, ap->tx_callback_auth); -+ -+ if (sta) { -+ sta->last_rx = jiffies; -+ atomic_dec(&sta->users); -+ } -+ -+#if 0 -+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth (alg=%d trans#=%d stat=%d len=%d" -+ " fc=%04x) ==> %d (%s)\n", dev->name, MAC2STR(rxdesc->addr2), -+ auth_alg, auth_transaction, status_code, len, fc, resp, txt); -+#endif -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_assoc(local_info_t *local, struct hfa384x_rx_frame *rxdesc, -+ int reassoc) -+{ -+ struct net_device *dev = local->dev; -+ char body[12], *p, *lpos; -+ int len, left; -+ u16 *pos; -+ u16 resp = WLAN_STATUS_SUCCESS; -+ struct sta_info *sta = NULL; -+ int send_deauth = 0; -+ char *txt = ""; -+ u8 prev_ap[ETH_ALEN]; -+ -+ left = len = __le16_to_cpu(rxdesc->data_len); -+ -+ if (len < (reassoc ? 10 : 4)) { -+ PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload " -+ "(len=%d, reassoc=%d) from " MACSTR "\n", -+ dev->name, len, reassoc, MAC2STR(rxdesc->addr2)); -+ return; -+ } -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ txt = "trying to associate before authentication"; -+ send_deauth = 1; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ -+ prism2_ap_update_sq(sta, rxdesc); -+ -+ pos = (u16 *) (rxdesc + 1); -+ sta->capability = __le16_to_cpu(*pos); -+ pos++; left -= 2; -+ sta->listen_interval = __le16_to_cpu(*pos); -+ pos++; left -= 2; -+ -+ if (reassoc) { -+ memcpy(prev_ap, pos, ETH_ALEN); -+ pos++; pos++; pos++; left -= 6; -+ } else -+ memset(prev_ap, 0, ETH_ALEN); -+ -+ if (left >= 2) { -+ unsigned int ileft; -+ unsigned char *u = (unsigned char *) pos; -+ -+ if (*u == WLAN_EID_SSID) { -+ u++; left--; -+ ileft = *u; -+ u++; left--; -+ -+ if (ileft > left || ileft > MAX_SSID_LEN) { -+ txt = "SSID overflow"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ -+ if (ileft != strlen(local->essid) || -+ memcmp(local->essid, u, ileft) != 0) { -+ txt = "not our SSID"; -+ resp = WLAN_STATUS_ASSOC_DENIED_UNSPEC; -+ goto fail; -+ } -+ -+ u += ileft; -+ left -= ileft; -+ } -+ -+ if (left >= 2 && *u == WLAN_EID_SUPP_RATES) { -+ u++; left--; -+ ileft = *u; -+ u++; left--; -+ -+ if (ileft > left || ileft == 0 || -+ ileft > WLAN_SUPP_RATES_MAX) { -+ txt = "SUPP_RATES len error"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ -+ memset(sta->supported_rates, 0, -+ sizeof(sta->supported_rates)); -+ memcpy(sta->supported_rates, u, ileft); -+ prism2_check_tx_rates(sta); -+ -+ u += ileft; -+ left -= ileft; -+ } -+ -+ if (left > 0) { -+ PDEBUG(DEBUG_AP, "%s: assoc from " MACSTR " with extra" -+ " data (%d bytes) [", -+ dev->name, MAC2STR(rxdesc->addr2), left); -+ while (left > 0) { -+ PDEBUG2(DEBUG_AP, "<%02x>", *u); -+ u++; left--; -+ } -+ PDEBUG2(DEBUG_AP, "]\n"); -+ } -+ } else { -+ txt = "frame underflow"; -+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -+ goto fail; -+ } -+ -+ /* get a unique AID */ -+ if (sta->aid > 0) -+ txt = "OK, old AID"; -+ else { -+ spin_lock_bh(&local->ap->sta_table_lock); -+ for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) -+ if (local->ap->sta_aid[sta->aid - 1] == NULL) -+ break; -+ if (sta->aid > MAX_AID_TABLE_SIZE) { -+ sta->aid = 0; -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; -+ txt = "no room for more AIDs"; -+ } else { -+ local->ap->sta_aid[sta->aid - 1] = sta; -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ txt = "OK, new AID"; -+ } -+ } -+ -+ fail: -+ pos = (u16 *) body; -+ -+ if (send_deauth) { -+ *pos = __constant_cpu_to_le16( -+ WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH); -+ pos++; -+ } else { -+ /* FIX: CF-Pollable and CF-PollReq should be set to match the -+ * values in beacons/probe responses */ -+ /* FIX: how about privacy and WEP? */ -+ /* capability */ -+ *pos = __constant_cpu_to_le16(WLAN_CAPABILITY_ESS); -+ pos++; -+ -+ /* status_code */ -+ *pos = __cpu_to_le16(resp); -+ pos++; -+ -+ *pos = __cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) | -+ BIT(14) | BIT(15)); /* AID */ -+ pos++; -+ -+ /* Supported rates (Information element) */ -+ p = (char *) pos; -+ *p++ = WLAN_EID_SUPP_RATES; -+ lpos = p; -+ *p++ = 0; /* len */ -+ if (local->tx_rate_control & WLAN_RATE_1M) { -+ *p++ = local->basic_rates & WLAN_RATE_1M ? 0x82 : 0x02; -+ (*lpos)++; -+ } -+ if (local->tx_rate_control & WLAN_RATE_2M) { -+ *p++ = local->basic_rates & WLAN_RATE_2M ? 0x84 : 0x04; -+ (*lpos)++; -+ } -+ if (local->tx_rate_control & WLAN_RATE_5M5) { -+ *p++ = local->basic_rates & WLAN_RATE_5M5 ? -+ 0x8b : 0x0b; -+ (*lpos)++; -+ } -+ if (local->tx_rate_control & WLAN_RATE_11M) { -+ *p++ = local->basic_rates & WLAN_RATE_11M ? -+ 0x96 : 0x16; -+ (*lpos)++; -+ } -+ pos = (u16 *) p; -+ } -+ -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_MGMT, -+ (send_deauth ? WLAN_FC_STYPE_DEAUTH : -+ (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : -+ WLAN_FC_STYPE_ASSOC_RESP)), -+ body, (u8 *) pos - (u8 *) body, 1, -+ rxdesc->addr2, -+ send_deauth ? 0 : local->ap->tx_callback_assoc); -+ -+ if (sta) { -+ if (resp == WLAN_STATUS_SUCCESS) { -+ sta->last_rx = jiffies; -+ /* STA will be marked associated from TX callback, if -+ * AssocResp is ACKed */ -+ } -+ atomic_dec(&sta->users); -+ } -+ -+#if 0 -+ PDEBUG(DEBUG_AP, "%s: " MACSTR " %sassoc (len=%d prev_ap=" MACSTR -+ ") => %d(%d) (%s)\n", -+ dev->name, MAC2STR(rxdesc->addr2), reassoc ? "re" : "", len, -+ MAC2STR(prev_ap), resp, send_deauth, txt); -+#endif -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_deauth(local_info_t *local, struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ char *body = (char *) (rxdesc + 1); -+ int len; -+ u16 reason_code, *pos; -+ struct sta_info *sta = NULL; -+ -+ len = __le16_to_cpu(rxdesc->data_len); -+ -+ if (len < 2) { -+ printk("handle_deauth - too short payload (len=%d)\n", len); -+ return; -+ } -+ -+ pos = (u16 *) body; -+ reason_code = __le16_to_cpu(*pos); -+ -+ PDEBUG(DEBUG_AP, "%s: deauthentication: " MACSTR " len=%d, " -+ "reason_code=%d\n", dev->name, MAC2STR(rxdesc->addr2), len, -+ reason_code); -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta != NULL) { -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) -+ hostap_event_expired_sta(local->dev, sta); -+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); -+ prism2_ap_update_sq(sta, rxdesc); -+ } -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ if (sta == NULL) { -+ printk("%s: deauthentication from " MACSTR ", " -+ "reason_code=%d, but STA not authenticated\n", dev->name, -+ MAC2STR(rxdesc->addr2), reason_code); -+ } -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_disassoc(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ char *body = (char *) (rxdesc + 1); -+ int len; -+ u16 reason_code, *pos; -+ struct sta_info *sta = NULL; -+ -+ len = __le16_to_cpu(rxdesc->data_len); -+ -+ if (len < 2) { -+ printk("handle_disassoc - too short payload (len=%d)\n", len); -+ return; -+ } -+ -+ pos = (u16 *) body; -+ reason_code = __le16_to_cpu(*pos); -+ -+ PDEBUG(DEBUG_AP, "%s: disassociation: " MACSTR " len=%d, " -+ "reason_code=%d\n", dev->name, MAC2STR(rxdesc->addr2), len, -+ reason_code); -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta != NULL) { -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) -+ hostap_event_expired_sta(local->dev, sta); -+ sta->flags &= ~WLAN_STA_ASSOC; -+ prism2_ap_update_sq(sta, rxdesc); -+ } -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ if (sta == NULL) { -+ printk("%s: disassociation from " MACSTR ", " -+ "reason_code=%d, but STA not authenticated\n", -+ dev->name, MAC2STR(rxdesc->addr2), reason_code); -+ } -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void ap_handle_data_nullfunc(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ -+ /* some STA f/w's seem to require control::ACK frame for -+ * data::nullfunc, but at least Prism2 station f/w version 0.8.0 does -+ * not send this.. -+ * send control::ACK for the data::nullfunc */ -+ -+ printk(KERN_DEBUG "Sending control::ACK for data::nullfunc\n"); -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_CTRL, WLAN_FC_STYPE_ACK, -+ NULL, 0, 0, rxdesc->addr2, 0); -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void ap_handle_dropped_data(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ struct sta_info *sta; -+ u16 reason; -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ -+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC)) { -+ PDEBUG(DEBUG_AP, "ap_handle_dropped_data: STA is now okay?\n"); -+ atomic_dec(&sta->users); -+ return; -+ } -+ -+ reason = __constant_cpu_to_le16( -+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); -+ prism2_send_mgmt(dev, WLAN_FC_TYPE_MGMT, -+ ((sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) ? -+ WLAN_FC_STYPE_DEAUTH : WLAN_FC_STYPE_DISASSOC), -+ (char *) &reason, sizeof(reason), 1, -+ rxdesc->addr2, 0); -+ -+ if (sta) -+ atomic_dec(&sta->users); -+} -+ -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta, -+ struct sk_buff *skb) -+{ -+ if (!(sta->flags & WLAN_STA_PS)) { -+ /* Station has moved to non-PS mode, so send all buffered -+ * frames using normal device queue. */ -+ dev_queue_xmit(skb); -+ return; -+ } -+ -+ /* add a flag for hostap_handle_sta_tx() to know that this skb should -+ * be passed through even though STA is using PS */ -+ memcpy(skb->cb, AP_SKB_CB_MAGIC, AP_SKB_CB_MAGIC_LEN); -+ skb->cb[AP_SKB_CB_MAGIC_LEN] = AP_SKB_CB_BUFFERED_FRAME; -+ if (!skb_queue_empty(&sta->tx_buf)) { -+ /* indicate to STA that more frames follow */ -+ skb->cb[AP_SKB_CB_MAGIC_LEN] |= AP_SKB_CB_ADD_MOREDATA; -+ } -+ if (skb->dev->hard_start_xmit(skb, skb->dev)) { -+ PDEBUG(DEBUG_AP, "%s: TX failed for buffered frame (PS Poll)" -+ "\n", skb->dev->name); -+ dev_kfree_skb(skb); -+ } -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_pspoll(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ struct net_device *dev = local->dev; -+ struct sta_info *sta; -+ u16 aid; -+ struct sk_buff *skb; -+ -+ PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MACSTR ", TA=" MACSTR -+ " PWRMGT=%d\n", -+ MAC2STR(rxdesc->addr1), MAC2STR(rxdesc->addr2), -+ !!(le16_to_cpu(rxdesc->frame_control) & WLAN_FC_PWRMGT)); -+ -+ if (memcmp(rxdesc->addr1, dev->dev_addr, 6)) { -+ PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MACSTR -+ " not own MAC\n", MAC2STR(rxdesc->addr1)); -+ return; -+ } -+ -+ aid = __le16_to_cpu(rxdesc->duration_id); -+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) { -+ PDEBUG(DEBUG_PS, " PSPOLL and AID[15:14] not set\n"); -+ return; -+ } -+ aid &= ~BIT(15) & ~BIT(14); -+ if (aid == 0 || aid > MAX_AID_TABLE_SIZE) { -+ PDEBUG(DEBUG_PS, " invalid aid=%d\n", aid); -+ return; -+ } -+ PDEBUG(DEBUG_PS2, " aid=%d\n", aid); -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ -+ if (sta == NULL) { -+ PDEBUG(DEBUG_PS, " STA not found\n"); -+ return; -+ } -+ prism2_ap_update_sq(sta, rxdesc); -+ if (sta->aid != aid) { -+ PDEBUG(DEBUG_PS, " received aid=%i does not match with " -+ "assoc.aid=%d\n", aid, sta->aid); -+ return; -+ } -+ -+ /* FIX: todo: -+ * - add timeout for buffering (clear aid in TIM vector if buffer timed -+ * out (expiry time must be longer than ListenInterval for -+ * the corresponding STA; "8802-11: 11.2.1.9 AP aging function" -+ * - what to do, if buffered, pspolled, and sent frame is not ACKed by -+ * sta; store buffer for later use and leave TIM aid bit set? use -+ * TX event to check whether frame was ACKed? -+ */ -+ -+ while ((skb = skb_dequeue(&sta->tx_buf)) != NULL) { -+ /* send buffered frame .. */ -+ PDEBUG(DEBUG_PS2, "Sending buffered frame to STA after PS POLL" -+ " (buffer_count=%d)\n", skb_queue_len(&sta->tx_buf)); -+ -+ pspoll_send_buffered(local, sta, skb); -+ -+ if (sta->flags & WLAN_STA_PS) { -+ /* send only one buffered packet per PS Poll */ -+ /* FIX: should ignore further PS Polls until the -+ * buffered packet that was just sent is acknowledged -+ * (Tx or TxExc event) */ -+ break; -+ } -+ } -+ -+ if (skb_queue_empty(&sta->tx_buf)) { -+ /* try to clear aid from TIM */ -+ if (!(sta->flags & WLAN_STA_TIM)) -+ PDEBUG(DEBUG_PS2, "Re-unsetting TIM for aid %d\n", -+ aid); -+ hostap_set_tim(local, aid, 0); -+ sta->flags &= ~WLAN_STA_TIM; -+ } -+ -+ atomic_dec(&sta->users); -+} -+ -+ -+static void prism2_ap_update_sq(struct sta_info *sta, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ sta->last_rx_silence = rxdesc->silence; -+ sta->last_rx_signal = rxdesc->signal; -+ sta->last_rx_rate = rxdesc->rate; -+ sta->last_rx_flow = rxdesc->rxflow; -+ sta->last_rx_updated = 7; -+ if (rxdesc->rate == 10) -+ sta->rx_count[0]++; -+ else if (rxdesc->rate == 20) -+ sta->rx_count[1]++; -+ else if (rxdesc->rate == 55) -+ sta->rx_count[2]++; -+ else if (rxdesc->rate == 110) -+ sta->rx_count[3]++; -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ -+static void handle_add_wds_queue(void *data) -+{ -+ local_info_t *local = data; -+ struct add_wds_data *entry, *prev; -+ -+ spin_lock_bh(&local->lock); -+ entry = local->ap->add_wds_entries; -+ local->ap->add_wds_entries = NULL; -+ spin_unlock_bh(&local->lock); -+ -+ while (entry) { -+ PDEBUG(DEBUG_AP, "%s: adding automatic WDS connection " -+ "to AP " MACSTR "\n", -+ local->dev->name, MAC2STR(entry->addr)); -+ prism2_wds_add(local, entry->addr, 0); -+ -+ prev = entry; -+ entry = entry->next; -+ kfree(prev); -+ } -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+/* Called only as a scheduled task for pending AP frames. */ -+static void handle_beacon(local_info_t *local, struct hfa384x_rx_frame *rxdesc) -+{ -+ char *body = (char *) (rxdesc + 1); -+ int len, left; -+ u16 *pos, beacon_int, capability; -+ char *ssid = NULL; -+ unsigned char *supp_rates = NULL; -+ int ssid_len = 0, supp_rates_len = 0; -+ struct sta_info *sta = NULL; -+ int new_sta = 0, channel = -1; -+ -+ len = __le16_to_cpu(rxdesc->data_len); -+ -+ if (len < 8 + 2 + 2) { -+ printk(KERN_DEBUG "handle_beacon - too short payload " -+ "(len=%d)\n", len); -+ return; -+ } -+ -+ pos = (u16 *) body; -+ left = len; -+ -+ /* Timestamp (8 octets) */ -+ pos += 4; left -= 8; -+ /* Beacon interval (2 octets) */ -+ beacon_int = __le16_to_cpu(*pos); -+ pos++; left -= 2; -+ /* Capability information (2 octets) */ -+ capability = __le16_to_cpu(*pos); -+ pos++; left -= 2; -+ -+ if (local->ap->ap_policy != AP_OTHER_AP_EVEN_IBSS && -+ capability & WLAN_CAPABILITY_IBSS) -+ return; -+ -+ if (left >= 2) { -+ unsigned int ileft; -+ unsigned char *u = (unsigned char *) pos; -+ -+ if (*u == WLAN_EID_SSID) { -+ u++; left--; -+ ileft = *u; -+ u++; left--; -+ -+ if (ileft > left || ileft > MAX_SSID_LEN) { -+ PDEBUG(DEBUG_AP, "SSID: overflow\n"); -+ return; -+ } -+ -+ if (local->ap->ap_policy == AP_OTHER_AP_SAME_SSID && -+ (ileft != strlen(local->essid) || -+ memcmp(local->essid, u, ileft) != 0)) { -+ /* not our SSID */ -+ return; -+ } -+ -+ ssid = u; -+ ssid_len = ileft; -+ -+ u += ileft; -+ left -= ileft; -+ } -+ -+ if (*u == WLAN_EID_SUPP_RATES) { -+ u++; left--; -+ ileft = *u; -+ u++; left--; -+ -+ if (ileft > left || ileft == 0 || ileft > 8) { -+ PDEBUG(DEBUG_AP, " - SUPP_RATES len error\n"); -+ return; -+ } -+ -+ supp_rates = u; -+ supp_rates_len = ileft; -+ -+ u += ileft; -+ left -= ileft; -+ } -+ -+ if (*u == WLAN_EID_DS_PARAMS) { -+ u++; left--; -+ ileft = *u; -+ u++; left--; -+ -+ if (ileft > left || ileft != 1) { -+ PDEBUG(DEBUG_AP, " - DS_PARAMS len error\n"); -+ return; -+ } -+ -+ channel = *u; -+ -+ u += ileft; -+ left -= ileft; -+ } -+ } -+ -+ spin_lock_bh(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta != NULL) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&local->ap->sta_table_lock); -+ -+ if (sta == NULL) { -+ /* add new AP */ -+ new_sta = 1; -+ sta = ap_add_sta(local->ap, rxdesc->addr2); -+ if (sta == NULL) { -+ printk(KERN_INFO "prism2: kmalloc failed for AP " -+ "data structure\n"); -+ return; -+ } -+ hostap_event_new_sta(local->dev, sta); -+ -+ /* mark APs authentication and associated for pseudo ad-hoc -+ * style communication */ -+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; -+ -+ if (local->ap->autom_ap_wds) { -+ /* schedule a non-interrupt context process to add the -+ * WDS device since register_netdevice() can sleep */ -+ struct add_wds_data *entry; -+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (entry) { -+ memcpy(entry->addr, sta->addr, ETH_ALEN); -+ spin_lock_bh(&local->lock); -+ entry->next = local->ap->add_wds_entries; -+ local->ap->add_wds_entries = entry; -+ spin_unlock_bh(&local->lock); -+ PRISM2_SCHEDULE_TASK(&local->ap-> -+ add_wds_queue); -+ } -+ } -+ } -+ -+ sta->ap = 1; -+ if (ssid) { -+ sta->u.ap.ssid_len = ssid_len; -+ memcpy(sta->u.ap.ssid, ssid, ssid_len); -+ sta->u.ap.ssid[ssid_len] = '\0'; -+ } else { -+ sta->u.ap.ssid_len = 0; -+ sta->u.ap.ssid[0] = '\0'; -+ } -+ sta->u.ap.channel = channel; -+ sta->rx_packets++; -+ sta->rx_bytes += len; -+ sta->u.ap.last_beacon = sta->last_rx = jiffies; -+ sta->capability = capability; -+ sta->listen_interval = beacon_int; -+ prism2_ap_update_sq(sta, rxdesc); -+ -+ atomic_dec(&sta->users); -+ -+ if (new_sta) { -+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); -+ memcpy(sta->supported_rates, supp_rates, supp_rates_len); -+ prism2_check_tx_rates(sta); -+ } -+} -+ -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+/* Called only as a tasklet. */ -+static void handle_ap_item(local_info_t *local, struct sk_buff *skb) -+{ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ struct net_device *dev = local->dev; -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ u16 fc, type, stype; -+ struct hfa384x_rx_frame *rxdesc; -+ -+ /* FIX: should give skb->len to handler functions and check that the -+ * buffer is long enough */ -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ fc = __le16_to_cpu(rxdesc->frame_control); -+ type = WLAN_FC_GET_TYPE(fc); -+ stype = WLAN_FC_GET_STYPE(fc); -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (!local->hostapd && type == WLAN_FC_TYPE_DATA) { -+ PDEBUG(DEBUG_AP, "handle_ap_item - data frame\n"); -+ -+ if (!(fc & WLAN_FC_TODS) || (fc & WLAN_FC_FROMDS)) { -+ if (stype == WLAN_FC_STYPE_NULLFUNC) { -+ /* no ToDS nullfunc seems to be used to check -+ * AP association; so send reject message to -+ * speed up re-association */ -+ ap_handle_dropped_data(local, rxdesc); -+ goto done; -+ } -+ PDEBUG(DEBUG_AP, " not ToDS frame (fc=0x%04x)\n", -+ fc); -+ goto done; -+ } -+ -+ if (memcmp(rxdesc->addr1, dev->dev_addr, 6)) { -+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=" -+ MACSTR " not own MAC\n", -+ MAC2STR(rxdesc->addr1)); -+ goto done; -+ } -+ -+ if (local->ap->nullfunc_ack && stype == WLAN_FC_STYPE_NULLFUNC) -+ ap_handle_data_nullfunc(local, rxdesc); -+ else -+ ap_handle_dropped_data(local, rxdesc); -+ goto done; -+ } -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ if (type == WLAN_FC_TYPE_CTRL && -+ stype == WLAN_FC_STYPE_PSPOLL) { -+ handle_pspoll(local, rxdesc); -+ goto done; -+ } -+ -+ if (local->hostapd) { -+ PDEBUG(DEBUG_AP, "Unknown frame in AP queue: type=0x%02x " -+ "subtype=0x%02x\n", type, stype); -+ goto done; -+ } -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (type != WLAN_FC_TYPE_MGMT) { -+ PDEBUG(DEBUG_AP, "handle_ap_item - not a management frame?\n"); -+ goto done; -+ } -+ -+ if (stype == WLAN_FC_STYPE_BEACON) { -+ handle_beacon(local, rxdesc); -+ goto done; -+ } -+ -+ if (memcmp(rxdesc->addr1, dev->dev_addr, 6)) { -+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MACSTR -+ " not own MAC\n", MAC2STR(rxdesc->addr1)); -+ goto done; -+ } -+ -+ if (memcmp(rxdesc->addr3, dev->dev_addr, 6)) { -+ PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MACSTR -+ " not own MAC\n", MAC2STR(rxdesc->addr3)); -+ goto done; -+ } -+ -+ switch (stype) { -+ case WLAN_FC_STYPE_ASSOC_REQ: -+ handle_assoc(local, rxdesc, 0); -+ break; -+ case WLAN_FC_STYPE_ASSOC_RESP: -+ PDEBUG(DEBUG_AP, "==> ASSOC RESP (ignored)\n"); -+ break; -+ case WLAN_FC_STYPE_REASSOC_REQ: -+ handle_assoc(local, rxdesc, 1); -+ break; -+ case WLAN_FC_STYPE_REASSOC_RESP: -+ PDEBUG(DEBUG_AP, "==> REASSOC RESP (ignored)\n"); -+ break; -+ case WLAN_FC_STYPE_ATIM: -+ PDEBUG(DEBUG_AP, "==> ATIM (ignored)\n"); -+ break; -+ case WLAN_FC_STYPE_DISASSOC: -+ handle_disassoc(local, rxdesc); -+ break; -+ case WLAN_FC_STYPE_AUTH: -+ handle_authen(local, rxdesc); -+ break; -+ case WLAN_FC_STYPE_DEAUTH: -+ handle_deauth(local, rxdesc); -+ break; -+ default: -+ PDEBUG(DEBUG_AP, "Unknown mgmt frame subtype 0x%02x\n", stype); -+ break; -+ } -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ done: -+ dev_kfree_skb(skb); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+void hostap_rx(struct net_device *dev, struct sk_buff *skb) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 fc; -+ struct hfa384x_rx_frame *rxdesc; -+ -+ if (skb->len < sizeof(*rxdesc)) -+ goto drop; -+ -+ local->stats.rx_packets++; -+ -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ fc = le16_to_cpu(rxdesc->frame_control); -+ -+ if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL && -+ WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && -+ WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) -+ goto drop; -+ -+ handle_ap_item(local, skb); -+ return; -+ -+ drop: -+ dev_kfree_skb(skb); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void schedule_packet_send(local_info_t *local, struct sta_info *sta) -+{ -+ struct sk_buff *skb; -+ struct hfa384x_rx_frame *rxdesc; -+ -+ if (skb_queue_empty(&sta->tx_buf)) -+ return; -+ -+ skb = dev_alloc_skb(sizeof(*rxdesc)); -+ if (skb == NULL) { -+ printk(KERN_DEBUG "%s: schedule_packet_send: skb alloc " -+ "failed\n", local->dev->name); -+ return; -+ } -+ -+ rxdesc = (struct hfa384x_rx_frame *) skb_put(skb, sizeof(*rxdesc)); -+ -+ /* Generate a fake pspoll frame to start packet delivery */ -+ memset(rxdesc, 0, sizeof(*rxdesc)); -+ rxdesc->frame_control = __constant_cpu_to_le16( -+ (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_PSPOLL << 4)); -+ memcpy(rxdesc->addr1, local->dev->dev_addr, 6); -+ memcpy(rxdesc->addr2, sta->addr, 6); -+ rxdesc->duration_id = __cpu_to_le16(sta->aid | BIT(15) | BIT(14)); -+ -+ PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for " -+ "STA " MACSTR "\n", local->dev->name, MAC2STR(sta->addr)); -+ -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ skb->dev = local->dev; -+ -+ hostap_rx(local->dev, skb); -+} -+ -+ -+#ifdef WIRELESS_EXT -+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], -+ struct iw_quality qual[], int buf_size, -+ int aplist) -+{ -+ struct ap_data *ap = local->ap; -+ struct list_head *ptr; -+ int count = 0; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ -+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list; -+ ptr = ptr->next) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ -+ if (aplist && !sta->ap) -+ continue; -+ addr[count].sa_family = ARPHRD_ETHER; -+ memcpy(addr[count].sa_data, sta->addr, ETH_ALEN); -+ if (sta->last_rx_silence == 0) -+ qual[count].qual = sta->last_rx_signal < 27 ? -+ 0 : (sta->last_rx_signal - 27) * 92 / 127; -+ else -+ qual[count].qual = sta->last_rx_signal - -+ sta->last_rx_silence - 35; -+ qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); -+ qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); -+ qual[count].updated = sta->last_rx_updated; -+ -+ sta->last_rx_updated = 0; -+ -+ count++; -+ if (count >= buf_size) -+ break; -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ return count; -+} -+ -+ -+#if WIRELESS_EXT > 13 -+/* Translate our list of Access Points & Stations to a card independant -+ * format that the Wireless Tools will understand - Jean II */ -+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct ap_data *ap = local->ap; -+ struct list_head *ptr; -+ struct iw_event iwe; -+ char *current_ev = buffer; -+ char *end_buf = buffer + IW_SCAN_MAX_DATA; -+#if !defined(PRISM2_NO_KERNEL_IEEE80211_MGMT) && (WIRELESS_EXT > 14) -+ char buf[64]; -+#endif -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ -+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list; -+ ptr = ptr->next) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ -+ /* First entry *MUST* be the AP MAC address */ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWAP; -+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; -+ memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN); -+ iwe.len = IW_EV_ADDR_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_ADDR_LEN); -+ -+ /* Use the mode to indicate if it's a station or -+ * an Access Point */ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWMODE; -+ if (sta->ap) -+ iwe.u.mode = IW_MODE_MASTER; -+ else -+ iwe.u.mode = IW_MODE_INFRA; -+ iwe.len = IW_EV_UINT_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_UINT_LEN); -+ -+ /* Some quality */ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = IWEVQUAL; -+ if (sta->last_rx_silence == 0) -+ iwe.u.qual.qual = sta->last_rx_signal < 27 ? -+ 0 : (sta->last_rx_signal - 27) * 92 / 127; -+ else -+ iwe.u.qual.qual = sta->last_rx_signal - -+ sta->last_rx_silence - 35; -+ iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); -+ iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); -+ iwe.u.qual.updated = sta->last_rx_updated; -+ iwe.len = IW_EV_QUAL_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_QUAL_LEN); -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (sta->ap) { -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWESSID; -+ iwe.u.data.length = sta->u.ap.ssid_len; -+ iwe.u.data.flags = 1; -+ current_ev = iwe_stream_add_point(current_ev, end_buf, -+ &iwe, -+ sta->u.ap.ssid); -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWENCODE; -+ if (sta->capability & WLAN_CAPABILITY_PRIVACY) -+ iwe.u.data.flags = -+ IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; -+ else -+ iwe.u.data.flags = IW_ENCODE_DISABLED; -+ current_ev = iwe_stream_add_point(current_ev, end_buf, -+ &iwe, -+ sta->u.ap.ssid -+ /* 0 byte memcpy */); -+ -+ if (sta->u.ap.channel > 0 && -+ sta->u.ap.channel <= FREQ_COUNT) { -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWFREQ; -+ iwe.u.freq.m = freq_list[sta->u.ap.channel - 1] -+ * 100000; -+ iwe.u.freq.e = 1; -+ current_ev = iwe_stream_add_event( -+ current_ev, end_buf, &iwe, -+ IW_EV_FREQ_LEN); -+ } -+ -+#if WIRELESS_EXT > 14 -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = IWEVCUSTOM; -+ sprintf(buf, "beacon_interval=%d", -+ sta->listen_interval); -+ iwe.u.data.length = strlen(buf); -+ current_ev = iwe_stream_add_point(current_ev, end_buf, -+ &iwe, buf); -+#endif /* WIRELESS_EXT > 14 */ -+ } -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ sta->last_rx_updated = 0; -+ -+ /* To be continued, we should make good use of IWEVCUSTOM */ -+ } -+ -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ return current_ev - buffer; -+} -+#endif /* WIRELESS_EXT > 13 */ -+#endif /* WIRELESS_EXT */ -+ -+ -+static int prism2_hostapd_add_sta(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, param->sta_addr); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (sta == NULL) { -+ sta = ap_add_sta(ap, param->sta_addr); -+ if (sta == NULL) -+ return -1; -+ } -+ -+ if (!(sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) -+ hostap_event_new_sta(sta->local->dev, sta); -+ -+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; -+ sta->last_rx = jiffies; -+ sta->aid = param->u.add_sta.aid; -+ sta->capability = param->u.add_sta.capability; -+ sta->tx_supp_rates = param->u.add_sta.tx_supp_rates; -+ if (sta->tx_supp_rates & WLAN_RATE_1M) -+ sta->supported_rates[0] = 2; -+ if (sta->tx_supp_rates & WLAN_RATE_2M) -+ sta->supported_rates[1] = 4; -+ if (sta->tx_supp_rates & WLAN_RATE_5M5) -+ sta->supported_rates[2] = 11; -+ if (sta->tx_supp_rates & WLAN_RATE_11M) -+ sta->supported_rates[3] = 22; -+ prism2_check_tx_rates(sta); -+ atomic_dec(&sta->users); -+ return 0; -+} -+ -+ -+static int prism2_hostapd_remove_sta(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, param->sta_addr); -+ if (sta) { -+ ap_sta_hash_del(ap, sta); -+ list_del(&sta->list); -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (!sta) -+ return -ENOENT; -+ -+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) -+ hostap_event_expired_sta(sta->local->dev, sta); -+ ap_free_sta(ap, sta); -+ -+ return 0; -+} -+ -+ -+static int prism2_hostapd_get_info_sta(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, param->sta_addr); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (!sta) -+ return -ENOENT; -+ -+ param->u.get_info_sta.inactive_sec = (jiffies - sta->last_rx) / HZ; -+ param->u.get_info_sta.txexc = sta->txexc; -+ -+ atomic_dec(&sta->users); -+ -+ return 1; -+} -+ -+ -+static int prism2_hostapd_reset_txexc_sta(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, param->sta_addr); -+ if (sta) -+ sta->txexc = 0; -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ return sta ? 0 : -ENOENT; -+} -+ -+ -+static int prism2_hostapd_set_flags_sta(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, param->sta_addr); -+ if (sta) { -+ sta->flags |= param->u.set_flags_sta.flags_or; -+ sta->flags &= param->u.set_flags_sta.flags_and; -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (!sta) -+ return -ENOENT; -+ -+ return 0; -+} -+ -+ -+static int prism2_hostapd(struct ap_data *ap, -+ struct prism2_hostapd_param *param) -+{ -+ switch (param->cmd) { -+ case PRISM2_HOSTAPD_FLUSH: -+ ap_control_kickall(ap); -+ return 0; -+ case PRISM2_HOSTAPD_ADD_STA: -+ return prism2_hostapd_add_sta(ap, param); -+ case PRISM2_HOSTAPD_REMOVE_STA: -+ return prism2_hostapd_remove_sta(ap, param); -+ case PRISM2_HOSTAPD_GET_INFO_STA: -+ return prism2_hostapd_get_info_sta(ap, param); -+ case PRISM2_HOSTAPD_RESET_TXEXC_STA: -+ return prism2_hostapd_reset_txexc_sta(ap, param); -+ case PRISM2_HOSTAPD_SET_FLAGS_STA: -+ return prism2_hostapd_set_flags_sta(ap, param); -+ default: -+ printk(KERN_WARNING "prism2_hostapd: unknown cmd=%d\n", -+ param->cmd); -+ return -EOPNOTSUPP; -+ } -+} -+ -+ -+/* Update station info for host-based TX rate control and return current -+ * TX rate */ -+static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev) -+{ -+ int ret = sta->tx_rate; -+ local_info_t *local = dev->priv; -+ -+ sta->tx_count[sta->tx_rate_idx]++; -+ sta->tx_since_last_failure++; -+ if (sta->tx_since_last_failure > WLAN_RATE_UPDATE_COUNT && -+ sta->tx_rate_idx < sta->tx_max_rate) { -+ /* use next higher rate */ -+ int old_rate, new_rate; -+ old_rate = new_rate = sta->tx_rate_idx; -+ while (new_rate < sta->tx_max_rate) { -+ new_rate++; -+ if (ap_tx_rate_ok(new_rate, sta, local)) { -+ sta->tx_rate_idx = new_rate; -+ break; -+ } -+ } -+ if (old_rate != sta->tx_rate_idx) { -+ switch (sta->tx_rate_idx) { -+ case 0: sta->tx_rate = 10; break; -+ case 1: sta->tx_rate = 20; break; -+ case 2: sta->tx_rate = 55; break; -+ case 3: sta->tx_rate = 110; break; -+ default: sta->tx_rate = 0; break; -+ } -+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate raised to" -+ " %d\n", dev->name, MAC2STR(sta->addr), -+ sta->tx_rate); -+ } -+ sta->tx_since_last_failure = 0; -+ } -+ -+ return ret; -+} -+ -+ -+/* Called only from software IRQ. Called for each TX frame prior possible -+ * encryption and transmit. */ -+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct sk_buff *skb, -+ struct hfa384x_tx_frame *txdesc, int wds, -+ int host_encrypt, -+ struct prism2_crypt_data **crypt, -+ void **sta_ptr) -+{ -+ struct sta_info *sta = NULL; -+ int set_tim, ret; -+ -+ ret = AP_TX_CONTINUE; -+ if (local->ap == NULL) -+ goto out; -+ -+ if (txdesc->addr1[0] & 0x01) { -+ /* broadcast/multicast frame - no AP related processing */ -+ goto out; -+ } -+ -+ /* unicast packet - check whether destination STA is associated */ -+ spin_lock(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, txdesc->addr1); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&local->ap->sta_table_lock); -+ -+ if (local->iw_mode == IW_MODE_MASTER && sta == NULL && !wds) { -+ /* remove FromDS flag from (pseudo) ad-hoc style -+ * communication between APs */ -+ txdesc->frame_control &= -+ ~(__constant_cpu_to_le16(WLAN_FC_FROMDS)); -+ -+ printk(KERN_DEBUG "AP: packet to non-associated STA " -+ MACSTR "\n", MAC2STR(txdesc->addr1)); -+ } -+ -+ if (sta == NULL) -+ goto out; -+ -+ if (!(sta->flags & WLAN_STA_AUTHORIZED)) -+ ret = AP_TX_CONTINUE_NOT_AUTHORIZED; -+ -+ /* Set tx_rate if using host-based TX rate control */ -+ if (!local->fw_tx_rate_control) -+ local->ap->last_tx_rate = txdesc->tx_rate = -+ ap_update_sta_tx_rate(sta, local->dev); -+ -+ if (local->iw_mode != IW_MODE_MASTER) -+ goto out; -+ -+ if (!(sta->flags & WLAN_STA_PS)) -+ goto out; -+ -+ if (memcmp(skb->cb, AP_SKB_CB_MAGIC, AP_SKB_CB_MAGIC_LEN) == 0) { -+ if (skb->cb[AP_SKB_CB_MAGIC_LEN] & AP_SKB_CB_ADD_MOREDATA) { -+ /* indicate to STA that more frames follow */ -+ txdesc->frame_control |= -+ __constant_cpu_to_le16(WLAN_FC_MOREDATA); -+ } -+ -+ if (skb->cb[AP_SKB_CB_MAGIC_LEN] & AP_SKB_CB_BUFFERED_FRAME) { -+ /* packet was already buffered and now send due to -+ * PS poll, so do not rebuffer it */ -+ goto out; -+ } -+ } -+ -+ if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) { -+ PDEBUG(DEBUG_PS, "%s: No more space in STA (" MACSTR ")'s PS " -+ "mode buffer\n", local->dev->name, MAC2STR(sta->addr)); -+ /* Make sure that TIM is set for the station (it might not be -+ * after AP wlan hw reset). */ -+ hostap_set_tim(local, sta->aid, 1); -+ sta->flags |= WLAN_STA_TIM; -+ ret = AP_TX_DROP; -+ goto out; -+ } -+ -+ /* STA in PS mode, buffer frame for later delivery */ -+ set_tim = skb_queue_empty(&sta->tx_buf); -+ skb_queue_tail(&sta->tx_buf, skb); -+ /* FIX: could save RX time to skb and expire buffered frames after -+ * some time if STA does not poll for them */ -+ -+ if (set_tim) { -+ if (sta->flags & WLAN_STA_TIM) -+ PDEBUG(DEBUG_PS2, "Re-setting TIM for aid %d\n", -+ sta->aid); -+ hostap_set_tim(local, sta->aid, 1); -+ sta->flags |= WLAN_STA_TIM; -+ } -+ -+ ret = AP_TX_BUFFERED; -+ -+ out: -+ if (sta != NULL) { -+ if (ret == AP_TX_CONTINUE || -+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) { -+ sta->tx_packets++; -+ sta->tx_bytes += le16_to_cpu(txdesc->data_len) + 36; -+ sta->last_tx = jiffies; -+ } -+ -+ if ((ret == AP_TX_CONTINUE || -+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) && -+ sta->crypt && host_encrypt) { -+ *crypt = sta->crypt; -+ *sta_ptr = sta; /* hostap_handle_sta_release() will be -+ * called to release sta info later */ -+ } else -+ atomic_dec(&sta->users); -+ } -+ -+ return ret; -+} -+ -+ -+void hostap_handle_sta_release(void *ptr) -+{ -+ struct sta_info *sta = ptr; -+ atomic_dec(&sta->users); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+void hostap_handle_sta_tx_exc(local_info_t *local, -+ struct hfa384x_tx_frame *txdesc) -+{ -+ struct sta_info *sta; -+ -+ spin_lock(&local->ap->sta_table_lock); -+ /* FIX: is addr1 correct for all frame types? */ -+ sta = ap_get_sta(local->ap, txdesc->addr1); -+ if (!sta) { -+ spin_unlock(&local->ap->sta_table_lock); -+ PDEBUG(DEBUG_AP, "%s: Could not find STA for this TX error\n", -+ local->dev->name); -+ return; -+ } -+ -+ sta->txexc++; -+ sta->tx_since_last_failure = 0; -+ if (sta->tx_rate_idx > 0 && txdesc->tx_rate <= sta->tx_rate) { -+ /* use next lower rate */ -+ int old, rate; -+ old = rate = sta->tx_rate_idx; -+ while (rate > 0) { -+ rate--; -+ if (ap_tx_rate_ok(rate, sta, local)) { -+ sta->tx_rate_idx = rate; -+ break; -+ } -+ } -+ if (old != sta->tx_rate_idx) { -+ switch (sta->tx_rate_idx) { -+ case 0: sta->tx_rate = 10; break; -+ case 1: sta->tx_rate = 20; break; -+ case 2: sta->tx_rate = 55; break; -+ case 3: sta->tx_rate = 110; break; -+ default: sta->tx_rate = 0; break; -+ } -+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate lowered " -+ "to %d\n", local->dev->name, MAC2STR(sta->addr), -+ sta->tx_rate); -+ } -+ } -+ spin_unlock(&local->ap->sta_table_lock); -+} -+ -+ -+static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta, -+ int pwrmgt, int type, int stype) -+{ -+ if (pwrmgt && !(sta->flags & WLAN_STA_PS)) { -+ sta->flags |= WLAN_STA_PS; -+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to use PS " -+ "mode (type=0x%02X, stype=0x%02X)\n", -+ MAC2STR(sta->addr), type, stype); -+ } else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) { -+ sta->flags &= ~WLAN_STA_PS; -+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to not use " -+ "PS mode (type=0x%02X, stype=0x%02X)\n", -+ MAC2STR(sta->addr), type, stype); -+ if (type != WLAN_FC_TYPE_CTRL || stype != WLAN_FC_STYPE_PSPOLL) -+ schedule_packet_send(local, sta); -+ } -+} -+ -+ -+/* Called only as a tasklet (software IRQ). Called for each RX frame to update -+ * STA power saving state. pwrmgt is a flag from 802.11 frame_control field. */ -+int hostap_update_sta_ps(local_info_t *local, struct hostap_ieee80211_hdr *hdr) -+{ -+ struct sta_info *sta; -+ u16 fc; -+ -+ spin_lock(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, hdr->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&local->ap->sta_table_lock); -+ -+ if (!sta) -+ return -1; -+ -+ fc = le16_to_cpu(hdr->frame_control); -+ hostap_update_sta_ps2(local, sta, fc & WLAN_FC_PWRMGT, -+ WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc)); -+ -+ atomic_dec(&sta->users); -+ return 0; -+} -+ -+ -+/* Called only as a tasklet (software IRQ). Called for each RX frame after -+ * getting RX header and payload from hardware. */ -+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, -+ struct sk_buff *skb, int wds) -+{ -+ int ret; -+ struct sta_info *sta; -+ u16 fc, type, stype; -+ struct hfa384x_rx_frame *rxdesc; -+ -+ if (local->ap == NULL) -+ return AP_RX_CONTINUE; -+ -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ -+ fc = le16_to_cpu(rxdesc->frame_control); -+ type = WLAN_FC_GET_TYPE(fc); -+ stype = WLAN_FC_GET_STYPE(fc); -+ -+ spin_lock(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&local->ap->sta_table_lock); -+ -+ if (sta && !(sta->flags & WLAN_STA_AUTHORIZED)) -+ ret = AP_RX_CONTINUE_NOT_AUTHORIZED; -+ else -+ ret = AP_RX_CONTINUE; -+ -+ -+ if (fc & WLAN_FC_TODS) { -+ if (!wds && (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) { -+ if (local->hostapd) { -+ local->func->rx_80211(local->apdev, skb, -+ PRISM2_RX_NON_ASSOC, -+ NULL, 0); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ } else { -+ printk(KERN_DEBUG "%s: dropped received packet" -+ " from non-associated STA " MACSTR -+ " (type=0x%02x, subtype=0x%02x)\n", -+ dev->name, MAC2STR(rxdesc->addr2), type, -+ stype); -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ hostap_rx(dev, skb); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ } -+ ret = AP_RX_EXIT; -+ goto out; -+ } -+ } else if (fc & WLAN_FC_FROMDS) { -+ if (!wds) { -+ /* FromDS frame - not for us; probably -+ * broadcast/multicast in another BSS - drop */ -+ if (memcmp(rxdesc->addr1, dev->dev_addr, 6) == 0) { -+ printk(KERN_DEBUG "Odd.. FromDS packet " -+ "received with own BSSID\n"); -+ hostap_dump_rx_header(dev->name, rxdesc); -+ } -+ ret = AP_RX_DROP; -+ goto out; -+ } -+ } else if (stype == WLAN_FC_STYPE_NULLFUNC && sta == NULL && -+ memcmp(rxdesc->addr1, dev->dev_addr, 6) == 0) { -+ -+ if (local->hostapd) { -+ local->func->rx_80211(local->apdev, skb, -+ PRISM2_RX_NON_ASSOC, NULL, 0); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ } else { -+ /* At least Lucent f/w seems to send data::nullfunc -+ * frames with no ToDS flag when the current AP returns -+ * after being unavailable for some time. Speed up -+ * re-association by informing the station about it not -+ * being associated. */ -+ printk(KERN_DEBUG "%s: rejected received nullfunc " -+ "frame without ToDS from not associated STA " -+ MACSTR "\n", -+ dev->name, MAC2STR(rxdesc->addr2)); -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ hostap_rx(dev, skb); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ } -+ ret = AP_RX_EXIT; -+ goto out; -+ } else if (stype == WLAN_FC_STYPE_NULLFUNC) { -+ /* At least Lucent cards seem to send periodic nullfunc -+ * frames with ToDS. Let these through to update SQ -+ * stats and PS state. Nullfunc frames do not contain -+ * any data and they will be dropped below. */ -+ } else { -+ printk(KERN_DEBUG "%s: dropped received packet from " -+ MACSTR " with no ToDS flag (type=0x%02x, " -+ "subtype=0x%02x)\n", dev->name, -+ MAC2STR(rxdesc->addr2), type, stype); -+ hostap_dump_rx_header(dev->name, rxdesc); -+ ret = AP_RX_DROP; -+ goto out; -+ } -+ -+ if (sta) { -+ prism2_ap_update_sq(sta, rxdesc); -+ -+ hostap_update_sta_ps2(local, sta, fc & WLAN_FC_PWRMGT, -+ type, stype); -+ -+ sta->rx_packets++; -+ sta->rx_bytes += le16_to_cpu(rxdesc->data_len); -+ sta->last_rx = jiffies; -+ } -+ -+ if (local->ap->nullfunc_ack && stype == WLAN_FC_STYPE_NULLFUNC && -+ fc & WLAN_FC_TODS) { -+ if (local->hostapd) { -+ local->func->rx_80211(local->apdev, skb, -+ PRISM2_RX_NULLFUNC_ACK, NULL, 0); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ } else { -+ /* some STA f/w's seem to require control::ACK frame -+ * for data::nullfunc, but Prism2 f/w 0.8.0 (at least -+ * from Compaq) does not send this.. Try to generate -+ * ACK for these frames from the host driver to make -+ * power saving work with, e.g., Lucent WaveLAN f/w */ -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ hostap_rx(dev, skb); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ } -+ ret = AP_RX_EXIT; -+ goto out; -+ } -+ -+ out: -+ if (sta) -+ atomic_dec(&sta->users); -+ -+ return ret; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+int hostap_handle_sta_crypto(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc, -+ struct prism2_crypt_data **crypt, void **sta_ptr) -+{ -+ struct sta_info *sta; -+ -+ spin_lock(&local->ap->sta_table_lock); -+ sta = ap_get_sta(local->ap, rxdesc->addr2); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock(&local->ap->sta_table_lock); -+ -+ if (!sta) -+ return -1; -+ -+ if (sta->crypt) { -+ *crypt = sta->crypt; -+ *sta_ptr = sta; -+ /* hostap_handle_sta_release() will be called to release STA -+ * info */ -+ } else -+ atomic_dec(&sta->users); -+ -+ return 0; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr) -+{ -+ struct sta_info *sta; -+ int ret = 0; -+ -+ spin_lock(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, sta_addr); -+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap) -+ ret = 1; -+ spin_unlock(&ap->sta_table_lock); -+ -+ return ret; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) -+{ -+ struct sta_info *sta; -+ int ret = 1; -+ -+ if (!ap) -+ return -1; -+ -+ spin_lock(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, sta_addr); -+ if (sta) -+ ret = 0; -+ spin_unlock(&ap->sta_table_lock); -+ -+ if (ret == 1) { -+ sta = ap_add_sta(ap, sta_addr); -+ if (!sta) -+ ret = -1; -+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; -+ sta->ap = 1; -+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); -+ /* No way of knowing which rates are supported since we did not -+ * get supported rates element from beacon/assoc req. Assume -+ * that remote end supports all 802.11b rates. */ -+ sta->supported_rates[0] = 0x82; -+ sta->supported_rates[1] = 0x84; -+ sta->supported_rates[2] = 0x0b; -+ sta->supported_rates[3] = 0x16; -+ sta->tx_supp_rates = WLAN_RATE_1M | WLAN_RATE_2M | -+ WLAN_RATE_5M5 | WLAN_RATE_11M; -+ sta->tx_rate = 110; -+ sta->tx_max_rate = sta->tx_rate_idx = 3; -+ } -+ -+ return ret; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+int hostap_update_rx_stats(struct ap_data *ap, struct hfa384x_rx_frame *rxdesc) -+{ -+ struct sta_info *sta; -+ -+ if (!ap || !rxdesc) -+ return -1; -+ -+ spin_lock(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, rxdesc->addr2); -+ if (sta) -+ prism2_ap_update_sq(sta, rxdesc); -+ spin_unlock(&ap->sta_table_lock); -+ -+ return sta ? 0 : -1; -+} -+ -+ -+void hostap_update_rates(local_info_t *local) -+{ -+ struct list_head *ptr; -+ struct ap_data *ap = local->ap; -+ -+ if (!ap) -+ return; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ prism2_check_tx_rates(sta); -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+} -+ -+ -+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, -+ struct prism2_crypt_data ***crypt) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ sta = ap_get_sta(ap, addr); -+ if (sta) -+ atomic_inc(&sta->users); -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ if (!sta && permanent) -+ sta = ap_add_sta(ap, addr); -+ -+ if (!sta) -+ return NULL; -+ -+ if (permanent) -+ sta->flags |= WLAN_STA_PERM; -+ -+ *crypt = &sta->crypt; -+ -+ return sta; -+} -+ -+ -+void hostap_add_wds_links(local_info_t *local) -+{ -+ struct ap_data *ap = local->ap; -+ struct list_head *ptr; -+ struct add_wds_data *entry; -+ -+ spin_lock_bh(&ap->sta_table_lock); -+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { -+ struct sta_info *sta = (struct sta_info *) ptr; -+ if (!sta->ap) -+ continue; -+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (!entry) -+ break; -+ memcpy(entry->addr, sta->addr, ETH_ALEN); -+ spin_lock_bh(&local->lock); -+ entry->next = local->ap->add_wds_entries; -+ local->ap->add_wds_entries = entry; -+ spin_unlock_bh(&local->lock); -+ } -+ spin_unlock_bh(&ap->sta_table_lock); -+ -+ PRISM2_SCHEDULE_TASK(&local->ap->add_wds_queue); -+} -+ -+ -+void hostap_add_wds_link(local_info_t *local, u8 *addr) -+{ -+ struct add_wds_data *entry; -+ -+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (!entry) -+ return; -+ memcpy(entry->addr, addr, ETH_ALEN); -+ spin_lock_bh(&local->lock); -+ entry->next = local->ap->add_wds_entries; -+ local->ap->add_wds_entries = entry; -+ spin_unlock_bh(&local->lock); -+ -+ PRISM2_SCHEDULE_TASK(&local->ap->add_wds_queue); -+} -+ -+ -+EXPORT_SYMBOL(hostap_rx); -+EXPORT_SYMBOL(hostap_init_data); -+EXPORT_SYMBOL(hostap_free_data); -+EXPORT_SYMBOL(hostap_check_sta_fw_version); -+EXPORT_SYMBOL(hostap_handle_sta_tx); -+EXPORT_SYMBOL(hostap_handle_sta_release); -+EXPORT_SYMBOL(hostap_handle_sta_tx_exc); -+EXPORT_SYMBOL(hostap_update_sta_ps); -+EXPORT_SYMBOL(hostap_handle_sta_rx); -+EXPORT_SYMBOL(hostap_handle_sta_crypto); -+EXPORT_SYMBOL(hostap_is_sta_assoc); -+EXPORT_SYMBOL(hostap_add_sta); -+EXPORT_SYMBOL(hostap_update_rx_stats); -+EXPORT_SYMBOL(hostap_update_rates); -+EXPORT_SYMBOL(hostap_add_wds_links); -+EXPORT_SYMBOL(hostap_add_wds_link); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+EXPORT_SYMBOL(hostap_deauth_all_stas); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - -Index: drivers/net/wireless/hostap_ap.h ---- drivers/net/wireless/hostap_ap.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_ap.h 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,263 @@ -+#ifndef HOSTAP_AP_H -+#define HOSTAP_AP_H -+ -+/* AP data structures for STAs */ -+ -+/* maximum number of frames to buffer per STA */ -+#define STA_MAX_TX_BUFFER 32 -+ -+/* Flags used in skb->cb[6] to control how the packet is handled in TX path. -+ * skb->cb[0..5] must contain magic value 'hostap' to indicate that cb[6] is -+ * used. */ -+#define AP_SKB_CB_MAGIC "hostap" -+#define AP_SKB_CB_MAGIC_LEN 6 -+#define AP_SKB_CB_BUFFERED_FRAME BIT(0) -+#define AP_SKB_CB_ADD_MOREDATA BIT(1) -+ -+ -+/* STA flags */ -+#define WLAN_STA_AUTH BIT(0) -+#define WLAN_STA_ASSOC BIT(1) -+#define WLAN_STA_PS BIT(2) -+#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */ -+#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */ -+#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is -+ * controlling whether STA is authorized to -+ * send and receive non-IEEE 802.1X frames -+ */ -+ -+#define WLAN_RATE_1M BIT(0) -+#define WLAN_RATE_2M BIT(1) -+#define WLAN_RATE_5M5 BIT(2) -+#define WLAN_RATE_11M BIT(3) -+#define WLAN_RATE_COUNT 4 -+ -+/* Maximum size of Supported Rates info element. IEEE 802.11 has a limit of 8, -+ * but some pre-standard IEEE 802.11g products use longer elements. */ -+#define WLAN_SUPP_RATES_MAX 32 -+ -+/* Try to increase TX rate after # successfully sent packets */ -+#define WLAN_RATE_UPDATE_COUNT 50 -+ -+struct sta_info { -+ struct list_head list; -+ struct sta_info *hnext; /* next entry in hash table list */ -+ atomic_t users; /* number of users (do not remove if > 0) */ -+ struct proc_dir_entry *proc; -+ -+ u8 addr[6]; -+ u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ -+ u32 flags; -+ u16 capability; -+ u16 listen_interval; /* or beacon_int for APs */ -+ u8 supported_rates[WLAN_SUPP_RATES_MAX]; -+ -+ unsigned long last_auth; -+ unsigned long last_assoc; -+ unsigned long last_rx; -+ unsigned long last_tx; -+ unsigned long rx_packets, tx_packets; -+ unsigned long rx_bytes, tx_bytes; -+ struct sk_buff_head tx_buf; -+ /* FIX: timeout buffers with an expiry time somehow derived from -+ * listen_interval */ -+ -+ u8 last_rx_silence; -+ u8 last_rx_signal; -+ u8 last_rx_rate; -+ u8 last_rx_flow; -+ u8 last_rx_updated; /* IWSPY's struct iw_quality::updated */ -+ -+ u8 tx_supp_rates; /* bit field of supported TX rates */ -+ u8 tx_rate; /* current TX rate (in 0.1 Mbps) */ -+ u8 tx_rate_idx; /* current TX rate (WLAN_RATE_*) */ -+ u8 tx_max_rate; /* max TX rate (WLAN_RATE_*) */ -+ u32 tx_count[WLAN_RATE_COUNT]; /* number of frames sent (per rate) */ -+ u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate) -+ */ -+ u32 tx_since_last_failure; -+ u32 txexc; -+ -+ struct prism2_crypt_data *crypt; -+ -+ int ap; /* whether this station is an AP */ -+ -+ local_info_t *local; -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ union { -+ struct { -+ char *challenge; /* shared key authentication -+ * challenge */ -+ } sta; -+ struct { -+ int ssid_len; -+ unsigned char ssid[MAX_SSID_LEN + 1]; /* AP's ssid */ -+ int channel; -+ unsigned long last_beacon; /* last RX beacon time */ -+ } ap; -+ } u; -+ -+ struct timer_list timer; -+ enum { STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH } timeout_next; -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+}; -+ -+ -+#define MAX_STA_COUNT 1024 -+ -+/* Maximum number of AIDs to use for STAs; must be 2007 or lower -+ * (8802.11 limitation) */ -+#define MAX_AID_TABLE_SIZE 128 -+ -+#define STA_HASH_SIZE 256 -+#define STA_HASH(sta) (sta[5]) -+ -+ -+/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has -+ * passed since last received frame from the station, a nullfunc data frame is -+ * sent to the station. If this frame is not acknowledged and no other frames -+ * have been received, the station will be disassociated after -+ * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after -+ * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with -+ * max inactivity timer. */ -+#define AP_MAX_INACTIVITY (5 * 60 * HZ) -+#define AP_DISASSOC_DELAY (HZ) -+#define AP_DEAUTH_DELAY (HZ) -+ -+/* ap_policy: whether to accept frames to/from other APs/IBSS */ -+typedef enum { -+ AP_OTHER_AP_SKIP_ALL = 0, -+ AP_OTHER_AP_SAME_SSID = 1, -+ AP_OTHER_AP_ALL = 2, -+ AP_OTHER_AP_EVEN_IBSS = 3 -+} ap_policy_enum; -+ -+#define PRISM2_AUTH_OPEN BIT(0) -+#define PRISM2_AUTH_SHARED_KEY BIT(1) -+ -+ -+/* MAC address-based restrictions */ -+struct mac_entry { -+ struct list_head list; -+ u8 addr[6]; -+}; -+ -+struct mac_restrictions { -+ enum { MAC_POLICY_OPEN = 0, MAC_POLICY_ALLOW, MAC_POLICY_DENY } policy; -+ unsigned int entries; -+ struct list_head mac_list; -+ spinlock_t lock; -+}; -+ -+ -+struct add_sta_proc_data { -+ u8 addr[ETH_ALEN]; -+ struct add_sta_proc_data *next; -+}; -+ -+ -+struct add_wds_data { -+ u8 addr[ETH_ALEN]; -+ struct add_wds_data *next; -+}; -+ -+ -+struct ap_data { -+ int initialized; /* whether ap_data has been initialized */ -+ local_info_t *local; -+ int bridge_packets; /* send packet to associated STAs directly to the -+ * wireless media instead of higher layers in the -+ * kernel */ -+ unsigned int bridged_unicast; /* number of unicast frames bridged on -+ * wireless media */ -+ unsigned int bridged_multicast; /* number of non-unicast frames -+ * bridged on wireless media */ -+ int nullfunc_ack; /* use workaround for nullfunc frame ACKs */ -+ -+ spinlock_t sta_table_lock; -+ int num_sta; /* number of entries in sta_list */ -+ struct list_head sta_list; /* STA info list head */ -+ struct sta_info *sta_hash[STA_HASH_SIZE]; -+ -+ struct proc_dir_entry *proc; -+ -+ ap_policy_enum ap_policy; -+ unsigned int max_inactivity; -+ int autom_ap_wds; -+ int auth_algs; /* PRISM2_AUTH_ flags */ -+ -+ struct mac_restrictions mac_restrictions; /* MAC-based auth */ -+ int last_tx_rate; -+ -+ HOSTAP_QUEUE set_tim_queue; -+ struct list_head set_tim_list; -+ spinlock_t set_tim_lock; -+ -+ HOSTAP_QUEUE add_sta_proc_queue; -+ struct add_sta_proc_data *add_sta_proc_entries; -+ -+ HOSTAP_QUEUE add_wds_queue; -+ struct add_wds_data *add_wds_entries; -+ -+ u16 tx_callback_idx; -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ /* pointers to STA info; based on allocated AID or NULL if AID free -+ * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 -+ * and so on -+ */ -+ struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; -+ -+ u16 tx_callback_auth, tx_callback_assoc; -+ -+ /* WEP operations for generating challenges to be used with shared key -+ * authentication */ -+ struct hostap_crypto_ops *crypt; -+ void *crypt_priv; -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+}; -+ -+ -+void hostap_rx(struct net_device *dev, struct sk_buff *skb); -+void hostap_init_data(local_info_t *local); -+void hostap_free_data(struct ap_data *ap); -+void hostap_check_sta_fw_version(struct ap_data *ap, int variant, int major, -+ int minor); -+ -+typedef enum { -+ AP_TX_CONTINUE, AP_TX_DROP, AP_TX_RETRY, AP_TX_BUFFERED, -+ AP_TX_CONTINUE_NOT_AUTHORIZED -+} ap_tx_ret; -+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct sk_buff *skb, -+ struct hfa384x_tx_frame *txdesc, int wds, -+ int host_encrypt, -+ struct prism2_crypt_data **crypt, -+ void **sta_ptr); -+void hostap_handle_sta_release(void *ptr); -+void hostap_handle_sta_tx_exc(local_info_t *local, -+ struct hfa384x_tx_frame *txdesc); -+int hostap_update_sta_ps(local_info_t *local, -+ struct hostap_ieee80211_hdr *hdr); -+typedef enum { -+ AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED -+} ap_rx_ret; -+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, -+ struct sk_buff *skb, int wds); -+int hostap_handle_sta_crypto(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc, -+ struct prism2_crypt_data **crypt, void **sta_ptr); -+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr); -+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr); -+int hostap_update_rx_stats(struct ap_data *ap, -+ struct hfa384x_rx_frame *rxdesc); -+void hostap_update_rates(local_info_t *local); -+void hostap_add_wds_links(local_info_t *local); -+void hostap_add_wds_link(local_info_t *local, u8 *addr); -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap, -+ int resend); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+#endif /* HOSTAP_AP_H */ - -Index: drivers/net/wireless/hostap.c ---- drivers/net/wireless/hostap.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap.c 2003-07-19 22:28:19.000000000 -0400 -@@ -0,0 +1,1034 @@ -+/* -+ * Host AP (software wireless LAN access point) driver for -+ * Intersil Prism2/2.5/3 - hostap.o module, common routines -+ * -+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen -+ * -+ * Copyright (c) 2002-2003, Jouni Malinen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. See README and COPYING for -+ * more details. -+ */ -+ -+#ifndef EXPORT_SYMTAB -+#define EXPORT_SYMTAB -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+#include -+#else -+#include -+#endif -+#include -+#include -+#if WIRELESS_EXT > 12 -+#include -+#endif /* WIRELESS_EXT > 12 */ -+ -+#include -+ -+ -+MODULE_AUTHOR("Jouni Malinen"); -+MODULE_DESCRIPTION("Host AP common routines"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#include "hostap_wlan.h" -+#include "hostap_ap.h" -+#include "hostap.h" -+#include "hostap_crypt.h" -+ -+#define TX_TIMEOUT (2 * HZ) -+ -+#define PRISM2_MAX_FRAME_SIZE 2304 -+#define PRISM2_MIN_MTU 256 -+/* FIX: */ -+#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */)) -+ -+ -+/* hostap.c */ -+static int prism2_wds_add(local_info_t *local, u8 *remote_addr, -+ int rtnl_locked); -+static int prism2_wds_del(local_info_t *local, u8 *remote_addr, -+ int rtnl_locked, int do_not_remove); -+ -+/* hostap_ap.c */ -+#ifdef WIRELESS_EXT -+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], -+ struct iw_quality qual[], int buf_size, -+ int aplist); -+#if WIRELESS_EXT > 13 -+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer); -+#endif /* WIRELESS_EXT > 13 */ -+#endif /* WIRELESS_EXT */ -+static int prism2_hostapd(struct ap_data *ap, -+ struct prism2_hostapd_param *param); -+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, -+ struct prism2_crypt_data ***crypt); -+static void ap_control_kickall(struct ap_data *ap); -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions, -+ u8 *mac); -+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions, -+ u8 *mac); -+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions); -+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, -+ u8 *mac); -+#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+#ifdef WIRELESS_EXT -+static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, -+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; -+#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0])) -+#endif /* WIRELESS_EXT */ -+ -+ -+/* FIX: these could be compiled separately and linked together to hostap.o */ -+#include "hostap_ap.c" -+#include "hostap_info.c" -+#include "hostap_ioctl.c" -+#include "hostap_proc.c" -+ -+ -+static inline int prism2_wds_special_addr(u8 *addr) -+{ -+ if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5]) -+ return 0; -+ -+ return 1; -+} -+ -+ -+static int prism2_wds_add(local_info_t *local, u8 *remote_addr, -+ int rtnl_locked) -+{ -+ prism2_wds_info_t *wds, *wds2 = NULL; -+ unsigned long flags; -+ int i, ret; -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL && -+ memcmp(wds->remote_addr, remote_addr, ETH_ALEN) != 0) { -+ if (!wds2 && prism2_wds_special_addr(wds->remote_addr)) -+ wds2 = wds; -+ wds = wds->next; -+ } -+ if (!wds && wds2) { -+ /* take pre-allocated entry into use */ -+ memcpy(wds2->remote_addr, remote_addr, ETH_ALEN); -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+ -+ if (!prism2_wds_special_addr(remote_addr)) { -+ if (wds) -+ return -EEXIST; -+ hostap_add_sta(local->ap, remote_addr); -+ } -+ -+ if (!wds && wds2) { -+ printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n", -+ local->dev->name, wds2->dev.name); -+ return 0; -+ } -+ -+ if (local->wds_connections >= local->wds_max_connections) -+ return -ENOBUFS; -+ -+ /* verify that there is room for wds# postfix in the interface name */ -+ if (strlen(local->dev->name) > IFNAMSIZ - 5) { -+ printk(KERN_DEBUG "'%s' too long base device name\n", -+ local->dev->name); -+ return -EINVAL; -+ } -+ -+ wds = (prism2_wds_info_t *) kmalloc(sizeof(*wds) + PRISM2_NETDEV_EXTRA, -+ GFP_ATOMIC); -+ if (wds == NULL) -+ return -ENOMEM; -+ -+ memset(wds, 0, sizeof(*wds) + PRISM2_NETDEV_EXTRA); -+ prism2_set_dev_name(&wds->dev, wds + 1); -+ -+ memcpy(wds->remote_addr, remote_addr, ETH_ALEN); -+ -+ hostap_setup_dev(&wds->dev, local, 0); -+ -+ wds->dev.priv = local; -+ memcpy(wds->dev.dev_addr, local->dev->dev_addr, ETH_ALEN); -+ wds->dev.base_addr = local->dev->base_addr; -+ wds->dev.irq = local->dev->irq; -+ wds->dev.mem_start = local->dev->mem_start; -+ wds->dev.mem_end = local->dev->mem_end; -+ -+ i = 0; -+ do { -+ sprintf(wds->dev.name, "%swds%d", local->dev->name, i++); -+ } while (i < 10000 && dev_get(wds->dev.name)); -+ -+ if (rtnl_locked) -+ ret = register_netdevice(&wds->dev); -+ else -+ ret = register_netdev(&wds->dev); -+ -+ if (ret) { -+ printk(KERN_WARNING "%s: registering WDS device '%s' failed\n", -+ local->dev->name, wds->dev.name); -+ kfree(wds); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ local->wds_connections++; -+ wds->next = local->wds; -+ local->wds = wds; -+ spin_unlock_irqrestore(&local->wdslock, flags); -+ -+ printk(KERN_DEBUG "%s: registered WDS netdevice %s\n", -+ local->dev->name, wds->dev.name); -+ -+ return 0; -+} -+ -+ -+static int prism2_wds_del(local_info_t *local, u8 *remote_addr, -+ int rtnl_locked, int do_not_remove) -+{ -+ prism2_wds_info_t *wds, *prev = NULL; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL && -+ memcmp(wds->remote_addr, remote_addr, ETH_ALEN) != 0) { -+ prev = wds; -+ wds = wds->next; -+ } -+ if (wds && !do_not_remove) { -+ if (prev != NULL) -+ prev->next = wds->next; -+ else -+ local->wds = wds->next; -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+ -+ if (!wds) -+ return -ENODEV; -+ -+ if (do_not_remove) { -+ memset(wds->remote_addr, 0, ETH_ALEN); -+ return 0; -+ } -+ -+ if (rtnl_locked) -+ unregister_netdevice(&wds->dev); -+ else -+ unregister_netdev(&wds->dev); -+ local->wds_connections--; -+ -+ printk(KERN_DEBUG "%s: unregistered WDS netdevice %s\n", -+ local->dev->name, wds->dev.name); -+ -+ kfree(wds); -+ -+ return 0; -+} -+ -+ -+u16 hostap_tx_callback_register(local_info_t *local, -+ void (*func)(struct sk_buff *, int ok, void *), -+ void *data) -+{ -+ unsigned long flags; -+ struct hostap_tx_callback_info *entry; -+ -+ entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry), -+ GFP_ATOMIC); -+ if (entry == NULL) -+ return 0; -+ -+ entry->func = func; -+ entry->data = data; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1; -+ entry->next = local->tx_callback; -+ local->tx_callback = entry; -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+ return entry->idx; -+} -+ -+ -+int hostap_tx_callback_unregister(local_info_t *local, u16 idx) -+{ -+ unsigned long flags; -+ struct hostap_tx_callback_info *cb, *prev = NULL; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ cb = local->tx_callback; -+ while (cb != NULL && cb->idx != idx) { -+ prev = cb; -+ cb = cb->next; -+ } -+ if (cb) { -+ if (prev == NULL) -+ local->tx_callback = cb->next; -+ else -+ prev->next = cb->next; -+ kfree(cb); -+ } -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+ return cb ? 0 : -1; -+} -+ -+ -+/* val is in host byte order */ -+int hostap_set_word(struct net_device *dev, int rid, u16 val) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 tmp = cpu_to_le16(val); -+ return local->func->set_rid(dev, rid, &tmp, 2); -+} -+ -+ -+int hostap_set_string(struct net_device *dev, int rid, const char *val) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ char buf[MAX_SSID_LEN + 2]; -+ int len; -+ -+ len = strlen(val); -+ if (len > MAX_SSID_LEN) -+ return -1; -+ memset(buf, 0, sizeof(buf)); -+ buf[0] = len; /* little endian 16 bit word */ -+ memcpy(buf + 2, val, len); -+ -+ return local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2); -+} -+ -+ -+u16 hostap_get_porttype(local_info_t *local) -+{ -+ if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc) -+ return HFA384X_PORTTYPE_PSEUDO_IBSS; -+ if (local->iw_mode == IW_MODE_ADHOC) -+ return HFA384X_PORTTYPE_IBSS; -+ if (local->iw_mode == IW_MODE_INFRA) -+ return HFA384X_PORTTYPE_BSS; -+ if (local->iw_mode == IW_MODE_REPEAT) -+ return HFA384X_PORTTYPE_WDS; -+ return HFA384X_PORTTYPE_HOSTAP; -+} -+ -+ -+int hostap_set_encryption(local_info_t *local) -+{ -+ u16 val; -+ int i, keylen, len, idx; -+ char keybuf[WEP_KEY_LEN + 1]; -+ enum { NONE, WEP, OTHER } encrypt_type; -+ -+ if (local->crypt == NULL || local->crypt->ops == NULL) -+ encrypt_type = NONE; -+ else if (strcmp(local->crypt->ops->name, "WEP") == 0) -+ encrypt_type = WEP; -+ else -+ encrypt_type = OTHER; -+ -+ if (local->func->get_rid(local->dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, -+ 1) < 0) { -+ printk(KERN_DEBUG "Could not read current WEP flags.\n"); -+ goto fail; -+ } -+ le16_to_cpus(&val); -+ -+ if (encrypt_type != NONE) -+ val |= HFA384X_WEPFLAGS_PRIVACYINVOKED; -+ else -+ val &= ~HFA384X_WEPFLAGS_PRIVACYINVOKED; -+ -+ if (local->open_wep || encrypt_type == NONE || -+ (local->ieee_802_1x && local->host_decrypt)) -+ val &= ~HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED; -+ else -+ val |= HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED; -+ -+ if (encrypt_type != NONE && -+ (encrypt_type == OTHER || local->host_encrypt)) -+ val |= HFA384X_WEPFLAGS_HOSTENCRYPT; -+ else -+ val &= ~HFA384X_WEPFLAGS_HOSTENCRYPT; -+ if (encrypt_type != NONE && -+ (encrypt_type == OTHER || local->host_decrypt)) -+ val |= HFA384X_WEPFLAGS_HOSTDECRYPT; -+ else -+ val &= ~HFA384X_WEPFLAGS_HOSTDECRYPT; -+ -+ if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPFLAGS, val)) { -+ printk(KERN_DEBUG "Could not write new WEP flags (0x%x)\n", -+ val); -+ goto fail; -+ } -+ -+ if (encrypt_type != WEP) -+ return 0; -+ -+ /* 104-bit support seems to require that all the keys are set to the -+ * same keylen */ -+ keylen = 6; /* first 5 octets */ -+ idx = local->crypt->ops->get_key_idx(local->crypt->priv); -+ len = local->crypt->ops->get_key(idx, keybuf, sizeof(keybuf), -+ local->crypt->priv); -+ if (idx >= 0 && idx < WEP_KEYS && len > 5) -+ keylen = WEP_KEY_LEN + 1; /* first 13 octets */ -+ -+ for (i = 0; i < WEP_KEYS; i++) { -+ memset(keybuf, 0, sizeof(keybuf)); -+ (void) local->crypt->ops->get_key(i, keybuf, sizeof(keybuf), -+ local->crypt->priv); -+ if (local->func->set_rid(local->dev, -+ HFA384X_RID_CNFDEFAULTKEY0 + i, -+ keybuf, keylen)) { -+ printk(KERN_DEBUG "Could not set key %d (len=%d)\n", -+ i, keylen); -+ goto fail; -+ } -+ } -+ if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPDEFAULTKEYID, idx)) { -+ printk(KERN_DEBUG "Could not set default keyid %d\n", idx); -+ goto fail; -+ } -+ -+ return 0; -+ -+ fail: -+ printk(KERN_DEBUG "%s: encryption setup failed\n", local->dev->name); -+ return -1; -+} -+ -+ -+int hostap_set_antsel(local_info_t *local) -+{ -+ u16 val; -+ int ret = 0; -+ -+ if (local->antsel_tx != HOSTAP_ANTSEL_DO_NOT_TOUCH && -+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF, -+ HFA386X_CR_TX_CONFIGURE, -+ NULL, &val) == 0) { -+ val &= ~(BIT(2) | BIT(1)); -+ switch (local->antsel_tx) { -+ case HOSTAP_ANTSEL_DIVERSITY: -+ val |= BIT(1); -+ break; -+ case HOSTAP_ANTSEL_LOW: -+ break; -+ case HOSTAP_ANTSEL_HIGH: -+ val |= BIT(2); -+ break; -+ } -+ -+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_TX_CONFIGURE, &val, NULL)) { -+ printk(KERN_INFO "%s: setting TX AntSel failed\n", -+ local->dev->name); -+ ret = -1; -+ } -+ } -+ -+ if (local->antsel_rx != HOSTAP_ANTSEL_DO_NOT_TOUCH && -+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF, -+ HFA386X_CR_RX_CONFIGURE, -+ NULL, &val) == 0) { -+ val &= ~(BIT(1) | BIT(0)); -+ switch (local->antsel_rx) { -+ case HOSTAP_ANTSEL_DIVERSITY: -+ break; -+ case HOSTAP_ANTSEL_LOW: -+ val |= BIT(0); -+ break; -+ case HOSTAP_ANTSEL_HIGH: -+ val |= BIT(0) | BIT(1); -+ break; -+ } -+ -+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_RX_CONFIGURE, &val, NULL)) { -+ printk(KERN_INFO "%s: setting RX AntSel failed\n", -+ local->dev->name); -+ ret = -1; -+ } -+ } -+ -+ return ret; -+} -+ -+ -+void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx) -+{ -+ u16 status, fc; -+ -+ status = __le16_to_cpu(rx->status); -+ -+ printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, " -+ "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; " -+ "jiffies=%ld\n", -+ name, status, (status >> 8) & 0x07, status >> 13, status & 1, -+ rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies); -+ -+ fc = __le16_to_cpu(rx->frame_control); -+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " -+ "data_len=%d%s%s\n", -+ fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc), -+ __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl), -+ __le16_to_cpu(rx->data_len), -+ fc & WLAN_FC_TODS ? " [ToDS]" : "", -+ fc & WLAN_FC_FROMDS ? " [FromDS]" : ""); -+ -+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4=" -+ MACSTR "\n", -+ MAC2STR(rx->addr1), MAC2STR(rx->addr2), MAC2STR(rx->addr3), -+ MAC2STR(rx->addr4)); -+ -+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n", -+ MAC2STR(rx->dst_addr), MAC2STR(rx->src_addr), -+ __be16_to_cpu(rx->len)); -+} -+ -+ -+void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx) -+{ -+ u16 fc; -+ -+ printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d " -+ "tx_control=0x%04x; jiffies=%ld\n", -+ name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate, -+ __le16_to_cpu(tx->tx_control), jiffies); -+ -+ fc = __le16_to_cpu(tx->frame_control); -+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " -+ "data_len=%d%s%s\n", -+ fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc), -+ __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl), -+ __le16_to_cpu(tx->data_len), -+ fc & WLAN_FC_TODS ? " [ToDS]" : "", -+ fc & WLAN_FC_FROMDS ? " [FromDS]" : ""); -+ -+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4=" -+ MACSTR "\n", -+ MAC2STR(tx->addr1), MAC2STR(tx->addr2), MAC2STR(tx->addr3), -+ MAC2STR(tx->addr4)); -+ -+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n", -+ MAC2STR(tx->dst_addr), MAC2STR(tx->src_addr), -+ __be16_to_cpu(tx->len)); -+} -+ -+ -+/* wake all netif queues in use */ -+void hostap_netif_wake_queues(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ prism2_wds_info_t *wds; -+ unsigned long flags; -+ -+ if (local->dev) -+ netif_wake_queue(local->dev); -+ if (local->apdev) -+ netif_wake_queue(local->apdev); -+ if (local->stadev) -+ netif_wake_queue(local->stadev); -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL) { -+ netif_wake_queue(&wds->dev); -+ wds = wds->next; -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+} -+ -+ -+/* stop all netif queues in use */ -+void hostap_netif_stop_queues(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ prism2_wds_info_t *wds; -+ unsigned long flags; -+ -+ if (local->dev) -+ netif_stop_queue(local->dev); -+ if (local->apdev) -+ netif_stop_queue(local->apdev); -+ if (local->stadev) -+ netif_stop_queue(local->stadev); -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL) { -+ netif_stop_queue(&wds->dev); -+ wds = wds->next; -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+} -+ -+ -+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr) -+{ -+ memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); /* addr2 */ -+ return ETH_ALEN; -+} -+ -+ -+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr) -+{ -+ if (*(u32 *)skb->mac.raw == LWNG_CAP_DID_BASE) { -+ memcpy(haddr, skb->mac.raw + -+ sizeof(struct linux_wlan_ng_prism_hdr) + 10, -+ ETH_ALEN); /* addr2 */ -+ } else { /* (*(u32 *)skb->mac.raw == htonl(LWNG_CAPHDR_VERSION)) */ -+ memcpy(haddr, skb->mac.raw + -+ sizeof(struct linux_wlan_ng_cap_hdr) + 10, -+ ETH_ALEN); /* addr2 */ -+ } -+ return ETH_ALEN; -+} -+ -+ -+int hostap_80211_get_hdrlen(u16 fc) -+{ -+ int hdrlen = 24; -+ -+ switch (WLAN_FC_GET_TYPE(fc)) { -+ case WLAN_FC_TYPE_DATA: -+ if ((fc & WLAN_FC_FROMDS) && (fc & WLAN_FC_TODS)) -+ hdrlen = 30; /* Addr4 */ -+ break; -+ case WLAN_FC_TYPE_CTRL: -+ switch (WLAN_FC_GET_STYPE(fc)) { -+ case WLAN_FC_STYPE_CTS: -+ case WLAN_FC_STYPE_ACK: -+ hdrlen = 10; -+ break; -+ default: -+ hdrlen = 16; -+ break; -+ } -+ break; -+ } -+ -+ return hdrlen; -+} -+ -+ -+struct net_device_stats *hostap_get_stats(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ if (local->apdev == dev) -+ return &local->apdevstats; -+ if (local->stadev == dev) -+ return &local->stadevstats; -+ if (local->dev != dev) { -+ prism2_wds_info_t *wds = (prism2_wds_info_t *) dev; -+ return &wds->stats; -+ } -+ return &local->stats; -+} -+ -+ -+static int prism2_close(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ PDEBUG(DEBUG_FLOW, "%s: prism2_close\n", dev->name); -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ if (!local->hostapd && dev == local->dev && -+ (!local->func->card_present || local->func->card_present(local)) && -+ local->hw_ready && local->ap && local->iw_mode == IW_MODE_MASTER) -+ hostap_deauth_all_stas(dev, local->ap, 1); -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ if (local->func->dev_close && local->func->dev_close(local)) -+ return 0; -+ -+ if (local->disable_on_close) { -+ local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL); -+ } -+ -+ if (netif_running(dev)) { -+ netif_stop_queue(dev); -+ netif_device_detach(dev); -+ } -+ -+ PRISM2_FLUSH_SCHEDULED_TASKS(); -+ -+#ifdef NEW_MODULE_CODE -+ module_put(local->hw_module); -+#elif MODULE -+ __MOD_DEC_USE_COUNT(local->hw_module); -+#endif -+ -+ return 0; -+} -+ -+ -+static int prism2_open(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ PDEBUG(DEBUG_FLOW, "%s: prism2_open\n", dev->name); -+ -+ if (local->func->dev_open && local->func->dev_open(local)) -+ return 1; -+ -+#ifdef NEW_MODULE_CODE -+ if (!try_module_get(local->hw_module)) -+ return -ENODEV; -+#elif MODULE -+ __MOD_INC_USE_COUNT(local->hw_module); -+#endif -+ -+ if (!local->dev_enabled && local->func->hw_enable(dev, 1)) { -+ printk(KERN_WARNING "%s: could not enable MAC port\n", -+ dev->name); -+ prism2_close(dev); -+ return 1; -+ } -+ if (!local->dev_enabled) -+ prism2_callback(local, PRISM2_CALLBACK_ENABLE); -+ local->dev_enabled = 1; -+ -+ netif_device_attach(dev); -+ netif_start_queue(dev); -+ -+ return 0; -+} -+ -+ -+#ifdef HAVE_SET_MAC_ADDR -+static int prism2_set_mac_address(struct net_device *dev, void *p) -+{ -+ struct sockaddr *addr = p; -+ local_info_t *local = (local_info_t *) dev->priv; -+ prism2_wds_info_t *wds; -+ unsigned long flags; -+ -+ if (local->func->set_rid(dev, HFA384X_RID_CNFOWNMACADDR, addr->sa_data, -+ ETH_ALEN) < 0 || local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ dev = local->dev; -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ if (local->apdev) -+ memcpy(local->apdev->dev_addr, dev->dev_addr, ETH_ALEN); -+ if (local->stadev) -+ memcpy(local->stadev->dev_addr, dev->dev_addr, ETH_ALEN); -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL) { -+ memcpy(wds->dev.dev_addr, dev->dev_addr, ETH_ALEN); -+ wds = wds->next; -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+ -+ return 0; -+} -+#endif /* HAVE_SET_MAC_ADDR */ -+ -+ -+/* TODO: to be further implemented as soon as Prism2 fully supports -+ * GroupAddresses and correct documentation is available */ -+void hostap_set_multicast_list_queue(void *data) -+{ -+ struct net_device *dev = (struct net_device *) data; -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, -+ local->is_promisc)) { -+ printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", -+ dev->name, local->is_promisc ? "en" : "dis"); -+ } -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+static void hostap_set_multicast_list(struct net_device *dev) -+{ -+#if 1 -+ /* FIX: promiscuous mode seems to be causing a lot of problems with -+ * some station firmware versions (FCSErr frames, invalid MACPort, etc. -+ * corrupted incoming frames). This code is now commented out while the -+ * problems are investigated. */ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if ((dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) { -+ local->is_promisc = 1; -+ } else { -+ local->is_promisc = 0; -+ } -+ -+ PRISM2_SCHEDULE_TASK(&local->set_multicast_list_queue); -+#endif -+} -+ -+ -+static int prism2_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU) -+ return -EINVAL; -+ -+ dev->mtu = new_mtu; -+ return 0; -+} -+ -+ -+#ifdef HAVE_TX_TIMEOUT -+static void prism2_tx_timeout(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct hfa384x_regs regs; -+ -+ printk(KERN_WARNING "%s Tx timed out! Resetting card\n", dev->name); -+ hostap_netif_stop_queues(dev); -+ -+ local->func->read_regs(dev, ®s); -+ printk(KERN_DEBUG "%s: CMD=%04x EVSTAT=%04x " -+ "OFFSET0=%04x OFFSET1=%04x SWSUPPORT0=%04x\n", -+ dev->name, regs.cmd, regs.evstat, regs.offset0, regs.offset1, -+ regs.swsupport0); -+ -+ local->func->schedule_reset(local); -+} -+#endif /* HAVE_TX_TIMEOUT */ -+ -+ -+void hostap_setup_dev(struct net_device *dev, local_info_t *local, -+ int main_dev) -+{ -+ ether_setup(dev); -+ -+ /* kernel callbacks */ -+ dev->get_stats = hostap_get_stats; -+#ifdef WIRELESS_EXT -+ dev->get_wireless_stats = main_dev ? hostap_get_wireless_stats : NULL; -+#if WIRELESS_EXT > 12 -+ dev->wireless_handlers = -+ (struct iw_handler_def *) &hostap_iw_handler_def; -+#endif /* WIRELESS_EXT > 12 */ -+#endif /* WIRELESS_EXT */ -+ dev->open = prism2_open; -+ dev->stop = prism2_close; -+ if (local->func) -+ dev->hard_start_xmit = local->func->tx; -+ else -+ printk(KERN_WARNING "hostap_setup_dev: local->func == NULL\n"); -+#ifdef HAVE_SET_MAC_ADDR -+ dev->set_mac_address = prism2_set_mac_address; -+#endif /* HAVE_SET_MAC_ADDR */ -+#ifdef HAVE_MULTICAST -+ dev->set_multicast_list = hostap_set_multicast_list; -+#endif -+#ifdef HAVE_PRIVATE_IOCTL -+ dev->do_ioctl = main_dev ? hostap_ioctl : NULL; -+#endif -+#ifdef HAVE_CHANGE_MTU -+ dev->change_mtu = prism2_change_mtu; -+#endif -+#ifdef HAVE_TX_TIMEOUT -+ dev->tx_timeout = prism2_tx_timeout; -+ dev->watchdog_timeo = TX_TIMEOUT; -+#endif -+ -+ dev->mtu = local->mtu; -+ -+ netif_stop_queue(dev); -+} -+ -+ -+static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked) -+{ -+ struct net_device *dev = local->dev; -+ int ret; -+ -+ printk(KERN_DEBUG "%s: enabling hostapd mode\n", dev->name); -+ -+ local->apdev = kmalloc(sizeof(struct net_device) + PRISM2_NETDEV_EXTRA, -+ GFP_KERNEL); -+ if (local->apdev == NULL) -+ return -ENOMEM; -+ memset(local->apdev, 0, sizeof(struct net_device) + -+ PRISM2_NETDEV_EXTRA); -+ prism2_set_dev_name(local->apdev, local->apdev + 1); -+ -+ local->apdev->priv = local; -+ memcpy(local->apdev->dev_addr, dev->dev_addr, ETH_ALEN); -+ hostap_setup_dev(local->apdev, local, 0); -+ local->apdev->hard_start_xmit = local->func->tx_80211; -+ local->apdev->type = ARPHRD_IEEE80211; -+ local->apdev->hard_header_parse = hostap_80211_header_parse; -+ -+ local->apdev->base_addr = dev->base_addr; -+ local->apdev->irq = dev->irq; -+ local->apdev->mem_start = dev->mem_start; -+ local->apdev->mem_end = dev->mem_end; -+ sprintf(local->apdev->name, "%sap", dev->name); -+ if (rtnl_locked) -+ ret = register_netdevice(local->apdev); -+ else -+ ret = register_netdev(local->apdev); -+ if (ret) { -+ printk(KERN_WARNING "%s: register_netdevice(AP) failed!\n", -+ dev->name); -+ return -1; -+ } -+ printk(KERN_DEBUG "%s: Registered netdevice %s for AP management\n", -+ dev->name, local->apdev->name); -+ -+ -+ local->stadev = kmalloc(sizeof(struct net_device) + -+ PRISM2_NETDEV_EXTRA, -+ GFP_KERNEL); -+ if (local->stadev == NULL) -+ return -ENOMEM; -+ memset(local->stadev, 0, sizeof(struct net_device) + -+ PRISM2_NETDEV_EXTRA); -+ prism2_set_dev_name(local->stadev, local->stadev + 1); -+ -+ local->stadev->priv = local; -+ memcpy(local->stadev->dev_addr, dev->dev_addr, ETH_ALEN); -+ hostap_setup_dev(local->stadev, local, 0); -+ -+ local->stadev->base_addr = dev->base_addr; -+ local->stadev->irq = dev->irq; -+ local->stadev->mem_start = dev->mem_start; -+ local->stadev->mem_end = dev->mem_end; -+ sprintf(local->stadev->name, "%ssta", dev->name); -+ if (rtnl_locked) -+ ret = register_netdevice(local->stadev); -+ else -+ ret = register_netdev(local->stadev); -+ if (ret) { -+ printk(KERN_WARNING "%s: register_netdevice(STA) failed!\n", -+ dev->name); -+ return -1; -+ } -+ printk(KERN_DEBUG "%s: Registered netdevice %s for STA use\n", -+ dev->name, local->stadev->name); -+ -+ return 0; -+} -+ -+ -+static int hostap_disable_hostapd(local_info_t *local, int rtnl_locked) -+{ -+ struct net_device *dev = local->dev; -+ -+ printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name); -+ -+ if (local->apdev && local->apdev->name && local->apdev->name[0]) { -+ if (rtnl_locked) -+ unregister_netdevice(local->apdev); -+ else -+ unregister_netdev(local->apdev); -+ printk(KERN_DEBUG "%s: Netdevice %s unregistered\n", -+ dev->name, local->apdev->name); -+ } -+ kfree(local->apdev); -+ local->apdev = NULL; -+ -+ if (local->stadev && local->stadev->name && local->stadev->name[0]) { -+ if (rtnl_locked) -+ unregister_netdevice(local->stadev); -+ else -+ unregister_netdev(local->stadev); -+ printk(KERN_DEBUG "%s: Netdevice %s unregistered\n", -+ dev->name, local->stadev->name); -+ } -+ kfree(local->stadev); -+ local->stadev = NULL; -+ -+ return 0; -+} -+ -+ -+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked) -+{ -+ if (val < 0 || val > 1) -+ return -EINVAL; -+ -+ if (local->hostapd == val) -+ return 0; -+ -+ local->hostapd = val; -+ -+ if (val) -+ return hostap_enable_hostapd(local, rtnl_locked); -+ else -+ return hostap_disable_hostapd(local, rtnl_locked); -+} -+ -+ -+struct proc_dir_entry *hostap_proc; -+ -+ -+static int __init hostap_init(void) -+{ -+ if (proc_net != NULL) { -+ hostap_proc = proc_mkdir("hostap", proc_net); -+ if (!hostap_proc) -+ printk(KERN_WARNING "Failed to mkdir " -+ "/proc/net/hostap\n"); -+ } else -+ hostap_proc = NULL; -+ -+ return 0; -+} -+ -+ -+static void __exit hostap_exit(void) -+{ -+ if (hostap_proc != NULL) { -+ hostap_proc = NULL; -+ remove_proc_entry("hostap", proc_net); -+ } -+} -+ -+EXPORT_SYMBOL(hostap_set_word); -+EXPORT_SYMBOL(hostap_set_string); -+EXPORT_SYMBOL(hostap_get_porttype); -+EXPORT_SYMBOL(hostap_set_encryption); -+EXPORT_SYMBOL(hostap_set_antsel); -+EXPORT_SYMBOL(hostap_dump_rx_header); -+EXPORT_SYMBOL(hostap_dump_tx_header); -+EXPORT_SYMBOL(hostap_netif_wake_queues); -+EXPORT_SYMBOL(hostap_netif_stop_queues); -+EXPORT_SYMBOL(hostap_80211_header_parse); -+EXPORT_SYMBOL(hostap_80211_prism_header_parse); -+EXPORT_SYMBOL(hostap_80211_get_hdrlen); -+EXPORT_SYMBOL(hostap_get_stats); -+EXPORT_SYMBOL(hostap_setup_dev); -+EXPORT_SYMBOL(hostap_proc); -+EXPORT_SYMBOL(hostap_set_multicast_list_queue); -+EXPORT_SYMBOL(hostap_set_hostapd); -+module_init(hostap_init); -+module_exit(hostap_exit); - -Index: drivers/net/wireless/hostap_compat.h ---- drivers/net/wireless/hostap_compat.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_compat.h 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,153 @@ -+#ifndef HOSTAP_COMPAT_H -+#define HOSTAP_COMPAT_H -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47)) -+#define NEW_MODULE_CODE -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) -+/* 2.2 compatibility */ -+ -+#include -+#include -+#include -+ -+#ifndef spin_lock_bh -+#define spin_lock_bh(lock) spin_lock_irq(lock) -+#define spin_unlock_bh(lock) spin_unlock_irq(lock) -+#endif -+#ifndef __constant_cpu_to_le16 -+#define __constant_cpu_to_le16 __cpu_to_le16 -+#endif -+ -+#define PRISM2_NETDEV_EXTRA IFNAMSIZ -+#define prism2_set_dev_name(dev, pos) (dev)->name = (char *) (pos) -+ -+#define HOSTAP_QUEUE struct tq_struct -+ -+/* tq_scheduler was removed in 2.4.0-test12 */ -+#define PRISM2_SCHEDULE_TASK(q) \ -+MOD_INC_USE_COUNT; \ -+queue_task((q), &tq_scheduler); -+ -+#define PRISM2_FLUSH_SCHEDULED_TASKS() do { schedule(); schedule(); } while (0) -+ -+static inline void HOSTAP_QUEUE_INIT(struct tq_struct *tq, -+ void (*routine)(void *), void *data) -+{ -+ tq->next = NULL; -+ tq->sync = 0; -+ tq->routine = routine; -+ tq->data = data; -+} -+ -+#define HOSTAP_TASKLET struct tq_struct -+ -+#define HOSTAP_TASKLET_SCHEDULE(q) \ -+do { queue_task((q), &tq_immediate); mark_bh(IMMEDIATE_BH); } while (0) -+ -+typedef void (*tasklet_func)(void *); -+ -+#define HOSTAP_TASKLET_INIT(q, f, d) \ -+do { memset((q), 0, sizeof(*(q))); \ -+(q)->routine = (tasklet_func) (f); \ -+(q)->data = (void *) (d); } \ -+while (0) -+ -+ -+static inline void dev_kfree_skb_any(struct sk_buff *skb) -+{ -+ if (in_interrupt()) -+ dev_kfree_skb_irq(skb); -+ else -+ dev_kfree_skb(skb); -+} -+ -+static __inline__ void list_del_init(struct list_head *entry) -+{ -+ __list_del(entry->prev, entry->next); -+ INIT_LIST_HEAD(entry); -+} -+ -+/* end 2.2 compatibility */ -+ -+#else /* kernel < 2.4.0 */ -+ -+/* no extra space needed for 2.4.x net_device */ -+#define PRISM2_NETDEV_EXTRA 0 -+#define prism2_set_dev_name(dev, pos) do { } while (0) -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+ -+#define HOSTAP_QUEUE struct tq_struct -+ -+#define PRISM2_SCHEDULE_TASK(q) \ -+MOD_INC_USE_COUNT; \ -+if (schedule_task((q)) == 0) \ -+ MOD_DEC_USE_COUNT; -+ -+#define PRISM2_FLUSH_SCHEDULED_TASKS() flush_scheduled_tasks() -+ -+static inline void HOSTAP_QUEUE_INIT(struct tq_struct *tq, -+ void (*routine)(void *), void *data) -+{ -+ INIT_LIST_HEAD(&tq->list); -+ tq->sync = 0; -+ tq->routine = routine; -+ tq->data = data; -+} -+ -+#else /* kernel < 2.5.44 */ -+ -+#define HOSTAP_QUEUE struct work_struct -+ -+#ifdef NEW_MODULE_CODE -+#define PRISM2_SCHEDULE_TASK(q) schedule_work(q); -+#else /* NEW_MODULE_CODE */ -+#define PRISM2_SCHEDULE_TASK(q) \ -+MOD_INC_USE_COUNT; \ -+if (schedule_work((q)) == 0) \ -+ MOD_DEC_USE_COUNT; -+#endif /* NEW_MODULE_CODE */ -+ -+#define PRISM2_FLUSH_SCHEDULED_TASKS() flush_scheduled_work() -+ -+static inline void HOSTAP_QUEUE_INIT(struct work_struct *wq, -+ void (*routine)(void *), void *data) -+{ -+ INIT_WORK(wq, routine, data); -+} -+ -+#endif /* kernel < 2.5.44 */ -+ -+#define HOSTAP_TASKLET struct tasklet_struct -+ -+#define HOSTAP_TASKLET_SCHEDULE(q) tasklet_schedule((q)) -+ -+#define HOSTAP_TASKLET_INIT(q, f, d) \ -+do { memset((q), 0, sizeof(*(q))); (q)->func = (f); (q)->data = (d); } \ -+while (0) -+ -+#endif /* kernel < 2.4.0 */ -+ -+ -+/* Interrupt handler backwards compatibility for Linux < 2.5.69 */ -+#ifndef IRQ_NONE -+#define IRQ_NONE -+#define IRQ_HANDLED -+#define IRQ_RETVAL(x) -+typedef void irqreturn_t; -+#endif -+ -+ -+#if WIRELESS_EXT > 12 -+#if IW_HANDLER_VERSION < 3 -+extern void wireless_send_event(struct net_device *dev, -+ unsigned int cmd, -+ union iwreq_data *wrqu, -+ char *extra); -+#endif /* IW_HANDLER_VERSION < 3 */ -+#endif /* WIRELESS_EXT > 12 */ -+ -+ -+#endif /* HOSTAP_COMPAT_H */ - -Index: drivers/net/wireless/hostap_config.h ---- drivers/net/wireless/hostap_config.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_config.h 2003-08-08 22:39:41.000000000 -0400 -@@ -0,0 +1,92 @@ -+#ifndef HOSTAP_CONFIG_H -+#define HOSTAP_CONFIG_H -+ -+#define PRISM2_VERSION "0.0.3 - 2003-05-18" -+ -+/* In the previous versions of Host AP driver, support for user space version -+ * of IEEE 802.11 management (hostapd) used to be disabled in the default -+ * configuration. From now on, support for hostapd is always included and it is -+ * possible to disable kernel driver version of IEEE 802.11 management with a -+ * separate define, PRISM2_NO_KERNEL_IEEE80211_MGMT. */ -+/* #define PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+/* Maximum number of events handler per one interrupt */ -+#define PRISM2_MAX_INTERRUPT_EVENTS 20 -+ -+/* Use PCI bus master to copy data to/from BAP (only available for -+ * hostap_pci.o). -+ * -+ * Note! This is extremely experimental. PCI bus master is not supported by -+ * Intersil and it seems to have some problems at least on TX path (see below). -+ * The driver code for implementing bus master support is based on guessing -+ * and experimenting suitable control bits and these might not be correct. -+ * This code is included because using bus master makes a huge difference in -+ * host CPU load (something like 40% host CPU usage to 5-10% when sending or -+ * receiving at maximum throughput). -+ * -+ * Note2! Station firmware version 1.3.5 and primary firmware version 1.0.7 -+ * have some fixes for PCI corruption and these (or newer) versions are -+ * recommended especially when using bus mastering. */ -+/* #define PRISM2_BUS_MASTER */ -+ -+#ifdef PRISM2_BUS_MASTER -+ -+/* PCI bus master implementation seems to be broken in current -+ * hardware/firmware versions. Enable this to use enable command to fix -+ * something before starting bus master operation on TX path. This will add -+ * some latency and an extra interrupt to each TX packet. */ -+#define PRISM2_ENABLE_BEFORE_TX_BUS_MASTER -+ -+#endif /* PRISM2_BUS_MASTER */ -+ -+/* Include code for downloading firmware images. */ -+/* #define PRISM2_DOWNLOAD_SUPPORT */ -+ -+/* Allow kernel configuration to enable download support. */ -+#if !defined(PRISM2_DOWNLOAD_SUPPORT) && defined(CONFIG_HOSTAP_FIRMWARE) -+#define PRISM2_DOWNLOAD_SUPPORT -+#endif -+ -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+/* Allow writing firmware images into flash, i.e., to non-volatile storage. -+ * Before you enable this option, you should make absolutely sure that you are -+ * using prism2_srec utility that comes with THIS version of the driver! -+ * In addition, please note that it is possible to kill your card with -+ * non-volatile download if you are using incorrect image. This feature has not -+ * been fully tested, so please be careful with it. */ -+/* #define PRISM2_NON_VOLATILE_DOWNLOAD */ -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ -+/* Include wireless extensions sub-ioctl support even if wireless extensions -+ * version is less than 15 (actually, only if it is 12 .. 14). If ver >= 15, -+ * these will be included. Please note, that this requires iwpriv version 25 -+ * or higher (older versions will segfault due to long ioctl list). */ -+#define PRISM2_USE_WE_SUB_IOCTLS -+ -+/* Use IW_PRIV_TYPE_ADDR with private WE ioctls taking MAC address argument -+ * (instead of old 18*char). This requires iwpriv ver >= 25. This will be -+ * automatically included for WIRELESS_EXT >= 15. */ -+/* #define PRISM2_USE_WE_TYPE_ADDR */ -+ -+/* Save low-level I/O for debugging. This should not be enabled in normal use. -+ */ -+/* #define PRISM2_IO_DEBUG */ -+ -+/* Following defines can be used to remove unneeded parts of the driver, e.g., -+ * to limit the size of the kernel module. Definitions can be added here in -+ * hostap_config.h or they can be added to make command with EXTRA_CFLAGS, -+ * e.g., -+ * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"' -+ */ -+ -+/* Do not include debug messages into the driver */ -+/* #define PRISM2_NO_DEBUG */ -+ -+/* Do not include /proc/net/prism2/wlan#/{registers,debug} */ -+/* #define PRISM2_NO_PROCFS_DEBUG */ -+ -+/* Do not include station functionality (i.e., allow only Master (Host AP) mode -+ */ -+/* #define PRISM2_NO_STATION_MODES */ -+ -+#endif /* HOSTAP_CONFIG_H */ - -Index: drivers/net/wireless/hostap_crypt.c ---- drivers/net/wireless/hostap_crypt.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_crypt.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,190 @@ -+/* -+ * Host AP crypto routines -+ * -+ * Copyright (c) 2002, Jouni Malinen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. See README and COPYING for -+ * more details. -+ */ -+ -+#ifndef EXPORT_SYMTAB -+#define EXPORT_SYMTAB -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Jouni Malinen"); -+MODULE_DESCRIPTION("Host AP crypto"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#include "hostap_crypt.h" -+ -+ -+struct hostap_crypto_alg { -+ struct list_head list; -+ struct hostap_crypto_ops *ops; -+}; -+ -+ -+struct hostap_crypto { -+ struct list_head algs; -+ spinlock_t lock; -+}; -+ -+static struct hostap_crypto *hcrypt; -+ -+ -+int hostap_register_crypto_ops(struct hostap_crypto_ops *ops) -+{ -+ unsigned long flags; -+ struct hostap_crypto_alg *alg; -+ -+ if (hcrypt == NULL) -+ return -1; -+ -+ alg = (struct hostap_crypto_alg *) kmalloc(sizeof(*alg), GFP_KERNEL); -+ if (alg == NULL) -+ return -ENOMEM; -+ -+ memset(alg, 0, sizeof(*alg)); -+ alg->ops = ops; -+ -+ spin_lock_irqsave(&hcrypt->lock, flags); -+ list_add(&alg->list, &hcrypt->algs); -+ spin_unlock_irqrestore(&hcrypt->lock, flags); -+ -+ printk(KERN_DEBUG "hostap_crypt: registered algorithm '%s'\n", -+ ops->name); -+ -+ return 0; -+} -+ -+ -+int hostap_unregister_crypto_ops(struct hostap_crypto_ops *ops) -+{ -+ unsigned long flags; -+ struct list_head *ptr; -+ struct hostap_crypto_alg *del_alg = NULL; -+ -+ if (hcrypt == NULL) -+ return -1; -+ -+ spin_lock_irqsave(&hcrypt->lock, flags); -+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { -+ struct hostap_crypto_alg *alg = -+ (struct hostap_crypto_alg *) ptr; -+ if (alg->ops == ops) { -+ list_del(&alg->list); -+ del_alg = alg; -+ break; -+ } -+ } -+ spin_unlock_irqrestore(&hcrypt->lock, flags); -+ -+ if (del_alg) { -+ printk(KERN_DEBUG "hostap_crypt: unregistered algorithm " -+ "'%s'\n", ops->name); -+ kfree(del_alg); -+ } -+ -+ return del_alg ? 0 : -1; -+} -+ -+ -+struct hostap_crypto_ops * hostap_get_crypto_ops(const char *name) -+{ -+ unsigned long flags; -+ struct list_head *ptr; -+ struct hostap_crypto_alg *found_alg = NULL; -+ -+ if (hcrypt == NULL) -+ return NULL; -+ -+ spin_lock_irqsave(&hcrypt->lock, flags); -+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { -+ struct hostap_crypto_alg *alg = -+ (struct hostap_crypto_alg *) ptr; -+ if (strcmp(alg->ops->name, name) == 0) { -+ found_alg = alg; -+ break; -+ } -+ } -+ spin_unlock_irqrestore(&hcrypt->lock, flags); -+ -+ if (found_alg) -+ return found_alg->ops; -+ else -+ return NULL; -+} -+ -+ -+static void * hostap_crypt_null_init(void) { return (void *) 1; } -+static void hostap_crypt_null_deinit(void *priv) {} -+ -+static struct hostap_crypto_ops hostap_crypt_null = { -+ .name = "NULL", -+ .init = hostap_crypt_null_init, -+ .deinit = hostap_crypt_null_deinit, -+ .encrypt = NULL, -+ .decrypt = NULL, -+ .set_key = NULL, -+ .get_key = NULL, -+ .set_key_idx = NULL, -+ .get_key_idx = NULL, -+ .extra_prefix_len = 0, -+ .extra_postfix_len = 0 -+}; -+ -+ -+static int __init hostap_crypto_init(void) -+{ -+ hcrypt = (struct hostap_crypto *) kmalloc(sizeof(*hcrypt), GFP_KERNEL); -+ if (hcrypt == NULL) -+ return -ENOMEM; -+ -+ memset(hcrypt, 0, sizeof(*hcrypt)); -+ INIT_LIST_HEAD(&hcrypt->algs); -+ spin_lock_init(&hcrypt->lock); -+ -+ (void) hostap_register_crypto_ops(&hostap_crypt_null); -+ -+ return 0; -+} -+ -+ -+static void __exit hostap_crypto_deinit(void) -+{ -+ struct list_head *ptr, *n; -+ -+ if (hcrypt == NULL) -+ return; -+ -+ for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; -+ ptr = n, n = ptr->next) { -+ struct hostap_crypto_alg *alg = -+ (struct hostap_crypto_alg *) ptr; -+ list_del(ptr); -+ printk(KERN_DEBUG "hostap_crypt: unregistered algorithm " -+ "'%s' (deinit)\n", alg->ops->name); -+ kfree(alg); -+ } -+ -+ kfree(hcrypt); -+} -+ -+ -+EXPORT_SYMBOL(hostap_register_crypto_ops); -+EXPORT_SYMBOL(hostap_unregister_crypto_ops); -+EXPORT_SYMBOL(hostap_get_crypto_ops); -+ -+module_init(hostap_crypto_init); -+module_exit(hostap_crypto_deinit); - -Index: drivers/net/wireless/hostap_crypt.h ---- drivers/net/wireless/hostap_crypt.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_crypt.h 2003-06-09 13:30:26.000000000 -0400 -@@ -0,0 +1,44 @@ -+#ifndef PRISM2_CRYPT_H -+#define PRISM2_CRYPT_H -+ -+/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() -+ */ -+#define HOSTAP_CRYPT_ALG_NAME_LEN 16 -+ -+ -+struct hostap_crypto_ops { -+ char *name; -+ -+ /* init new crypto context (e.g., allocate private data space, -+ * select IV, etc.); returns NULL on failure or pointer to allocated -+ * private data on success */ -+ void * (*init)(void); -+ -+ /* deinitialize crypto context and free allocated private data */ -+ void (*deinit)(void *priv); -+ -+ /* encrypt/decrypt return < 0 on error or number of bytes written -+ * to out_buf; len is number of bytes in in_buf */ -+ int (*encrypt)(u8 *buf, int len, void *priv); -+ int (*decrypt)(u8 *buf, int len, void *priv); -+ -+ int (*set_key)(int idx, void *key, int len, void *priv); -+ int (*get_key)(int idx, void *key, int len, void *priv); -+ -+ int (*set_key_idx)(int idx, void *priv); -+ int (*get_key_idx)(void *priv); -+ -+ /* maximum number of bytes added by encryption; encrypt buf is -+ * allocated with extra_prefix_len bytes, copy of in_buf, and -+ * extra_postfix_len; encrypt need not use all this space, but -+ * the result must start at the beginning of the buffer and correct -+ * length must be returned */ -+ int extra_prefix_len, extra_postfix_len; -+}; -+ -+ -+int hostap_register_crypto_ops(struct hostap_crypto_ops *ops); -+int hostap_unregister_crypto_ops(struct hostap_crypto_ops *ops); -+struct hostap_crypto_ops * hostap_get_crypto_ops(const char *name); -+ -+#endif /* PRISM2_CRYPT_H */ - -Index: drivers/net/wireless/hostap_crypt_wep.c ---- drivers/net/wireless/hostap_crypt_wep.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_crypt_wep.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,366 @@ -+/* -+ * Host AP crypt: host-based WEP encryption implementation for Host AP driver -+ * -+ * Copyright (c) 2002, Jouni Malinen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. See README and COPYING for -+ * more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+#include -+#else -+#include -+#endif -+#include -+ -+MODULE_AUTHOR("Jouni Malinen"); -+MODULE_DESCRIPTION("Host AP crypt: WEP"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+#include "hostap_crypt.h" -+#include "hostap_compat.h" -+ -+ -+struct prism2_wep_data { -+ u32 iv; -+#define WEP_KEYS 4 -+#define WEP_KEY_LEN 13 -+ u8 keys[WEP_KEYS][WEP_KEY_LEN + 1]; -+ u8 key_lens[WEP_KEYS]; -+ int tx_key; -+}; -+ -+static const __u32 crc32_table[256] = { -+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -+ 0x2d02ef8dL -+}; -+ -+ -+static void * prism2_wep_init(void) -+{ -+ struct prism2_wep_data *priv; -+ -+#ifndef NEW_MODULE_CODE -+ MOD_INC_USE_COUNT; -+#endif -+ -+ priv = (struct prism2_wep_data *) kmalloc(sizeof(*priv), GFP_ATOMIC); -+ if (priv == NULL) { -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+ return NULL; -+ } -+ memset(priv, 0, sizeof(*priv)); -+ -+ /* start WEP IV from a random value */ -+ get_random_bytes(&priv->iv, 4); -+ -+ return priv; -+} -+ -+ -+static void prism2_wep_deinit(void *priv) -+{ -+ kfree(priv); -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+/* Perform WEP encryption on given buffer. Buffer needs to has 4 bytes of -+ * extra space (IV) in the beginning, then len bytes of data, and finally -+ * 4 bytes of extra space (ICV). Both IV and ICV will be transmitted, so the -+ * payload length increases with 8 bytes. -+ * -+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) -+ */ -+static int prism2_wep_encrypt(u8 *buf, int len, void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ u32 i, j, k, crc, klen; -+ u8 S[256], key[WEP_KEY_LEN + 3]; -+ u8 kpos, *pos; -+#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) -+ -+ klen = 3 + wep->key_lens[wep->tx_key]; -+ -+ wep->iv++; -+ -+ /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key -+ * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) -+ * can be used to speedup attacks, so avoid using them. */ -+ if ((wep->iv & 0xff00) == 0xff00) { -+ u8 B = (wep->iv >> 16) & 0xff; -+ if (B >= 3 && B < klen) -+ wep->iv += 0x0100; -+ } -+ -+ /* Prepend 24-bit IV to RC4 key and TX frame */ -+ pos = buf; -+ *pos++ = key[0] = (wep->iv >> 16) & 0xff; -+ *pos++ = key[1] = (wep->iv >> 8) & 0xff; -+ *pos++ = key[2] = wep->iv & 0xff; -+ *pos++ = wep->tx_key << 6; -+ -+ /* Copy rest of the WEP key (the secret part) */ -+ memcpy(key + 3, wep->keys[wep->tx_key], -+ wep->key_lens[wep->tx_key]); -+ -+ /* Setup RC4 state */ -+ for (i = 0; i < 256; i++) -+ S[i] = i; -+ j = 0; -+ kpos = 0; -+ for (i = 0; i < 256; i++) { -+ j = (j + S[i] + key[kpos]) & 0xff; -+ kpos++; -+ if (kpos >= klen) -+ kpos = 0; -+ S_SWAP(i, j); -+ } -+ -+ /* Compute CRC32 over unencrypted data and apply RC4 to data */ -+ crc = ~0; -+ i = j = 0; -+ for (k = 0; k < len; k++) { -+ crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8); -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ S_SWAP(i, j); -+ *pos++ ^= S[(S[i] + S[j]) & 0xff]; -+ } -+ crc = ~crc; -+ -+ /* Append little-endian CRC32 and encrypt it to produce ICV */ -+ pos[0] = crc; -+ pos[1] = crc >> 8; -+ pos[2] = crc >> 16; -+ pos[3] = crc >> 24; -+ for (k = 0; k < 4; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ S_SWAP(i, j); -+ *pos++ ^= S[(S[i] + S[j]) & 0xff]; -+ } -+ -+ return len + 8; -+} -+ -+ -+/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of -+ * the frame: IV (4 bytes), encrypted payload (including SNAP header), -+ * ICV (4 bytes). len includes both IV and ICV. -+ * -+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on -+ * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload -+ * is moved to beginning of buf and last 8 bytes of buf should be ignored. -+ */ -+static int prism2_wep_decrypt(u8 *buf, int len, void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ u32 i, j, k, crc, klen; -+ u8 S[256], key[WEP_KEY_LEN + 3]; -+ u8 keyidx, kpos, *dpos, *cpos; -+ -+ if (len < 8) -+ return -1; -+ -+ key[0] = buf[0]; -+ key[1] = buf[1]; -+ key[2] = buf[2]; -+ keyidx = buf[3] >> 6; -+ -+ klen = 3 + wep->key_lens[keyidx]; -+ -+ /* Copy rest of the WEP key (the secret part) */ -+ memcpy(key + 3, wep->keys[keyidx], wep->key_lens[keyidx]); -+ -+ /* Setup RC4 state */ -+ for (i = 0; i < 256; i++) -+ S[i] = i; -+ j = 0; -+ kpos = 0; -+ for (i = 0; i < 256; i++) { -+ j = (j + S[i] + key[kpos]) & 0xff; -+ kpos++; -+ if (kpos >= klen) -+ kpos = 0; -+ S_SWAP(i, j); -+ } -+ -+ /* Apply RC4 to data and compute CRC32 over decrypted data */ -+ dpos = buf; -+ cpos = buf + 4; -+ crc = ~0; -+ i = j = 0; -+ for (k = 0; k < len - 8; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ S_SWAP(i, j); -+ *dpos = *cpos++ ^ S[(S[i] + S[j]) & 0xff]; -+ crc = crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8); -+ } -+ crc = ~crc; -+ -+ /* Encrypt little-endian CRC32 and verify that it matches with the -+ * received ICV */ -+ dpos[0] = crc; -+ dpos[1] = crc >> 8; -+ dpos[2] = crc >> 16; -+ dpos[3] = crc >> 24; -+ for (k = 0; k < 4; k++) { -+ i = (i + 1) & 0xff; -+ j = (j + S[i]) & 0xff; -+ S_SWAP(i, j); -+ if ((*dpos++ ^ S[(S[i] + S[j]) & 0xff]) != *cpos++) { -+ /* ICV mismatch - drop frame */ -+ return -1; -+ } -+ } -+ -+ return len - 8; -+} -+ -+ -+static int prism2_wep_set_key(int idx, void *key, int len, void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ -+ if (idx < 0 || idx >= WEP_KEYS || len < 0 || len > WEP_KEY_LEN) -+ return -1; -+ -+ memcpy(wep->keys[idx], key, len); -+ wep->key_lens[idx] = len; -+ -+ return 0; -+} -+ -+ -+static int prism2_wep_get_key(int idx, void *key, int len, void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ -+ if (idx < 0 || idx >= WEP_KEYS || len < wep->key_lens[idx]) -+ return -1; -+ -+ memcpy(key, wep->keys[idx], wep->key_lens[idx]); -+ -+ return wep->key_lens[idx]; -+} -+ -+ -+static int prism2_wep_set_key_idx(int idx, void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ -+ if (idx < 0 || idx >= WEP_KEYS || wep->key_lens[idx] == 0) -+ return -1; -+ -+ wep->tx_key = idx; -+ -+ return 0; -+} -+ -+ -+static int prism2_wep_get_key_idx(void *priv) -+{ -+ struct prism2_wep_data *wep = priv; -+ return wep->tx_key; -+} -+ -+ -+static struct hostap_crypto_ops hostap_crypt_wep = { -+ .name = "WEP", -+ .init = prism2_wep_init, -+ .deinit = prism2_wep_deinit, -+ .encrypt = prism2_wep_encrypt, -+ .decrypt = prism2_wep_decrypt, -+ .set_key = prism2_wep_set_key, -+ .get_key = prism2_wep_get_key, -+ .set_key_idx = prism2_wep_set_key_idx, -+ .get_key_idx = prism2_wep_get_key_idx, -+ .extra_prefix_len = 4 /* IV */, -+ .extra_postfix_len = 4 /* ICV */ -+}; -+ -+ -+static int __init hostap_crypto_wep_init(void) -+{ -+ if (hostap_register_crypto_ops(&hostap_crypt_wep) < 0) -+ return -1; -+ -+ return 0; -+} -+ -+ -+static void __exit hostap_crypto_wep_exit(void) -+{ -+ hostap_unregister_crypto_ops(&hostap_crypt_wep); -+} -+ -+ -+module_init(hostap_crypto_wep_init); -+module_exit(hostap_crypto_wep_exit); - -Index: drivers/net/wireless/hostap_cs.c ---- drivers/net/wireless/hostap_cs.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_cs.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,805 @@ -+#define PRISM2_PCCARD -+ -+#include -+#ifdef __IN_PCMCIA_PACKAGE__ -+#include -+#endif /* __IN_PCMCIA_PACKAGE__ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+#include -+#else -+#include -+#endif -+#include -+#if WIRELESS_EXT > 12 -+#include -+#endif /* WIRELESS_EXT > 12 */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "hostap_wlan.h" -+ -+ -+#ifdef __IN_PCMCIA_PACKAGE__ -+#include -+#endif /* __IN_PCMCIA_PACKAGE__ */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -+/* This behavior changed in some Linux 2.5.x version. I don't remember when and -+ * don't really care if this does not work with some early 2.5.x versions.. -+ */ -+#define HOSTAP_USE_RELEASE_TIMER -+#endif -+ -+ -+static char *version = PRISM2_VERSION " (Jouni Malinen )"; -+static dev_info_t dev_info = "hostap_cs"; -+static dev_link_t *dev_list = NULL; -+ -+MODULE_AUTHOR("SSH Communications Security Corp, Jouni Malinen"); -+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " -+ "cards (PC Card)."); -+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+ -+static unsigned int irq_mask = 0xdeb8; -+MODULE_PARM(irq_mask, "i"); -+ -+static int irq_list[4] = { -1 }; -+MODULE_PARM(irq_list, "1-4i"); -+ -+static int ignore_cis_vcc = 0; -+MODULE_PARM(ignore_cis_vcc, "i"); -+MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); -+ -+ -+#ifdef PRISM2_IO_DEBUG -+ -+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); -+ outb(v, dev->base_addr + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u8 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = inb(dev->base_addr + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); -+ outw(v, dev->base_addr + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u16 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = inw(dev->base_addr + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+static inline void hfa384x_outsw_debug(struct net_device *dev, int a, -+ u8 *buf, int wc) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc); -+ outsw(dev->base_addr + a, buf, wc); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline void hfa384x_insw_debug(struct net_device *dev, int a, -+ u8 *buf, int wc) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc); -+ insw(dev->base_addr + a, buf, wc); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc)) -+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc)) -+ -+#else /* PRISM2_IO_DEBUG */ -+ -+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a)) -+#define HFA384X_INB(a) inb(dev->base_addr + (a)) -+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a)) -+#define HFA384X_INW(a) inw(dev->base_addr + (a)) -+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc) -+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc) -+ -+#endif /* PRISM2_IO_DEBUG */ -+ -+ -+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, -+ int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ if (len / 2) -+ HFA384X_INSW(d_off, buf, len / 2); -+ pos += len / 2; -+ -+ if (len & 1) -+ *((char *) pos) = HFA384X_INB(d_off); -+ -+ return 0; -+} -+ -+ -+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ if (len / 2) -+ HFA384X_OUTSW(d_off, buf, len / 2); -+ pos += len / 2; -+ -+ if (len & 1) -+ HFA384X_OUTB(*((char *) pos), d_off); -+ -+ return 0; -+} -+ -+ -+/* FIX: This might change at some point.. */ -+#include "hostap_hw.c" -+ -+ -+ -+static void prism2_detach(dev_link_t *link); -+static void prism2_release(u_long arg); -+static int prism2_event(event_t event, int priority, -+ event_callback_args_t *args); -+ -+ -+static int prism2_pccard_card_present(local_info_t *local) -+{ -+ if (local->link != NULL && -+ ((local->link->state & (DEV_PRESENT | DEV_CONFIG)) == -+ (DEV_PRESENT | DEV_CONFIG))) -+ return 1; -+ return 0; -+} -+ -+static void prism2_pccard_cor_sreset(local_info_t *local) -+{ -+ int res; -+ conf_reg_t reg; -+ -+ reg.Function = 0; -+ reg.Action = CS_READ; -+ reg.Offset = CISREG_COR; -+ reg.Value = 0; -+ res = CardServices(AccessConfigurationRegister, local->link->handle, -+ ®); -+ if (res != CS_SUCCESS) { -+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", -+ res); -+ return; -+ } -+ printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n", -+ reg.Value); -+ -+ reg.Action = CS_WRITE; -+ reg.Value |= COR_SOFT_RESET; -+ res = CardServices(AccessConfigurationRegister, local->link->handle, -+ ®); -+ if (res != CS_SUCCESS) { -+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", -+ res); -+ return; -+ } -+ -+ mdelay(1); -+ -+ reg.Value &= ~COR_SOFT_RESET; -+ res = CardServices(AccessConfigurationRegister, local->link->handle, -+ ®); -+ if (res != CS_SUCCESS) { -+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", -+ res); -+ return; -+ } -+ -+ mdelay(1); -+} -+ -+ -+static int prism2_pccard_dev_open(local_info_t *local) -+{ -+ local->link->open++; -+ return 0; -+} -+ -+ -+static int prism2_pccard_dev_close(local_info_t *local) -+{ -+ if (local == NULL || local->link == NULL) -+ return 1; -+ -+ if (!local->link->open) { -+ printk(KERN_WARNING "%s: prism2_pccard_dev_close(): " -+ "link not open?!\n", local->dev->name); -+ return 1; -+ } -+ -+ local->link->open--; -+ -+ if (local->link->state & DEV_STALE_CONFIG) { -+#ifdef HOSTAP_USE_RELEASE_TIMER -+ mod_timer(&local->link->release, jiffies + HZ / 20); -+#else /* HOSTAP_USE_RELEASE_TIMER */ -+ prism2_release((u_long) local->link); -+#endif /* HOSTAP_USE_RELEASE_TIMER */ -+ } -+ -+ return 0; -+} -+ -+ -+static struct prism2_helper_functions prism2_pccard_funcs = -+{ -+ .card_present = prism2_pccard_card_present, -+ .cor_sreset = prism2_pccard_cor_sreset, -+ .dev_open = prism2_pccard_dev_open, -+ .dev_close = prism2_pccard_dev_close -+}; -+ -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,68) -+static void cs_error(client_handle_t handle, int func, int ret) -+{ -+ error_info_t err = { func, ret }; -+ CardServices(ReportError, handle, &err); -+} -+#endif -+ -+ -+/* allocate local data and register with CardServices -+ * initialize dev_link structure, but do not configure the card yet */ -+static dev_link_t *prism2_attach(void) -+{ -+ dev_link_t *link; -+ local_info_t *local; -+ client_reg_t client_reg; -+ int ret; -+ -+ for (link = dev_list; link; link = link->next) { -+ if (link->state & DEV_STALE_LINK) { -+ printk("%s: flushing stale link\n", dev_info); -+ prism2_detach(link); -+ } -+ } -+ -+ link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); -+ if (link == NULL) -+ return NULL; -+ -+ memset(link, 0, sizeof(dev_link_t)); -+ -+ local = prism2_init_local_data(&prism2_pccard_funcs, 0); -+ if (local == NULL) { -+ kfree(link); -+ return NULL; -+ } -+ -+ link->priv = local->dev; -+ local->link = link; -+ -+#ifdef HOSTAP_USE_RELEASE_TIMER -+ init_timer(&link->release); -+ link->release.function = &prism2_release; -+ link->release.data = (u_long)link; -+#endif /* HOSTAP_USE_RELEASE_TIMER */ -+ -+ PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); -+ link->conf.Vcc = 33; -+ link->conf.IntType = INT_MEMORY_AND_IO; -+ -+ /* register with CardServices */ -+ link->next = dev_list; -+ dev_list = link; -+ client_reg.dev_info = &dev_info; -+ client_reg.Attributes = INFO_IO_CLIENT; -+ client_reg.EventMask = CS_EVENT_CARD_INSERTION | -+ CS_EVENT_CARD_REMOVAL | -+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | -+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; -+ client_reg.event_handler = &prism2_event; -+ client_reg.Version = 0x0210; -+ client_reg.event_callback_args.client_data = link; -+ ret = CardServices(RegisterClient, &link->handle, &client_reg); -+ if (ret != CS_SUCCESS) { -+ cs_error(link->handle, RegisterClient, ret); -+ prism2_detach(link); -+ return NULL; -+ } -+ return link; -+} -+ -+ -+static void prism2_detach(dev_link_t *link) -+{ -+ dev_link_t **linkp; -+ -+ PDEBUG(DEBUG_FLOW, "prism2_detach\n"); -+ -+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) -+ if (*linkp == link) -+ break; -+ if (*linkp == NULL) { -+ printk(KERN_WARNING "%s: Attempt to detach non-existing " -+ "PCMCIA client\n", dev_info); -+ return; -+ } -+ -+#ifdef HOSTAP_USE_RELEASE_TIMER -+ del_timer(&link->release); -+#endif /* HOSTAP_USE_RELEASE_TIMER */ -+ if (link->state & DEV_CONFIG) { -+ printk("%s: detach postponed, '%s' still locked\n", -+ dev_info, link->dev->dev_name); -+ prism2_release((u_long)link); -+ if (link->state & DEV_STALE_CONFIG) { -+ link->state |= DEV_STALE_LINK; -+ return; -+ } -+ } -+ -+ if (link->handle) { -+ int res = CardServices(DeregisterClient, link->handle); -+ if (res) { -+ printk("CardService(DeregisterClient) => %d\n", res); -+ cs_error(link->handle, DeregisterClient, res); -+ } -+ } -+ -+ *linkp = link->next; -+ /* release local_info_t struct */ -+ if (link->priv) { -+ struct net_device *dev = (struct net_device *) link->priv; -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ prism2_free_local_data(local); -+ -+ } -+ kfree(link); -+} -+ -+ -+#define CS_CHECK(fn, args...) \ -+while ((last_ret = CardServices(last_fn = (fn), args)) != 0) goto cs_failed -+ -+#define CFG_CHECK2(fn, args...) \ -+do { int ret = CardServices(fn, args); \ -+if (ret != 0) { \ -+ PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \ -+ cs_error(link->handle, fn, ret); \ -+ goto next_entry; \ -+} \ -+} while (0) -+ -+ -+/* run after a CARD_INSERTATION event is received to configure the PCMCIA -+ * socket and make the device available to the system */ -+static int prism2_config(dev_link_t *link) -+{ -+ struct net_device *dev = (struct net_device *) link->priv; -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret; -+ tuple_t tuple; -+ cisparse_t parse; -+ int last_fn, last_ret; -+ u_char buf[64]; -+ config_info_t conf; -+ cistpl_cftable_entry_t dflt = { 0 }; -+ -+ PDEBUG(DEBUG_FLOW, "prism2_config()\n"); -+ -+ tuple.DesiredTuple = CISTPL_CONFIG; -+ tuple.Attributes = 0; -+ tuple.TupleData = buf; -+ tuple.TupleDataMax = sizeof(buf); -+ tuple.TupleOffset = 0; -+ CS_CHECK(GetFirstTuple, link->handle, &tuple); -+ CS_CHECK(GetTupleData, link->handle, &tuple); -+ CS_CHECK(ParseTuple, link->handle, &tuple, &parse); -+ link->conf.ConfigBase = parse.config.base; -+ link->conf.Present = parse.config.rmask[0]; -+ -+ CS_CHECK(GetConfigurationInfo, link->handle, &conf); -+ PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info, -+ ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc); -+ link->conf.Vcc = conf.Vcc; -+ -+ /* Look for an appropriate configuration table entry in the CIS */ -+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -+ CS_CHECK(GetFirstTuple, link->handle, &tuple); -+ for (;;) { -+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -+ CFG_CHECK2(GetTupleData, link->handle, &tuple); -+ CFG_CHECK2(ParseTuple, link->handle, &tuple, &parse); -+ -+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -+ dflt = *cfg; -+ if (cfg->index == 0) -+ goto next_entry; -+ link->conf.ConfigIndex = cfg->index; -+ PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " -+ "(default 0x%02X)\n", cfg->index, dflt.index); -+ -+ /* Does this card need audio output? */ -+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -+ link->conf.Attributes |= CONF_ENABLE_SPKR; -+ link->conf.Status = CCSR_AUDIO_ENA; -+ } -+ -+ /* Use power settings for Vcc and Vpp if present */ -+ /* Note that the CIS values need to be rescaled */ -+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { -+ if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / -+ 10000 && !ignore_cis_vcc) { -+ PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" -+ " this entry\n"); -+ goto next_entry; -+ } -+ } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { -+ if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / -+ 10000 && !ignore_cis_vcc) { -+ PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " -+ "- skipping this entry\n"); -+ goto next_entry; -+ } -+ } -+ -+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) -+ link->conf.Vpp1 = link->conf.Vpp2 = -+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; -+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) -+ link->conf.Vpp1 = link->conf.Vpp2 = -+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; -+ -+ /* Do we need to allocate an interrupt? */ -+ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -+ link->conf.Attributes |= CONF_ENABLE_IRQ; -+ else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) { -+ /* At least Compaq WL200 does not have IRQInfo1 set, -+ * but it does not work without interrupts.. */ -+ printk("Config has no IRQ info, but trying to enable " -+ "IRQ anyway..\n"); -+ link->conf.Attributes |= CONF_ENABLE_IRQ; -+ } -+ -+ /* IO window settings */ -+ PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " -+ "dflt.io.nwin=%d\n", -+ cfg->io.nwin, dflt.io.nwin); -+ link->io.NumPorts1 = link->io.NumPorts2 = 0; -+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -+ PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " -+ "io.base=0x%04x, len=%d\n", io->flags, -+ io->win[0].base, io->win[0].len); -+ if (!(io->flags & CISTPL_IO_8BIT)) -+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -+ if (!(io->flags & CISTPL_IO_16BIT)) -+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -+ link->io.IOAddrLines = io->flags & -+ CISTPL_IO_LINES_MASK; -+ link->io.BasePort1 = io->win[0].base; -+ link->io.NumPorts1 = io->win[0].len; -+ if (io->nwin > 1) { -+ link->io.Attributes2 = link->io.Attributes1; -+ link->io.BasePort2 = io->win[1].base; -+ link->io.NumPorts2 = io->win[1].len; -+ } -+ } -+ -+ /* This reserves IO space but doesn't actually enable it */ -+ CFG_CHECK2(RequestIO, link->handle, &link->io); -+ -+ /* This configuration table entry is OK */ -+ break; -+ -+ next_entry: -+ CS_CHECK(GetNextTuple, link->handle, &tuple); -+ } -+ -+ /* -+ * Allocate an interrupt line. Note that this does not assign a -+ * handler to the interrupt, unless the 'Handler' member of the -+ * irq structure is initialized. -+ */ -+ if (link->conf.Attributes & CONF_ENABLE_IRQ) { -+ int i; -+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; -+ link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; -+ if (irq_list[0] == -1) -+ link->irq.IRQInfo2 = irq_mask; -+ else -+ for (i = 0; i < 4; i++) -+ link->irq.IRQInfo2 |= 1 << irq_list[i]; -+ link->irq.Handler = (void *) prism2_interrupt; -+ link->irq.Instance = dev; -+ CS_CHECK(RequestIRQ, link->handle, &link->irq); -+ } -+ -+ /* -+ * This actually configures the PCMCIA socket -- setting up -+ * the I/O windows and the interrupt mapping, and putting the -+ * card and host interface into "Memory and IO" mode. -+ */ -+ CS_CHECK(RequestConfiguration, link->handle, &link->conf); -+ -+ dev->irq = link->irq.AssignedIRQ; -+ dev->base_addr = link->io.BasePort1; -+ -+ /* Finally, report what we've done */ -+ printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", -+ dev_info, link->conf.ConfigIndex, -+ link->conf.Vcc / 10, link->conf.Vcc % 10); -+ if (link->conf.Vpp1) -+ printk(", Vpp %d.%d", link->conf.Vpp1 / 10, -+ link->conf.Vpp1 % 10); -+ if (link->conf.Attributes & CONF_ENABLE_IRQ) -+ printk(", irq %d", link->irq.AssignedIRQ); -+ if (link->io.NumPorts1) -+ printk(", io 0x%04x-0x%04x", link->io.BasePort1, -+ link->io.BasePort1+link->io.NumPorts1-1); -+ if (link->io.NumPorts2) -+ printk(" & 0x%04x-0x%04x", link->io.BasePort2, -+ link->io.BasePort2+link->io.NumPorts2-1); -+ printk("\n"); -+ -+ link->state |= DEV_CONFIG; -+ link->state &= ~DEV_CONFIG_PENDING; -+ -+ if (prism2_init_dev(local)) { -+ prism2_release((u_long) link); -+ return 1; -+ } -+ -+ strcpy(local->node.dev_name, dev->name); -+ link->dev = &local->node; -+ -+ local->shutdown = 0; -+ -+ ret = prism2_hw_config(dev, 1); -+ return ret; -+ -+ cs_failed: -+ cs_error(link->handle, last_fn, last_ret); -+ prism2_release((u_long)link); -+ return 1; -+} -+ -+ -+static void prism2_release(u_long arg) -+{ -+ dev_link_t *link = (dev_link_t *)arg; -+ struct net_device *dev = (struct net_device *) link->priv; -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ PDEBUG(DEBUG_FLOW, "prism2_release\n"); -+ -+ if (link->open) { -+ printk("%s: release postponed, '%s' still open\n", -+ dev_info, link->dev->dev_name); -+ link->state |= DEV_STALE_CONFIG; -+ return; -+ } -+ -+ if (dev != NULL) -+ prism2_hw_shutdown(dev, 0); -+ -+ local->shutdown = 1; -+ -+ if (link->win) -+ CardServices(ReleaseWindow, link->win); -+ CardServices(ReleaseConfiguration, link->handle); -+ if (link->io.NumPorts1) -+ CardServices(ReleaseIO, link->handle, &link->io); -+ if (link->irq.AssignedIRQ) -+ CardServices(ReleaseIRQ, link->handle, &link->irq); -+ -+ link->state &= ~DEV_CONFIG; -+ -+ PDEBUG(DEBUG_FLOW, "release - done\n"); -+} -+ -+ -+static int prism2_event(event_t event, int priority, -+ event_callback_args_t *args) -+{ -+ dev_link_t *link = args->client_data; -+ struct net_device *dev = (struct net_device *) link->priv; -+ -+ switch (event) { -+ case CS_EVENT_CARD_INSERTION: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info); -+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; -+ if (prism2_config(link)) -+ dev->irq = 0; -+ break; -+ -+ case CS_EVENT_CARD_REMOVAL: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info); -+ link->state &= ~DEV_PRESENT; -+ if (link->state & DEV_CONFIG) { -+ hostap_netif_stop_queues(dev); -+ netif_device_detach(dev); -+#ifdef HOSTAP_USE_RELEASE_TIMER -+ mod_timer(&link->release, jiffies + HZ / 20); -+#else /* HOSTAP_USE_RELEASE_TIMER */ -+ prism2_release((u_long) link); -+#endif /* HOSTAP_USE_RELEASE_TIMER */ -+ } -+ break; -+ -+ case CS_EVENT_PM_SUSPEND: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); -+ link->state |= DEV_SUSPEND; -+ /* fall through */ -+ -+ case CS_EVENT_RESET_PHYSICAL: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info); -+ if (link->state & DEV_CONFIG) { -+ if (link->open) { -+ hostap_netif_stop_queues(dev); -+ netif_device_detach(dev); -+ } -+ CardServices(ReleaseConfiguration, link->handle); -+ } -+ break; -+ -+ case CS_EVENT_PM_RESUME: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); -+ link->state &= ~DEV_SUSPEND; -+ /* fall through */ -+ -+ case CS_EVENT_CARD_RESET: -+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info); -+ if (link->state & DEV_CONFIG) { -+ CardServices(RequestConfiguration, link->handle, -+ &link->conf); -+ if (link->open) { -+ prism2_hw_shutdown(dev, 1); -+ prism2_hw_config(dev, 0); -+ netif_device_attach(dev); -+ netif_start_queue(dev); -+ } -+ } -+ break; -+ -+ default: -+ PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n", -+ dev_info, event); -+ break; -+ } -+ return 0; -+} -+ -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) -+static struct pcmcia_driver hostap_driver = { -+ .drv = { -+ .name = "hostap_cs", -+ }, -+ .attach = prism2_attach, -+ .detach = prism2_detach, -+ .owner = THIS_MODULE, -+}; -+ -+static int __init init_prism2_pccard(void) -+{ -+ printk(KERN_INFO "%s: %s\n", dev_info, version); -+ return pcmcia_register_driver(&hostap_driver); -+} -+ -+static void __exit exit_prism2_pccard(void) -+{ -+ pcmcia_unregister_driver(&hostap_driver); -+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -+} -+ -+#else -+ -+static int __init init_prism2_pccard(void) -+{ -+ servinfo_t serv; -+ -+ printk(KERN_INFO "%s: %s\n", dev_info, version); -+ CardServices(GetCardServicesInfo, &serv); -+ if (serv.Revision != CS_RELEASE_CODE) { -+ printk(KERN_NOTICE -+ "%s: CardServices release does not match!\n", dev_info); -+ return -1; -+ } -+ register_pccard_driver(&dev_info, &prism2_attach, &prism2_detach); -+ -+ return 0; -+} -+ -+ -+static void __exit exit_prism2_pccard(void) -+{ -+ unregister_pccard_driver(&dev_info); -+ while (dev_list) { -+ PDEBUG(DEBUG_FLOW, "exit_prism2 - detaching device\n"); -+#ifdef HOSTAP_USE_RELEASE_TIMER -+ del_timer(&dev_list->release); -+#endif /* HOSTAP_USE_RELEASE_TIMER */ -+ if (dev_list->state & DEV_CONFIG) -+ prism2_release((u_long)dev_list); -+ prism2_detach(dev_list); -+ } -+ -+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -+} -+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) */ -+ -+ -+module_init(init_prism2_pccard); -+module_exit(exit_prism2_pccard); - -Index: drivers/net/wireless/hostap_download.c ---- drivers/net/wireless/hostap_download.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_download.c 2003-06-27 23:28:21.000000000 -0400 -@@ -0,0 +1,547 @@ -+static int prism2_enable_aux_port(struct net_device *dev, int enable) -+{ -+ u16 val, reg; -+ int i, tries; -+ unsigned long flags; -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ -+ /* wait until busy bit is clear */ -+ tries = HFA384X_CMD_BUSY_TIMEOUT; -+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { -+ tries--; -+ udelay(1); -+ } -+ if (tries == 0) { -+ reg = HFA384X_INW(HFA384X_CMD_OFF); -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n", -+ dev->name, reg); -+ return -ETIMEDOUT; -+ } -+ -+ val = HFA384X_INW(HFA384X_CONTROL_OFF); -+ -+ if (enable) { -+ HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF); -+ HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF); -+ HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF); -+ -+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED) -+ printk("prism2_enable_aux_port: was not disabled!?\n"); -+ val &= ~HFA384X_AUX_PORT_MASK; -+ val |= HFA384X_AUX_PORT_ENABLE; -+ } else { -+ HFA384X_OUTW(0, HFA384X_PARAM0_OFF); -+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF); -+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF); -+ -+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED) -+ printk("prism2_enable_aux_port: was not enabled!?\n"); -+ val &= ~HFA384X_AUX_PORT_MASK; -+ val |= HFA384X_AUX_PORT_DISABLE; -+ } -+ HFA384X_OUTW(val, HFA384X_CONTROL_OFF); -+ -+ udelay(5); -+ -+ i = 10000; -+ while (i > 0) { -+ val = HFA384X_INW(HFA384X_CONTROL_OFF); -+ val &= HFA384X_AUX_PORT_MASK; -+ -+ if ((enable && val == HFA384X_AUX_PORT_ENABLED) || -+ (!enable && val == HFA384X_AUX_PORT_DISABLED)) -+ break; -+ -+ udelay(10); -+ i--; -+ } -+ -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ -+ if (i == 0) { -+ printk("prism2_enable_aux_port(%d) timed out\n", -+ enable); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+ -+static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len, -+ void *buf) -+{ -+ u16 page, offset; -+ if (addr & 1 || len & 1) -+ return -1; -+ -+ page = addr >> 7; -+ offset = addr & 0x7f; -+ -+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF); -+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF); -+ -+ udelay(5); -+ -+#ifdef PRISM2_PCI -+ { -+ u16 *pos = (u16 *) buf; -+ while (len > 0) { -+ *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF); -+ len -= 2; -+ } -+ } -+#else /* PRISM2_PCI */ -+ HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2); -+#endif /* PRISM2_PCI */ -+ -+ return 0; -+} -+ -+ -+static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len, -+ void *buf) -+{ -+ u16 page, offset; -+ if (addr & 1 || len & 1) -+ return -1; -+ -+ page = addr >> 7; -+ offset = addr & 0x7f; -+ -+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF); -+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF); -+ -+ udelay(5); -+ -+#ifdef PRISM2_PCI -+ { -+ u16 *pos = (u16 *) buf; -+ while (len > 0) { -+ HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF); -+ len -= 2; -+ } -+ } -+#else /* PRISM2_PCI */ -+ HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2); -+#endif /* PRISM2_PCI */ -+ -+ return 0; -+} -+ -+ -+static int prism2_pda_ok(u8 *buf) -+{ -+ u16 *pda = (u16 *) buf; -+ int pos; -+ u16 len, pdr; -+ -+ if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff && -+ buf[3] == 0x00) -+ return 0; -+ -+ pos = 0; -+ while (pos + 1 < PRISM2_PDA_SIZE / 2) { -+ len = le16_to_cpu(pda[pos]); -+ pdr = le16_to_cpu(pda[pos + 1]); -+ if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2) -+ return 0; -+ -+ if (pdr == 0x0000 && len == 2) { -+ /* PDA end found */ -+ return 1; -+ } -+ -+ pos += len + 1; -+ } -+ -+ return 0; -+} -+ -+ -+static u8 * prism2_read_pda(struct net_device *dev) -+{ -+ u8 *buf; -+ int res, i, found = 0; -+#define NUM_PDA_ADDRS 3 -+ unsigned int pda_addr[NUM_PDA_ADDRS] = { -+ 0x7f0000 /* others than HFA3841 */, -+ 0x3f0000 /* HFA3841 */, -+ 0x390000 /* apparently used in older cards */ -+ }; -+ -+ buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL); -+ if (buf == NULL) -+ return NULL; -+ -+ /* Note: wlan card should be in initial state (just after init cmd) -+ * and no other operations should be performed concurrently. */ -+ -+ prism2_enable_aux_port(dev, 1); -+ -+ for (i = 0; i < NUM_PDA_ADDRS; i++) { -+ printk(KERN_DEBUG "%s: trying to read PDA from 0x%08x", -+ dev->name, pda_addr[i]); -+ res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf); -+ if (res) -+ continue; -+ if (res == 0 && prism2_pda_ok(buf)) { -+ printk(": OK\n"); -+ found = 1; -+ break; -+ } else { -+ printk(": failed\n"); -+ } -+ } -+ -+ prism2_enable_aux_port(dev, 0); -+ -+ if (!found) { -+ kfree(buf); -+ buf = NULL; -+ } -+ -+ return buf; -+} -+ -+ -+static int prism2_download_volatile(local_info_t *local, -+ struct prism2_download_param *param, -+ u8 **copied_data) -+{ -+ struct net_device *dev = local->dev; -+ int ret = 0, i; -+ u16 param0, param1; -+ -+ if (local->hw_downloading) { -+ printk(KERN_WARNING "%s: Already downloading - aborting new " -+ "request\n", dev->name); -+ return -1; -+ } -+ -+ local->hw_downloading = 1; -+ prism2_hw_shutdown(dev, 0); -+ -+ if (prism2_hw_init(dev, 0)) { -+ printk(KERN_WARNING "%s: Could not initialize card for " -+ "download\n", dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ if (prism2_enable_aux_port(dev, 1)) { -+ printk(KERN_WARNING "%s: Could not enable AUX port\n", -+ dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ param0 = param->start_addr & 0xffff; -+ param1 = param->start_addr >> 16; -+ -+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF); -+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); -+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | -+ (HFA384X_PROGMODE_ENABLE_VOLATILE << 8), -+ param0, NULL), 0) { -+ printk(KERN_WARNING "%s: Download command execution failed\n", -+ dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ for (i = 0; i < param->num_areas; i++) { -+ printk(KERN_DEBUG "%s: Writing %d bytes at 0x%08x\n", -+ dev->name, param->data[i].len, param->data[i].addr); -+ if (hfa384x_to_aux(dev, param->data[i].addr, -+ param->data[i].len, copied_data[i])) { -+ printk(KERN_WARNING "%s: RAM download at 0x%08x " -+ "(len=%d) failed\n", dev->name, -+ param->data[i].addr, param->data[i].len); -+ ret = -1; -+ goto out; -+ } -+ } -+ -+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); -+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF); -+ if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD | -+ (HFA384X_PROGMODE_DISABLE << 8), param0)) { -+ printk(KERN_WARNING "%s: Download command execution failed\n", -+ dev->name); -+ ret = -1; -+ goto out; -+ } -+ /* ProgMode disable causes the hardware to restart itself from the -+ * given starting address. Give hw some time and ACK command just in -+ * case restart did not happen. */ -+ mdelay(5); -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ -+ if (prism2_enable_aux_port(dev, 0)) { -+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n", -+ dev->name); -+ /* continue anyway.. restart should have taken care of this */ -+ } -+ -+ mdelay(5); -+ local->hw_downloading = 0; -+ if (prism2_hw_config(dev, 2)) { -+ printk(KERN_WARNING "%s: Card configuration after RAM " -+ "download failed\n", dev->name); -+ ret = -1; -+ goto out2; -+ } -+ -+ goto out2; -+ out: -+ local->hw_downloading = 0; -+ out2: -+ return ret; -+} -+ -+ -+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD -+/* Note! Non-volatile downloading functionality has not yet been tested -+ * thoroughly and it may corrupt flash image and effectively kill the card that -+ * is being updated. You have been warned. */ -+ -+static inline int prism2_download_block(struct net_device *dev, -+ struct prism2_download_param *param, -+ u8 **copied_data, u32 bufaddr, -+ int idx, int rest_len, int data_off) -+{ -+ u16 param0, param1; -+ int block_len; -+ -+ block_len = rest_len < 4096 ? rest_len : 4096; -+ -+ param0 = (param->data[idx].addr + data_off) & 0xffff; -+ param1 = (param->data[idx].addr + data_off) >> 16; -+ -+ HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF); -+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); -+ -+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | -+ (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8), -+ param0, NULL)) { -+ printk(KERN_WARNING "%s: Flash download command execution " -+ "failed\n", dev->name); -+ return -1; -+ } -+ -+ if (hfa384x_to_aux(dev, bufaddr, -+ block_len, copied_data[idx] + data_off)) { -+ printk(KERN_WARNING "%s: flash download at 0x%08x " -+ "(len=%d) failed\n", dev->name, -+ param->data[idx].addr, param->data[idx].len); -+ return -1; -+ } -+ -+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF); -+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF); -+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | -+ (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8), -+ 0, NULL)) { -+ printk(KERN_WARNING "%s: Flash write command execution " -+ "failed\n", dev->name); -+ return -1; -+ } -+ -+ return block_len; -+} -+ -+ -+static int prism2_download_nonvolatile(local_info_t *local, -+ struct prism2_download_param *param, -+ u8 **copied_data) -+{ -+ struct net_device *dev = local->dev; -+ int ret = 0, i; -+ struct { -+ u16 page; -+ u16 offset; -+ u16 len; -+ } dlbuffer; -+ u32 bufaddr; -+ -+ if (local->hw_downloading) { -+ printk(KERN_WARNING "%s: Already downloading - aborting new " -+ "request\n", dev->name); -+ return -1; -+ } -+ -+ local->hw_downloading = 1; -+ -+ ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER, -+ &dlbuffer, 6, 0); -+ -+ if (ret < 0) { -+ printk(KERN_WARNING "%s: Could not read download buffer " -+ "parameters\n", dev->name); -+ goto out; -+ } -+ -+ dlbuffer.page = le16_to_cpu(dlbuffer.page); -+ dlbuffer.offset = le16_to_cpu(dlbuffer.offset); -+ dlbuffer.len = le16_to_cpu(dlbuffer.len); -+ -+ printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n", -+ dlbuffer.len, dlbuffer.page, dlbuffer.offset); -+ -+ bufaddr = (dlbuffer.page << 7) + dlbuffer.offset; -+ -+ prism2_hw_shutdown(dev, 0); -+ -+ if (prism2_hw_init(dev, 0)) { -+ printk(KERN_WARNING "%s: Could not initialize card for " -+ "download\n", dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ hfa384x_disable_interrupts(dev); -+ -+ if (prism2_enable_aux_port(dev, 1)) { -+ printk(KERN_WARNING "%s: Could not enable AUX port\n", -+ dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ printk(KERN_DEBUG "%s: starting flash download\n", dev->name); -+ for (i = 0; i < param->num_areas; i++) { -+ int rest_len = param->data[i].len; -+ int data_off = 0; -+ -+ while (rest_len > 0) { -+ int block_len; -+ -+ block_len = prism2_download_block( -+ dev, param, copied_data, bufaddr, -+ i, rest_len, data_off); -+ -+ if (block_len < 0) { -+ ret = -1; -+ goto out; -+ } -+ -+ rest_len -= block_len; -+ data_off += block_len; -+ } -+ } -+ -+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF); -+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF); -+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | -+ (HFA384X_PROGMODE_DISABLE << 8), 0, NULL)) { -+ printk(KERN_WARNING "%s: Download command execution failed\n", -+ dev->name); -+ ret = -1; -+ goto out; -+ } -+ -+ if (prism2_enable_aux_port(dev, 0)) { -+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n", -+ dev->name); -+ /* continue anyway.. restart should have taken care of this */ -+ } -+ -+ mdelay(5); -+ -+ local->func->hw_reset(dev); -+ local->hw_downloading = 0; -+ if (prism2_hw_config(dev, 2)) { -+ printk(KERN_WARNING "%s: Card configuration after flash " -+ "download failed\n", dev->name); -+ ret = -1; -+ } else { -+ printk(KERN_INFO "%s: Card initialized successfully after " -+ "flash download\n", dev->name); -+ } -+ -+ out: -+ local->hw_downloading = 0; -+ return ret; -+} -+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */ -+ -+ -+ -+static int prism2_download(local_info_t *local, -+ struct prism2_download_param *param) -+{ -+ int ret = 0; -+ int i; -+ u32 total_len = 0; -+ u8 **copied_data; -+ -+ printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x " -+ "num_areas=%d\n", -+ param->dl_cmd, param->start_addr, param->num_areas); -+ -+ copied_data = (u8 **) kmalloc(param->num_areas * sizeof(u8 *), -+ GFP_KERNEL); -+ if (copied_data == NULL) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ memset(copied_data, 0, param->num_areas * sizeof(u8 *)); -+ -+ for (i = 0; i < param->num_areas; i++) { -+ printk(KERN_DEBUG " area %d: addr=0x%08x len=%d ptr=0x%p\n", -+ i, param->data[i].addr, param->data[i].len, -+ param->data[i].ptr); -+ total_len += param->data[i].len; -+ if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN || -+ total_len > PRISM2_MAX_DOWNLOAD_LEN) { -+ ret = -E2BIG; -+ goto out; -+ } -+ -+ copied_data[i] = (u8 *) -+ kmalloc(param->data[i].len, GFP_KERNEL); -+ if (copied_data[i] == NULL) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ if (copy_from_user(copied_data[i], param->data[i].ptr, -+ param->data[i].len)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ } -+ -+ switch (param->dl_cmd) { -+ case PRISM2_DOWNLOAD_VOLATILE: -+ ret = prism2_download_volatile(local, param, copied_data); -+ break; -+ case PRISM2_DOWNLOAD_NON_VOLATILE: -+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD -+ ret = prism2_download_nonvolatile(local, param, copied_data); -+#else /* PRISM2_NON_VOLATILE_DOWNLOAD */ -+ printk(KERN_INFO "%s: non-volatile downloading not enabled\n", -+ local->dev->name); -+ ret = -EOPNOTSUPP; -+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */ -+ break; -+ default: -+ printk(KERN_DEBUG "%s: unsupported download command %d\n", -+ local->dev->name, param->dl_cmd); -+ ret = -EINVAL; -+ break; -+ }; -+ -+ out: -+ if (copied_data) { -+ for (i = 0; i < param->num_areas; i++) -+ if (copied_data[i] != NULL) -+ kfree(copied_data[i]); -+ kfree(copied_data); -+ } -+ return ret; -+} - -Index: drivers/net/wireless/hostap.h ---- drivers/net/wireless/hostap.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap.h 2003-07-08 14:51:41.000000000 -0400 -@@ -0,0 +1,45 @@ -+#ifndef HOSTAP_H -+#define HOSTAP_H -+ -+/* hostap.c */ -+ -+extern struct proc_dir_entry *hostap_proc; -+ -+u16 hostap_tx_callback_register(local_info_t *local, -+ void (*func)(struct sk_buff *, int ok, void *), -+ void *data); -+int hostap_tx_callback_unregister(local_info_t *local, u16 idx); -+int hostap_set_word(struct net_device *dev, int rid, u16 val); -+int hostap_set_string(struct net_device *dev, int rid, const char *val); -+u16 hostap_get_porttype(local_info_t *local); -+int hostap_set_encryption(local_info_t *local); -+int hostap_set_antsel(local_info_t *local); -+void hostap_dump_rx_header(const char *name, -+ const struct hfa384x_rx_frame *rx); -+void hostap_dump_tx_header(const char *name, -+ const struct hfa384x_tx_frame *tx); -+void hostap_netif_wake_queues(struct net_device *dev); -+void hostap_netif_stop_queues(struct net_device *dev); -+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr); -+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr); -+int hostap_80211_get_hdrlen(u16 fc); -+struct net_device_stats *hostap_get_stats(struct net_device *dev); -+void hostap_setup_dev(struct net_device *dev, local_info_t *local, -+ int main_dev); -+void hostap_set_multicast_list_queue(void *data); -+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked); -+ -+ -+/* hostap_proc.c */ -+ -+void hostap_init_proc(local_info_t *local); -+void hostap_remove_proc(local_info_t *local); -+ -+ -+/* hostap_info.c */ -+ -+void hostap_info_init(local_info_t *local); -+void hostap_info_process(local_info_t *local, struct sk_buff *skb); -+ -+ -+#endif /* HOSTAP_H */ - -Index: drivers/net/wireless/hostap_hw.c ---- drivers/net/wireless/hostap_hw.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_hw.c 2003-08-08 22:39:41.000000000 -0400 -@@ -0,0 +1,4551 @@ -+/* -+ * Host AP (software wireless LAN access point) driver for -+ * Intersil Prism2/2.5/3. -+ * -+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen -+ * -+ * Copyright (c) 2002-2003, Jouni Malinen -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. See README and COPYING for -+ * more details. -+ * -+ * FIX: -+ * - there is currently no way of associating TX packets to correct wds device -+ * when TX Exc/OK event occurs, so all tx_packets and some -+ * tx_errors/tx_dropped are added to the main netdevice; using sw_support -+ * field in txdesc might be used to fix this (using Alloc event to increment -+ * tx_packets would need some further info in txfid table) -+ * -+ * Buffer Access Path (BAP) usage: -+ * Prism2 cards have two separate BAPs for accessing the card memory. These -+ * should allow concurrent access to two different frames and the driver -+ * previously used BAP0 for sending data and BAP1 for receiving data. -+ * However, there seems to be number of issues with concurrent access and at -+ * least one know hardware bug in using BAP0 and BAP1 concurrently with PCI -+ * Prism2.5. Therefore, the driver now only uses BAP0 for moving data between -+ * host and card memories. BAP0 accesses are protected with local->baplock -+ * (spin_lock_bh) to prevent concurrent use. -+ */ -+ -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT > 12 -+#include -+#endif /* WIRELESS_EXT > 12 */ -+#include -+ -+ -+#include "hostap.h" -+#include "hostap_ap.h" -+ -+ -+/* #define final_version */ -+ -+static int mtu = 1500; -+MODULE_PARM(mtu, "i"); -+MODULE_PARM_DESC(mtu, "Maximum transfer unit"); -+ -+static int channel[MAX_PARM_DEVICES] = { 3, DEF_INTS }; -+MODULE_PARM(channel, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(channel, "Initial channel"); -+ -+static char *essid[MAX_PARM_DEVICES] = { "test" }; -+MODULE_PARM(essid, PARM_MIN_MAX "s"); -+MODULE_PARM_DESC(essid, "Host AP's ESSID"); -+ -+static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS }; -+MODULE_PARM(iw_mode, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(iw_mode, "Initial operation mode"); -+ -+static int beacon_int[MAX_PARM_DEVICES] = { 100, DEF_INTS }; -+MODULE_PARM(beacon_int, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(beacon_int, "Beacon interval (1 = 1024 usec)"); -+ -+static int dtim_period[MAX_PARM_DEVICES] = { 1, DEF_INTS }; -+MODULE_PARM(dtim_period, PARM_MIN_MAX "i"); -+MODULE_PARM_DESC(dtim_period, "DTIM period"); -+ -+static int delayed_enable /* = 0 */; -+MODULE_PARM(delayed_enable, "i"); -+MODULE_PARM_DESC(delayed_enable, "Delay MAC port enable until netdevice open"); -+ -+static int disable_on_close /* = 0 */; -+MODULE_PARM(disable_on_close, "i"); -+MODULE_PARM_DESC(disable_on_close, "Disable MAC port on netdevice close"); -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+static int bus_master_threshold_rx[MAX_PARM_DEVICES] = { 100, DEF_INTS }; -+MODULE_PARM(bus_master_threshold_rx, "i"); -+MODULE_PARM_DESC(bus_master_threshold_rx, "Packet length threshold for using " -+ "PCI bus master on RX"); -+ -+static int bus_master_threshold_tx[MAX_PARM_DEVICES] = { 100, DEF_INTS }; -+MODULE_PARM(bus_master_threshold_tx, "i"); -+MODULE_PARM_DESC(bus_master_threshold_tx, "Packet length threshold for using " -+ "PCI bus master on TX"); -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ -+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -+static unsigned char rfc1042_header[] = -+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -+static unsigned char bridge_tunnel_header[] = -+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -+/* No encapsulation header if EtherType < 0x600 (=length) */ -+ -+ -+#ifdef final_version -+#define EXTRA_EVENTS_WTERR 0 -+#else -+/* check WTERR events (Wait Time-out) in development versions */ -+#define EXTRA_EVENTS_WTERR HFA384X_EV_WTERR -+#endif -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+#define EXTRA_EVENTS_BUS_MASTER (HFA384X_EV_PCI_M0 | HFA384X_EV_PCI_M1) -+#else -+#define EXTRA_EVENTS_BUS_MASTER 0 -+#endif -+ -+/* Events that will be using BAP0 */ -+#define HFA384X_BAP0_EVENTS \ -+ (HFA384X_EV_TXEXC | HFA384X_EV_RX | HFA384X_EV_INFO | HFA384X_EV_TX) -+ -+/* event mask, i.e., events that will result in an interrupt */ -+#define HFA384X_EVENT_MASK \ -+ (HFA384X_BAP0_EVENTS | HFA384X_EV_ALLOC | HFA384X_EV_INFDROP | \ -+ HFA384X_EV_CMD | HFA384X_EV_TICK | \ -+ EXTRA_EVENTS_WTERR | EXTRA_EVENTS_BUS_MASTER) -+ -+/* Default TX control flags: use 802.11 headers and request interrupt for -+ * failed transmits. Frames that request ACK callback, will add -+ * _TX_OK flag and _ALT_RTRY flag may be used to select different retry policy. -+ */ -+ -+/* -+ * click - we always want callbacks, so also at TX_OK to that -+ * --jbicket -+ */ -+ -+#define HFA384X_TX_CTRL_FLAGS \ -+ (HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX | HFA384X_TX_CTRL_TX_OK) -+ -+ -+/* ca. 1 usec */ -+#define HFA384X_CMD_BUSY_TIMEOUT 5000 -+ -+/* ca. 10 usec */ -+#define HFA384X_BAP_BUSY_TIMEOUT 5000 -+#define HFA384X_INIT_TIMEOUT 50000 -+#define HFA384X_CMD_COMPL_TIMEOUT 20000 -+#define HFA384X_DL_COMPL_TIMEOUT 1000000 -+#define HFA384X_ALLOC_COMPL_TIMEOUT 5000 -+ -+ -+ -+static void prism2_hw_reset(struct net_device *dev); -+static void prism2_check_sta_fw_version(local_info_t *local); -+ -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+/* hostap_download.c */ -+static u8 * prism2_read_pda(struct net_device *dev); -+static int prism2_download(local_info_t *local, -+ struct prism2_download_param *param); -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ -+ -+ -+ -+#ifndef final_version -+/* magic value written to SWSUPPORT0 reg. for detecting whether card is still -+ * present */ -+#define HFA384X_MAGIC 0x8A32 -+#endif -+ -+ -+static u16 hfa384x_read_reg(struct net_device *dev, u16 reg) -+{ -+ return HFA384X_INW(reg); -+} -+ -+ -+static void hfa384x_read_regs(struct net_device *dev, -+ struct hfa384x_regs *regs) -+{ -+ regs->cmd = HFA384X_INW(HFA384X_CMD_OFF); -+ regs->evstat = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ regs->offset0 = HFA384X_INW(HFA384X_OFFSET0_OFF); -+ regs->offset1 = HFA384X_INW(HFA384X_OFFSET1_OFF); -+ regs->swsupport0 = HFA384X_INW(HFA384X_SWSUPPORT0_OFF); -+} -+ -+ -+/* local->cmdlock must be locked when calling this helper function */ -+static inline void __hostap_cmd_queue_free(local_info_t *local, -+ struct hostap_cmd_queue *entry, -+ int del_req) -+{ -+ if (del_req) { -+ entry->del_req = 1; -+ if (!list_empty(&entry->list)) { -+ list_del_init(&entry->list); -+ local->cmd_queue_len--; -+ } -+ } -+ -+ if (atomic_dec_and_test(&entry->usecnt) && entry->del_req) -+ kfree(entry); -+} -+ -+static inline void hostap_cmd_queue_free(local_info_t *local, -+ struct hostap_cmd_queue *entry, -+ int del_req) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ __hostap_cmd_queue_free(local, entry, del_req); -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+} -+ -+ -+static inline int hfa384x_cmd_issue(struct net_device *dev, -+ struct hostap_cmd_queue *entry) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int tries; -+ u16 reg; -+ unsigned long flags; -+ -+ if (entry->issued) { -+ printk(KERN_DEBUG "%s: driver bug - re-issuing command @%p\n", -+ dev->name, entry); -+ } -+ -+ /* wait until busy bit is clear; this should always be clear since the -+ * commands are serialized */ -+ tries = HFA384X_CMD_BUSY_TIMEOUT; -+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { -+ tries--; -+ udelay(1); -+ } -+#ifndef final_version -+ if (tries != HFA384X_CMD_BUSY_TIMEOUT) { -+ prism2_io_debug_error(dev, 1); -+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue: cmd reg was busy " -+ "for %d usec\n", dev->name, -+ HFA384X_CMD_BUSY_TIMEOUT - tries); -+ } -+#endif -+ if (tries == 0) { -+ reg = HFA384X_INW(HFA384X_CMD_OFF); -+ prism2_io_debug_error(dev, 2); -+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue - timeout - " -+ "reg=0x%04x\n", dev->name, reg); -+ return -ETIMEDOUT; -+ } -+ -+ /* write command */ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ HFA384X_OUTW(entry->param0, HFA384X_PARAM0_OFF); -+ HFA384X_OUTW(entry->param1, HFA384X_PARAM1_OFF); -+ HFA384X_OUTW(entry->cmd, HFA384X_CMD_OFF); -+ entry->issued = 1; -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ -+ return 0; -+} -+ -+ -+/* Issue given command (possibly after waiting in command queue) and sleep -+ * until the command is completed (or timed out). This can be called only -+ * from user context. */ -+static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0, -+ u16 *param1, u16 *resp0) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int err, res, issue, issued = 0; -+ unsigned long flags; -+ struct hostap_cmd_queue *entry; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ if (in_interrupt()) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd called from interrupt " -+ "context\n", dev->name); -+ return -1; -+ } -+ -+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n", -+ dev->name); -+ return -1; -+ } -+ -+ if (signal_pending(current)) -+ return -EINTR; -+ -+ entry = (struct hostap_cmd_queue *) -+ kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (entry == NULL) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n", -+ dev->name); -+ return -ENOMEM; -+ } -+ memset(entry, 0, sizeof(*entry)); -+ atomic_set(&entry->usecnt, 1); -+ entry->type = CMD_SLEEP; -+ entry->cmd = cmd; -+ entry->param0 = param0; -+ if (param1) -+ entry->param1 = *param1; -+ init_waitqueue_head(&entry->compl); -+ -+ /* prepare to wait for command completion event, but do not sleep yet -+ */ -+ add_wait_queue(&entry->compl, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ issue = list_empty(&local->cmd_queue); -+ if (issue) -+ entry->issuing = 1; -+ list_add_tail(&entry->list, &local->cmd_queue); -+ local->cmd_queue_len++; -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ -+ err = 0; -+ if (!issue) -+ goto wait_completion; -+ -+ if (signal_pending(current)) -+ err = -EINTR; -+ -+ if (!err) { -+ if (hfa384x_cmd_issue(dev, entry)) -+ err = -ETIMEDOUT; -+ else -+ issued = 1; -+ } -+ -+ wait_completion: -+ if (!err && entry->type != CMD_COMPLETED) { -+ /* sleep until command is completed or timed out */ -+ res = schedule_timeout(2 * HZ); -+ } else -+ res = -1; -+ -+ if (!err && signal_pending(current)) -+ err = -EINTR; -+ -+ if (err && issued) { -+ /* the command was issued, so a CmdCompl event should occur -+ * soon; however, there's a pending signal and -+ * schedule_timeout() would be interrupted; wait a short period -+ * of time to avoid removing entry from the list before -+ * CmdCompl event */ -+ udelay(300); -+ } -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&entry->compl, &wait); -+ -+ /* If entry->list is still in the list, it must be removed -+ * first and in this case prism2_cmd_ev() does not yet have -+ * local reference to it, and the data can be kfree()'d -+ * here. If the command completion event is still generated, -+ * it will be assigned to next (possibly) pending command, but -+ * the driver will reset the card anyway due to timeout -+ * -+ * If the entry is not in the list prism2_cmd_ev() has a local -+ * reference to it, but keeps cmdlock as long as the data is -+ * needed, so the data can be kfree()'d here. */ -+ -+ /* FIX: if the entry->list is in the list, it has not been completed -+ * yet, so removing it here is somewhat wrong.. this could cause -+ * references to freed memory and next list_del() causing NULL pointer -+ * dereference.. it would probably be better to leave the entry in the -+ * list and the list should be emptied during hw reset */ -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ if (!list_empty(&entry->list)) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd: entry still in list? " -+ "(entry=%p, type=%d, res=%d)\n", dev->name, entry, -+ entry->type, res); -+ list_del_init(&entry->list); -+ local->cmd_queue_len--; -+ } -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ -+ if (err) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd: interrupted; err=%d\n", -+ dev->name, err); -+ res = err; -+ goto done; -+ } -+ -+ if (entry->type != CMD_COMPLETED) { -+ u16 reg = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ printk(KERN_DEBUG "%s: hfa384x_cmd: command was not " -+ "completed (res=%d, entry=%p, type=%d, cmd=0x%04x, " -+ "param0=0x%04x, EVSTAT=%04x)\n", dev->name, res, -+ entry, entry->type, entry->cmd, entry->param0, reg); -+ if (reg & HFA384X_EV_CMD) { -+ /* Command completion event is pending, but the -+ * interrupt was not delivered - probably an issue -+ * with pcmcia-cs configuration. */ -+ printk(KERN_WARNING "%s: interrupt delivery does not " -+ "seem to work\n", dev->name); -+ } -+ prism2_io_debug_error(dev, 3); -+ res = -ETIMEDOUT; -+ goto done; -+ } -+ -+ if (resp0 != NULL) -+ *resp0 = entry->resp0; -+#ifndef final_version -+ if (entry->res) { -+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x, " -+ "resp0=0x%04x\n", -+ dev->name, cmd, entry->res, entry->resp0); -+ } -+#endif /* final_version */ -+ -+ res = entry->res; -+ done: -+ hostap_cmd_queue_free(local, entry, 1); -+ return res; -+} -+ -+ -+/* Issue given command (possibly after waiting in command queue) and use -+ * callback function to indicate command completion. This can be called both -+ * from user and interrupt context. */ -+static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0, -+ u16 *param1, -+ void (*callback)(struct net_device *dev, -+ void *context, u16 resp0, -+ u16 status), -+ void *context) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int issue, ret; -+ unsigned long flags; -+ struct hostap_cmd_queue *entry; -+ -+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN + 2) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n", -+ dev->name); -+ return -1; -+ } -+ -+ entry = (struct hostap_cmd_queue *) -+ kmalloc(sizeof(*entry), GFP_ATOMIC); -+ if (entry == NULL) { -+ printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc " -+ "failed\n", dev->name); -+ return -ENOMEM; -+ } -+ memset(entry, 0, sizeof(*entry)); -+ atomic_set(&entry->usecnt, 1); -+ entry->type = CMD_CALLBACK; -+ entry->cmd = cmd; -+ entry->param0 = param0; -+ if (param1) { -+ entry->param1 = *param1; -+ } -+ entry->callback = callback; -+ entry->context = context; -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ issue = list_empty(&local->cmd_queue); -+ if (issue) -+ entry->issuing = 1; -+ list_add_tail(&entry->list, &local->cmd_queue); -+ local->cmd_queue_len++; -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+ -+ if (issue && hfa384x_cmd_issue(dev, entry)) -+ ret = -ETIMEDOUT; -+ else -+ ret = 0; -+ -+ hostap_cmd_queue_free(local, entry, ret); -+ -+ return ret; -+} -+ -+ -+static int hfa384x_cmd_wait(struct net_device *dev, u16 cmd, u16 param0, u16 *param1) -+{ -+ int res, tries; -+ u16 reg; -+ -+ /* wait until busy bit is clear; this should always be clear since the -+ * commands are serialized */ -+ tries = HFA384X_CMD_BUSY_TIMEOUT; -+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { -+ tries--; -+ udelay(1); -+ } -+ if (tries == 0) { -+ prism2_io_debug_error(dev, 4); -+ printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout - " -+ "reg=0x%04x\n", dev->name, -+ HFA384X_INW(HFA384X_CMD_OFF)); -+ return -ETIMEDOUT; -+ } -+ -+ /* write command */ -+ HFA384X_OUTW(param0, HFA384X_PARAM0_OFF); -+ if (param1) { -+ HFA384X_OUTW(*param1, HFA384X_PARAM1_OFF); -+ } -+ HFA384X_OUTW(cmd, HFA384X_CMD_OFF); -+ -+ /* wait for command completion */ -+ if ((cmd & HFA384X_CMDCODE_MASK) == HFA384X_CMDCODE_DOWNLOAD) -+ tries = HFA384X_DL_COMPL_TIMEOUT; -+ else -+ tries = HFA384X_CMD_COMPL_TIMEOUT; -+ -+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) && -+ tries > 0) { -+ tries--; -+ udelay(10); -+ } -+ if (tries == 0) { -+ reg = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ prism2_io_debug_error(dev, 5); -+ printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout2 - " -+ "reg=0x%04x\n", dev->name, reg); -+ return -ETIMEDOUT; -+ } -+ -+ res = (HFA384X_INW(HFA384X_STATUS_OFF) & -+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | -+ BIT(8))) >> 8; -+#ifndef final_version -+ if (res) { -+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x\n", -+ dev->name, cmd, res); -+ } -+#endif -+ -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ -+ return res; -+} -+ -+ -+static int hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, u16 param0) -+{ -+ int tries; -+ u16 reg; -+ -+ /* wait until busy bit is clear */ -+ tries = HFA384X_CMD_BUSY_TIMEOUT; -+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { -+ tries--; -+ udelay(1); -+ } -+ if (tries == 0) { -+ reg = HFA384X_INW(HFA384X_CMD_OFF); -+ prism2_io_debug_error(dev, 6); -+ printk("%s: hfa384x_cmd - timeout - reg=0x%04x\n", dev->name, -+ reg); -+ return -ETIMEDOUT; -+ } -+ -+ /* write command */ -+ HFA384X_OUTW(param0, HFA384X_PARAM0_OFF); -+ HFA384X_OUTW(cmd, HFA384X_CMD_OFF); -+ -+ return 0; -+} -+ -+ -+static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off) -+{ -+ int tries = HFA384X_BAP_BUSY_TIMEOUT; -+ -+ while ((HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY) && tries > 0) { -+ tries--; -+ udelay(10); -+ } -+ return (HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY); -+} -+ -+ -+/* Offset must be even */ -+static int hfa384x_setup_bap(struct net_device *dev, u16 bap, u16 id, -+ int offset) -+{ -+ u16 o_off, s_off; -+ int ret = 0; -+ -+ if (offset % 2 || bap > 1) -+ return -EINVAL; -+ -+ if (bap == BAP1) { -+ o_off = HFA384X_OFFSET1_OFF; -+ s_off = HFA384X_SELECT1_OFF; -+ } else { -+ o_off = HFA384X_OFFSET0_OFF; -+ s_off = HFA384X_SELECT0_OFF; -+ } -+ -+ if (hfa384x_wait_offset(dev, o_off)) { -+ prism2_io_debug_error(dev, 7); -+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout before\n", -+ dev->name); -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ HFA384X_OUTW(id, s_off); -+ HFA384X_OUTW(offset, o_off); -+ -+ if (hfa384x_wait_offset(dev, o_off)) { -+ prism2_io_debug_error(dev, 8); -+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout after\n", -+ dev->name); -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+#ifndef final_version -+ if (HFA384X_INW(o_off) & HFA384X_OFFSET_ERR) { -+ prism2_io_debug_error(dev, 9); -+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - offset error " -+ "(%d,%d,%d)\n", -+ dev->name, bap, id, offset); -+ ret = -EINVAL; -+ } -+#endif -+ -+ out: -+ return ret; -+} -+ -+ -+static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len, -+ int exact_len) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res, rlen = 0; -+ struct hfa384x_rid_hdr rec; -+ -+ res = down_interruptible(&local->rid_bap_sem); -+ if (res) -+ return res; -+ -+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS, rid, NULL, NULL); -+ if (res) { -+ printk(KERN_DEBUG "%s: hfa384x_get_rid: CMDCODE_ACCESS failed " -+ "(res=%d, rid=%04x, len=%d)\n", -+ dev->name, res, rid, len); -+ up(&local->rid_bap_sem); -+ return res; -+ } -+ -+ spin_lock_bh(&local->baplock); -+ -+ res = hfa384x_setup_bap(dev, BAP0, rid, 0); -+ if (!res) -+ res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); -+ -+ if (le16_to_cpu(rec.len) == 0) { -+ /* RID not available */ -+ res = -ENODATA; -+ } -+ -+ rlen = (le16_to_cpu(rec.len) - 1) * 2; -+ if (!res && exact_len && rlen != len) { -+ printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: " -+ "rid=0x%04x, len=%d (expected %d)\n", -+ dev->name, rid, rlen, len); -+ res = -ENODATA; -+ } -+ -+ if (!res) -+ res = hfa384x_from_bap(dev, BAP0, buf, len); -+ -+ spin_unlock_bh(&local->baplock); -+ up(&local->rid_bap_sem); -+ -+ if (res) { -+ if (res != -ENODATA) -+ printk(KERN_DEBUG "%s: hfa384x_get_rid (rid=%04x, " -+ "len=%d) - failed - res=%d\n", dev->name, rid, -+ len, res); -+ if (res == -ETIMEDOUT) -+ prism2_hw_reset(dev); -+ return res; -+ } -+ -+ return rlen; -+} -+ -+ -+static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct hfa384x_rid_hdr rec; -+ int res; -+ -+ rec.rid = cpu_to_le16(rid); -+ /* RID len in words and +1 for rec.rid */ -+ rec.len = cpu_to_le16(len / 2 + len % 2 + 1); -+ -+ res = down_interruptible(&local->rid_bap_sem); -+ if (res) -+ return res; -+ -+ spin_lock_bh(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, rid, 0); -+ if (!res) -+ res = hfa384x_to_bap(dev, BAP0, &rec, sizeof(rec)); -+ if (!res) -+ res = hfa384x_to_bap(dev, BAP0, buf, len); -+ spin_unlock_bh(&local->baplock); -+ -+ if (res) { -+ printk(KERN_DEBUG "%s: hfa384x_set_rid (rid=%04x, len=%d) - " -+ "failed - res=%d\n", dev->name, rid, len, res); -+ up(&local->rid_bap_sem); -+ return res; -+ } -+ -+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); -+ up(&local->rid_bap_sem); -+ if (res) { -+ printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " -+ "failed (res=%d, rid=%04x, len=%d)\n", -+ dev->name, res, rid, len); -+ return res; -+ } -+ -+ if (res == -ETIMEDOUT) -+ prism2_hw_reset(dev); -+ -+ return res; -+} -+ -+ -+static void hfa384x_disable_interrupts(struct net_device *dev) -+{ -+ /* disable interrupts and clear event status */ -+ HFA384X_OUTW(0, HFA384X_INTEN_OFF); -+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); -+} -+ -+ -+static void hfa384x_enable_interrupts(struct net_device *dev) -+{ -+ /* ack pending events and enable interrupts from selected events */ -+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); -+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF); -+} -+ -+ -+static void hfa384x_events_no_bap0(struct net_device *dev) -+{ -+ HFA384X_OUTW(HFA384X_EVENT_MASK & ~HFA384X_BAP0_EVENTS, -+ HFA384X_INTEN_OFF); -+} -+ -+ -+static void hfa384x_events_all(struct net_device *dev) -+{ -+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF); -+} -+ -+ -+static void hfa384x_events_only_cmd(struct net_device *dev) -+{ -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_INTEN_OFF); -+} -+ -+static u16 hfa384x_allocate_fid(struct net_device *dev, int len) -+{ -+ int tries; -+ u16 fid; -+ -+ /* FIX: this could be replace with hfa384x_cmd() if the Alloc event -+ * below would be handled like CmdCompl event (sleep here, wake up from -+ * interrupt handler */ -+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_ALLOC, len, NULL)) { -+ printk(KERN_DEBUG "%s: cannot allocate fid, len=%d\n", -+ dev->name, len); -+ return 0xffff; -+ } -+ -+ tries = HFA384X_ALLOC_COMPL_TIMEOUT; -+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC) && -+ tries > 0) { -+ tries--; -+ udelay(10); -+ } -+ if (tries == 0) { -+ printk("%s: fid allocate, len=%d - timeout\n", dev->name, len); -+ return 0xffff; -+ } -+ -+ fid = HFA384X_INW(HFA384X_ALLOCFID_OFF); -+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF); -+ -+ return fid; -+} -+ -+ -+static int prism2_reset_port(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res; -+ -+ if (!local->dev_enabled) -+ return 0; -+ -+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, -+ NULL, NULL); -+ if (res) -+ printk(KERN_DEBUG "%s: reset port failed to disable port\n", -+ dev->name); -+ else { -+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, -+ NULL, NULL); -+ if (res) -+ printk(KERN_DEBUG "%s: reset port failed to enable " -+ "port\n", dev->name); -+ } -+ -+ return res; -+} -+ -+ -+static int prism2_get_version_info(struct net_device *dev, u16 rid, -+ const char *txt) -+{ -+ struct hfa384x_comp_ident comp; -+ -+ if (hfa384x_get_rid(dev, rid, &comp, sizeof(comp), 1) < 0) { -+ printk(KERN_DEBUG "Could not get RID for component %s\n", txt); -+ return -1; -+ } -+ -+ printk(KERN_INFO "%s: %s: id=0x%02x v%d.%d.%d\n", dev->name, txt, -+ __le16_to_cpu(comp.id), __le16_to_cpu(comp.major), -+ __le16_to_cpu(comp.minor), __le16_to_cpu(comp.variant)); -+ return 0; -+} -+ -+ -+static int prism2_setup_rids(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 tmp; -+ int ret = 0; -+ -+ hostap_set_word(dev, HFA384X_RID_TICKTIME, 2000); -+ -+ if (!local->fw_ap) { -+ tmp = hostap_get_porttype(local); -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp); -+ if (ret) { -+ printk("%s: Port type setting to %d failed\n", -+ dev->name, tmp); -+ goto fail; -+ } -+ } -+ -+ /* Setting SSID to empty string seems to kill the card in Host AP mode -+ */ -+ if (local->iw_mode != IW_MODE_MASTER || local->essid[0] != '\0') { -+ ret = hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, -+ local->essid); -+ if (ret) { -+ printk("%s: AP own SSID setting failed\n", dev->name); -+ goto fail; -+ } -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXDATALEN, -+ PRISM2_DATA_MAXLEN); -+ if (ret) { -+ printk("%s: MAC data length setting to %d failed\n", -+ dev->name, PRISM2_DATA_MAXLEN); -+ goto fail; -+ } -+ -+ if (hfa384x_get_rid(dev, HFA384X_RID_CHANNELLIST, &tmp, 2, 1) < 0) { -+ printk("%s: Channel list read failed\n", dev->name); -+ ret = -EINVAL; -+ goto fail; -+ } -+ local->channel_mask = __le16_to_cpu(tmp); -+ -+ if (local->channel < 1 || local->channel > 14 || -+ !(local->channel_mask & (1 << (local->channel - 1)))) { -+ printk(KERN_WARNING "%s: Channel setting out of range " -+ "(%d)!\n", dev->name, local->channel); -+ ret = -EBUSY; -+ goto fail; -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel); -+ if (ret) { -+ printk("%s: Channel setting to %d failed\n", -+ dev->name, local->channel); -+ goto fail; -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, -+ local->beacon_int); -+ if (ret) { -+ printk("%s: Beacon interval setting to %d failed\n", -+ dev->name, local->beacon_int); -+ /* this may fail with Symbol/Lucent firmware */ -+ if (ret == -ETIMEDOUT) -+ goto fail; -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, -+ local->dtim_period); -+ if (ret) { -+ printk("%s: DTIM period setting to %d failed\n", -+ dev->name, local->dtim_period); -+ /* this may fail with Symbol/Lucent firmware */ -+ if (ret == -ETIMEDOUT) -+ goto fail; -+ } -+ -+ /* click promisc */ -+ //local->is_promisc = 1; -+ /* click promisc */ -+ -+ ret = hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, -+ local->is_promisc); -+ if (ret) -+ printk(KERN_INFO "%s: Setting promiscuous mode (%d) failed\n", -+ dev->name, local->is_promisc); -+ -+ if (!local->fw_ap) { -+ ret = hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, -+ local->essid); -+ if (ret) { -+ printk("%s: Desired SSID setting failed\n", dev->name); -+ goto fail; -+ } -+ } -+ -+ /* Setup TXRateControl, defaults to allow use of 1, 2, 5.5, and -+ * 11 Mbps in automatic TX rate fallback and 1 and 2 Mbps as basic -+ * rates */ -+ if (local->tx_rate_control == 0) { -+ local->tx_rate_control = -+ HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS | -+ HFA384X_RATES_5MBPS | -+ HFA384X_RATES_11MBPS; -+ } -+ if (local->basic_rates == 0) -+ local->basic_rates = HFA384X_RATES_1MBPS | HFA384X_RATES_2MBPS; -+ -+ if (!local->fw_ap) { -+ ret = hostap_set_word(dev, HFA384X_RID_TXRATECONTROL, -+ local->tx_rate_control); -+ if (ret) { -+ printk("%s: TXRateControl setting to %d failed\n", -+ dev->name, local->tx_rate_control); -+ goto fail; -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES, -+ local->tx_rate_control); -+ if (ret) { -+ printk("%s: cnfSupportedRates setting to %d failed\n", -+ dev->name, local->tx_rate_control); -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CNFBASICRATES, -+ local->basic_rates); -+ if (ret) { -+ printk("%s: cnfBasicRates setting to %d failed\n", -+ dev->name, local->basic_rates); -+ } -+ -+ ret = hostap_set_word(dev, HFA384X_RID_CREATEIBSS, 1); -+ if (ret) { -+ printk("%s: Create IBSS setting to 1 failed\n", -+ dev->name); -+ } -+ } -+ -+ if (local->name_set) -+ (void) hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, -+ local->name); -+ -+ if (hostap_set_encryption(local)) { -+ printk(KERN_INFO "%s: could not configure encryption\n", -+ dev->name); -+ } -+ -+ (void) hostap_set_antsel(local); -+ -+ if (local->host_roaming && -+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, -+ HFA384X_ROAMING_HOST)) { -+ printk(KERN_INFO "%s: could not set host roaming\n", -+ dev->name); -+ } -+ -+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,6,3) && -+ hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, local->enh_sec)) -+ printk(KERN_INFO "%s: cnfEnhSecurity setting to 0x%x failed\n", -+ dev->name, local->enh_sec); -+ -+ fail: -+ return ret; -+} -+ -+ -+static void prism2_clear_cmd_queue(local_info_t *local) -+{ -+ struct list_head *ptr, *n; -+ unsigned long flags; -+ struct hostap_cmd_queue *entry; -+ -+ spin_lock_irqsave(&local->cmdlock, flags); -+ for (ptr = local->cmd_queue.next, n = ptr->next; -+ ptr != &local->cmd_queue; ptr = n, n = ptr->next) { -+ entry = list_entry(ptr, struct hostap_cmd_queue, list); -+ atomic_inc(&entry->usecnt); -+ printk(KERN_DEBUG "%s: removed pending cmd_queue entry " -+ "(type=%d, cmd=0x%04x, param0=0x%04x)\n", -+ local->dev->name, entry->type, entry->cmd, -+ entry->param0); -+ __hostap_cmd_queue_free(local, entry, 1); -+ } -+ if (local->cmd_queue_len) { -+ printk(KERN_DEBUG "%s: cmd_queue_len (%d) not zero after " -+ "flush\n", local->dev->name, local->cmd_queue_len); -+ local->cmd_queue_len = 0; -+ } -+ spin_unlock_irqrestore(&local->cmdlock, flags); -+} -+ -+ -+static int prism2_hw_init(struct net_device *dev, int initial) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret, i, first = 1; -+ -+ PDEBUG(DEBUG_FLOW, "prism2_hw_init()\n"); -+ -+ clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits); -+ -+ init: -+ /* initialize HFA 384x */ -+ ret = hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_INIT, 0); -+ if (ret) { -+ printk("%s: first command failed - is the card compatible?\n", -+ dev_info); -+ goto failed; -+ } -+ i = HFA384X_INIT_TIMEOUT; -+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) && i > 0) { -+ i--; -+ udelay(10); -+ } -+ if (first && i == HFA384X_INIT_TIMEOUT) { -+ /* EvStat has Cmd bit set in some cases, so retry once if no -+ * wait was needed */ -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ printk(KERN_DEBUG "%s: init command completed too quickly - " -+ "retrying\n", dev->name); -+ first = 0; -+ goto init; -+ } -+ if (i == 0) { -+ printk("%s: card initialization timed out\n", dev_info); -+ goto failed; -+ } -+ printk(KERN_DEBUG "prism2_hw_init: initialized in %d iterations\n", -+ HFA384X_INIT_TIMEOUT - i); -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ -+ if (local->hw_downloading) -+ return 0; -+ -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+ local->pda = prism2_read_pda(dev); -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ -+ hfa384x_disable_interrupts(dev); -+ -+#ifndef final_version -+ HFA384X_OUTW(HFA384X_MAGIC, HFA384X_SWSUPPORT0_OFF); -+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) { -+ printk("SWSUPPORT0 write/read failed: %04X != %04X\n", -+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF), HFA384X_MAGIC); -+ goto failed; -+ } -+#endif -+ -+ /* FIX: could convert allocate_fid to use sleeping CmdCompl wait and -+ * enable interrupts before this. This would also require some sort of -+ * sleeping AllocEv waiting */ -+ -+ /* allocate TX FIDs */ -+ local->txfid_len = PRISM2_TXFID_LEN; -+ for (i = 0; i < PRISM2_TXFID_COUNT; i++) { -+ local->txfid[i] = hfa384x_allocate_fid(dev, local->txfid_len); -+ if (local->txfid[i] == 0xffff && local->txfid_len > 1600) { -+ local->txfid[i] = hfa384x_allocate_fid(dev, 1600); -+ if (local->txfid[i] != 0xffff) { -+ printk(KERN_DEBUG "%s: Using shorter TX FID " -+ "(1600 bytes)\n", dev->name); -+ local->txfid_len = 1600; -+ } -+ } -+ if (local->txfid[i] == 0xffff) -+ goto failed; -+ local->intransmitfid[i] = PRISM2_TXFID_EMPTY; -+ } -+ -+ hfa384x_events_only_cmd(dev); -+ -+ if (initial) { -+ /* get card version information */ -+ prism2_get_version_info(dev, HFA384X_RID_NICID, "NIC"); -+ prism2_get_version_info(dev, HFA384X_RID_PRIID, "PRI"); -+ prism2_get_version_info(dev, HFA384X_RID_STAID, "STA"); -+ -+ prism2_check_sta_fw_version(local); -+ -+ if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR, -+ &dev->dev_addr, 6, 1) < 0) { -+ printk("%s: could not get own MAC address\n", -+ dev->name); -+ } -+ if (local->apdev) -+ memcpy(local->apdev->dev_addr, dev->dev_addr, -+ ETH_ALEN); -+ if (local->stadev) -+ memcpy(local->stadev->dev_addr, dev->dev_addr, -+ ETH_ALEN); -+ } else if (local->fw_ap) -+ prism2_check_sta_fw_version(local); -+ -+ prism2_setup_rids(dev); -+ -+ /* MAC is now configured, but port 0 is not yet enabled */ -+ return 0; -+ -+ failed: -+ printk(KERN_WARNING "%s: Initialization failed\n", dev_info); -+ return 1; -+} -+ -+ -+static int prism2_hw_enable(struct net_device *dev, int initial) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int was_resetting = local->hw_resetting; -+ -+ if (hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, NULL)) { -+ printk("%s: MAC port 0 enabling failed\n", dev->name); -+ return 1; -+ } -+ -+ local->hw_ready = 1; -+ local->hw_reset_tries = 0; -+ local->hw_resetting = 0; -+ hfa384x_enable_interrupts(dev); -+ -+ /* at least D-Link DWL-650 seems to require additional port reset -+ * before it starts acting as an AP, so reset port automatically -+ * here just in case */ -+ if (initial && prism2_reset_port(dev)) { -+ printk("%s: MAC port 0 reseting failed\n", dev->name); -+ return 1; -+ } -+ -+ if (was_resetting && netif_queue_stopped(dev)) { -+ /* If hw_reset() was called during pending transmit, netif -+ * queue was stopped. Wake it up now since the wlan card has -+ * been resetted. */ -+ hostap_netif_wake_queues(dev); -+ } -+ -+ return 0; -+} -+ -+ -+static int prism2_hw_config(struct net_device *dev, int initial) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ if (local->hw_downloading) -+ return 1; -+ -+ if (prism2_hw_init(dev, initial)) -+ return 1; -+ -+ if (!initial || !delayed_enable) { -+ if (!local->dev_enabled) -+ prism2_callback(local, PRISM2_CALLBACK_ENABLE); -+ local->dev_enabled = 1; -+ return prism2_hw_enable(dev, initial); -+ } -+ -+ return 0; -+} -+ -+ -+static void prism2_hw_shutdown(struct net_device *dev, int no_disable) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ /* Allow only command completion events during disable */ -+ hfa384x_events_only_cmd(dev); -+ -+ local->hw_ready = 0; -+ if (local->dev_enabled) -+ prism2_callback(local, PRISM2_CALLBACK_DISABLE); -+ local->dev_enabled = 0; -+ -+ if (local->func->card_present && !local->func->card_present(local)) { -+ printk(KERN_DEBUG "%s: card already removed or not configured " -+ "during shutdown\n", dev->name); -+ return; -+ } -+ -+ if ((no_disable & HOSTAP_HW_NO_DISABLE) == 0 && -+ hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, NULL)) -+ printk(KERN_WARNING "%s: Shutdown failed\n", dev_info); -+ -+ hfa384x_disable_interrupts(dev); -+ -+ if (no_disable & HOSTAP_HW_ENABLE_CMDCOMPL) -+ hfa384x_events_only_cmd(dev); -+ else -+ prism2_clear_cmd_queue(local); -+} -+ -+ -+static void prism2_hw_reset(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+#if 0 -+ static long last_reset = 0; -+ -+ /* do not reset card more than once per second to avoid ending up in a -+ * busy loop reseting the card */ -+ if (last_reset + HZ >= jiffies) -+ return; -+ last_reset = jiffies; -+#endif -+ -+ if (in_interrupt()) { -+ printk(KERN_DEBUG "%s: driver bug - prism2_hw_reset() called " -+ "in interrupt context\n", dev->name); -+ return; -+ } -+ -+ if (local->hw_downloading) -+ return; -+ -+ if (local->hw_resetting) { -+ printk(KERN_WARNING "%s: %s: already resetting card - " -+ "ignoring reset request\n", dev_info, dev->name); -+ return; -+ } -+ -+ local->hw_reset_tries++; -+ if (local->hw_reset_tries > 10) { -+ printk(KERN_WARNING "%s: too many reset tries, skipping\n", -+ dev->name); -+ return; -+ } -+ -+ printk(KERN_WARNING "%s: %s: resetting card\n", dev_info, dev->name); -+ hfa384x_disable_interrupts(dev); -+ local->hw_resetting = 1; -+ if (local->func->cor_sreset) { -+ /* Host system seems to hang in some cases with high traffic -+ * load or shared interrupts during COR sreset. Disable shared -+ * interrupts during reset to avoid these crashes. COS sreset -+ * takes quite a long time, so it is unfortunate that this -+ * seems to be needed. Anyway, I do not know of any better way -+ * of avoiding the crash. */ -+ disable_irq(dev->irq); -+ local->func->cor_sreset(local); -+ enable_irq(dev->irq); -+ } -+ prism2_hw_shutdown(dev, 1); -+ prism2_hw_config(dev, 0); -+ local->hw_resetting = 0; -+} -+ -+ -+static void prism2_schedule_reset(local_info_t *local) -+{ -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+} -+ -+ -+/* Called only as scheduled task after noticing card timeout in interrupt -+ * context */ -+static void handle_reset_queue(void *data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ -+ printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name); -+ prism2_hw_reset(local->dev); -+ -+ if (netif_queue_stopped(local->dev)) { -+ int i; -+ -+ for (i = 0; i < PRISM2_TXFID_COUNT; i++) -+ if (local->intransmitfid[i] == PRISM2_TXFID_EMPTY) { -+ PDEBUG(DEBUG_EXTRA, "prism2_tx_timeout: " -+ "wake up queue\n"); -+ hostap_netif_wake_queues(local->dev); -+ break; -+ } -+ } -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+ -+/* update trans_start for all used devices */ -+static void prism2_netif_update_trans_start(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ prism2_wds_info_t *wds; -+ -+ if (local->dev) -+ local->dev->trans_start = jiffies; -+ if (local->apdev) -+ local->apdev->trans_start = jiffies; -+ if (local->stadev) -+ local->stadev->trans_start = jiffies; -+ -+ wds = local->wds; -+ while (wds != NULL) { -+ wds->dev.trans_start = jiffies; -+ wds = wds->next; -+ } -+} -+ -+ -+static int prism2_get_txfid_idx(local_info_t *local) -+{ -+ int idx, end; -+ -+ spin_lock_bh(&local->txfidlock); -+ end = idx = local->next_txfid; -+ do { -+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) { -+ local->intransmitfid[idx] = PRISM2_TXFID_RESERVED; -+ spin_unlock_bh(&local->txfidlock); -+ return idx; -+ } -+ idx++; -+ if (idx >= PRISM2_TXFID_COUNT) -+ idx = 0; -+ } while (idx != end); -+ spin_unlock_bh(&local->txfidlock); -+ -+ PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: " -+ "packet dropped\n"); -+ local->stats.tx_dropped++; -+ -+ return -1; -+} -+ -+ -+/* Called only from hardware IRQ */ -+static void prism2_transmit_cb(struct net_device *dev, void *context, -+ u16 resp0, u16 res) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int idx = (int) context; -+ -+ if (res) { -+ printk(KERN_DEBUG "%s: prism2_transmit_cb - res=0x%02x\n", -+ dev->name, res); -+ return; -+ } -+ -+ if (idx < 0 || idx >= PRISM2_TXFID_COUNT) { -+ printk(KERN_DEBUG "%s: prism2_transmit_cb called with invalid " -+ "idx=%d\n", dev->name, idx); -+ return; -+ } -+ -+ if (!test_and_clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { -+ printk(KERN_DEBUG "%s: driver bug: prism2_transmit_cb called " -+ "with no pending transmit\n", dev->name); -+ } -+ -+ if (netif_queue_stopped(dev)) { -+ /* ready for next TX, so wake up queue that was stopped in -+ * prism2_transmit() */ -+ hostap_netif_wake_queues(dev); -+ } -+ -+ /* FIX: is some locking needed for txfid data? */ -+ -+ /* With reclaim, Resp0 contains new txfid for transmit; the old txfid -+ * will be automatically allocated for the next TX frame */ -+ local->intransmitfid[idx] = resp0; -+ -+ PDEBUG(DEBUG_FID, "%s: prism2_cmd_ev: txfid[%d]=0x%04x, resp0=0x%04x, " -+ "transmit_txfid=0x%04x\n", dev->name, idx, local->txfid[idx], -+ resp0, local->intransmitfid[local->next_txfid]); -+ -+ idx++; -+ if (idx >= PRISM2_TXFID_COUNT) -+ idx = 0; -+ local->next_txfid = idx; -+ -+ /* check if all TX buffers are occupied */ -+ do { -+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) { -+ return; -+ } -+ idx++; -+ if (idx >= PRISM2_TXFID_COUNT) -+ idx = 0; -+ } while (idx != local->next_txfid); -+ -+ /* no empty TX buffers, stop queue */ -+ hostap_netif_stop_queues(dev); -+} -+ -+ -+/* Called only from software IRQ if PCI bus master is not used (with bus master -+ * this can be called both from software and hardware IRQ) */ -+static int prism2_transmit(struct net_device *dev, int idx) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res; -+ -+ /* The driver tries to stop netif queue so that there would not be -+ * more than one attempt to transmit frames going on; check that this -+ * is really the case */ -+ -+ if (test_and_set_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { -+ printk(KERN_DEBUG "%s: driver bug - prism2_transmit() called " -+ "when previous TX was pending\n", dev->name); -+ return -1; -+ } -+ -+ /* stop the queue for the time that transmit is pending */ -+ hostap_netif_stop_queues(dev); -+ -+ /* transmit packet */ -+ res = hfa384x_cmd_callback( -+ dev, -+ HFA384X_CMDCODE_TRANSMIT | HFA384X_CMD_TX_RECLAIM, -+ local->txfid[idx], -+ NULL, -+ prism2_transmit_cb, (void *) idx); -+ -+ if (res) { -+ struct net_device_stats *stats; -+ printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT " -+ "failed (res=%d)\n", dev->name, res); -+ stats = hostap_get_stats(dev); -+ stats->tx_dropped++; -+ hostap_netif_wake_queues(dev); -+ return -1; -+ } -+ prism2_netif_update_trans_start(dev); -+ -+ /* Since we did not wait for command completion, the card continues -+ * to process on the background and we will finish handling when -+ * command completion event is handled (prism2_cmd_ev() function) */ -+ -+ return 0; -+} -+ -+ -+/* Called only from hardware IRQ */ -+static void prism2_cmd_ev(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct hostap_cmd_queue *entry = NULL; -+ spin_lock(&local->cmdlock); -+ if (!list_empty(&local->cmd_queue)) { -+ entry = list_entry(local->cmd_queue.next, -+ struct hostap_cmd_queue, list); -+ atomic_inc(&entry->usecnt); -+ list_del_init(&entry->list); -+ local->cmd_queue_len--; -+ -+ if (!entry->issued) { -+ printk(KERN_DEBUG "%s: Command completion event, but " -+ "cmd not issued\n", dev->name); -+ __hostap_cmd_queue_free(local, entry, 1); -+ entry = NULL; -+ } -+ } -+ spin_unlock(&local->cmdlock); -+ -+ if (!entry) { -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ printk(KERN_DEBUG "%s: Command completion event, but no " -+ "pending commands\n", dev->name); -+ return; -+ } -+ -+ entry->resp0 = HFA384X_INW(HFA384X_RESP0_OFF); -+ entry->res = (HFA384X_INW(HFA384X_STATUS_OFF) & -+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | -+ BIT(9) | BIT(8))) >> 8; -+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); -+ -+ /* TODO: rest of the CmdEv handling could be moved to tasklet */ -+ if (entry->type == CMD_SLEEP) { -+ entry->type = CMD_COMPLETED; -+ wake_up_interruptible(&entry->compl); -+ } else if (entry->type == CMD_CALLBACK) { -+ if (entry->callback) -+ entry->callback(dev, entry->context, entry->resp0, -+ entry->res); -+ } else { -+ printk(KERN_DEBUG "%s: Invalid command completion type %d\n", -+ dev->name, entry->type); -+ } -+ hostap_cmd_queue_free(local, entry, 1); -+ -+ /* issue next command, if pending */ -+ entry = NULL; -+ spin_lock(&local->cmdlock); -+ if (!list_empty(&local->cmd_queue)) { -+ entry = list_entry(local->cmd_queue.next, -+ struct hostap_cmd_queue, list); -+ if (entry->issuing) { -+ /* hfa384x_cmd() has already started issuing this -+ * command, so do not start here */ -+ entry = NULL; -+ } -+ if (entry) -+ atomic_inc(&entry->usecnt); -+ } -+ spin_unlock(&local->cmdlock); -+ -+ if (entry) { -+ /* issue next command; if command issuing fails, remove the -+ * entry from cmd_queue */ -+ int res = hfa384x_cmd_issue(dev, entry); -+ spin_lock(&local->cmdlock); -+ __hostap_cmd_queue_free(local, entry, res); -+ spin_unlock(&local->cmdlock); -+ } -+} -+ -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+static void prism2_tx_cb(struct net_device *dev, void *context, -+ u16 resp0, u16 res) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ unsigned long addr; -+ int buf_len = (int) context; -+ -+ if (res) { -+ printk(KERN_DEBUG "%s: prism2_tx_cb - res=0x%02x\n", -+ dev->name, res); -+ return; -+ } -+ -+ addr = virt_to_phys(local->bus_m0_buf); -+ HFA384X_OUTW((addr & 0xffff0000) >> 16, HFA384X_PCI_M0_ADDRH_OFF); -+ HFA384X_OUTW(addr & 0x0000ffff, HFA384X_PCI_M0_ADDRL_OFF); -+ HFA384X_OUTW(buf_len / 2, HFA384X_PCI_M0_LEN_OFF); -+ HFA384X_OUTW(HFA384X_PCI_CTL_TO_BAP, HFA384X_PCI_M0_CTL_OFF); -+} -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+/* Called only from software IRQ */ -+static void prism2_tx(struct net_device *dev, void *context, -+ u16 resp0, u16 res0) -+{ -+ struct sk_buff *skb = (struct sk_buff *) context; -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res, idx = -1, ret = 1, data_len; -+ struct hfa384x_tx_frame txdesc; -+ u16 fc, ethertype = 0; -+ prism2_wds_info_t *wds = NULL; -+ enum { WDS_NO, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME } use_wds = WDS_NO; -+ struct net_device_stats *stats; -+ u8 *wepbuf = NULL; -+ int wepbuf_len = 0, host_encrypt = 0; -+ struct prism2_crypt_data *crypt = NULL; -+ void *sta = NULL; -+ u8 *encaps_data; -+ int encaps_len, skip_header_bytes; -+ int no_encrypt = 0; -+ int to_assoc_ap = 0; -+ -+ if (res0) { -+ local->txpower = 0; -+ printk(KERN_DEBUG "%s: prism2_tx - res=0x%02x\n", -+ dev->name, res0); -+ return; -+ } -+ -+ prism2_callback(local, PRISM2_CALLBACK_TX_START); -+ stats = hostap_get_stats(dev); -+ -+ if ((local->func->card_present && !local->func->card_present(local)) || -+ !local->hw_ready) { -+ if (net_ratelimit()) -+ printk(KERN_DEBUG "%s: prism2_tx: hw not ready - " -+ "skipping\n", dev->name); -+ ret = 0; -+ goto fail; -+ } -+ -+ if (skb->len < ETH_HLEN) { -+ printk(KERN_DEBUG "%s: prism2_tx: short skb (len=%d)\n", -+ dev->name, skb->len); -+ ret = 0; -+ goto fail; -+ } -+ -+ if (local->dev != dev) { -+ wds = (prism2_wds_info_t *) dev; -+ use_wds = (local->iw_mode == IW_MODE_MASTER && -+ !(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ? -+ WDS_OWN_FRAME : WDS_COMPLIANT_FRAME; -+ if (dev == local->stadev) { -+ to_assoc_ap = 1; -+ wds = NULL; -+ use_wds = WDS_NO; -+ } -+ } else { -+ if (local->iw_mode == IW_MODE_REPEAT) { -+ printk(KERN_DEBUG "%s: prism2_tx: trying to use " -+ "non-WDS link in Repeater mode\n", dev->name); -+ ret = 0; -+ goto fail; -+ } else if (local->iw_mode == IW_MODE_INFRA && -+ (local->wds_type & HOSTAP_WDS_AP_CLIENT) && -+ memcmp(skb->data + ETH_ALEN, dev->dev_addr, -+ ETH_ALEN) != 0) { -+ /* AP client mode: send frames with foreign src addr -+ * using 4-addr WDS frames */ -+ use_wds = WDS_COMPLIANT_FRAME; -+ } -+ } -+ -+ if (local->host_encrypt) { -+ /* Set crypt to default algorithm and key; will be replaced in -+ * AP code if STA has own alg/key */ -+ crypt = local->crypt; -+ host_encrypt = 1; -+ } -+ -+ if (skb->protocol == __constant_htons(ETH_P_HOSTAP)) { -+ /* frame from prism2_send_mgmt() */ -+ if (skb->len < sizeof(txdesc)) { -+ printk(KERN_DEBUG "%s: prism2_tx: short ETH_P_HOSTAP " -+ "skb\n", dev->name); -+ ret = 0; -+ goto fail; -+ } -+ memcpy(&txdesc, skb->data, sizeof(txdesc)); -+ skb_pull(skb, sizeof(txdesc)); -+ encaps_data = NULL; -+ encaps_len = 0; -+ skip_header_bytes = 0; -+ data_len = skb->len; -+ -+ fc = le16_to_cpu(txdesc.frame_control); -+ -+ /* data frames use normal host encryption, if needed */ -+ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) -+ goto data_txdesc_set; -+ -+ /* mgmt/ctrl frames do not need further processing, so skip to -+ * frame transmit */ -+ goto frame_processing_done; -+ } -+ -+ /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload -+ * ==> -+ * Prism2 TX frame with 802.11 header: -+ * txdesc (address order depending on used mode; includes dst_addr and -+ * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel; -+ * proto[2], payload {, possible addr4[6]} */ -+ -+ ethertype = (skb->data[12] << 8) | skb->data[13]; -+ -+ memset(&txdesc, 0, sizeof(txdesc)); -+ -+ txdesc.tx_control = __cpu_to_le16(local->tx_control); -+ -+ /* Length of data after txdesc */ -+ data_len = skb->len - ETH_HLEN; -+ encaps_data = NULL; -+ encaps_len = 0; -+ skip_header_bytes = ETH_HLEN; -+ if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { -+ encaps_data = bridge_tunnel_header; -+ encaps_len = sizeof(bridge_tunnel_header); -+ data_len += encaps_len + 2; -+ skip_header_bytes -= 2; -+ } else if (ethertype >= 0x600) { -+ encaps_data = rfc1042_header; -+ encaps_len = sizeof(rfc1042_header); -+ data_len += encaps_len + 2; -+ skip_header_bytes -= 2; -+ } -+ -+ fc = (WLAN_FC_TYPE_DATA << 2) | (WLAN_FC_STYPE_DATA << 4); -+ if (use_wds != WDS_NO) { -+ /* Note! Prism2 station firmware has problems with sending real -+ * 802.11 frames with four addresses; until these problems can -+ * be fixed or worked around, 4-addr frames needed for WDS are -+ * using incompatible format: FromDS flag is not set and the -+ * fourth address is added after the frame payload; it is -+ * assumed, that the receiving station knows how to handle this -+ * frame format */ -+ -+ if (use_wds == WDS_COMPLIANT_FRAME) { -+ fc |= WLAN_FC_FROMDS | WLAN_FC_TODS; -+ /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA, -+ * Addr4 = SA */ -+ memcpy(&txdesc.addr4, skb->data + ETH_ALEN, ETH_ALEN); -+ } else { -+ /* bogus 4-addr format to workaround Prism2 station -+ * f/w bug */ -+ fc |= WLAN_FC_TODS; -+ /* From DS: Addr1 = DA (used as RA), -+ * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA), -+ */ -+ -+ /* SA from skb->data + ETH_ALEN will be added after -+ * frame payload */ -+ data_len += ETH_ALEN; -+ } -+ -+ /* send broadcast and multicast frames to broadcast RA, if -+ * configured; otherwise, use unicast RA of the WDS link */ -+ if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) && -+ skb->data[0] & 0x01) -+ memset(&txdesc.addr1, 0xff, ETH_ALEN); -+ else if (wds) -+ memcpy(&txdesc.addr1, wds->remote_addr, ETH_ALEN); -+ else -+ memcpy(&txdesc.addr1, local->bssid, ETH_ALEN); -+ memcpy(&txdesc.addr2, dev->dev_addr, ETH_ALEN); -+ memcpy(&txdesc.addr3, skb->data, ETH_ALEN); -+ -+ memcpy(&txdesc.dst_addr, &txdesc.addr3, ETH_ALEN); -+ memcpy(&txdesc.src_addr, &txdesc.addr2, ETH_ALEN); -+ } else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) { -+ fc |= WLAN_FC_FROMDS; -+ /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */ -+ memcpy(&txdesc.addr1, skb->data, ETH_ALEN); -+ /* FIX - addr2 replaced by f/w, so no need to fill it now(?) */ -+ memcpy(&txdesc.addr2, dev->dev_addr, ETH_ALEN); -+ memcpy(&txdesc.addr3, skb->data + ETH_ALEN, ETH_ALEN); -+ } else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) { -+ fc |= WLAN_FC_TODS; -+ /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ -+ memcpy(&txdesc.addr1, to_assoc_ap ? -+ local->assoc_ap_addr : local->bssid, ETH_ALEN); -+ memcpy(&txdesc.addr2, skb->data + ETH_ALEN, ETH_ALEN); -+ memcpy(&txdesc.addr3, skb->data, ETH_ALEN); -+ } else if (local->iw_mode == IW_MODE_ADHOC) { -+ /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ -+ memcpy(&txdesc.addr1, skb->data, ETH_ALEN); -+ memcpy(&txdesc.addr2, skb->data + ETH_ALEN, ETH_ALEN); -+ memcpy(&txdesc.addr3, local->bssid, ETH_ALEN); -+ } -+ -+ if (WIFI_FROM_CLICK(skb)) { -+ /* begin click hack */ -+ int rate = WIFI_RATE_ANNO(skb); -+ switch (rate) { -+ /* -+ * see section 4.3.2.3.2 (page 4-30) in the developors manual -+ * for these values -+ * --jbicket -+ */ -+ case 0: -+ txdesc.tx_rate = 0x00; -+ break; -+ case 1: -+ txdesc.tx_rate = 0x0A; -+ break; -+ case 2: -+ txdesc.tx_rate = 0x14; -+ break; -+ case 5: -+ txdesc.tx_rate = 0x37; -+ break; -+ case 11: -+ txdesc.tx_rate = 0x6E; -+ break; -+ default: -+ printk(KERN_WARNING "%s: invalid attempt for packet rate %d\n", -+ local->dev->name, rate); -+ txdesc.tx_rate = 0; -+ } -+ } -+ /* end click hack */ -+ txdesc.frame_control = __cpu_to_le16(fc); -+ txdesc.data_len = __cpu_to_le16(data_len); -+ txdesc.len = __cpu_to_be16(data_len); -+ if (use_wds == WDS_NO) -+ memcpy(&txdesc.dst_addr, skb->data, 2 * ETH_ALEN); -+ -+ skb->dev = dev; -+ -+ data_txdesc_set: -+ if (to_assoc_ap) -+ goto skip_ap_processing; -+ -+ switch (hostap_handle_sta_tx(local, skb, &txdesc, use_wds != WDS_NO, -+ host_encrypt, &crypt, &sta)) { -+ case AP_TX_CONTINUE: -+ break; -+ case AP_TX_CONTINUE_NOT_AUTHORIZED: -+ if (local->ieee_802_1x && ethertype != ETH_P_PAE && -+ use_wds == WDS_NO) { -+ printk(KERN_DEBUG "%s: dropped frame to unauthorized " -+ "port (IEEE 802.1X): ethertype=0x%04x\n", -+ dev->name, ethertype); -+ hostap_dump_tx_header(dev->name, &txdesc); -+ -+ ret = 0; /* drop packet */ -+ stats->tx_dropped++; -+ goto fail; -+ } -+ break; -+ case AP_TX_DROP: -+ ret = 0; /* drop packet */ -+ stats->tx_dropped++; -+ goto fail; -+ case AP_TX_RETRY: -+ goto fail; -+ case AP_TX_BUFFERED: -+ /* do not free skb here, it will be freed when the -+ * buffered frame is sent/timed out */ -+ ret = 0; -+ goto tx_exit; -+ } -+ -+ skip_ap_processing: -+ -+ if (local->ieee_802_1x && ethertype == ETH_P_PAE) { -+ if (crypt) { -+ no_encrypt = 1; -+ printk(KERN_DEBUG "%s: TX: IEEE 802.1X - passing " -+ "unencrypted EAPOL frame\n", dev->name); -+ } -+ crypt = NULL; /* no encryption for IEEE 802.1X frames */ -+ } -+ -+ if (crypt && (!crypt->ops || !crypt->ops->encrypt)) -+ crypt = NULL; -+ else if ((crypt || local->crypt) && !no_encrypt) { -+ /* Add ISWEP flag both for firmware and host based encryption -+ */ -+ fc |= WLAN_FC_ISWEP; -+ txdesc.frame_control = cpu_to_le16(fc); -+ } -+ -+ if (crypt) { -+ /* Perform host driver -based encryption */ -+ u8 *pos; -+ int olen; -+ -+ olen = data_len; -+ data_len += crypt->ops->extra_prefix_len + -+ crypt->ops->extra_postfix_len; -+ txdesc.data_len = cpu_to_le16(data_len); -+ txdesc.len = cpu_to_be16(data_len); -+ -+ wepbuf_len = data_len; -+ wepbuf = (u8 *) kmalloc(wepbuf_len, GFP_ATOMIC); -+ if (wepbuf == NULL) { -+ printk(KERN_DEBUG "%s: could not allocate TX wepbuf\n", -+ dev->name); -+ goto fail; -+ } -+ -+ pos = wepbuf + crypt->ops->extra_prefix_len; -+ if (encaps_len > 0) { -+ memcpy(pos, encaps_data, encaps_len); -+ pos += encaps_len; -+ } -+ memcpy(pos, skb->data + skip_header_bytes, -+ skb->len - skip_header_bytes); -+ if (use_wds == WDS_OWN_FRAME) { -+ memcpy(pos + skb->len - skip_header_bytes, -+ skb->data + ETH_ALEN, ETH_ALEN); -+ } -+ -+ atomic_inc(&crypt->refcnt); -+ olen = crypt->ops->encrypt(wepbuf, olen, crypt->priv); -+ atomic_dec(&crypt->refcnt); -+ if (olen > wepbuf_len) { -+ printk(KERN_WARNING "%s: encrypt overwrote wepbuf " -+ "(%d > %d)\n", dev->name, olen, wepbuf_len); -+ } -+ if (olen < 0) -+ goto fail; -+ -+ data_len = wepbuf_len = olen; -+ txdesc.data_len = cpu_to_le16(data_len); -+ txdesc.len = cpu_to_be16(data_len); -+ } -+ -+ -+ if (txdesc.sw_support != 0) { -+ printk(KERN_WARNING "%s: warning, sw_support is %d\n", dev->name, txdesc.sw_support); -+ } -+ int txskb_idx = 1; -+ while(txskb_idx < PRISM2_TXSKB_COUNT && local->txskb[txskb_idx]) { -+ txskb_idx++; -+ } -+ -+ if (txskb_idx < PRISM2_TXSKB_COUNT) { -+ //printk(KERN_WARNING "%s: using txskb buffer %d\n", dev->name, txskb_idx); -+ txdesc.sw_support = txskb_idx; -+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); -+ local->txskb[txskb_idx] = skb2; -+ } else { -+ printk(KERN_WARNING "%s: out of txskb buffers!\n", dev->name); -+ txdesc.sw_support = 0; -+ } -+ -+ -+ frame_processing_done: -+ -+ -+ idx = prism2_get_txfid_idx(local); -+ if (idx < 0) -+ goto fail; -+ -+ if (local->frame_dump & PRISM2_DUMP_TX_HDR) -+ hostap_dump_tx_header(dev->name, &txdesc); -+ -+ spin_lock(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0); -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ if (!res && skb->len >= local->bus_master_threshold_tx) { -+ u8 *pos; -+ int buf_len; -+ -+ local->bus_m0_tx_idx = idx; -+ -+ /* FIX: BAP0 should be locked during bus master transfer, but -+ * baplock with BH's disabled is not OK for this; netif queue -+ * stopping is not enough since BAP0 is used also for RID -+ * read/write */ -+ -+ /* stop the queue for the time that bus mastering on BAP0 is -+ * in use */ -+ hostap_netif_stop_queues(dev); -+ -+ spin_unlock(&local->baplock); -+ -+ /* Copy frame data to bus_m0_buf */ -+ pos = local->bus_m0_buf; -+ memcpy(pos, &txdesc, sizeof(txdesc)); -+ pos += sizeof(txdesc); -+ -+ if (!wepbuf) { -+ if (encaps_len > 0) { -+ memcpy(pos, encaps_data, encaps_len); -+ pos += encaps_len; -+ } -+ memcpy(pos, skb->data + skip_header_bytes, -+ skb->len - skip_header_bytes); -+ pos += skb->len - skip_header_bytes; -+ } -+ if (!wepbuf && use_wds == WDS_OWN_FRAME) { -+ /* add addr4 (SA) to bogus frame format if WDS is used -+ */ -+ memcpy(pos, skb->data + ETH_ALEN, ETH_ALEN); -+ pos += ETH_ALEN; -+ } -+ -+ if (wepbuf) { -+ memcpy(pos, wepbuf, wepbuf_len); -+ pos += wepbuf_len; -+ } -+ -+ buf_len = pos - local->bus_m0_buf; -+ if (buf_len & 1) -+ buf_len++; -+ -+#ifdef PRISM2_ENABLE_BEFORE_TX_BUS_MASTER -+ /* Any RX packet seems to break something with TX bus -+ * mastering; enable command is enough to fix this.. */ -+ if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, -+ prism2_tx_cb, (void *) buf_len)) { -+ printk(KERN_DEBUG "%s: TX: enable port0 failed\n", -+ dev->name); -+ } -+#else /* PRISM2_ENABLE_BEFORE_TX_BUS_MASTER */ -+ prism2_tx_cb(dev, (void *) buf_len, 0, 0); -+#endif /* PRISM2_ENABLE_BEFORE_TX_BUS_MASTER */ -+ -+ /* Bus master transfer will be started from command completion -+ * event handler and TX handling will be finished by calling -+ * prism2_transmit() from bus master event handler */ -+ goto tx_stats; -+ } -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ if (!res) -+ res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc)); -+ if (!res && !wepbuf && encaps_len > 0) -+ res = hfa384x_to_bap(dev, BAP0, encaps_data, encaps_len); -+ if (!res && !wepbuf && use_wds != WDS_OWN_FRAME) -+ res = hfa384x_to_bap(dev, BAP0, skb->data + skip_header_bytes, -+ skb->len - skip_header_bytes); -+ else if (!res && !wepbuf && use_wds == WDS_OWN_FRAME) { -+ int wlen, is_odd; -+ -+ wlen = skb->len - skip_header_bytes; -+ is_odd = wlen & 1; -+ -+ if (is_odd) -+ wlen--; /* need to avoid using odd offset */ -+ -+ res = hfa384x_to_bap(dev, BAP0, skb->data + skip_header_bytes, -+ wlen); -+ -+ /* add addr4 (SA) to bogus frame format if WDS is used */ -+ if (!res && is_odd) { -+ char tmpbuf[ETH_ALEN + 1]; -+ tmpbuf[0] = *(skb->data + skb->len - 1); -+ memcpy(tmpbuf + 1, skb->data + ETH_ALEN, ETH_ALEN); -+ res = hfa384x_to_bap(dev, BAP0, tmpbuf, ETH_ALEN + 1); -+ } else if (!res) { -+ res = hfa384x_to_bap(dev, BAP0, skb->data + ETH_ALEN, -+ ETH_ALEN); -+ } -+ } -+ -+ if (!res && wepbuf) -+ res = hfa384x_to_bap(dev, BAP0, wepbuf, wepbuf_len); -+ spin_unlock(&local->baplock); -+ -+ if (!res) -+ res = prism2_transmit(dev, idx); -+ if (res) { -+ printk(KERN_DEBUG "%s: prism2_tx - to BAP0 failed\n", -+ dev->name); -+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY; -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ ret = 0; /* do not retry failed frames to avoid problems */ -+ goto fail; -+ } -+ -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ tx_stats: -+#endif -+ stats->tx_packets++; -+ stats->tx_bytes += data_len + 36; -+ -+ ret = 0; -+ fail: -+ if (wepbuf) -+ kfree(wepbuf); -+ -+ if (!ret) { -+ dev_kfree_skb(skb); -+ } -+ -+ tx_exit: -+ if (sta) -+ hostap_handle_sta_release(sta); -+ -+ prism2_callback(local, PRISM2_CALLBACK_TX_END); -+ return; /* ret; */ -+} -+static int prism2_tx_set_power(struct sk_buff *sk, struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 txp = WIFI_TX_POWER_ANNO(sk); -+ int ret = 1; -+ -+ if ((local->func->card_present && !local->func->card_present(local)) || -+ !local->hw_ready) { -+ printk(KERN_DEBUG "%s: prism2_tx_set_power: hw not ready - " -+ "skipping\n", dev->name); -+ ret = 0; -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } -+ -+ if (sk->len < 24) { -+ printk(KERN_DEBUG "%s: prism2_tx_set_power: short skb (len=%d)\n", -+ dev->name, sk->len); -+ ret = 0; -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } -+ -+ if (!WIFI_FROM_CLICK(sk) || txp == 0 || txp == local->txpower) { -+ /* -+ * we don't have to switch the power level, so go -+ * ahead and tx the packet -+ */ -+ prism2_tx(dev, (void *)sk, 0, 0); -+ ret = 0; -+ } else { -+ /* switch the power level and register a cb for the transmit fn */ -+ /* txpwr */ -+ local->txpower = txp; -+ if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_MANUAL_TX_POWER, &txp, -+ prism2_tx, (void *) sk)) { -+ printk(KERN_DEBUG "%s: prism2_tx_set_power: register cmd cb failed\n", -+ dev->name); -+ ret = 0; -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } else { -+ ret = 0; -+ } -+ } -+ -+ return ret; -+ -+ fail: -+ if (!ret) -+ dev_kfree_skb(sk); -+ -+ return ret; -+ -+} -+ -+ -+ -+/* Called only from software IRQ */ -+static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct hfa384x_tx_frame txdesc; -+ int hdr_len, data_len, ret = 1, idx, res; -+ u16 fc, tx_control; -+ -+ -+ if ((local->func->card_present && !local->func->card_present(local)) || -+ !local->hw_ready) { -+ printk(KERN_DEBUG "%s: prism2_tx_80211: hw not ready - " -+ "skipping\n", dev->name); -+ ret = 0; -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } -+ -+ if (skb->len < 24) { -+ printk(KERN_DEBUG "%s: prism2_tx_80211: short skb (len=%d)\n", -+ dev->name, skb->len); -+ ret = 0; -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } -+ -+ memset(&txdesc, 0, sizeof(txdesc)); -+ /* txdesc.tx_rate might need to be set if f/w does not select suitable -+ * TX rate */ -+ -+ /* skb->data starts with txdesc->frame_control */ -+ hdr_len = 24; -+ memcpy(&txdesc.frame_control, skb->data, hdr_len); -+ fc = le16_to_cpu(txdesc.frame_control); -+ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && -+ (fc & WLAN_FC_FROMDS) && (fc & WLAN_FC_TODS) && skb->len >= 30) { -+ /* Addr4 */ -+ memcpy(txdesc.addr4, skb->data + hdr_len, ETH_ALEN); -+ hdr_len += ETH_ALEN; -+ } -+ -+ tx_control = local->tx_control; -+ -+ /* Request TX callback if protocol version is 2 in 802.11 header; -+ * this version 2 is a special case used between hostapd and kernel -+ * driver */ -+ if (((fc & WLAN_FC_PVER) == BIT(1)) && -+ local->ap && local->ap->tx_callback_idx) { -+ tx_control |= HFA384X_TX_CTRL_TX_OK; -+ txdesc.sw_support = cpu_to_le16(local->ap->tx_callback_idx); -+ -+ /* remove special version from the frame header */ -+ fc &= ~WLAN_FC_PVER; -+ txdesc.frame_control = cpu_to_le16(fc); -+ } -+ txdesc.tx_control = cpu_to_le16(tx_control); -+ -+ data_len = skb->len - hdr_len; -+ txdesc.data_len = __cpu_to_le16(data_len); -+ txdesc.len = __cpu_to_be16(data_len); -+ -+ idx = prism2_get_txfid_idx(local); -+ if (idx < 0) { -+ local->apdevstats.tx_dropped++; -+ goto fail; -+ } -+ -+ spin_lock(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0); -+ if (!res) -+ res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc)); -+ if (!res) -+ res = hfa384x_to_bap(dev, BAP0, skb->data + hdr_len, -+ skb->len - hdr_len); -+ spin_unlock(&local->baplock); -+ -+ if (!res) -+ res = prism2_transmit(dev, idx); -+ if (res) { -+ printk(KERN_DEBUG "%s: prism2_tx_80211 - to BAP0 failed\n", -+ dev->name); -+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY; -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ local->apdevstats.tx_dropped++; -+ ret = 0; -+ goto fail; -+ } -+ -+ ret = 0; -+ -+ local->apdevstats.tx_packets++; -+ local->apdevstats.tx_bytes += skb->len; -+ -+ fail: -+ if (!ret) -+ dev_kfree_skb(skb); -+ -+ return ret; -+} -+ -+ -+/* Send RX frame to netif with 802.11 (and possible prism) header. -+ * Called from hardware or software IRQ context. */ -+static int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb, -+ int type, char *extra, int extra_len) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int hdrlen, phdrlen, head_need, tail_need; -+ u16 len, fc; -+ int prism_header; -+ struct hfa384x_rx_frame rxdesc; -+ -+ dev->last_rx = jiffies; -+ -+ if (skb->len < sizeof(rxdesc)) { -+ printk(KERN_DEBUG "%s: prism2_rx_80211() called with too " -+ "short skb (len=%d)\n", dev->name, skb->len); -+ dev_kfree_skb_any(skb); -+ return 0; -+ } -+ -+ /* make a local copy of rxdesc, since we will be changing the head of -+ * the skb data */ -+ memcpy(&rxdesc, skb->data, sizeof(rxdesc)); -+ skb_pull(skb, sizeof(rxdesc)); -+ -+ if (dev->type == ARPHRD_IEEE80211_PRISM) { -+ if (local->monitor_type == PRISM2_MONITOR_PRISM) { -+ prism_header = 1; -+ phdrlen = sizeof(struct linux_wlan_ng_prism_hdr); -+ } else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */ -+ prism_header = 2; -+ phdrlen = sizeof(struct linux_wlan_ng_cap_hdr); -+ } -+ } else { -+ prism_header = 0; -+ phdrlen = 0; -+ } -+ -+ fc = le16_to_cpu(rxdesc.frame_control); -+ -+ if (type == PRISM2_RX_MGMT && (fc & WLAN_FC_PVER)) { -+ printk(KERN_DEBUG "%s: dropped management frame with header " -+ "version %d\n", dev->name, fc & WLAN_FC_PVER); -+ dev_kfree_skb_any(skb); -+ return 0; -+ } -+ -+ hdrlen = hostap_80211_get_hdrlen(fc); -+ -+ if (extra) { -+ /* set 802.11 protocol version to 3 to indicate extra data -+ * after the payload */ -+ fc |= WLAN_FC_PVER; -+ rxdesc.frame_control = cpu_to_le16(fc); -+ } -+ -+ len = le16_to_cpu(rxdesc.data_len); -+ /* Monitor mode reports different data_len values for packets. For -+ * example ctrl::ack frames may get values like -14 to 92 when heard -+ * from neighboring channel. Start of the frames seems to be OK anyway, -+ * so pass them through. Set signed negative values to zero so that -+ * hdrlen is used to get the proper length of data. */ -+ if (type == PRISM2_RX_MONITOR && len >= (u16) -14 && len != 0xffff) -+ len = 0; -+ if (len > PRISM2_DATA_MAXLEN || extra_len > 65535) { -+ printk(KERN_WARNING "%s: prism2_rx_80211: len(%d) > " -+ "MAX(%d)\n", dev->name, len, PRISM2_DATA_MAXLEN); -+ dev_kfree_skb_any(skb); -+ return 0; -+ } -+ -+ /* check if there is enough room for extra data; if not, expand skb -+ * buffer to be large enough for the changes */ -+ head_need = phdrlen + hdrlen; -+ tail_need = extra_len; -+ if (extra_len) -+ tail_need += 2; -+#ifdef PRISM2_ADD_BOGUS_CRC -+ tail_need += 4; -+#endif /* PRISM2_ADD_BOGUS_CRC */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) -+ if (head_need > skb_headroom(skb) || tail_need > skb_tailroom(skb)) { -+ struct sk_buff *nskb; -+ -+ nskb = dev_alloc_skb(skb->len + head_need + tail_need); -+ if (nskb == NULL) { -+ dev_kfree_skb_any(skb); -+ return 0; -+ } -+ -+ skb_reserve(nskb, head_need); -+ memcpy(skb_put(nskb, skb->len), skb->data, skb->len); -+ dev_kfree_skb_any(skb); -+ skb = nskb; -+ } -+#else /* Linux 2.4.0 or newer */ -+ head_need -= skb_headroom(skb); -+ tail_need -= skb_tailroom(skb); -+ -+ if (head_need > 0 || tail_need > 0) { -+ if (pskb_expand_head(skb, head_need > 0 ? head_need : 0, -+ tail_need > 0 ? tail_need : 0, -+ GFP_ATOMIC)) { -+ printk(KERN_DEBUG "%s: prism2_rx_80211 failed to " -+ "reallocate skb buffer\n", dev->name); -+ dev_kfree_skb_any(skb); -+ return 0; -+ } -+ } -+#endif -+ -+ /* We now have an skb with enough head and tail room, so just insert -+ * the extra data */ -+ memcpy(skb_push(skb, hdrlen), &rxdesc.frame_control, hdrlen); -+ -+ if (prism_header == 1) { -+ struct linux_wlan_ng_prism_hdr *hdr; -+ hdr = (struct linux_wlan_ng_prism_hdr *) -+ skb_push(skb, phdrlen); -+ memset(hdr, 0, phdrlen); -+ hdr->msgcode = LWNG_CAP_DID_BASE; -+ hdr->msglen = sizeof(*hdr); -+ memcpy(hdr->devname, dev->name, sizeof(hdr->devname)); -+#define LWNG_SETVAL(f,i,s,l,d) \ -+hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \ -+hdr->f.status = s; hdr->f.len = l; hdr->f.data = d -+ LWNG_SETVAL(hosttime, 1, 0, 4, jiffies); -+ LWNG_SETVAL(mactime, 2, 0, 0, le32_to_cpu(rxdesc.time)); -+ LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0); -+ LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0); -+ LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0); -+ LWNG_SETVAL(signal, 6, 0, 4, rxdesc.signal); -+ LWNG_SETVAL(noise, 7, 0, 4, rxdesc.silence); -+ LWNG_SETVAL(rate, 8, 0, 4, rxdesc.rate / 5); -+ LWNG_SETVAL(istx, 9, 0, 4, 0); -+#ifdef PRISM2_ADD_BOGUS_CRC -+ LWNG_SETVAL(frmlen, 10, 0, 4, hdrlen + len + 4 /* CRC */); -+#else /* PRISM2_ADD_BOGUS_CRC */ -+ LWNG_SETVAL(frmlen, 10, 0, 4, hdrlen + len); -+#endif /* PRISM2_ADD_BOGUS_CRC */ -+#undef LWNG_SETVAL -+ } else if (prism_header == 2) { -+ struct linux_wlan_ng_cap_hdr *hdr; -+ hdr = (struct linux_wlan_ng_cap_hdr *) -+ skb_push(skb, phdrlen); -+ memset(hdr, 0, phdrlen); -+ hdr->version = htonl(LWNG_CAPHDR_VERSION); -+ hdr->length = htonl(phdrlen); -+ hdr->mactime = __cpu_to_be64(rxdesc.time); -+ hdr->hosttime = __cpu_to_be64(jiffies); -+ hdr->phytype = htonl(4); /* dss_dot11_b */ -+ hdr->channel = htonl(local->channel); -+ hdr->datarate = htonl(rxdesc.rate); -+ hdr->antenna = htonl(0); /* unknown */ -+ hdr->priority = htonl(0); /* unknown */ -+ hdr->ssi_type = htonl(3); /* raw */ -+ hdr->ssi_signal = htonl(rxdesc.signal); -+ hdr->ssi_noise = htonl(rxdesc.silence); -+ hdr->preamble = htonl(0); /* unknown */ -+ hdr->encoding = htonl(1); /* cck */ -+ } -+ -+#ifdef PRISM2_ADD_BOGUS_CRC -+ memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */ -+#endif /* PRISM2_ADD_BOGUS_CRC */ -+ -+ /* TODO: could add 'type' information into the end of the data if it -+ * is needed in the user space daemon */ -+ if (extra != NULL) { -+ u16 *elen; -+ memcpy(skb_put(skb, extra_len), extra, extra_len); -+ elen = (u16 *) skb_put(skb, 2); -+ *elen = __cpu_to_le16(extra_len); -+ } -+ -+ skb->dev = dev; -+ skb->mac.raw = skb->data; -+ skb_pull(skb, hdrlen); -+ if (prism_header) -+ skb_pull(skb, phdrlen); -+ skb->pkt_type = PACKET_OTHERHOST; -+ skb->protocol = __constant_htons(ETH_P_802_2); -+ memset(skb->cb, 0, sizeof(skb->cb)); -+ netif_rx(skb); -+ -+ return (hdrlen + len); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void monitor_rx(struct net_device *dev, struct sk_buff *skb) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct net_device_stats *stats; -+ int len; -+ struct hfa384x_rx_frame *rxdesc = -+ (struct hfa384x_rx_frame *) skb->data; -+ -+ if (le16_to_cpu(rxdesc->status) & HFA384X_RX_STATUS_FCSERR && -+ !local->monitor_allow_fcserr) { -+ dev_kfree_skb(skb); -+ return; -+ } -+ -+ len = prism2_rx_80211(dev, skb, PRISM2_RX_MONITOR, NULL, 0); -+ stats = hostap_get_stats(dev); -+ stats->rx_packets++; -+ stats->rx_bytes += len; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static struct prism2_frag_entry * -+prism2_frag_cache_find(local_info_t *local, unsigned int seq, -+ unsigned int frag, u8 *src, u8 *dst) -+{ -+ struct prism2_frag_entry *entry; -+ int i; -+ -+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) { -+ entry = &local->frag_cache[i]; -+ if (entry->skb != NULL && -+ entry->first_frag_time + 2 * HZ < jiffies) { -+ printk(KERN_DEBUG "%s: expiring fragment cache entry " -+ "seq=%u last_frag=%u\n", -+ local->dev->name, entry->seq, entry->last_frag); -+ dev_kfree_skb(entry->skb); -+ entry->skb = NULL; -+ } -+ -+ if (entry->skb != NULL && entry->seq == seq && -+ (entry->last_frag + 1 == frag || frag == -1) && -+ memcmp(entry->src_addr, src, ETH_ALEN) == 0 && -+ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) -+ return entry; -+ } -+ -+ return NULL; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static struct sk_buff *prism2_frag_cache_get(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ struct sk_buff *skb = NULL; -+ u16 sc; -+ unsigned int frag, seq; -+ struct prism2_frag_entry *entry; -+ -+ sc = le16_to_cpu(rxdesc->seq_ctrl); -+ frag = WLAN_GET_SEQ_FRAG(sc); -+ seq = WLAN_GET_SEQ_SEQ(sc); -+ -+ if (frag == 0) { -+ /* Reserve enough space to fit maximum frame length */ -+ skb = dev_alloc_skb(local->dev->mtu + -+ sizeof(struct hfa384x_rx_frame) + -+ 8 /* LLC */ + -+ 2 /* alignment */ + -+ 8 /* WEP */ + ETH_ALEN /* WDS */); -+ if (skb == NULL) -+ return NULL; -+ -+ entry = &local->frag_cache[local->frag_next_idx]; -+ local->frag_next_idx++; -+ if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN) -+ local->frag_next_idx = 0; -+ -+ if (entry->skb != NULL) -+ dev_kfree_skb(entry->skb); -+ -+ entry->first_frag_time = jiffies; -+ entry->seq = seq; -+ entry->last_frag = frag; -+ entry->skb = skb; -+ memcpy(entry->src_addr, rxdesc->addr2, ETH_ALEN); -+ memcpy(entry->dst_addr, rxdesc->addr1, ETH_ALEN); -+ } else { -+ /* received a fragment of a frame for which the head fragment -+ * should have already been received */ -+ entry = prism2_frag_cache_find(local, seq, frag, rxdesc->addr2, -+ rxdesc->addr1); -+ if (entry != NULL) { -+ entry->last_frag = frag; -+ skb = entry->skb; -+ } -+ } -+ -+ return skb; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static int prism2_frag_cache_invalidate(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc) -+{ -+ u16 sc; -+ unsigned int seq; -+ struct prism2_frag_entry *entry; -+ -+ sc = le16_to_cpu(rxdesc->seq_ctrl); -+ seq = WLAN_GET_SEQ_SEQ(sc); -+ -+ entry = prism2_frag_cache_find(local, seq, -1, rxdesc->addr2, -+ rxdesc->addr1); -+ -+ if (entry == NULL) { -+ printk(KERN_DEBUG "%s: could not invalidate fragment cache " -+ "entry (seq=%u)\n", -+ local->dev->name, seq); -+ return -1; -+ } -+ -+ entry->skb = NULL; -+ return 0; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static inline prism2_wds_info_t *prism2_rx_get_wds(local_info_t *local, -+ u8 *addr) -+{ -+ prism2_wds_info_t *wds; -+ -+ spin_lock(&local->wdslock); -+ wds = local->wds; -+ while (wds != NULL && memcmp(wds->remote_addr, addr, ETH_ALEN) != 0) -+ wds = wds->next; -+ spin_unlock(&local->wdslock); -+ -+ return wds; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_rx(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ int res, rx_pending = 0; -+ u16 len, rxfid, status, macport; -+ struct net_device_stats *stats; -+ struct hfa384x_rx_frame rxdesc; -+ struct sk_buff *skb = NULL; -+ -+ prism2_callback(local, PRISM2_CALLBACK_RX_START); -+ stats = hostap_get_stats(dev); -+ -+ rxfid = HFA384X_INW(HFA384X_RXFID_OFF); -+#ifndef final_version -+ if (rxfid == 0) { -+ rxfid = HFA384X_INW(HFA384X_RXFID_OFF); -+ printk(KERN_DEBUG "prism2_rx: rxfid=0 (next 0x%04x)\n", -+ rxfid); -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ goto rx_dropped; -+ } -+#endif -+ -+ spin_lock(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, rxfid, 0); -+ if (!res) -+ res = hfa384x_from_bap(dev, BAP0, &rxdesc, sizeof(rxdesc)); -+ -+ if (res) { -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "%s: copy from BAP0 failed %d\n", dev->name, -+ res); -+ if (res == -ETIMEDOUT) { -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ } -+ goto rx_dropped; -+ } -+ -+ len = le16_to_cpu(rxdesc.data_len); -+ status = le16_to_cpu(rxdesc.status); -+ macport = (status >> 8) & 0x07; -+ -+ /* Drop frames with too large reported payload length. Monitor mode -+ * seems to sometimes pass frames (e.g., ctrl::ack) with signed and -+ * negative value, so allow also values 65522 .. 65534 (-14 .. -2) for -+ * macport 7 */ -+ if ((len & 0x8000) && -+ (macport != 7 || ((len < (u16) -14) && len != 0xffff))) { -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "%s: Received frame with invalid length " -+ "0x%04x\n", dev->name, len); -+ hostap_dump_rx_header(dev->name, &rxdesc); -+ goto rx_dropped; -+ } -+ -+ skb = dev_alloc_skb(sizeof(rxdesc) + len); -+ if (!skb) { -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "%s: RX failed to allocate skb\n", -+ dev->name); -+ goto rx_dropped; -+ } -+ skb->dev = dev; -+ memcpy(skb_put(skb, sizeof(rxdesc)), &rxdesc, sizeof(rxdesc)); -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ if (len >= local->bus_master_threshold_rx) { -+ unsigned long addr; -+ -+ hfa384x_events_no_bap1(dev); -+ -+ local->rx_skb = skb; -+ /* Internal BAP0 offset points to the byte following rxdesc; -+ * copy rest of the data using bus master */ -+ addr = virt_to_phys(skb_put(skb, len)); -+ HFA384X_OUTW((addr & 0xffff0000) >> 16, -+ HFA384X_PCI_M0_ADDRH_OFF); -+ HFA384X_OUTW(addr & 0x0000ffff, HFA384X_PCI_M0_ADDRL_OFF); -+ if (len & 1) -+ len++; -+ HFA384X_OUTW(len / 2, HFA384X_PCI_M0_LEN_OFF); -+ HFA384X_OUTW(HFA384X_PCI_CTL_FROM_BAP, HFA384X_PCI_M0_CTL_OFF); -+ -+ /* pci_bus_m1 event will be generated when data transfer is -+ * complete and the frame will then be added to rx_list and -+ * rx_tasklet is scheduled */ -+ rx_pending = 1; -+ -+ /* Have to release baplock before returning, although BAP0 -+ * should really not be used before DMA transfer has been -+ * completed. */ -+ spin_unlock(&local->baplock); -+ } else -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ { -+ res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len); -+ spin_unlock(&local->baplock); -+ if (res) { -+ printk(KERN_DEBUG "%s: RX failed to read " -+ "frame data\n", dev->name); -+ goto rx_dropped; -+ } -+ -+ skb_queue_tail(&local->rx_list, skb); -+ HOSTAP_TASKLET_SCHEDULE(&local->rx_tasklet); -+ } -+ -+ rx_exit: -+ prism2_callback(local, PRISM2_CALLBACK_RX_END); -+ if (!rx_pending) { -+ HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF); -+ } -+ -+ return; -+ -+ rx_dropped: -+ stats->rx_dropped++; -+ if (skb) -+ dev_kfree_skb(skb); -+ goto rx_exit; -+} -+ -+ -+static inline int -+hostap_rx_frame_invalid(struct net_device *dev, u16 macport, u16 status, -+ u16 len, struct sk_buff *skb) -+{ -+ if (macport != 0) { -+ printk(KERN_DEBUG "%s: RX: unknown MACPort %d\n", -+ dev->name, macport); -+ return -1; -+ } -+ -+ /* FCS errors should not come this far, but let's make sure that frames -+ * with errors will be dropped even in Host AP mode */ -+ if (status & HFA384X_RX_STATUS_FCSERR) { -+ -+ { -+ struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); -+ click_wifi_rx_fcserr(nskb); -+ } -+ -+ printk(KERN_DEBUG "%s: RX: dropped FCSErr frame " -+ "(status=%02X)\n", dev->name, status); -+ return -1; -+ } -+ -+ if (len > PRISM2_DATA_MAXLEN) { -+ printk(KERN_DEBUG "%s: RX: len(%d) > MAX(%d)\n", -+ dev->name, len, PRISM2_DATA_MAXLEN); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+ -+static inline int -+hostap_rx_frame_invalid_data(struct net_device *dev, u16 msg_type, u16 type, -+ u16 stype) -+{ -+ if (msg_type != HFA384X_RX_MSGTYPE_NORMAL && -+ msg_type != HFA384X_RX_MSGTYPE_RFC1042 && -+ msg_type != HFA384X_RX_MSGTYPE_BRIDGETUNNEL) { -+ printk(KERN_DEBUG "%s: RX: dropped frame " -+ "(msg_type=%d)\n", dev->name, msg_type); -+ return -1; -+ } -+ -+ if (type != WLAN_FC_TYPE_DATA) { -+ printk(KERN_DEBUG "%s: RX: dropped non-data frame " -+ "(type=0x%02x, subtype=0x%02x)\n", -+ dev->name, type, stype); -+ return -1; -+ } -+ -+ -+ return 0; -+} -+ -+ -+static inline int -+hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, u16 type, -+ u16 stype) -+{ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ struct hfa384x_rx_frame *rxdesc; -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ hostap_update_sta_ps(local, (struct hostap_ieee80211_hdr *) -+ &rxdesc->frame_control); -+ } -+ -+ if (local->hostapd && type == WLAN_FC_TYPE_MGMT) { -+ /* send management frames to the user space daemon for -+ * processing */ -+ local->apdevstats.rx_packets++; -+ local->apdevstats.rx_bytes += skb->len; -+ prism2_rx_80211(local->apdev, skb, PRISM2_RX_MGMT, NULL, 0); -+ return 0; -+ } -+ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { -+ printk(KERN_DEBUG "%s: unknown management frame " -+ "(type=0x%02x, stype=0x%02x) dropped\n", -+ skb->dev->name, type, stype); -+ return -1; -+ } -+ -+ skb->protocol = __constant_htons(ETH_P_HOSTAP); -+ hostap_rx(skb->dev, skb); -+ return 0; -+ } else { -+ printk(KERN_DEBUG "%s: prism2_rx: management frame " -+ "received in non-Host AP mode\n", skb->dev->name); -+ return -1; -+ } -+} -+ -+ -+static inline int -+hostap_rx_frame_wds(local_info_t *local, struct hfa384x_rx_frame *rxdesc, -+ u16 fc, prism2_wds_info_t **wds) -+{ -+ if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) != -+ (WLAN_FC_TODS | WLAN_FC_FROMDS) && -+ (!local->wds || local->iw_mode != IW_MODE_MASTER || -+ !(fc & WLAN_FC_TODS))) -+ return 0; /* not a WDS frame */ -+ -+ /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS) -+ * or own non-standard frame with 4th address after payload */ -+ if (memcmp(rxdesc->addr1, local->dev->dev_addr, ETH_ALEN) != 0 && -+ (rxdesc->addr1[0] != 0xff || rxdesc->addr1[1] != 0xff || -+ rxdesc->addr1[2] != 0xff || rxdesc->addr1[3] != 0xff || -+ rxdesc->addr1[4] != 0xff || rxdesc->addr1[5] != 0xff)) { -+ /* RA (or BSSID) is not ours - drop */ -+ PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with " -+ "not own or broadcast %s=" MACSTR "\n", -+ local->dev->name, fc & WLAN_FC_FROMDS ? "RA" : "BSSID", -+ MAC2STR(rxdesc->addr1)); -+ return -1; -+ } -+ -+ /* check if the frame came from a registered WDS connection */ -+ *wds = prism2_rx_get_wds(local, rxdesc->addr2); -+ if (*wds == NULL && fc & WLAN_FC_FROMDS && -+ (local->iw_mode != IW_MODE_INFRA || -+ !(local->wds_type & HOSTAP_WDS_AP_CLIENT) || -+ memcmp(rxdesc->addr2, local->bssid, ETH_ALEN) != 0)) { -+ /* require that WDS link has been registered with TA or the -+ * frame is from current AP when using 'AP client mode' */ -+ PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame " -+ "from unknown TA=" MACSTR "\n", -+ local->dev->name, MAC2STR(rxdesc->addr2)); -+ if (local->ap && local->ap->autom_ap_wds) -+ hostap_add_wds_link(local, rxdesc->addr2); -+ return -1; -+ } -+ -+ if (*wds && !(fc & WLAN_FC_FROMDS) && local->ap && -+ hostap_is_sta_assoc(local->ap, rxdesc->addr2)) { -+ /* STA is actually associated with us even though it has a -+ * registered WDS link. Assume it is in 'AP client' mode. -+ * Since this is a 3-addr frame, assume it is not (bogus) WDS -+ * frame and process it like any normal ToDS frame from -+ * associated STA. */ -+ *wds = NULL; -+ } -+ -+ return 0; -+} -+ -+ -+static int hostap_is_eapol_frame(local_info_t *local, -+ struct hfa384x_rx_frame *rxdesc, u8 *buf, -+ int len) -+{ -+ struct net_device *dev = local->dev; -+ u16 fc, ethertype; -+ -+ fc = le16_to_cpu(rxdesc->frame_control); -+ -+ /* check that the frame is unicast frame to us */ -+ if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_TODS && -+ memcmp(rxdesc->addr1, dev->dev_addr, ETH_ALEN) == 0 && -+ memcmp(rxdesc->addr3, dev->dev_addr, ETH_ALEN) == 0) { -+ /* ToDS frame with own addr BSSID and DA */ -+ } else if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_FROMDS && -+ memcmp(rxdesc->addr1, dev->dev_addr, ETH_ALEN) == 0) { -+ /* FromDS frame with own addr as DA */ -+ } else -+ return 0; -+ -+ if (len < 8) -+ return 0; -+ -+ /* check for port access entity Ethernet type */ -+ ethertype = (buf[6] << 8) | buf[7]; -+ if (ethertype == ETH_P_PAE) -+ return 1; -+ -+ return 0; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static inline int -+hostap_rx_frame_decrypt(local_info_t *local, int iswep, struct sk_buff *skb) -+{ -+ struct hfa384x_rx_frame *rxdesc; -+ struct prism2_crypt_data *crypt; -+ void *sta = NULL; -+ int ret = 0, olen, len; -+ char *payload; -+ -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ len = skb->len - sizeof(*rxdesc); -+ payload = (char *) (rxdesc + 1); -+ crypt = local->crypt; -+ sta = NULL; -+ -+ /* Use station specific key to override default keys if the receiver -+ * address is a unicast address ("individual RA"). If bcrx_sta_key -+ * parameter is set, station specific key is used even with -+ * broad/multicast targets (this is against IEEE 802.11, but makes it -+ * easier to use different keys with stations that do not support WEP -+ * key mapping). */ -+ if (!(rxdesc->addr1[0] & 0x01) || local->bcrx_sta_key) -+ (void) hostap_handle_sta_crypto(local, rxdesc, &crypt, &sta); -+ -+ /* allow NULL decrypt to indicate an station specific override for -+ * default encryption */ -+ if (crypt && (crypt->ops == NULL || crypt->ops->decrypt == NULL)) -+ crypt = NULL; -+ -+ if (!crypt && iswep) { -+ printk(KERN_DEBUG "%s: WEP decryption failed (not set) (SA=" -+ MACSTR ")\n", local->dev->name, MAC2STR(rxdesc->addr2)); -+ local->comm_tallies.rx_discards_wep_undecryptable++; -+ ret = -1; -+ goto done; -+ } -+ -+ if (!crypt) -+ goto done; -+ -+ if (!iswep && !local->open_wep) { -+ if (local->ieee_802_1x && -+ hostap_is_eapol_frame(local, rxdesc, payload, len)) { -+ /* pass unencrypted EAPOL frames even if encryption is -+ * configured */ -+ printk(KERN_DEBUG "%s: RX: IEEE 802.1X - passing " -+ "unencrypted EAPOL frame\n", local->dev->name); -+ goto done; -+ } -+ printk(KERN_DEBUG "%s: encryption configured, but RX frame " -+ "not encrypted (SA=" MACSTR ")\n", -+ local->dev->name, MAC2STR(rxdesc->addr2)); -+ ret = -1; -+ goto done; -+ } -+ -+ /* decrypt WEP part of the frame: IV (4 bytes), encrypted -+ * payload (including SNAP header), ICV (4 bytes) */ -+ atomic_inc(&crypt->refcnt); -+ olen = crypt->ops->decrypt(payload, len, crypt->priv); -+ atomic_dec(&crypt->refcnt); -+ if (olen < 0) { -+ printk(KERN_DEBUG "%s: WEP decryption failed (SA=" MACSTR -+ ")\n", local->dev->name, MAC2STR(rxdesc->addr2)); -+ local->comm_tallies.rx_discards_wep_undecryptable++; -+ ret = -1; -+ goto done; -+ } -+ -+ skb_trim(skb, skb->len - (len - olen)); -+ -+ done: -+ if (sta) -+ hostap_handle_sta_release(sta); -+ -+ return ret; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb) -+{ -+ u16 status, macport, msg_type, fc, type, stype, sc; -+ prism2_wds_info_t *wds = NULL; -+ struct hfa384x_rx_frame *rxdesc; -+ struct net_device *dev = skb->dev; -+ struct net_device_stats *stats; -+ unsigned int frag; -+ u8 *payload; -+ struct sk_buff *skb2 = NULL; -+ u16 ethertype; -+ int frame_authorized = 0; -+ int from_assoc_ap = 0; -+ -+ stats = hostap_get_stats(dev); -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ status = le16_to_cpu(rxdesc->status); -+ macport = HFA384X_RX_STATUS_GET_MACPORT(status); -+ msg_type = HFA384X_RX_STATUS_GET_MSGTYPE(status); -+ fc = le16_to_cpu(rxdesc->frame_control); -+ type = WLAN_FC_GET_TYPE(fc); -+ stype = WLAN_FC_GET_STYPE(fc); -+ sc = le16_to_cpu(rxdesc->seq_ctrl); -+ frag = WLAN_GET_SEQ_FRAG(sc); -+ -+ if (local->frame_dump & PRISM2_DUMP_RX_HDR) -+ hostap_dump_rx_header(dev->name, rxdesc); -+ -+#if WIRELESS_EXT > 15 -+ /* Put this code here so that we avoid duplicating it in all -+ * Rx paths. - Jean II */ -+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ -+ /* If spy monitoring on */ -+ if (local->spy_data.spy_number > 0) { -+ struct iw_quality wstats; -+ wstats.level = HFA384X_RSSI_LEVEL_TO_dBm(rxdesc->signal); -+ wstats.noise = HFA384X_RSSI_LEVEL_TO_dBm(rxdesc->silence); -+ wstats.updated = 6; /* No qual value */ -+ /* Update spy records */ -+ wireless_spy_update(dev, rxdesc->addr2, &wstats); -+ } -+#endif /* IW_WIRELESS_SPY */ -+#endif /* WIRELESS_EXT > 15 */ -+ -+ if (macport == 7) { -+ monitor_rx(dev, skb); -+ return; -+ } -+ -+ if (hostap_rx_frame_invalid(dev, macport, status, skb->len - -+ sizeof(struct hfa384x_rx_frame), -+ skb)) -+ goto rx_dropped; -+ -+ if (msg_type == HFA384X_RX_MSGTYPE_MGMT || type != WLAN_FC_TYPE_DATA) { -+ if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH && -+ fc & WLAN_FC_ISWEP && local->host_decrypt && -+ hostap_rx_frame_decrypt(local, fc & WLAN_FC_ISWEP, skb)) { -+ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " -+ "from " MACSTR "\n", dev->name, -+ MAC2STR(rxdesc->addr2)); -+ /* TODO: could inform hostapd about this so that it -+ * could send auth failure report */ -+ goto rx_dropped; -+ } -+ -+ if (hostap_rx_frame_mgmt(local, skb, type, stype)) -+ goto rx_dropped; -+ else -+ goto rx_exit; -+ } -+ -+ if (hostap_rx_frame_invalid_data(dev, msg_type, type, stype)) -+ goto rx_dropped; -+ -+ if (hostap_rx_frame_wds(local, rxdesc, fc, &wds)) -+ goto rx_dropped; -+ if (wds) { -+ skb->dev = dev = &wds->dev; -+ stats = hostap_get_stats(dev); -+ } -+ -+ if (local->iw_mode == IW_MODE_MASTER && !wds && -+ (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_FROMDS && -+ local->stadev && -+ memcmp(rxdesc->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) { -+ /* Frame from BSSID of the AP for which we are a client */ -+ skb->dev = dev = local->stadev; -+ stats = hostap_get_stats(dev); -+ from_assoc_ap = 1; -+ } -+ -+ dev->last_rx = jiffies; -+ -+ if (local->iw_mode == IW_MODE_MASTER && !from_assoc_ap) { -+ switch (hostap_handle_sta_rx(local, dev, skb, wds != NULL)) -+ { -+ case AP_RX_CONTINUE_NOT_AUTHORIZED: -+ frame_authorized = 0; -+ break; -+ case AP_RX_CONTINUE: -+ frame_authorized = 1; -+ break; -+ case AP_RX_DROP: -+ goto rx_dropped; -+ case AP_RX_EXIT: -+ goto rx_exit; -+ } -+ } else if (local->iw_mode == IW_MODE_REPEAT || -+ local->wds_type & HOSTAP_WDS_AP_CLIENT) -+ hostap_update_rx_stats(local->ap, rxdesc); -+ -+ /* Nullfunc frames may have PS-bit set, so they must be passed to -+ * hostap_handle_sta_rx() before being dropped here. */ -+ if (stype != WLAN_FC_STYPE_DATA && -+ stype != WLAN_FC_STYPE_DATA_CFACK && -+ stype != WLAN_FC_STYPE_DATA_CFPOLL && -+ stype != WLAN_FC_STYPE_DATA_CFACKPOLL) { -+ if (stype != WLAN_FC_STYPE_NULLFUNC) -+ printk(KERN_DEBUG "%s: RX: dropped data frame " -+ "with no data (type=0x%02x, subtype=0x%02x)\n", -+ dev->name, type, stype); -+ goto rx_dropped; -+ } -+ -+ /* skb: rxdesc + (possibly fragmented, possibly encrypted) payload */ -+ -+ if (local->host_decrypt && -+ hostap_rx_frame_decrypt(local, fc & WLAN_FC_ISWEP, skb)) -+ goto rx_dropped; -+ -+ /* skb: rxdesc + (possibly fragmented) plaintext payload */ -+ -+ if (local->host_decrypt && (fc & WLAN_FC_ISWEP) && -+ (frag != 0 || (fc & WLAN_FC_MOREFRAG))) { -+ int flen; -+ struct sk_buff *frag_skb = -+ prism2_frag_cache_get(local, rxdesc); -+ if (!frag_skb) { -+ printk(KERN_DEBUG "%s: Rx cannot get skb from " -+ "fragment cache (morefrag=%d seq=%u frag=%u)\n", -+ dev->name, (fc & WLAN_FC_MOREFRAG) != 0, -+ WLAN_GET_SEQ_SEQ(sc), frag); -+ goto rx_dropped; -+ } -+ -+ flen = skb->len; -+ if (frag != 0) -+ flen -= sizeof(struct hfa384x_rx_frame); -+ -+ if (frag_skb->tail + flen > frag_skb->end) { -+ printk(KERN_WARNING "%s: host decrypted and " -+ "reassembled frame did not fit skb\n", -+ dev->name); -+ prism2_frag_cache_invalidate(local, rxdesc); -+ goto rx_dropped; -+ } -+ -+ if (frag == 0) { -+ /* copy first fragment (including full headers) into -+ * beginning of the fragment cache skb */ -+ memcpy(skb_put(frag_skb, flen), skb->data, flen); -+ } else { -+ /* append frame payload to the end of the fragment -+ * cache skb */ -+ memcpy(skb_put(frag_skb, flen), -+ skb->data + sizeof(struct hfa384x_rx_frame), -+ flen); -+ } -+ dev_kfree_skb(skb); -+ skb = NULL; -+ -+ if (fc & WLAN_FC_MOREFRAG) { -+ /* more fragments expected - leave the skb in fragment -+ * cache for now; it will be delivered to upper layers -+ * after all fragments have been received */ -+ goto rx_exit; -+ } -+ -+ /* this was the last fragment and the frame will be -+ * delivered, so remove skb from fragment cache */ -+ skb = frag_skb; -+ rxdesc = (struct hfa384x_rx_frame *) skb->data; -+ prism2_frag_cache_invalidate(local, rxdesc); -+ } -+ -+ /* skb: rxdesc + (possible reassembled) full plaintext payload */ -+ -+ payload = skb->data + sizeof(*rxdesc); -+ ethertype = (payload[6] << 8) | payload[7]; -+ -+ /* If IEEE 802.1X is used, check whether the port is authorized to send -+ * the received frame. */ -+ if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) { -+ if (ethertype == ETH_P_PAE) { -+ printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n", -+ dev->name); -+ if (local->hostapd && local->apdev) { -+ /* Send IEEE 802.1X frames to the user -+ * space daemon for processing */ -+ prism2_rx_80211(local->apdev, skb, -+ PRISM2_RX_MGMT, NULL, 0); -+ local->apdevstats.rx_packets++; -+ local->apdevstats.rx_bytes += skb->len; -+ goto rx_exit; -+ } -+ } else if (!frame_authorized && !wds) { -+ printk(KERN_DEBUG "%s: dropped frame from " -+ "unauthorized port (IEEE 802.1X): " -+ "ethertype=0x%04x\n", -+ dev->name, ethertype); -+ hostap_dump_rx_header(dev->name, rxdesc); -+ goto rx_dropped; -+ } -+ } -+ -+ /* convert rxdesc + possible LLC headers into Ethernet header */ -+ if (skb->len - sizeof(struct hfa384x_rx_frame) >= 8 && -+ ((memcmp(payload, rfc1042_header, 6) == 0 && -+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || -+ memcmp(payload, bridge_tunnel_header, 6) == 0)) { -+ /* remove RFC1042 or Bridge-Tunnel encapsulation and -+ * replace EtherType */ -+ skb_pull(skb, sizeof(*rxdesc) + 6); -+ memmove(skb_push(skb, 2 * ETH_ALEN), rxdesc->dst_addr, -+ 2 * ETH_ALEN); -+ } else { -+ /* Leave Ethernet header part of rxdesc and full payload */ -+ skb_pull(skb, sizeof(*rxdesc) - ETH_HLEN); -+ } -+ -+ if (wds || ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == -+ (WLAN_FC_TODS | WLAN_FC_FROMDS))) { -+ /* Get original source address (Addr4 = SA) */ -+ if (fc & WLAN_FC_FROMDS) { -+ /* IEEE 802.11 compliant WDS frame */ -+ memcpy(skb->data + ETH_ALEN, rxdesc->addr4, ETH_ALEN); -+ } else if (skb->len >= ETH_HLEN + ETH_ALEN) { -+ /* Non-standard frame: get addr4 from its bogus -+ * location after the payload */ -+ memcpy(skb->data + ETH_ALEN, -+ skb->data + skb->len - ETH_ALEN, ETH_ALEN); -+ skb_trim(skb, skb->len - ETH_ALEN); -+ } -+ } -+ -+ int rate = 0; -+ switch (rxdesc->rate) { -+ case 0x0A: -+ rate = 1; -+ break; -+ case 0x014: -+ rate = 2; -+ break; -+ case 0x37: -+ rate = 5; -+ break; -+ case 0x6E: -+ rate = 11; -+ break; -+ default: -+ rate = rxdesc->rate; -+ } -+ -+ -+ memset(skb->cb, 0, sizeof(skb->cb)); -+ SET_WIFI_RATE_ANNO(skb, rate); -+ SET_WIFI_SIGNAL_ANNO(skb, rxdesc->signal); -+ SET_WIFI_NOISE_ANNO(skb, rxdesc->silence); -+ -+ -+ -+ stats->rx_packets++; -+ stats->rx_bytes += skb->len; -+ -+ if (local->iw_mode == IW_MODE_MASTER && !wds && -+ local->ap->bridge_packets) { -+ if (rxdesc->addr3[0] & 0x01) { -+ /* copy multicast frame both to the higher layers and -+ * to the wireless media */ -+ local->ap->bridged_multicast++; -+ skb2 = skb_clone(skb, GFP_ATOMIC); -+ if (skb2 == NULL) -+ printk(KERN_DEBUG "%s: skb_clone failed for " -+ "multicast frame\n", dev->name); -+ } else if (hostap_is_sta_assoc(local->ap, rxdesc->addr3)) { -+ /* send frame directly to the associated STA using -+ * wireless media and not passing to higher layers */ -+ local->ap->bridged_unicast++; -+ skb2 = skb; -+ skb = NULL; -+ } -+ } -+ -+ if (skb2 != NULL) { -+ /* send to wireless media */ -+ skb2->protocol = __constant_htons(ETH_P_802_3); -+ skb2->mac.raw = skb2->nh.raw = skb2->data; -+ /* skb2->nh.raw = skb2->data + ETH_HLEN; */ -+ dev_queue_xmit(skb2); -+ } -+ -+ if (skb) { -+ skb->protocol = eth_type_trans(skb, dev); -+ /* don't clear the cb - we need click packet annos */ -+ /* jbicket */ -+ /* memset(skb->cb, 0, sizeof(skb->cb)); */ -+ skb->dev = dev; -+ netif_rx(skb); -+ } -+ -+ rx_exit: -+ return; -+ -+ rx_dropped: -+ dev_kfree_skb(skb); -+ -+ stats->rx_dropped++; -+ goto rx_exit; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_rx_tasklet(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct sk_buff *skb; -+ -+ while ((skb = skb_dequeue(&local->rx_list)) != NULL) -+ hostap_rx_skb(local, skb); -+} -+ -+ -+/* Called only from hardware IRQ */ -+static void prism2_alloc_ev(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int idx; -+ u16 fid; -+ -+ fid = HFA384X_INW(HFA384X_ALLOCFID_OFF); -+ -+ PDEBUG(DEBUG_FID, "FID: interrupt: ALLOC - fid=0x%04x\n", fid); -+ -+ idx = local->next_alloc; -+ -+ do { -+ if (local->txfid[idx] == fid) { -+ PDEBUG(DEBUG_FID, "FID: found matching txfid[%d]\n", -+ idx); -+ -+#ifndef final_version -+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) -+ printk("Already released txfid found at idx " -+ "%d\n", idx); -+ if (local->intransmitfid[idx] == PRISM2_TXFID_RESERVED) -+ printk("Already reserved txfid found at idx " -+ "%d\n", idx); -+#endif -+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY; -+ idx++; -+ local->next_alloc = idx >= PRISM2_TXFID_COUNT ? 0 : -+ idx; -+ -+ if (!test_bit(HOSTAP_BITS_TRANSMIT, &local->bits) && -+ netif_queue_stopped(dev)) -+ hostap_netif_wake_queues(dev); -+ -+ return; -+ } -+ -+ idx++; -+ if (idx >= PRISM2_TXFID_COUNT) -+ idx = 0; -+ } while (idx != local->next_alloc); -+ -+ printk(KERN_WARNING "%s: could not find matching txfid (0x%04x) for " -+ "alloc event\n", dev->name, HFA384X_INW(HFA384X_ALLOCFID_OFF)); -+} -+ -+ -+/* TX callback data stored in skb->cb; this must not grow over the maximum -+ * skb->cb size (48 bytes) */ -+struct hostap_tx_callback_skb_cb { -+ struct hostap_tx_callback_info *cb; -+ int ok; -+}; -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_tx_callback_tasklet(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct sk_buff *skb; -+ struct hostap_tx_callback_skb_cb *cb_data; -+ -+ while ((skb = skb_dequeue(&local->tx_callback_list)) != NULL) { -+ cb_data = (struct hostap_tx_callback_skb_cb *) skb->cb; -+ cb_data->cb->func(skb, cb_data->ok, cb_data->cb->data); -+ } -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_tx_callback(local_info_t *local, -+ struct hfa384x_tx_frame *txdesc, int ok, -+ char *payload) -+{ -+ u16 sw_support, hdrlen, len; -+ struct sk_buff *skb; -+ struct hostap_tx_callback_info *cb; -+ struct hostap_tx_callback_skb_cb *cb_data; -+ -+ /* Make sure that frame was from us. */ -+ if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) { -+ printk(KERN_DEBUG "%s: TX callback - foreign frame\n", -+ local->dev->name); -+ return; -+ } -+ -+ sw_support = le16_to_cpu(txdesc->sw_support); -+ -+ spin_lock(&local->lock); -+ cb = local->tx_callback; -+ while (cb != NULL && cb->idx != sw_support) -+ cb = cb->next; -+ spin_unlock(&local->lock); -+ -+ if (cb == NULL) { -+ printk(KERN_DEBUG "%s: could not find TX callback (idx %d)\n", -+ local->dev->name, sw_support); -+ return; -+ } -+ -+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(txdesc->frame_control)); -+ len = le16_to_cpu(txdesc->data_len); -+ skb = dev_alloc_skb(hdrlen + len); -+ if (skb == NULL) { -+ printk(KERN_DEBUG "%s: hostap_tx_callback failed to allocate " -+ "skb\n", local->dev->name); -+ return; -+ } -+ -+ memcpy(skb_put(skb, hdrlen), (void *) &txdesc->frame_control, hdrlen); -+ if (payload) -+ memcpy(skb_put(skb, len), payload, len); -+ -+ skb->dev = local->dev; -+ skb->mac.raw = skb->data; -+ -+ /* Store TX callback info pointer to private data in the skb and finish -+ * TX callback handling in tasklet so that hw IRQ can be ACKed now */ -+ cb_data = (struct hostap_tx_callback_skb_cb *) skb->cb; -+ cb_data->cb = cb; -+ cb_data->ok = ok; -+ skb_queue_tail(&local->tx_callback_list, skb); -+ HOSTAP_TASKLET_SCHEDULE(&local->tx_callback_tasklet); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static int hostap_tx_compl_read(local_info_t *local, int error, -+ struct hfa384x_tx_frame *txdesc, -+ char **payload) -+{ -+ u16 fid, len; -+ int res, ret = 0; -+ struct net_device *dev = local->dev; -+ -+ fid = HFA384X_INW(HFA384X_TXCOMPLFID_OFF); -+ -+ spin_lock(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, fid, 0); -+ if (!res) -+ res = hfa384x_from_bap(dev, BAP0, txdesc, sizeof(*txdesc)); -+ if (res) { -+ printk(KERN_WARNING "%s: TX (err=%d) - fid=0x%04x - could not " -+ "read txdesc\n", dev->name, error, fid); -+ if (res == -ETIMEDOUT) { -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ } -+ ret = -1; -+ goto fail; -+ } -+ -+ if (0 && txdesc->sw_support) { -+ len = le16_to_cpu(txdesc->data_len); -+ if (len < PRISM2_DATA_MAXLEN) { -+ *payload = (char *) kmalloc(len, GFP_ATOMIC); -+ if (*payload == NULL || -+ hfa384x_from_bap(dev, BAP0, *payload, len)) { -+ PDEBUG(DEBUG_EXTRA, "%s: could not read TX " -+ "frame payload\n", dev->name); -+ kfree(*payload); -+ *payload = NULL; -+ ret = -1; -+ goto fail; -+ } -+ } -+ } -+ -+ fail: -+ spin_unlock(&local->baplock); -+ -+ return ret; -+} -+ -+static void prism2_tx_click_cb(local_info_t *local, struct hfa384x_tx_frame *txdesc) -+{ -+ if (txdesc->sw_support < PRISM2_TXSKB_COUNT && txdesc->sw_support != 0) { -+ struct sk_buff *skb = local->txskb[txdesc->sw_support]; -+ -+ local->txskb[txdesc->sw_support] = NULL; -+ -+ if (NULL != skb) { -+ u16 status = le16_to_cpu(txdesc->status); -+ int success = !status; -+ SET_WIFI_TX_SUCCESS_ANNO(skb, success); -+ /* -+ * don't set the rate anno, since it was already set in -+ * the skb. -+ * jbicket -+ */ -+ /* also don't set the retries anno, since hostap doesn't support it */ -+ click_wifi_tx_ev(skb); -+ -+ } else { -+ printk(KERN_WARNING "%s: prism2_txexc skb %d NULL\n", -+ local->dev->name, txdesc->sw_support); -+ } -+ } else { -+ printk(KERN_WARNING "%s: prism2_txexc sw_support = %d (NULL)\n", -+ local->dev->name, txdesc->sw_support); -+ } -+} -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_tx_ev(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ char *payload = NULL; -+ struct hfa384x_tx_frame txdesc; -+ -+ if (hostap_tx_compl_read(local, 0, &txdesc, &payload)) { -+ printk(KERN_WARNING "%s: hostap_tx_compl_read failed\n", -+ local->dev->name); -+ goto fail; -+ } -+ -+ prism2_tx_click_cb(local, &txdesc); -+ -+ if (local->frame_dump & PRISM2_DUMP_TX_HDR) { -+ PDEBUG(DEBUG_EXTRA, "%s: TX - status=0x%04x " -+ "retry_count=%d tx_rate=%d seq_ctrl=%d " -+ "duration_id=%d\n", -+ dev->name, le16_to_cpu(txdesc.status), -+ txdesc.retry_count, txdesc.tx_rate, -+ le16_to_cpu(txdesc.seq_ctrl), -+ le16_to_cpu(txdesc.duration_id)); -+ } -+ -+ if (0 && txdesc.sw_support) { -+ hostap_tx_callback(local, &txdesc, 1, payload); -+ } -+ kfree(payload); -+ -+ fail: -+ HFA384X_OUTW(HFA384X_EV_TX, HFA384X_EVACK_OFF); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_sta_tx_exc_tasklet(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct sk_buff *skb; -+ -+ while ((skb = skb_dequeue(&local->sta_tx_exc_list)) != NULL) { -+ struct hfa384x_tx_frame *txdesc = -+ (struct hfa384x_tx_frame *) skb->data; -+ hostap_handle_sta_tx_exc(local, txdesc); -+ dev_kfree_skb(skb); -+ } -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_txexc(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ u16 status, fc; -+ int show_dump, res; -+ char *payload = NULL; -+ struct hfa384x_tx_frame txdesc; -+ -+ show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR; -+ local->stats.tx_errors++; -+ -+ res = hostap_tx_compl_read(local, 1, &txdesc, &payload); -+ HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF); -+ if (res) -+ return; -+ -+ status = le16_to_cpu(txdesc.status); -+ -+ prism2_tx_click_cb(local, &txdesc); -+ -+ -+#if WIRELESS_EXT > 13 -+ /* We produce a TXDROP event only for retry or lifetime -+ * exceeded, because that's the only status that really mean -+ * that this particular node went away. -+ * Other errors means that *we* screwed up. - Jean II */ -+ if (status & (HFA384X_TX_STATUS_RETRYERR | HFA384X_TX_STATUS_AGEDERR)) -+ { -+ union iwreq_data wrqu; -+ -+ /* Copy 802.11 dest address. */ -+ memcpy(wrqu.addr.sa_data, txdesc.addr1, ETH_ALEN); -+ wrqu.addr.sa_family = ARPHRD_ETHER; -+ wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); -+ } else -+ show_dump = 1; -+#endif /* WIRELESS_EXT > 13 */ -+ -+ if (local->iw_mode == IW_MODE_MASTER || -+ local->iw_mode == IW_MODE_REPEAT || -+ local->wds_type & HOSTAP_WDS_AP_CLIENT) { -+ struct sk_buff *skb; -+ skb = dev_alloc_skb(sizeof(txdesc)); -+ if (skb) { -+ memcpy(skb_put(skb, sizeof(txdesc)), &txdesc, -+ sizeof(txdesc)); -+ skb_queue_tail(&local->sta_tx_exc_list, skb); -+ HOSTAP_TASKLET_SCHEDULE(&local->sta_tx_exc_tasklet); -+ } -+ } -+ -+ if (0 && txdesc.sw_support) { -+ hostap_tx_callback(local, &txdesc, 0, payload); -+ } -+ -+ kfree(payload); -+ -+ if (!show_dump) -+ return; -+ -+ PDEBUG(DEBUG_EXTRA, "%s: TXEXC - status=0x%04x (%s%s%s%s)" -+ " tx_control=%04x\n", -+ dev->name, status, -+ status & HFA384X_TX_STATUS_RETRYERR ? "[RetryErr]" : "", -+ status & HFA384X_TX_STATUS_AGEDERR ? "[AgedErr]" : "", -+ status & HFA384X_TX_STATUS_DISCON ? "[Discon]" : "", -+ status & HFA384X_TX_STATUS_FORMERR ? "[FormErr]" : "", -+ le16_to_cpu(txdesc.tx_control)); -+ -+ fc = le16_to_cpu(txdesc.frame_control); -+ PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x " -+ "(%s%s%s::%d%s%s)\n", -+ txdesc.retry_count, txdesc.tx_rate, fc, -+ WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT ? "Mgmt" : "", -+ WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_CTRL ? "Ctrl" : "", -+ WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA ? "Data" : "", -+ WLAN_FC_GET_STYPE(fc), -+ fc & WLAN_FC_TODS ? " ToDS" : "", -+ fc & WLAN_FC_FROMDS ? " FromDS" : ""); -+ PDEBUG(DEBUG_EXTRA, " A1=" MACSTR " A2=" MACSTR " A3=" -+ MACSTR " A4=" MACSTR "\n", -+ MAC2STR(txdesc.addr1), MAC2STR(txdesc.addr2), -+ MAC2STR(txdesc.addr3), MAC2STR(txdesc.addr4)); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_info_tasklet(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct sk_buff *skb; -+ -+ while ((skb = skb_dequeue(&local->info_list)) != NULL) { -+ hostap_info_process(local, skb); -+ dev_kfree_skb(skb); -+ } -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_info(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ u16 fid; -+ int res, left; -+ struct hfa384x_info_frame info; -+ struct sk_buff *skb; -+ -+ fid = HFA384X_INW(HFA384X_INFOFID_OFF); -+ -+ spin_lock(&local->baplock); -+ res = hfa384x_setup_bap(dev, BAP0, fid, 0); -+ if (!res) -+ res = hfa384x_from_bap(dev, BAP0, &info, sizeof(info)); -+ if (res) { -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "Could not get info frame (fid=0x%04x)\n", -+ fid); -+ if (res == -ETIMEDOUT) { -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ } -+ goto out; -+ } -+ -+ le16_to_cpus(&info.len); -+ le16_to_cpus(&info.type); -+ left = (info.len - 1) * 2; -+ -+ if (info.len & 0x8000 || info.len == 0 || left > 2060) { -+ /* data register seems to give 0x8000 in some error cases even -+ * though busy bit is not set in offset register; -+ * in addition, length must be at least 1 due to type field */ -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "%s: Received info frame with invalid " -+ "length 0x%04x (type 0x%04x)\n", dev->name, info.len, -+ info.type); -+ goto out; -+ } -+ -+ skb = dev_alloc_skb(sizeof(info) + left); -+ if (skb == NULL) { -+ spin_unlock(&local->baplock); -+ printk(KERN_DEBUG "%s: Could not allocate skb for info " -+ "frame\n", dev->name); -+ goto out; -+ } -+ -+ memcpy(skb_put(skb, sizeof(info)), &info, sizeof(info)); -+ if (left > 0 && hfa384x_from_bap(dev, BAP0, skb_put(skb, left), left)) -+ { -+ spin_unlock(&local->baplock); -+ printk(KERN_WARNING "%s: Info frame read failed (fid=0x%04x, " -+ "len=0x%04x, type=0x%04x\n", -+ dev->name, fid, info.len, info.type); -+ dev_kfree_skb(skb); -+ goto out; -+ } -+ spin_unlock(&local->baplock); -+ -+ skb_queue_tail(&local->info_list, skb); -+ HOSTAP_TASKLET_SCHEDULE(&local->info_tasklet); -+ -+ out: -+ HFA384X_OUTW(HFA384X_EV_INFO, HFA384X_EVACK_OFF); -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void hostap_bap_tasklet(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct net_device *dev = local->dev; -+ u16 ev; -+ int frames = 30; -+ -+ if (local->func->card_present && !local->func->card_present(local)) -+ return; -+ -+ set_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits); -+ -+ /* Process all pending BAP events without generating new interrupts -+ * for them */ -+ while (frames-- > 0) { -+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ if (ev == 0xffff || !(ev & HFA384X_BAP0_EVENTS)) -+ break; -+ if (ev & HFA384X_EV_RX) -+ prism2_rx(local); -+ if (ev & HFA384X_EV_INFO) -+ prism2_info(local); -+ if (ev & HFA384X_EV_TX) -+ prism2_tx_ev(local); -+ if (ev & HFA384X_EV_TXEXC) -+ prism2_txexc(local); -+ } -+ -+ set_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits); -+ clear_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits); -+ -+ /* Enable interrupts for new BAP events */ -+ hfa384x_events_all(dev); -+ clear_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits); -+} -+ -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+/* Called only from hardware IRQ */ -+static void prism2_bus_master_ev(struct net_device *dev, int bap) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ if (bap == BAP1) { -+ /* FIX: frame payload was DMA'd to skb->data; might need to -+ * invalidate data cache for that memory area */ -+ skb_queue_tail(&local->rx_list, local->rx_skb); -+ HOSTAP_TASKLET_SCHEDULE(&local->rx_tasklet); -+ HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF); -+ } else { -+ if (prism2_transmit(dev, local->bus_m0_tx_idx)) { -+ printk(KERN_DEBUG "%s: prism2_transmit() failed " -+ "when called from bus master event\n", -+ dev->name); -+ local->intransmitfid[local->bus_m0_tx_idx] = -+ PRISM2_TXFID_EMPTY; -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ } -+ } -+} -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ -+/* Called only from hardware IRQ */ -+static void prism2_infdrop(struct net_device *dev) -+{ -+ static long last_inquire = 0; -+ -+ PDEBUG(DEBUG_EXTRA, "%s: INFDROP event\n", dev->name); -+ -+ /* some firmware versions seem to get stuck with -+ * full CommTallies in high traffic load cases; every -+ * packet will then cause INFDROP event and CommTallies -+ * info frame will not be sent automatically. Try to -+ * get out of this state by inquiring CommTallies. */ -+ if (last_inquire + HZ < jiffies) { -+ hfa384x_cmd_callback(dev, HFA384X_CMDCODE_INQUIRE, -+ HFA384X_INFO_COMMTALLIES, NULL, NULL, NULL); -+ last_inquire = jiffies; -+ } -+} -+ -+ -+/* Called only from hardware IRQ */ -+static void prism2_ev_tick(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 evstat, inten; -+ -+ if (local->last_tick_timer + 5 * HZ < jiffies && -+ local->last_tick_timer) { -+ evstat = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ inten = HFA384X_INW(HFA384X_INTEN_OFF); -+ printk(KERN_INFO "%s: SW TICK stuck? " -+ "bits=0x%lx EvStat=%04x IntEn=%04x\n", -+ dev->name, local->bits, evstat, inten); -+ local->sw_tick_stuck++; -+ if ((evstat & HFA384X_BAP0_EVENTS) && -+ (inten & HFA384X_BAP0_EVENTS)) { -+ printk(KERN_INFO "%s: trying to recover from IRQ " -+ "hang\n", dev->name); -+ hfa384x_events_no_bap0(dev); -+ } -+ } -+} -+ -+ -+/* Called only from hardware IRQ */ -+static inline void prism2_check_magic(local_info_t *local) -+{ -+ /* at least PCI Prism2.5 with bus mastering seems to sometimes -+ * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the -+ * register once or twice seems to get the correct value.. PCI cards -+ * cannot anyway be removed during normal operation, so there is not -+ * really any need for this verification with them. */ -+ -+#ifndef PRISM2_PCI -+#ifndef final_version -+ static long int last_magic_err = 0; -+ struct net_device *dev = local->dev; -+ -+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) { -+ if (!local->hw_ready) -+ return; -+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); -+ if (jiffies - last_magic_err > 10 * HZ) { -+ printk("%s: Interrupt, but SWSUPPORT0 does not match: " -+ "%04X != %04X - card removed?\n", dev->name, -+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF), -+ HFA384X_MAGIC); -+ last_magic_err = jiffies; -+ } else if (net_ratelimit()) { -+ printk(KERN_DEBUG "%s: interrupt - SWSUPPORT0=%04x " -+ "MAGIC=%04x\n", dev->name, -+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF), -+ HFA384X_MAGIC); -+ } -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ return; -+ } -+#endif /* final_version */ -+#endif /* !PRISM2_PCI */ -+} -+ -+ -+/* Called only from hardware IRQ */ -+static irqreturn_t prism2_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct net_device *dev = (struct net_device *) dev_id; -+ local_info_t *local = (local_info_t *) dev->priv; -+ int events = 0; -+ u16 ev; -+ -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); -+ -+ if (local->func->card_present && !local->func->card_present(local)) { -+ printk(KERN_DEBUG "%s: Interrupt, but dev not OK\n", -+ dev->name); -+ return IRQ_HANDLED; -+ } -+ -+ prism2_check_magic(local); -+ -+ for (;;) { -+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ if (ev == 0xffff) { -+ if (local->shutdown) -+ return IRQ_HANDLED; -+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); -+ printk(KERN_DEBUG "%s: prism2_interrupt: ev=0xffff\n", -+ dev->name); -+ PRISM2_SCHEDULE_TASK(&local->reset_queue); -+ return IRQ_HANDLED; -+ } -+ -+ ev &= HFA384X_INW(HFA384X_INTEN_OFF); -+ if (ev == 0) -+ break; -+ -+ if (ev & HFA384X_EV_CMD) { -+ prism2_cmd_ev(dev); -+ } -+ -+ /* Above events are needed even before hw is ready, but other -+ * events should be skipped during initialization. This may -+ * change for AllocEv if allocate_fid is implemented without -+ * busy waiting. */ -+ if (!local->hw_ready || local->hw_resetting || -+ !local->dev_enabled) { -+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF); -+ if (ev & HFA384X_EV_CMD) -+ goto next_event; -+ if ((ev & HFA384X_EVENT_MASK) == 0) -+ return IRQ_HANDLED; -+ if (local->dev_enabled && (ev & ~HFA384X_EV_TICK) && -+ net_ratelimit()) { -+ printk(KERN_DEBUG "%s: prism2_interrupt: hw " -+ "not ready; skipping events 0x%04x " -+ "(IntEn=0x%04x)%s%s%s\n", -+ dev->name, ev, -+ HFA384X_INW(HFA384X_INTEN_OFF), -+ !local->hw_ready ? " (!hw_ready)" : "", -+ local->hw_resetting ? -+ " (hw_resetting)" : "", -+ !local->dev_enabled ? -+ " (!dev_enabled)" : ""); -+ } -+ HFA384X_OUTW(ev, HFA384X_EVACK_OFF); -+ return IRQ_HANDLED; -+ } -+ -+ if (ev & HFA384X_EV_TICK) { -+ prism2_ev_tick(dev); -+ HFA384X_OUTW(HFA384X_EV_TICK, HFA384X_EVACK_OFF); -+ } -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ if (ev & HFA384X_EV_PCI_M0) { -+ prism2_bus_master_ev(dev, BAP0); -+ HFA384X_OUTW(HFA384X_EV_PCI_M0, HFA384X_EVACK_OFF); -+ } -+ -+ if (ev & HFA384X_EV_PCI_M1) { -+ /* previous RX has been copied can be ACKed now */ -+ HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF); -+ -+ prism2_bus_master_ev(dev, BAP1); -+ HFA384X_OUTW(HFA384X_EV_PCI_M1, HFA384X_EVACK_OFF); -+ } -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ if (ev & HFA384X_EV_ALLOC) { -+ prism2_alloc_ev(dev); -+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF); -+ } -+ -+ /* Reading data from the card is quite time consuming, so do it -+ * in tasklets. TX, TXEXC, RX, and INFO events will be ACKed -+ * and unmasked after needed data has been read completely. */ -+ if (ev & HFA384X_BAP0_EVENTS) { -+ hfa384x_events_no_bap0(dev); -+ HOSTAP_TASKLET_SCHEDULE(&local->bap_tasklet); -+ } -+ -+#ifndef final_version -+ if (ev & HFA384X_EV_WTERR) { -+ PDEBUG(DEBUG_EXTRA, "%s: WTERR event\n", dev->name); -+ HFA384X_OUTW(HFA384X_EV_WTERR, HFA384X_EVACK_OFF); -+ } -+#endif /* final_version */ -+ -+ if (ev & HFA384X_EV_INFDROP) { -+ prism2_infdrop(dev); -+ HFA384X_OUTW(HFA384X_EV_INFDROP, HFA384X_EVACK_OFF); -+ } -+ -+ next_event: -+ events++; -+ if (events >= PRISM2_MAX_INTERRUPT_EVENTS) { -+ PDEBUG(DEBUG_EXTRA, "prism2_interrupt: >%d events " -+ "(EvStat=0x%04x)\n", -+ PRISM2_MAX_INTERRUPT_EVENTS, -+ HFA384X_INW(HFA384X_EVSTAT_OFF)); -+ break; -+ } -+ } -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 1); -+ return IRQ_RETVAL(events); -+} -+ -+ -+static void prism2_check_sta_fw_version(local_info_t *local) -+{ -+ struct hfa384x_comp_ident comp; -+ int id, variant, major, minor; -+ -+ if (hfa384x_get_rid(local->dev, HFA384X_RID_STAID, -+ &comp, sizeof(comp), 1) < 0) -+ return; -+ -+ local->fw_ap = 0; -+ id = le16_to_cpu(comp.id); -+ if (id != HFA384X_COMP_ID_STA) { -+ if (id == HFA384X_COMP_ID_FW_AP) -+ local->fw_ap = 1; -+ return; -+ } -+ -+ major = __le16_to_cpu(comp.major); -+ minor = __le16_to_cpu(comp.minor); -+ variant = __le16_to_cpu(comp.variant); -+ local->sta_fw_ver = PRISM2_FW_VER(major, minor, variant); -+ -+ /* Station firmware versions before 1.4.x seem to have a bug in -+ * firmware-based WEP encryption when using Host AP mode, so use -+ * host_encrypt as a default for them. Firmware version 1.4.9 is the -+ * first one that has been seen to produce correct encryption, but the -+ * bug might be fixed before that (although, at least 1.4.2 is broken). -+ */ -+ local->fw_encrypt_ok = major > 1 || -+ (major == 1 && (minor > 4 || (minor == 4 && variant >= 9))); -+ -+ if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt && -+ !local->fw_encrypt_ok) { -+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as " -+ "a workaround for firmware bug in Host AP mode WEP\n", -+ local->dev->name); -+ local->host_encrypt = 1; -+ } -+ -+ /* IEEE 802.11 standard compliant WDS frames (4 addresses) were broken -+ * in station firmware versions before 1.5.x. With these versions, the -+ * driver uses a workaround with bogus frame format (4th address after -+ * the payload). This is not compatible with other AP devices. Since -+ * the firmware bug is fixed in the latest station firmware versions, -+ * automatically enable standard compliant mode for cards using station -+ * firmware version 1.5.0 or newer. */ -+ if (major > 1 || (major == 1 && (minor >= 5))) -+ local->wds_type |= HOSTAP_WDS_STANDARD_FRAME; -+ else { -+ printk(KERN_DEBUG "%s: defaulting to bogus WDS frame as a " -+ "workaround for firmware bug in Host AP mode WDS\n", -+ local->dev->name); -+ } -+ -+ hostap_check_sta_fw_version(local->ap, major, minor, variant); -+} -+ -+ -+static void prism2_crypt_deinit_entries(local_info_t *local, int force) -+{ -+ struct list_head *ptr, *n; -+ struct prism2_crypt_data *entry; -+ -+ for (ptr = local->crypt_deinit_list.next, n = ptr->next; -+ ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) { -+ entry = list_entry(ptr, struct prism2_crypt_data, list); -+ -+ if (atomic_read(&entry->refcnt) != 0 && !force) -+ continue; -+ -+ list_del(ptr); -+ -+ if (entry->ops) -+ entry->ops->deinit(entry->priv); -+ kfree(entry); -+ } -+} -+ -+ -+static void prism2_crypt_deinit_handler(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_crypt_deinit_entries(local, 0); -+ if (!list_empty(&local->crypt_deinit_list)) { -+ printk(KERN_DEBUG "%s: entries remaining in delayed crypt " -+ "deletion list\n", local->dev->name); -+ local->crypt_deinit_timer.expires = jiffies + HZ; -+ add_timer(&local->crypt_deinit_timer); -+ } -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+} -+ -+ -+static void hostap_passive_scan(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ struct net_device *dev = local->dev; -+ u16 channel; -+ -+ if (local->passive_scan_interval <= 0) -+ return; -+ -+ if (local->passive_scan_state == PASSIVE_SCAN_LISTEN) { -+ int max_tries = 16; -+ -+ /* Even though host system does not really know when the WLAN -+ * MAC is sending frames, try to avoid changing channels for -+ * passive scanning when a host-generated frame is being -+ * transmitted */ -+ if (test_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { -+ printk(KERN_DEBUG "%s: passive scan detected pending " -+ "TX - delaying\n", dev->name); -+ local->passive_scan_timer.expires = jiffies + HZ / 10; -+ add_timer(&local->passive_scan_timer); -+ return; -+ } -+ -+ do { -+ local->passive_scan_channel++; -+ if (local->passive_scan_channel > 14) -+ local->passive_scan_channel = 1; -+ max_tries--; -+ } while (!(local->channel_mask & -+ (1 << (local->passive_scan_channel - 1))) && -+ max_tries > 0); -+ -+ if (max_tries == 0) { -+ printk(KERN_INFO "%s: no allowed passive scan channels" -+ " found\n", dev->name); -+ return; -+ } -+ -+ printk(KERN_DEBUG "%s: passive scan channel %d\n", -+ dev->name, local->passive_scan_channel); -+ channel = local->passive_scan_channel; -+ local->passive_scan_state = PASSIVE_SCAN_WAIT; -+ local->passive_scan_timer.expires = jiffies + HZ / 10; -+ } else { -+ channel = local->channel; -+ local->passive_scan_state = PASSIVE_SCAN_LISTEN; -+ local->passive_scan_timer.expires = jiffies + -+ local->passive_scan_interval * HZ; -+ } -+ -+ if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_CHANGE_CHANNEL << 8), -+ channel, NULL, NULL, NULL)) -+ printk(KERN_ERR "%s: passive scan channel set %d " -+ "failed\n", dev->name, channel); -+ -+ add_timer(&local->passive_scan_timer); -+} -+ -+ -+/* Software watchdog - called as a timer. Hardware interrupt (Tick event) is -+ * used to monitor that local->last_tick_timer is being updated. If not, -+ * interrupt busy-loop is assumed and driver tries to recover by masking out -+ * some events. */ -+static void hostap_tick_timer(unsigned long data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ local->last_tick_timer = jiffies; -+ local->tick_timer.expires = jiffies + 2 * HZ; -+ add_timer(&local->tick_timer); -+} -+ -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+static int prism2_registers_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ local_info_t *local = (local_info_t *) data; -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+#define SHOW_REG(n) \ -+p += sprintf(p, "%s=%04x\n", #n, \ -+hfa384x_read_reg(local->dev, HFA384X_##n##_OFF)) -+ -+ SHOW_REG(CMD); -+ SHOW_REG(PARAM0); -+ SHOW_REG(PARAM1); -+ SHOW_REG(PARAM2); -+ SHOW_REG(STATUS); -+ SHOW_REG(RESP0); -+ SHOW_REG(RESP1); -+ SHOW_REG(RESP2); -+ SHOW_REG(INFOFID); -+ SHOW_REG(CONTROL); -+ SHOW_REG(SELECT0); -+ SHOW_REG(SELECT1); -+ SHOW_REG(OFFSET0); -+ SHOW_REG(OFFSET1); -+ SHOW_REG(RXFID); -+ SHOW_REG(ALLOCFID); -+ SHOW_REG(TXCOMPLFID); -+ SHOW_REG(SWSUPPORT0); -+ SHOW_REG(SWSUPPORT1); -+ SHOW_REG(SWSUPPORT2); -+ SHOW_REG(EVSTAT); -+ SHOW_REG(INTEN); -+ SHOW_REG(EVACK); -+ /* Do not read data registers, because they change the state of the -+ * MAC (offset += 2) */ -+ /* SHOW_REG(DATA0); */ -+ /* SHOW_REG(DATA1); */ -+ SHOW_REG(AUXPAGE); -+ SHOW_REG(AUXOFFSET); -+ /* SHOW_REG(AUXDATA); */ -+#ifdef PRISM2_PCI -+ SHOW_REG(PCICOR); -+ SHOW_REG(PCIHCR); -+ SHOW_REG(PCI_M0_ADDRH); -+ SHOW_REG(PCI_M0_ADDRL); -+ SHOW_REG(PCI_M0_LEN); -+ SHOW_REG(PCI_M0_CTL); -+ SHOW_REG(PCI_STATUS); -+ SHOW_REG(PCI_M1_ADDRH); -+ SHOW_REG(PCI_M1_ADDRL); -+ SHOW_REG(PCI_M1_LEN); -+ SHOW_REG(PCI_M1_CTL); -+#endif /* PRISM2_PCI */ -+ -+ return (p - page); -+} -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ -+ -+static local_info_t * -+prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx) -+{ -+ local_info_t *local; -+ int len, i; -+ -+ if (funcs == NULL) -+ return NULL; -+ -+ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); -+ if (local == NULL) -+ return NULL; -+ -+ memset(local, 0, sizeof(local_info_t)); -+ local->hw_module = THIS_MODULE; -+ local->ap = kmalloc(sizeof(struct ap_data), GFP_KERNEL); -+ if (local->ap == NULL) -+ goto fail; -+ -+ memset(local->ap, 0, sizeof(struct ap_data)); -+ -+#ifdef PRISM2_IO_DEBUG -+ local->io_debug_enabled = 1; -+#endif /* PRISM2_IO_DEBUG */ -+ -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ local->bus_m0_buf = (u8 *) kmalloc(sizeof(struct hfa384x_tx_frame) + -+ PRISM2_DATA_MAXLEN, GFP_DMA); -+ if (local->bus_m0_buf == NULL) -+ goto fail; -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ local->dev = kmalloc(sizeof(struct net_device) + PRISM2_NETDEV_EXTRA, -+ GFP_KERNEL); -+ if (local->dev == NULL) -+ goto fail; -+ memset(local->dev, 0, sizeof(struct net_device) + PRISM2_NETDEV_EXTRA); -+ prism2_set_dev_name(local->dev, local->dev + 1); -+ local->dev->priv = local; -+ -+ local->func = funcs; -+ local->func->cmd = hfa384x_cmd; -+ local->func->read_regs = hfa384x_read_regs; -+ local->func->get_rid = hfa384x_get_rid; -+ local->func->set_rid = hfa384x_set_rid; -+ local->func->hw_enable = prism2_hw_enable; -+ local->func->hw_config = prism2_hw_config; -+ local->func->hw_reset = prism2_hw_reset; -+ local->func->hw_shutdown = prism2_hw_shutdown; -+ local->func->reset_port = prism2_reset_port; -+ local->func->tx = prism2_tx_set_power; -+ local->func->schedule_reset = prism2_schedule_reset; -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+ local->func->download = prism2_download; -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ local->func->rx_80211 = prism2_rx_80211; -+ local->func->tx_80211 = prism2_tx_80211; -+ -+ local->disable_on_close = disable_on_close; -+ local->mtu = mtu; -+ -+ spin_lock_init(&local->txfidlock); -+ spin_lock_init(&local->cmdlock); -+ spin_lock_init(&local->baplock); -+ spin_lock_init(&local->wdslock); -+ spin_lock_init(&local->lock); -+ init_MUTEX(&local->rid_bap_sem); -+ -+ if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) -+ card_idx = 0; -+ local->card_idx = card_idx; -+ -+ i = essid[card_idx] == NULL ? 0 : card_idx; -+ len = strlen(essid[i]); -+ memcpy(local->essid, essid[i], -+ len > MAX_SSID_LEN ? MAX_SSID_LEN : len); -+ local->essid[MAX_SSID_LEN] = '\0'; -+#ifdef WIRELESS_EXT -+ i = GET_INT_PARM(iw_mode, card_idx); -+ if ((i >= IW_MODE_ADHOC && i <= IW_MODE_REPEAT) || -+ i == IW_MODE_MONITOR) { -+ local->iw_mode = i; -+ } else { -+ printk(KERN_WARNING "prism2: Unknown iw_mode %d; using " -+ "IW_MODE_MASTER\n", i); -+ local->iw_mode = IW_MODE_MASTER; -+ } -+#endif -+ local->channel = GET_INT_PARM(channel, card_idx); -+ local->beacon_int = GET_INT_PARM(beacon_int, card_idx); -+ local->dtim_period = GET_INT_PARM(dtim_period, card_idx); -+ local->wds_max_connections = 16; -+ local->tx_control = HFA384X_TX_CTRL_FLAGS; -+ local->manual_retry_count = -1; -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ local->bus_master_threshold_rx = GET_INT_PARM(bus_master_threshold_rx, -+ card_idx); -+ local->bus_master_threshold_tx = GET_INT_PARM(bus_master_threshold_tx, -+ card_idx); -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ -+ /* Initialize task queue structures */ -+ HOSTAP_QUEUE_INIT(&local->reset_queue, handle_reset_queue, local); -+ HOSTAP_QUEUE_INIT(&local->set_multicast_list_queue, -+ hostap_set_multicast_list_queue, local->dev); -+ -+ /* Initialize tasklets for handling hardware IRQ related operations -+ * outside hw IRQ handler */ -+ HOSTAP_TASKLET_INIT(&local->bap_tasklet, hostap_bap_tasklet, -+ (unsigned long) local); -+ -+ HOSTAP_TASKLET_INIT(&local->info_tasklet, hostap_info_tasklet, -+ (unsigned long) local); -+ hostap_info_init(local); -+ -+ HOSTAP_TASKLET_INIT(&local->tx_callback_tasklet, -+ hostap_tx_callback_tasklet, (unsigned long) local); -+ skb_queue_head_init(&local->tx_callback_list); -+ -+ HOSTAP_TASKLET_INIT(&local->rx_tasklet, -+ hostap_rx_tasklet, (unsigned long) local); -+ skb_queue_head_init(&local->rx_list); -+ -+ HOSTAP_TASKLET_INIT(&local->sta_tx_exc_tasklet, -+ hostap_sta_tx_exc_tasklet, (unsigned long) local); -+ skb_queue_head_init(&local->sta_tx_exc_list); -+ -+ INIT_LIST_HEAD(&local->cmd_queue); -+ init_waitqueue_head(&local->hostscan_wq); -+ INIT_LIST_HEAD(&local->crypt_deinit_list); -+ init_timer(&local->crypt_deinit_timer); -+ local->crypt_deinit_timer.data = (unsigned long) local; -+ local->crypt_deinit_timer.function = prism2_crypt_deinit_handler; -+ -+ init_timer(&local->passive_scan_timer); -+ local->passive_scan_timer.data = (unsigned long) local; -+ local->passive_scan_timer.function = hostap_passive_scan; -+ -+ init_timer(&local->tick_timer); -+ local->tick_timer.data = (unsigned long) local; -+ local->tick_timer.function = hostap_tick_timer; -+ local->tick_timer.expires = jiffies + 2 * HZ; -+ add_timer(&local->tick_timer); -+ -+ hostap_setup_dev(local->dev, local, 1); -+ -+ local->saved_eth_header_parse = local->dev->hard_header_parse; -+ -+ return local; -+ -+ fail: -+ kfree(local->ap); -+ kfree(local->dev); -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ kfree(local->bus_m0_buf); -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ kfree(local->apdev); -+ kfree(local->stadev); -+ kfree(local); -+ return NULL; -+} -+ -+ -+static int prism2_init_dev(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) -+ { -+ int i = 0; -+ do { -+ sprintf(dev->name, "wlan%d", i++); -+ } while (dev_get(dev->name)); -+ } -+#else -+ memcpy(dev->name, "wlan%d", 7); -+#endif -+ if (register_netdev(dev)) { -+ printk(KERN_WARNING "%s: register_netdev() failed!\n", -+ dev_info); -+ return 1; -+ } -+ printk(KERN_INFO "%s: Registered netdevice %s\n", dev_info, dev->name); -+ -+ hostap_init_proc(local); -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ create_proc_read_entry("registers", 0, local->proc, -+ prism2_registers_proc_read, local); -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ hostap_init_data(local); -+ -+ return 0; -+} -+ -+ -+static void prism2_free_local_data(local_info_t *local) -+{ -+ prism2_wds_info_t *wds, *prev; -+ struct hostap_tx_callback_info *tx_cb, *tx_cb_prev; -+ int i; -+ struct sk_buff *skb; -+ -+ if (local == NULL) -+ return; -+ -+ if (timer_pending(&local->crypt_deinit_timer)) -+ del_timer(&local->crypt_deinit_timer); -+ prism2_crypt_deinit_entries(local, 1); -+ -+ if (timer_pending(&local->passive_scan_timer)) -+ del_timer(&local->passive_scan_timer); -+ -+ if (timer_pending(&local->tick_timer)) -+ del_timer(&local->tick_timer); -+ -+ prism2_clear_cmd_queue(local); -+ -+ while ((skb = skb_dequeue(&local->info_list)) != NULL) -+ dev_kfree_skb(skb); -+ -+ while ((skb = skb_dequeue(&local->tx_callback_list)) != NULL) -+ dev_kfree_skb(skb); -+ -+ while ((skb = skb_dequeue(&local->rx_list)) != NULL) -+ dev_kfree_skb(skb); -+ -+ while ((skb = skb_dequeue(&local->sta_tx_exc_list)) != NULL) -+ dev_kfree_skb(skb); -+ -+ if (local->dev_enabled) -+ prism2_callback(local, PRISM2_CALLBACK_DISABLE); -+ -+ if (local->crypt) { -+ if (local->crypt->ops) -+ local->crypt->ops->deinit(local->crypt->priv); -+ kfree(local->crypt); -+ local->crypt = NULL; -+ } -+ -+ if (local->ap != NULL) -+ hostap_free_data(local->ap); -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ if (local->proc != NULL) -+ remove_proc_entry("registers", local->proc); -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ hostap_remove_proc(local); -+ -+ wds = local->wds; -+ local->wds = NULL; -+ while (wds != NULL) { -+ unregister_netdev(&wds->dev); -+ prev = wds; -+ wds = wds->next; -+ kfree(prev); -+ } -+ -+ tx_cb = local->tx_callback; -+ while (tx_cb != NULL) { -+ tx_cb_prev = tx_cb; -+ tx_cb = tx_cb->next; -+ kfree(tx_cb_prev); -+ } -+ -+ hostap_set_hostapd(local, 0, 0); -+ -+ if (local->dev && local->dev->name && local->dev->name[0]) { -+ unregister_netdev(local->dev); -+ printk(KERN_INFO "%s: Netdevice %s unregistered\n", -+ dev_info, local->dev->name); -+ } -+ kfree(local->dev); -+ -+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) { -+ if (local->frag_cache[i].skb != NULL) -+ dev_kfree_skb(local->frag_cache[i].skb); -+ } -+ -+ kfree(local->ap); -+#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER) -+ kfree(local->bus_m0_buf); -+#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */ -+ kfree(local->pda); -+ kfree(local->last_scan_results); -+ kfree(local); -+} -+ -+ -+/* These might at some point be compiled separately and used as separate -+ * kernel modules or linked into one */ -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+#include "hostap_download.c" -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ -+#ifdef PRISM2_CALLBACK -+/* External hostap_callback.c file can be used to, e.g., blink activity led. -+ * This can use platform specific code and must define prism2_callback() -+ * function (if PRISM2_CALLBACK is not defined, these function calls are not -+ * used. */ -+#include "hostap_callback.c" -+#endif /* PRISM2_CALLBACK */ - -Index: drivers/net/wireless/hostap_info.c ---- drivers/net/wireless/hostap_info.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_info.c 2003-07-08 21:39:41.000000000 -0400 -@@ -0,0 +1,450 @@ -+/* Host AP driver Info Frame processing (part of hostap.o module) */ -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_info_commtallies(local_info_t *local, unsigned char *buf, -+ int left) -+{ -+ struct hfa384x_comm_tallies *tallies; -+ -+ if (left < sizeof(struct hfa384x_comm_tallies)) { -+ printk(KERN_DEBUG "%s: too short (len=%d) commtallies " -+ "info frame\n", local->dev->name, left); -+ return; -+ } -+ -+ tallies = (struct hfa384x_comm_tallies *) buf; -+#define ADD_COMM_TALLIES(name) local->comm_tallies.name += tallies->name -+ ADD_COMM_TALLIES(tx_unicast_frames); -+ ADD_COMM_TALLIES(tx_multicast_frames); -+ ADD_COMM_TALLIES(tx_fragments); -+ ADD_COMM_TALLIES(tx_unicast_octets); -+ ADD_COMM_TALLIES(tx_multicast_octets); -+ ADD_COMM_TALLIES(tx_deferred_transmissions); -+ ADD_COMM_TALLIES(tx_single_retry_frames); -+ ADD_COMM_TALLIES(tx_multiple_retry_frames); -+ ADD_COMM_TALLIES(tx_retry_limit_exceeded); -+ ADD_COMM_TALLIES(tx_discards); -+ ADD_COMM_TALLIES(rx_unicast_frames); -+ ADD_COMM_TALLIES(rx_multicast_frames); -+ ADD_COMM_TALLIES(rx_fragments); -+ ADD_COMM_TALLIES(rx_unicast_octets); -+ ADD_COMM_TALLIES(rx_multicast_octets); -+ ADD_COMM_TALLIES(rx_fcs_errors); -+ ADD_COMM_TALLIES(rx_discards_no_buffer); -+ ADD_COMM_TALLIES(tx_discards_wrong_sa); -+ ADD_COMM_TALLIES(rx_discards_wep_undecryptable); -+ ADD_COMM_TALLIES(rx_message_in_msg_fragments); -+ ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments); -+#undef ADD_COMM_TALLIES -+} -+ -+ -+#ifndef PRISM2_NO_STATION_MODES -+#ifndef PRISM2_NO_DEBUG -+static const char* hfa384x_linkstatus_str(u16 linkstatus) -+{ -+ switch (linkstatus) { -+ case HFA384X_LINKSTATUS_CONNECTED: -+ return "Connected"; -+ case HFA384X_LINKSTATUS_DISCONNECTED: -+ return "Disconnected"; -+ case HFA384X_LINKSTATUS_AP_CHANGE: -+ return "Access point change"; -+ case HFA384X_LINKSTATUS_AP_OUT_OF_RANGE: -+ return "Access point out of range"; -+ case HFA384X_LINKSTATUS_AP_IN_RANGE: -+ return "Access point in range"; -+ case HFA384X_LINKSTATUS_ASSOC_FAILED: -+ return "Association failed"; -+ default: -+ return "Unknown"; -+ } -+} -+#endif /* PRISM2_NO_DEBUG */ -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_info_linkstatus(local_info_t *local, unsigned char *buf, -+ int left) -+{ -+ u16 val; -+ int non_sta_mode; -+ -+ /* Alloc new JoinRequests to occur since LinkStatus for the previous -+ * has been received */ -+ local->last_join_time = 0; -+ -+ if (left != 2) { -+ printk(KERN_DEBUG "%s: invalid linkstatus info frame " -+ "length %d\n", local->dev->name, left); -+ return; -+ } -+ -+ non_sta_mode = local->iw_mode == IW_MODE_MASTER || -+ local->iw_mode == IW_MODE_REPEAT || -+ local->iw_mode == IW_MODE_MONITOR; -+ -+ val = buf[0] | (buf[1] << 8); -+ if (!non_sta_mode || val != HFA384X_LINKSTATUS_DISCONNECTED) { -+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus=%d (%s)\n", -+ local->dev->name, val, hfa384x_linkstatus_str(val)); -+ } -+ -+ if (non_sta_mode) -+ return; -+ -+ /* Get current BSSID later in scheduled task */ -+ set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info); -+ local->prev_link_status = val; -+ PRISM2_SCHEDULE_TASK(&local->info_queue); -+} -+ -+ -+static void prism2_host_roaming(local_info_t *local) -+{ -+ struct hfa384x_join_request req; -+ struct net_device *dev = local->dev; -+ struct hfa384x_scan_result *selected, *entry; -+ int i; -+ unsigned long flags; -+ -+ if (local->last_join_time && -+ time_before(jiffies, local->last_join_time + 10 * HZ)) { -+ PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been " -+ "completed - waiting for it before issuing new one\n", -+ dev->name); -+ return; -+ } -+ -+ /* ScanResults are sorted: first ESS results in decreasing signal -+ * quality then IBSS results in similar order. -+ * Trivial roaming policy: just select the first entry. -+ * This could probably be improved by adding hysteresis to limit -+ * number of handoffs, etc. -+ * -+ * Could do periodic RID_SCANREQUEST or Inquire F101 to get new -+ * ScanResults */ -+ spin_lock_irqsave(&local->lock, flags); -+ if (local->last_scan_results == NULL || -+ local->last_scan_results_count == 0) { -+ spin_unlock_irqrestore(&local->lock, flags); -+ PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n", -+ dev->name); -+ return; -+ } -+ -+ selected = &local->last_scan_results[0]; -+ -+ if (local->preferred_ap[0] || local->preferred_ap[1] || -+ local->preferred_ap[2] || local->preferred_ap[3] || -+ local->preferred_ap[4] || local->preferred_ap[5]) { -+ /* Try to find preferred AP */ -+ PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n", -+ dev->name, MAC2STR(local->preferred_ap)); -+ for (i = 0; i < local->last_scan_results_count; i++) { -+ entry = &local->last_scan_results[i]; -+ if (memcmp(local->preferred_ap, entry->bssid, 6) == 0) -+ { -+ PDEBUG(DEBUG_EXTRA, "%s: using preferred AP " -+ "selection\n", dev->name); -+ selected = entry; -+ break; -+ } -+ } -+ } -+ -+ memcpy(req.bssid, selected->bssid, 6); -+ req.channel = selected->chid; -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+ PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n", -+ dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel)); -+ if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req, -+ sizeof(req))) { -+ printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name); -+ } -+ local->last_join_time = jiffies; -+} -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_info_scanresults(local_info_t *local, unsigned char *buf, -+ int left) -+{ -+ u16 *pos; -+ int new_count; -+ unsigned long flags; -+ -+ if (left < 4) { -+ printk(KERN_DEBUG "%s: invalid scanresult info frame " -+ "length %d\n", local->dev->name, left); -+ return; -+ } -+ -+ PDEBUG(DEBUG_EXTRA, "%s: ScanResults:", local->dev->name); -+ pos = (u16 *) buf; -+ PDEBUG2(DEBUG_EXTRA, " Reserved=0x%04x", le16_to_cpu(*pos)); -+ pos++; -+ PDEBUG2(DEBUG_EXTRA, " ScanReason=%d\n", le16_to_cpu(*pos)); -+ pos++; -+ left -= 4; -+ -+ /* Reserve large enough buffer to fit all ScanResults entries. -+ * If the previous buffer is large enough, do not free and re-allocate -+ * unnecessarily. This forgets the original buffer size, so -+ * re-allocation is used when more APs are found. */ -+ new_count = left / sizeof(struct hfa384x_scan_result); -+ spin_lock_irqsave(&local->lock, flags); -+ if (local->last_scan_results == NULL || -+ local->last_scan_results_count < new_count) { -+ if (local->last_scan_results) -+ kfree(local->last_scan_results); -+ local->last_scan_results = -+ kmalloc(new_count * sizeof(struct hfa384x_scan_result), -+ GFP_ATOMIC); -+ if (local->last_scan_results == NULL) { -+ local->last_scan_results_count = 0; -+ spin_unlock_irqrestore(&local->lock, flags); -+ printk(KERN_DEBUG "%s: could not kmalloc memory for " -+ "scan results\n", local->dev->name); -+ return; -+ } -+ } -+ local->last_scan_results_count = new_count; -+ memcpy(local->last_scan_results, pos, -+ new_count * sizeof(struct hfa384x_scan_result)); -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+ /* Perform rest of ScanResults handling later in scheduled task */ -+ set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info); -+ PRISM2_SCHEDULE_TASK(&local->info_queue); -+} -+ -+ -+#ifndef PRISM2_NO_DEBUG -+/* Called only as a tasklet (software IRQ) */ -+static void prism2_info_hostscanresults(local_info_t *local, -+ unsigned char *buf, int left) -+{ -+ u16 *pos, val, result_size; -+ u8 *ptr; -+ int i; -+ -+ wake_up_interruptible(&local->hostscan_wq); -+ -+ if (left < 4) { -+ printk(KERN_DEBUG "%s: invalid hostscanresult info frame " -+ "length %d\n", local->dev->name, left); -+ return; -+ } -+ -+ pos = (u16 *) buf; -+ result_size = le16_to_cpu(*pos); -+ -+ PDEBUG(DEBUG_EXTRA, "%s: HostScanResults (%d):\n", local->dev->name, -+ (left - 4) / result_size); -+ PDEBUG(DEBUG_EXTRA, " ResultSize=0x%04x\n", result_size); -+ pos++; -+ PDEBUG(DEBUG_EXTRA, " Reserved=%u\n", le16_to_cpu(*pos)); -+ pos++; -+ left -= 4; -+ ptr = (u8 *) pos; -+ -+ val = 1; -+ while (left >= result_size) { -+ struct hfa384x_hostscan_result *scan; -+ u16 len; -+ -+ PDEBUG(DEBUG_EXTRA, " Host Scan Result %u\n", val); -+ scan = (struct hfa384x_hostscan_result *) ptr; -+ left -= result_size; -+ ptr += result_size; -+ val++; -+ -+ if (result_size == sizeof(*scan)) { -+ PDEBUG(DEBUG_EXTRA, " CHID=%d ANL=%d SL=%d BSSID=" -+ MACSTR " BeaconInt=%d\n", -+ le16_to_cpu(scan->chid), -+ (signed short) le16_to_cpu(scan->anl), -+ (signed short) le16_to_cpu(scan->sl), -+ MAC2STR(scan->bssid), -+ le16_to_cpu(scan->beacon_interval)); -+ PDEBUG(DEBUG_EXTRA, " Capability=0x%x", -+ le16_to_cpu(scan->capability)); -+ len = le16_to_cpu(scan->ssid_len); -+ if (len > 0 && len < sizeof(scan->ssid)) { -+ PDEBUG2(DEBUG_EXTRA, " SSID[%d]=", len); -+ for (i = 0; i < len; i++) { -+ PDEBUG2(DEBUG_EXTRA, -+ (scan->ssid[i] < 32 || -+ scan->ssid[i] >= 127) ? -+ "<%02x>" : "%c", -+ scan->ssid[i]); -+ } -+ } -+ PDEBUG2(DEBUG_EXTRA, "\n"); -+ PDEBUG(DEBUG_EXTRA, " SUP_RATES="); -+ for (i = 0; i < sizeof(scan->sup_rates); i++) -+ if (scan->sup_rates[i]) -+ PDEBUG2(DEBUG_EXTRA, "<%02x>", -+ scan->sup_rates[i]); -+ PDEBUG2(DEBUG_EXTRA, " RATE=%d ATIM=%d\n", -+ le16_to_cpu(scan->rate), -+ le16_to_cpu(scan->atim)); -+ } -+ } -+ if (left) { -+ PDEBUG(DEBUG_EXTRA, " Unknown extra data: "); -+ for (i = 0; i < left; i++) -+ PDEBUG2(DEBUG_EXTRA, " %02x", *ptr++); -+ PDEBUG2(DEBUG_EXTRA, "\n"); -+ } -+} -+#endif /* PRISM2_NO_DEBUG */ -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ -+/* Called only as a tasklet (software IRQ) */ -+void hostap_info_process(local_info_t *local, struct sk_buff *skb) -+{ -+ struct hfa384x_info_frame *info; -+ unsigned char *buf; -+ int left; -+#ifndef PRISM2_NO_DEBUG -+ int i; -+#endif /* PRISM2_NO_DEBUG */ -+ -+ info = (struct hfa384x_info_frame *) skb->data; -+ buf = skb->data + sizeof(*info); -+ left = skb->len - sizeof(*info); -+ -+ switch (info->type) { -+ case HFA384X_INFO_COMMTALLIES: -+ prism2_info_commtallies(local, buf, left); -+ break; -+ -+#ifndef PRISM2_NO_STATION_MODES -+ case HFA384X_INFO_LINKSTATUS: -+ prism2_info_linkstatus(local, buf, left); -+ break; -+ -+ case HFA384X_INFO_SCANRESULTS: -+ prism2_info_scanresults(local, buf, left); -+ break; -+ -+#ifndef PRISM2_NO_DEBUG -+ case HFA384X_INFO_HOSTSCANRESULTS: -+ prism2_info_hostscanresults(local, buf, left); -+ break; -+#endif /* PRISM2_NO_DEBUG */ -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+#ifndef PRISM2_NO_DEBUG -+ default: -+ PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n", -+ local->dev->name, info->len, info->type); -+ PDEBUG(DEBUG_EXTRA, "Unknown info frame:"); -+ for (i = 0; i < (left < 100 ? left : 100); i++) -+ PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]); -+ PDEBUG2(DEBUG_EXTRA, "\n"); -+ break; -+#endif /* PRISM2_NO_DEBUG */ -+ } -+} -+ -+ -+#ifndef PRISM2_NO_STATION_MODES -+static void handle_info_queue_linkstatus(local_info_t *local) -+{ -+ int val = local->prev_link_status; -+ int connected; -+ -+ connected = -+ val == HFA384X_LINKSTATUS_CONNECTED || -+ val == HFA384X_LINKSTATUS_AP_CHANGE || -+ val == HFA384X_LINKSTATUS_AP_IN_RANGE; -+ -+ if (local->func->get_rid(local->dev, HFA384X_RID_CURRENTBSSID, -+ local->bssid, ETH_ALEN, 1) < 0) { -+ printk(KERN_DEBUG "%s: could not read CURRENTBSSID after " -+ "LinkStatus event\n", local->dev->name); -+ } else { -+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=" MACSTR "\n", -+ local->dev->name, -+ MAC2STR((unsigned char *) local->bssid)); -+ if (local->wds_type & HOSTAP_WDS_AP_CLIENT) -+ hostap_add_sta(local->ap, local->bssid); -+ } -+ -+#if WIRELESS_EXT > 13 -+ { -+ union iwreq_data wrqu; -+ -+ /* Get BSSID if we have a valid AP address */ -+ if (connected) -+ memcpy(wrqu.ap_addr.sa_data, local->bssid, ETH_ALEN); -+ else -+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); -+ wrqu.ap_addr.sa_family = ARPHRD_ETHER; -+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); -+ } -+#endif /* WIRELESS_EXT > 13 */ -+} -+ -+ -+static void handle_info_queue_scanresults(local_info_t *local) -+{ -+ if (local->host_roaming && local->iw_mode == IW_MODE_INFRA) -+ prism2_host_roaming(local); -+ -+#if WIRELESS_EXT > 13 -+ { -+ union iwreq_data wrqu; -+ -+ /* Inform user space about new scan results (just empty event, -+ * SIOCGIWSCAN can be used to fetch data */ -+ wrqu.data.length = 0; -+ wrqu.data.flags = 0; -+ wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL); -+ -+ /* Allow SIOCGIWSCAN handling to occur since we have received -+ * scanning result */ -+ local->scan_timestamp = 0; -+ } -+#endif /* WIRELESS_EXT > 13 */ -+} -+ -+ -+/* Called only as scheduled task after receiving info frames (used to avoid -+ * pending too much time in HW IRQ handler). */ -+static void handle_info_queue(void *data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ -+ if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS, -+ &local->pending_info)) -+ handle_info_queue_linkstatus(local); -+ -+ if (test_and_clear_bit(PRISM2_INFO_PENDING_SCANRESULTS, -+ &local->pending_info)) -+ handle_info_queue_scanresults(local); -+ -+#ifndef NEW_MODULE_CODE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ -+void hostap_info_init(local_info_t *local) -+{ -+ skb_queue_head_init(&local->info_list); -+#ifndef PRISM2_NO_STATION_MODES -+ HOSTAP_QUEUE_INIT(&local->info_queue, handle_info_queue, local); -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+ -+EXPORT_SYMBOL(hostap_info_init); -+EXPORT_SYMBOL(hostap_info_process); - -Index: drivers/net/wireless/hostap_ioctl.c ---- drivers/net/wireless/hostap_ioctl.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_ioctl.c 2003-07-10 22:49:55.000000000 -0400 -@@ -0,0 +1,3592 @@ -+/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */ -+ -+#ifdef in_atomic -+/* Get kernel_locked() for in_atomic() */ -+#include -+#endif -+ -+#ifdef WIRELESS_EXT -+ -+/* Conversion to new driver API by Jean II */ -+ -+#if WIRELESS_EXT <= 12 -+/* Wireless extensions backward compatibility */ -+ -+/* Dummy prototype, as we don't really need it */ -+struct iw_request_info; -+#endif /* WIRELESS_EXT <= 12 */ -+ -+ -+#if WIRELESS_EXT >= 15 -+/* Wireless ext ver15 allows verification of iwpriv support and sub-ioctls can -+ * be included even if not especially configured. */ -+#ifndef PRISM2_USE_WE_SUB_IOCTLS -+#define PRISM2_USE_WE_SUB_IOCTLS -+#endif /* PRISM2_USE_WE_SUB_IOCTLS */ -+ -+/* Assume that hosts using new wireless ext also have new wireless tools -+ * (ver >= 25) */ -+#ifndef PRISM2_USE_WE_TYPE_ADDR -+#define PRISM2_USE_WE_TYPE_ADDR -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+#endif /* WIRELESS_EXT >= 15 */ -+ -+ -+#ifdef PRISM2_USE_WE_TYPE_ADDR -+/* Added in WIRELESS_EXT 15, but can be used with older versions assuming -+ * iwpriv ver >= 25 */ -+#ifndef IW_PRIV_TYPE_ADDR -+#define IW_PRIV_TYPE_ADDR 0x6000 -+#endif /* IW_PRIV_TYPE_ADDR */ -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+ -+ -+#if WIRELESS_EXT < 9 -+struct iw_point { -+ caddr_t pointer; -+ __u16 length; -+ __u16 flags; -+}; -+#endif /* WIRELESS_EXT < 9 */ -+ -+ -+static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ local->wstats.status = 0; -+ local->wstats.discard.code = -+ local->comm_tallies.rx_discards_wep_undecryptable; -+ local->wstats.discard.misc = -+ local->comm_tallies.rx_fcs_errors + -+ local->comm_tallies.rx_discards_no_buffer + -+ local->comm_tallies.tx_discards_wrong_sa; -+ -+#if WIRELESS_EXT > 11 -+ local->wstats.discard.retries = -+ local->comm_tallies.tx_retry_limit_exceeded; -+ local->wstats.discard.fragment = -+ local->comm_tallies.rx_message_in_bad_msg_fragments; -+#endif /* WIRELESS_EXT > 11 */ -+ -+ if (local->iw_mode != IW_MODE_MASTER && -+ local->iw_mode != IW_MODE_REPEAT) { -+ struct hfa384x_comms_quality sq; -+#ifdef in_atomic -+ /* FIX: get_rid() will sleep and it must not be called -+ * in interrupt context or while atomic. However, this -+ * function seems to be called while atomic (at least in Linux -+ * 2.5.59). Now, we just avoid illegal call, but in this case -+ * the signal quality values are not shown. Statistics could be -+ * collected before, if this really needs to be called while -+ * atomic. */ -+ if (in_atomic()) { -+ printk(KERN_DEBUG "%s: hostap_get_wireless_stats() " -+ "called while atomic - skipping signal " -+ "quality query\n", dev->name); -+ } else -+#endif /* in_atomic */ -+ if (local->func->get_rid(local->dev, -+ HFA384X_RID_COMMSQUALITY, -+ &sq, sizeof(sq), 1) >= 0) { -+ local->wstats.qual.qual = le16_to_cpu(sq.comm_qual); -+ local->wstats.qual.level = HFA384X_LEVEL_TO_dBm( -+ le16_to_cpu(sq.signal_level)); -+ local->wstats.qual.noise = HFA384X_LEVEL_TO_dBm( -+ le16_to_cpu(sq.noise_level)); -+ local->wstats.qual.updated = 7; -+ } -+ } -+ -+ return &local->wstats; -+} -+ -+ -+static int prism2_get_datarates(struct net_device *dev, u8 *rates) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u8 buf[12]; -+ int len; -+ u16 val; -+ -+ len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf, -+ sizeof(buf), 0); -+ if (len < 2) -+ return 0; -+ -+ val = le16_to_cpu(*(u16 *) buf); /* string length */ -+ -+ if (len - 2 < val || val > 10) -+ return 0; -+ -+ memcpy(rates, buf + 2, val); -+ return val; -+} -+ -+ -+static int prism2_get_name(struct net_device *dev, -+ struct iw_request_info *info, -+ char *name, char *extra) -+{ -+ u8 rates[10]; -+ int len, i, over2 = 0; -+ -+ len = prism2_get_datarates(dev, rates); -+ -+ for (i = 0; i < len; i++) { -+ if (rates[i] == 0x0b || rates[i] == 0x16) { -+ over2 = 1; -+ break; -+ } -+ } -+ -+ strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS"); -+ -+ return 0; -+} -+ -+ -+static void prism2_crypt_delayed_deinit(local_info_t *local, -+ struct prism2_crypt_data **crypt) -+{ -+ struct prism2_crypt_data *tmp; -+ unsigned long flags; -+ -+ tmp = *crypt; -+ *crypt = NULL; -+ -+ if (tmp == NULL) -+ return; -+ -+ /* must not run ops->deinit() while there may be pending encrypt or -+ * decrypt operations. Use a list of delayed deinits to avoid needing -+ * locking. */ -+ -+ spin_lock_irqsave(&local->lock, flags); -+ list_add(&tmp->list, &local->crypt_deinit_list); -+ if (!timer_pending(&local->crypt_deinit_timer)) { -+ local->crypt_deinit_timer.expires = jiffies + HZ; -+ add_timer(&local->crypt_deinit_timer); -+ } -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+ -+#if WIRELESS_EXT > 8 -+static int prism2_ioctl_siwencode(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *erq, char *keybuf) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int i; -+ int first = 0; -+ -+ if (erq->flags & IW_ENCODE_DISABLED) { -+ prism2_crypt_delayed_deinit(local, &local->crypt); -+ goto done; -+ } -+ -+ if (local->crypt != NULL && local->crypt->ops != NULL && -+ strcmp(local->crypt->ops->name, "WEP") != 0) { -+ /* changing to use WEP; deinit previously used algorithm */ -+ prism2_crypt_delayed_deinit(local, &local->crypt); -+ } -+ -+ if (local->crypt == NULL) { -+ struct prism2_crypt_data *new_crypt; -+ -+ /* take WEP into use */ -+ new_crypt = (struct prism2_crypt_data *) -+ kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL); -+ if (new_crypt == NULL) -+ return -ENOMEM; -+ memset(new_crypt, 0, sizeof(struct prism2_crypt_data)); -+ new_crypt->ops = hostap_get_crypto_ops("WEP"); -+ if (!new_crypt->ops) { -+ request_module("hostap_crypt_wep"); -+ new_crypt->ops = hostap_get_crypto_ops("WEP"); -+ } -+ if (new_crypt->ops) -+ new_crypt->priv = new_crypt->ops->init(); -+ if (!new_crypt->ops || !new_crypt->priv) { -+ kfree(new_crypt); -+ new_crypt = NULL; -+ -+ printk(KERN_WARNING "%s: could not initialize WEP: " -+ "load module hostap_crypt_wep.o\n", -+ dev->name); -+ return -EOPNOTSUPP; -+ } -+ first = 1; -+ local->crypt = new_crypt; -+ } -+ -+ i = erq->flags & IW_ENCODE_INDEX; -+ if (i < 1 || i > 4) -+ i = local->crypt->ops->get_key_idx(local->crypt->priv); -+ else -+ i--; -+ if (i < 0 || i >= WEP_KEYS) -+ return -EINVAL; -+ -+ if (erq->length > 0) { -+ int len = erq->length <= 5 ? 5 : 13; -+ if (len > erq->length) -+ memset(keybuf + erq->length, 0, len - erq->length); -+ local->crypt->ops->set_key(i, keybuf, len, local->crypt->priv); -+ if (first) -+ local->crypt->ops->set_key_idx(i, local->crypt->priv); -+ } else { -+ if (local->crypt->ops->set_key_idx(i, local->crypt->priv) < 0) -+ return -EINVAL; /* keyidx not valid */ -+ } -+ -+ done: -+ local->open_wep = erq->flags & IW_ENCODE_OPEN; -+ -+ if (hostap_set_encryption(local)) { -+ printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name); -+ return -EINVAL; -+ } -+ -+ /* Do not reset port0 if card is in Managed mode since resetting will -+ * generate new IEEE 802.11 authentication which may end up in looping -+ * with IEEE 802.1X. Prism2 documentation seem to require port reset -+ * after WEP configuration. However, keys are apparently changed at -+ * least in Managed mode. */ -+ if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) { -+ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_giwencode(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *erq, char *key) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int i, len; -+ u16 val; -+ -+ if (local->crypt == NULL || local->crypt->ops == NULL) { -+ erq->length = 0; -+ erq->flags = IW_ENCODE_DISABLED; -+ return 0; -+ } -+ -+ if (strcmp(local->crypt->ops->name, "WEP") != 0) { -+ /* only WEP is supported with wireless extensions, so just -+ * report that encryption is used */ -+ erq->length = 0; -+ erq->flags = IW_ENCODE_ENABLED; -+ return 0; -+ } -+ -+ i = erq->flags & IW_ENCODE_INDEX; -+ if (i < 1 || i > 4) -+ i = local->crypt->ops->get_key_idx(local->crypt->priv); -+ else -+ i--; -+ if (i < 0 || i >= WEP_KEYS) -+ return -EINVAL; -+ -+ erq->flags = i + 1; -+ -+ /* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show -+ * the keys from driver buffer */ -+ len = local->crypt->ops->get_key(i, key, WEP_KEY_LEN, -+ local->crypt->priv); -+ erq->length = (len >= 0 ? len : 0); -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0) -+ { -+ printk("CNFWEPFLAGS reading failed\n"); -+ return -EOPNOTSUPP; -+ } -+ le16_to_cpus(&val); -+ if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED) -+ erq->flags |= IW_ENCODE_ENABLED; -+ else -+ erq->flags |= IW_ENCODE_DISABLED; -+ if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED) -+ erq->flags |= IW_ENCODE_RESTRICTED; -+ else -+ erq->flags |= IW_ENCODE_OPEN; -+ -+ return 0; -+} -+ -+ -+#if WIRELESS_EXT <= 15 -+static int prism2_ioctl_giwspy(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *srq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct sockaddr addr[IW_MAX_SPY]; -+ struct iw_quality qual[IW_MAX_SPY]; -+ -+ if (local->iw_mode != IW_MODE_MASTER) { -+ printk("SIOCGIWSPY is currently only supported in Host AP " -+ "mode\n"); -+ srq->length = 0; -+ return -EOPNOTSUPP; -+ } -+ -+ srq->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_SPY, 0); -+ -+ memcpy(extra, &addr, sizeof(addr[0]) * srq->length); -+ memcpy(extra + sizeof(addr[0]) * srq->length, &qual, -+ sizeof(qual[0]) * srq->length); -+ -+ return 0; -+} -+#endif /* WIRELESS_EXT <= 15 */ -+ -+ -+static int hostap_set_rate(struct net_device *dev) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret; -+ -+ ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL, -+ local->tx_rate_control) || -+ hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES, -+ local->tx_rate_control) || -+ local->func->reset_port(dev)); -+ -+ if (ret) { -+ printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates " -+ "setting to 0x%x failed\n", -+ dev->name, local->tx_rate_control); -+ } -+ -+ /* Update TX rate configuration for all STAs based on new operational -+ * rate set. */ -+ hostap_update_rates(local); -+ -+ return ret; -+} -+ -+ -+static int prism2_ioctl_siwrate(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (rrq->fixed) { -+ switch (rrq->value) { -+ case 11000000: -+ local->tx_rate_control = HFA384X_RATES_11MBPS; -+ break; -+ case 5500000: -+ local->tx_rate_control = HFA384X_RATES_5MBPS; -+ break; -+ case 2000000: -+ local->tx_rate_control = HFA384X_RATES_2MBPS; -+ break; -+ case 1000000: -+ local->tx_rate_control = HFA384X_RATES_1MBPS; -+ break; -+ default: -+ local->tx_rate_control = HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | -+ HFA384X_RATES_11MBPS; -+ break; -+ } -+ } else { -+ switch (rrq->value) { -+ case 11000000: -+ local->tx_rate_control = HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | -+ HFA384X_RATES_11MBPS; -+ break; -+ case 5500000: -+ local->tx_rate_control = HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS; -+ break; -+ case 2000000: -+ local->tx_rate_control = HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS; -+ break; -+ case 1000000: -+ local->tx_rate_control = HFA384X_RATES_1MBPS; -+ break; -+ default: -+ local->tx_rate_control = HFA384X_RATES_1MBPS | -+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | -+ HFA384X_RATES_11MBPS; -+ break; -+ } -+ } -+ -+ return hostap_set_rate(dev); -+} -+ -+ -+static int prism2_ioctl_giwrate(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ u16 val; -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret = 0; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) < -+ 0) -+ return -EINVAL; -+ -+ if ((val & 0x1) && (val > 1)) -+ rrq->fixed = 0; -+ else -+ rrq->fixed = 1; -+ -+ if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL && -+ !local->fw_tx_rate_control) { -+ /* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in -+ * Host AP mode, so use the recorded TX rate of the last sent -+ * frame */ -+ rrq->value = local->ap->last_tx_rate > 0 ? -+ local->ap->last_tx_rate * 100000 : 11000000; -+ return 0; -+ } -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) < -+ 0) -+ return -EINVAL; -+ -+ switch (val) { -+ case HFA384X_RATES_1MBPS: -+ rrq->value = 1000000; -+ break; -+ case HFA384X_RATES_2MBPS: -+ rrq->value = 2000000; -+ break; -+ case HFA384X_RATES_5MBPS: -+ rrq->value = 5500000; -+ break; -+ case HFA384X_RATES_11MBPS: -+ rrq->value = 11000000; -+ break; -+ default: -+ /* should not happen */ -+ rrq->value = 11000000; -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+ -+static int prism2_ioctl_siwsens(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *sens, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ /* Set the desired AP density */ -+ if (sens->value < 1 || sens->value > 3) -+ return -EINVAL; -+ -+ if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) || -+ local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwsens(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *sens, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ /* Get the current AP density */ -+ if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) < -+ 0) -+ return -EINVAL; -+ -+ sens->value = __le16_to_cpu(val); -+ sens->fixed = 1; -+ -+ return 0; -+} -+ -+ -+/* Deprecated in new wireless extension API */ -+static int prism2_ioctl_giwaplist(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct sockaddr addr[IW_MAX_AP]; -+ struct iw_quality qual[IW_MAX_AP]; -+ -+ if (local->iw_mode != IW_MODE_MASTER) { -+ printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported " -+ "in Host AP mode\n"); -+ data->length = 0; -+ return -EOPNOTSUPP; -+ } -+ -+ data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1); -+ -+ memcpy(extra, &addr, sizeof(addr[0]) * data->length); -+ data->flags = 1; /* has quality information */ -+ memcpy(extra + sizeof(addr[0]) * data->length, &qual, -+ sizeof(qual[0]) * data->length); -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_siwrts(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rts, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ if (rts->disabled) -+ val = __constant_cpu_to_le16(2347); -+ else if (rts->value < 0 || rts->value > 2347) -+ return -EINVAL; -+ else -+ val = __cpu_to_le16(rts->value); -+ -+ if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) || -+ local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwrts(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rts, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) < -+ 0) -+ return -EINVAL; -+ -+ rts->value = __le16_to_cpu(val); -+ rts->disabled = (rts->value == 2347); -+ rts->fixed = 1; -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_siwfrag(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rts, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ if (rts->disabled) -+ val = __constant_cpu_to_le16(2346); -+ else if (rts->value < 256 || rts->value > 2346) -+ return -EINVAL; -+ else -+ val = __cpu_to_le16(rts->value & ~0x1); /* even numbers only */ -+ -+ if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val, -+ 2) -+ || local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwfrag(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rts, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, -+ &val, 2, 1) < 0) -+ return -EINVAL; -+ -+ rts->value = __le16_to_cpu(val); -+ rts->disabled = (rts->value == 2346); -+ rts->fixed = 1; -+ -+ return 0; -+} -+#endif /* WIRELESS_EXT > 8 */ -+ -+ -+static int prism2_ioctl_siwap(struct net_device *dev, -+ struct iw_request_info *info, -+ struct sockaddr *ap_addr, char *extra) -+{ -+#ifdef PRISM2_NO_STATION_MODES -+ return -EOPNOTSUPP; -+#else /* PRISM2_NO_STATION_MODES */ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN); -+ -+ if (local->host_roaming && local->iw_mode == IW_MODE_INFRA) { -+ struct hfa384x_scan_request scan_req; -+ memset(&scan_req, 0, sizeof(scan_req)); -+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff); -+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS); -+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, -+ &scan_req, sizeof(scan_req))) { -+ printk(KERN_DEBUG "%s: ScanResults request failed - " -+ "preferred AP delayed to next unsolicited " -+ "scan\n", dev->name); -+ } -+ } else { -+ printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only " -+ "in Managed mode when host_roaming is enabled\n", -+ dev->name); -+ } -+ -+ return 0; -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+static int prism2_ioctl_giwap(struct net_device *dev, -+ struct iw_request_info *info, -+ struct sockaddr *ap_addr, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (dev == local->stadev) { -+ memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN); -+ ap_addr->sa_family = ARPHRD_ETHER; -+ return 0; -+ } -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID, -+ &ap_addr->sa_data, ETH_ALEN, 1) < 0) -+ return -EOPNOTSUPP; -+ -+ /* local->bssid is also updated in LinkStatus handler when in station -+ * mode */ -+ memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN); -+ ap_addr->sa_family = ARPHRD_ETHER; -+ -+ return 0; -+} -+ -+ -+#if WIRELESS_EXT > 8 -+static int prism2_ioctl_siwnickn(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *nickname) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ memset(local->name, 0, sizeof(local->name)); -+ memcpy(local->name, nickname, data->length); -+ local->name_set = 1; -+ -+ if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) || -+ local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwnickn(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *nickname) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int len; -+ char name[MAX_NAME_LEN + 3]; -+ u16 val; -+ -+ len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME, -+ &name, MAX_NAME_LEN + 2, 0); -+ val = __le16_to_cpu(*(u16 *) name); -+ if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN) -+ return -EOPNOTSUPP; -+ -+ name[val + 2] = '\0'; -+ data->length = val + 1; -+ memcpy(nickname, name + 2, val + 1); -+ -+ return 0; -+} -+#endif /* WIRELESS_EXT > 8 */ -+ -+ -+static int prism2_ioctl_siwfreq(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_freq *freq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ /* freq => chan. */ -+ if (freq->e == 1 && -+ freq->m / 100000 >= freq_list[0] && -+ freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) { -+ int ch; -+ int fr = freq->m / 100000; -+ for (ch = 0; ch < FREQ_COUNT; ch++) { -+ if (fr == freq_list[ch]) { -+ freq->e = 0; -+ freq->m = ch + 1; -+ break; -+ } -+ } -+ } -+ -+ if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT || -+ !(local->channel_mask & (1 << (freq->m - 1)))) -+ return -EINVAL; -+ -+ local->channel = freq->m; /* channel is used in prism2_setup_rids() */ -+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) || -+ local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwfreq(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_freq *freq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) < -+ 0) -+ return -EINVAL; -+ -+ le16_to_cpus(&val); -+ if (val < 1 || val > FREQ_COUNT) -+ return -EINVAL; -+ -+ freq->m = freq_list[val - 1] * 100000; -+ freq->e = 1; -+ -+ return 0; -+} -+ -+ -+static void hostap_monitor_set_type(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ -+ if (local->monitor_type == PRISM2_MONITOR_PRISM || -+ local->monitor_type == PRISM2_MONITOR_CAPHDR) { -+ dev->type = ARPHRD_IEEE80211_PRISM; -+ dev->hard_header_parse = -+ hostap_80211_prism_header_parse; -+ } else { -+ dev->type = ARPHRD_IEEE80211; -+ dev->hard_header_parse = hostap_80211_header_parse; -+ } -+} -+ -+ -+#if WIRELESS_EXT > 8 -+static int prism2_ioctl_siwessid(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *ssid) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (data->flags == 0) -+ ssid[0] = '\0'; /* ANY */ -+ -+ if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') { -+ /* Setting SSID to empty string seems to kill the card in -+ * Host AP mode */ -+ printk(KERN_DEBUG "%s: Host AP mode does not support " -+ "'Any' essid\n", dev->name); -+ return -EINVAL; -+ } -+ -+ memcpy(local->essid, ssid, IW_ESSID_MAX_SIZE); -+ local->essid[MAX_SSID_LEN] = '\0'; -+ -+ if ((!local->fw_ap && -+ hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid)) -+ || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) || -+ local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int prism2_ioctl_giwessid(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *essid) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 val; -+ -+ data->flags = 1; /* active */ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ data->length = strlen(local->essid); -+ memcpy(essid, local->essid, IW_ESSID_MAX_SIZE); -+ } else { -+ int len; -+ char ssid[MAX_SSID_LEN + 2]; -+ memset(ssid, 0, sizeof(ssid)); -+ len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID, -+ &ssid, MAX_SSID_LEN + 2, 0); -+ val = __le16_to_cpu(*(u16 *) ssid); -+ if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) { -+ return -EOPNOTSUPP; -+ } -+ data->length = val; -+ memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE); -+ } -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_giwrange(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ struct iw_range *range = (struct iw_range *) extra; -+ u8 rates[10]; -+ u16 val; -+ int i, len, over2; -+ -+ data->length = sizeof(struct iw_range); -+ memset(range, 0, sizeof(struct iw_range)); -+ -+#if WIRELESS_EXT > 9 -+ /* TODO: could fill num_txpower and txpower array with -+ * something; however, there are 128 different values.. */ -+ -+ range->txpower_capa = IW_TXPOW_DBM; -+ -+ if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC) -+ { -+ range->min_pmp = 1 * 1024; -+ range->max_pmp = 65535 * 1024; -+ range->min_pmt = 1 * 1024; -+ range->max_pmt = 1000 * 1024; -+ range->pmp_flags = IW_POWER_PERIOD; -+ range->pmt_flags = IW_POWER_TIMEOUT; -+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | -+ IW_POWER_UNICAST_R | IW_POWER_ALL_R; -+ } -+#endif /* WIRELESS_EXT > 9 */ -+ -+#if WIRELESS_EXT > 10 -+ range->we_version_compiled = WIRELESS_EXT; -+ range->we_version_source = 13; -+ -+ range->retry_capa = IW_RETRY_LIMIT; -+ range->retry_flags = IW_RETRY_LIMIT; -+ range->min_retry = 0; -+ range->max_retry = 255; -+#endif /* WIRELESS_EXT > 10 */ -+ -+ range->num_channels = FREQ_COUNT; -+ -+ val = 0; -+ for (i = 0; i < FREQ_COUNT; i++) { -+ if (local->channel_mask & (1 << i)) { -+ range->freq[val].i = i + 1; -+ range->freq[val].m = freq_list[i] * 100000; -+ range->freq[val].e = 1; -+ val++; -+ } -+ if (val == IW_MAX_FREQUENCIES) -+ break; -+ } -+ range->num_frequency = val; -+ -+ range->max_qual.qual = 92; /* 0 .. 92 */ -+ range->max_qual.level = 154; /* 27 .. 154 */ -+ range->max_qual.noise = 154; /* 27 .. 154 */ -+ range->sensitivity = 3; -+ -+ range->max_encoding_tokens = WEP_KEYS; -+ range->num_encoding_sizes = 2; -+ range->encoding_size[0] = 5; -+ range->encoding_size[1] = 13; -+ -+ over2 = 0; -+ len = prism2_get_datarates(dev, rates); -+ range->num_bitrates = 0; -+ for (i = 0; i < len; i++) { -+ if (range->num_bitrates < IW_MAX_BITRATES) { -+ range->bitrate[range->num_bitrates] = -+ rates[i] * 500000; -+ range->num_bitrates++; -+ } -+ if (rates[i] == 0x0b || rates[i] == 0x16) -+ over2 = 1; -+ } -+ /* estimated maximum TCP throughput values (bps) */ -+ range->throughput = over2 ? 5500000 : 1500000; -+ -+ range->min_rts = 0; -+ range->max_rts = 2347; -+ range->min_frag = 256; -+ range->max_frag = 2346; -+ -+ return 0; -+} -+ -+ -+static int hostap_monitor_mode_enable(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ -+ printk(KERN_DEBUG "Enabling monitor mode\n"); -+ hostap_monitor_set_type(local); -+ -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, -+ HFA384X_PORTTYPE_PSEUDO_IBSS)) { -+ printk(KERN_DEBUG "Port type setting for monitor mode " -+ "failed\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ /* Host decrypt is needed to get the IV and ICV fields; -+ * however, monitor mode seems to remove WEP flag from frame -+ * control field */ -+ if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS, -+ HFA384X_WEPFLAGS_HOSTENCRYPT | -+ HFA384X_WEPFLAGS_HOSTDECRYPT)) { -+ printk(KERN_DEBUG "WEP flags setting failed\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ if (local->func->reset_port(dev) || -+ local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_MONITOR << 8), -+ 0, NULL, NULL)) { -+ printk(KERN_DEBUG "Setting monitor mode failed\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+ -+static int hostap_monitor_mode_disable(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ -+ printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name); -+ dev->type = ARPHRD_ETHER; -+ dev->hard_header_parse = local->saved_eth_header_parse; -+ if (local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_STOP << 8), -+ 0, NULL, NULL)) -+ return -1; -+ return hostap_set_encryption(local); -+} -+ -+ -+static int prism2_ioctl_siwmode(struct net_device *dev, -+ struct iw_request_info *info, -+ __u32 *mode, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int double_reset = 0; -+ -+ if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && -+ *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT && -+ *mode != IW_MODE_MONITOR) -+ return -EOPNOTSUPP; -+ -+#ifdef PRISM2_NO_STATION_MODES -+ if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA) -+ return -EOPNOTSUPP; -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ if (*mode == local->iw_mode) -+ return 0; -+ -+ if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') { -+ printk(KERN_WARNING "%s: empty SSID not allowed in Master " -+ "mode\n", dev->name); -+ return -EINVAL; -+ } -+ -+ if (local->iw_mode == IW_MODE_MONITOR) -+ hostap_monitor_mode_disable(local); -+ -+ if (local->iw_mode == IW_MODE_ADHOC && *mode == IW_MODE_MASTER) { -+ /* There seems to be a firmware bug in at least STA f/w v1.5.6 -+ * that leaves beacon frames to use IBSS type when moving from -+ * IBSS to Host AP mode. Doing double Port0 reset seems to be -+ * enough to workaround this. */ -+ double_reset = 1; -+ } -+ -+ printk(KERN_DEBUG "prism2: %s: operating mode changed " -+ "%d -> %d\n", dev->name, local->iw_mode, *mode); -+ local->iw_mode = *mode; -+ -+ if (local->iw_mode == IW_MODE_MONITOR) -+ hostap_monitor_mode_enable(local); -+ else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt && -+ !local->fw_encrypt_ok) { -+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as " -+ "a workaround for firmware bug in Host AP mode WEP\n", -+ dev->name); -+ local->host_encrypt = 1; -+ } -+ -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, -+ hostap_get_porttype(local))) -+ return -EOPNOTSUPP; -+ -+ if (local->func->reset_port(dev)) -+ return -EINVAL; -+ if (double_reset && local->func->reset_port(dev)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_giwmode(struct net_device *dev, -+ struct iw_request_info *info, -+ __u32 *mode, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (dev == local->stadev) { -+ *mode = IW_MODE_INFRA; -+ return 0; -+ } -+ -+ *mode = local->iw_mode; -+ return 0; -+} -+ -+ -+static int prism2_ioctl_siwpower(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *wrq, char *extra) -+{ -+#ifdef PRISM2_NO_STATION_MODES -+ return -EOPNOTSUPP; -+#else /* PRISM2_NO_STATION_MODES */ -+ int ret = 0; -+ -+ if (wrq->disabled) -+ return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0); -+ -+ switch (wrq->flags & IW_POWER_MODE) { -+ case IW_POWER_UNICAST_R: -+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0); -+ if (ret) -+ return ret; -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); -+ if (ret) -+ return ret; -+ break; -+ case IW_POWER_ALL_R: -+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1); -+ if (ret) -+ return ret; -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); -+ if (ret) -+ return ret; -+ break; -+ case IW_POWER_ON: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (wrq->flags & IW_POWER_TIMEOUT) { -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); -+ if (ret) -+ return ret; -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION, -+ wrq->value / 1024); -+ if (ret) -+ return ret; -+ } -+ if (wrq->flags & IW_POWER_PERIOD) { -+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); -+ if (ret) -+ return ret; -+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION, -+ wrq->value / 1024); -+ if (ret) -+ return ret; -+ } -+ -+ return ret; -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+ -+static int prism2_ioctl_giwpower(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+#ifdef PRISM2_NO_STATION_MODES -+ return -EOPNOTSUPP; -+#else /* PRISM2_NO_STATION_MODES */ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 enable, mcast; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1) -+ < 0) -+ return -EINVAL; -+ -+ if (!__le16_to_cpu(enable)) { -+ rrq->disabled = 1; -+ return 0; -+ } -+ -+ rrq->disabled = 0; -+ -+ if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { -+ u16 timeout; -+ if (local->func->get_rid(dev, -+ HFA384X_RID_CNFPMHOLDOVERDURATION, -+ &timeout, 2, 1) < 0) -+ return -EINVAL; -+ -+ rrq->flags = IW_POWER_TIMEOUT; -+ rrq->value = __le16_to_cpu(timeout) * 1024; -+ } else { -+ u16 period; -+ if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION, -+ &period, 2, 1) < 0) -+ return -EINVAL; -+ -+ rrq->flags = IW_POWER_PERIOD; -+ rrq->value = __le16_to_cpu(period) * 1024; -+ } -+ -+ if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast, -+ 2, 1) < 0) -+ return -EINVAL; -+ -+ if (__le16_to_cpu(mcast)) -+ rrq->flags |= IW_POWER_ALL_R; -+ else -+ rrq->flags |= IW_POWER_UNICAST_R; -+ -+ return 0; -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+#endif /* WIRELESS_EXT > 8 */ -+ -+ -+#if WIRELESS_EXT > 10 -+static int prism2_ioctl_siwretry(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (rrq->disabled) -+ return -EINVAL; -+ -+ /* setting retry limits is not supported with the current station -+ * firmware code; simulate this with alternative retry count for now */ -+ if (rrq->flags == IW_RETRY_LIMIT) { -+ if (rrq->value < 0) { -+ /* disable manual retry count setting and use firmware -+ * defaults */ -+ local->manual_retry_count = -1; -+ local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY; -+ } else { -+ if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT, -+ rrq->value)) { -+ printk(KERN_DEBUG "%s: Alternate retry count " -+ "setting to %d failed\n", -+ dev->name, rrq->value); -+ return -EOPNOTSUPP; -+ } -+ -+ local->manual_retry_count = rrq->value; -+ local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY; -+ } -+ return 0; -+ } -+ -+ return -EOPNOTSUPP; -+ -+#if 0 -+ /* what could be done, if firmware would support this.. */ -+ -+ if (rrq->flags & IW_RETRY_LIMIT) { -+ if (rrq->flags & IW_RETRY_MAX) -+ HFA384X_RID_LONGRETRYLIMIT = rrq->value; -+ else if (rrq->flags & IW_RETRY_MIN) -+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value; -+ else { -+ HFA384X_RID_LONGRETRYLIMIT = rrq->value; -+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value; -+ } -+ -+ } -+ -+ if (rrq->flags & IW_RETRY_LIFETIME) { -+ HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024; -+ } -+ -+ return 0; -+#endif /* 0 */ -+} -+ -+static int prism2_ioctl_giwretry(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 shortretry, longretry, lifetime; -+ -+ if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry, -+ 2, 1) < 0 || -+ local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry, -+ 2, 1) < 0 || -+ local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME, -+ &lifetime, 2, 1) < 0) -+ return -EINVAL; -+ -+ le16_to_cpus(&shortretry); -+ le16_to_cpus(&longretry); -+ le16_to_cpus(&lifetime); -+ -+ rrq->disabled = 0; -+ -+ if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { -+ rrq->flags = IW_RETRY_LIFETIME; -+ rrq->value = lifetime * 1024; -+ } else { -+ if (local->manual_retry_count >= 0) { -+ rrq->flags = IW_RETRY_LIMIT; -+ rrq->value = local->manual_retry_count; -+ } else if ((rrq->flags & IW_RETRY_MAX)) { -+ rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; -+ rrq->value = longretry; -+ } else { -+ rrq->flags = IW_RETRY_LIMIT; -+ rrq->value = shortretry; -+ if (shortretry != longretry) -+ rrq->flags |= IW_RETRY_MIN; -+ } -+ } -+ return 0; -+} -+#endif /* WIRELESS_EXT > 10 */ -+ -+ -+#if WIRELESS_EXT > 9 -+/* Map HFA386x's CR31 to and from dBm with some sort of ad hoc mapping.. -+ * This version assumes following mapping: -+ * CR31 is 7-bit value with -64 to +63 range. -+ * -64 is mapped into +20dBm and +63 into -43dBm. -+ * This is certainly not an exact mapping for every card, but at least -+ * increasing dBm value should correspond to increasing TX power. -+ */ -+ -+static int prism2_txpower_hfa386x_to_dBm(u16 val) -+{ -+ signed char tmp; -+ -+ if (val > 255) -+ val = 255; -+ -+ tmp = val; -+ tmp >>= 2; -+ -+ return -12 - tmp; -+} -+ -+static u16 prism2_txpower_dBm_to_hfa386x(int val) -+{ -+ signed char tmp; -+ -+ if (val > 20) -+ return 128; -+ else if (val < -43) -+ return 127; -+ -+ tmp = val; -+ tmp = -12 - tmp; -+ tmp <<= 2; -+ -+ return (unsigned char) tmp; -+} -+ -+ -+static int prism2_ioctl_siwtxpow(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ char *tmp; -+ u16 val; -+ int ret = 0; -+ -+ if (rrq->disabled) { -+ if (local->txpower_type != PRISM2_TXPOWER_OFF) { -+ val = 0xff; /* use all standby and sleep modes */ -+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_A_D_TEST_MODES2, -+ &val, NULL); -+ printk(KERN_DEBUG "%s: Turning radio off: %s\n", -+ dev->name, ret ? "failed" : "OK"); -+ local->txpower_type = PRISM2_TXPOWER_OFF; -+ } -+ return (ret ? -EOPNOTSUPP : 0); -+ } -+ -+ if (local->txpower_type == PRISM2_TXPOWER_OFF) { -+ val = 0; /* disable all standby and sleep modes */ -+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_A_D_TEST_MODES2, &val, NULL); -+ printk(KERN_DEBUG "%s: Turning radio on: %s\n", -+ dev->name, ret ? "failed" : "OK"); -+ local->txpower_type = PRISM2_TXPOWER_UNKNOWN; -+ } -+ -+ if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) { -+ printk(KERN_DEBUG "Setting ALC on\n"); -+ val = HFA384X_TEST_CFG_BIT_ALC; -+ local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL); -+ local->txpower_type = PRISM2_TXPOWER_AUTO; -+ return 0; -+ } -+ -+ if (local->txpower_type != PRISM2_TXPOWER_FIXED) { -+ printk(KERN_DEBUG "Setting ALC off\n"); -+ val = HFA384X_TEST_CFG_BIT_ALC; -+ local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL); -+ local->txpower_type = PRISM2_TXPOWER_FIXED; -+ } -+ -+ if (rrq->flags == IW_TXPOW_DBM) -+ tmp = "dBm"; -+ else if (rrq->flags == IW_TXPOW_MWATT) -+ tmp = "mW"; -+ else -+ tmp = "UNKNOWN"; -+ printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp); -+ -+ if (rrq->flags != IW_TXPOW_DBM) { -+ printk("SIOCSIWTXPOW with mW is not supported; use dBm\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ local->txpower = rrq->value; -+ val = prism2_txpower_dBm_to_hfa386x(local->txpower); -+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL)) -+ ret = -EOPNOTSUPP; -+ -+ return ret; -+} -+ -+static int prism2_ioctl_giwtxpow(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_param *rrq, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 resp0; -+ -+ rrq->flags = IW_TXPOW_DBM; -+ rrq->disabled = 0; -+ rrq->fixed = 0; -+ -+ if (local->txpower_type == PRISM2_TXPOWER_AUTO) { -+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, -+ HFA386X_CR_MANUAL_TX_POWER, -+ NULL, &resp0) == 0) { -+ rrq->value = prism2_txpower_hfa386x_to_dBm(resp0); -+ } else { -+ /* Could not get real txpower; guess 15 dBm */ -+ rrq->value = 15; -+ } -+ } else if (local->txpower_type == PRISM2_TXPOWER_OFF) { -+ rrq->value = 0; -+ rrq->disabled = 1; -+ } else if (local->txpower_type == PRISM2_TXPOWER_FIXED) { -+ rrq->value = local->txpower; -+ rrq->fixed = 1; -+ } else { -+ printk("SIOCGIWTXPOW - unknown txpower_type=%d\n", -+ local->txpower_type); -+ } -+ return 0; -+} -+#endif /* WIRELESS_EXT > 9 */ -+ -+ -+#if WIRELESS_EXT > 13 -+static int prism2_ioctl_siwscan(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+#ifndef PRISM2_NO_STATION_MODES -+ struct hfa384x_scan_request scan_req; -+ int ret = 0; -+#endif /* !PRISM2_NO_STATION_MODES */ -+ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ /* In master mode, we just return the results of our local -+ * tables, so we don't need to start anything... -+ * Jean II */ -+ data->length = 0; -+ return 0; -+ } -+ -+#ifdef PRISM2_NO_STATION_MODES -+ return -EOPNOTSUPP; -+#else /* PRISM2_NO_STATION_MODES */ -+ -+ memset(&scan_req, 0, sizeof(scan_req)); -+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff); -+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS); -+ -+ /* FIX: -+ * It seems to be enough to set roaming mode for a short moment to -+ * host-based and then setup scanrequest data and return the mode to -+ * firmware-based. -+ * -+ * Master mode would need to drop to Managed mode for a short while -+ * to make scanning work.. Or sweep through the different channels and -+ * use passive scan based on beacons. */ -+ -+ if (!local->host_roaming) -+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, -+ HFA384X_ROAMING_HOST); -+ -+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req, -+ sizeof(scan_req))) { -+ printk(KERN_DEBUG "SCANREQUEST failed\n"); -+ ret = -EINVAL; -+ } -+ -+ if (!local->host_roaming) -+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, -+ HFA384X_ROAMING_FIRMWARE); -+ -+ local->scan_timestamp = jiffies; -+ -+#if 0 -+ /* NOTE! longer hostscan_request struct! Additional ssid field (empty -+ * means any). HostScan would be better than "old scan" since it keeps -+ * old association status. However, it requires newer station firmware -+ * (1.3.x?). */ -+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req, -+ sizeof(scan_req))) { -+ printk(KERN_DEBUG "HOSTSCAN failed\n"); -+ return -EINVAL; -+ } -+#endif -+ -+ /* inquire F101, F103 or wait for SIOCGIWSCAN and read RID */ -+ -+ return ret; -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+ -+#ifndef PRISM2_NO_STATION_MODES -+/* Translate scan data returned from the card to a card independant -+ * format that the Wireless Tools will understand - Jean II */ -+static inline int prism2_translate_scan(struct net_device *dev, char *buffer, -+ char *scan, int scan_len) -+{ -+ struct hfa384x_scan_result *atom; -+ int left, i; -+ struct iw_event iwe; -+ char *current_ev = buffer; -+ char *end_buf = buffer + IW_SCAN_MAX_DATA; -+ char *current_val; -+ -+ left = scan_len; -+ -+ if (left % sizeof(*atom) != 0) { -+ printk(KERN_DEBUG "%s: invalid total scan result length %d " -+ "(entry length %d)\n", -+ dev->name, left, sizeof(*atom)); -+ return -EINVAL; -+ } -+ -+ atom = (struct hfa384x_scan_result *) scan; -+ while (left > 0) { -+ u16 capabilities; -+ -+ /* First entry *MUST* be the AP MAC address */ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWAP; -+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; -+ memcpy(iwe.u.ap_addr.sa_data, atom->bssid, ETH_ALEN); -+ /* FIX: -+ * I do not know how this is possible, but iwe_stream_add_event -+ * seems to re-order memcpy execution so that len is set only -+ * after copying.. Pre-setting len here "fixes" this, but real -+ * problems should be solved (after which these iwe.len -+ * settings could be removed from this function). */ -+ iwe.len = IW_EV_ADDR_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_ADDR_LEN); -+ -+ /* Other entries will be displayed in the order we give them */ -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWESSID; -+ iwe.u.data.length = le16_to_cpu(atom->ssid_len); -+ if (iwe.u.data.length > 32) -+ iwe.u.data.length = 32; -+ iwe.u.data.flags = 1; -+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; -+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, -+ atom->ssid); -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWMODE; -+ capabilities = le16_to_cpu(atom->capability); -+ if (capabilities & (WLAN_CAPABILITY_ESS | -+ WLAN_CAPABILITY_IBSS)) { -+ if (capabilities & WLAN_CAPABILITY_ESS) -+ iwe.u.mode = IW_MODE_MASTER; -+ else -+ iwe.u.mode = IW_MODE_ADHOC; -+ iwe.len = IW_EV_UINT_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, -+ &iwe, -+ IW_EV_UINT_LEN); -+ } -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWFREQ; -+ iwe.u.freq.m = freq_list[le16_to_cpu(atom->chid) - 1] * 100000; -+ iwe.u.freq.e = 1; -+ iwe.len = IW_EV_FREQ_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_FREQ_LEN); -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = IWEVQUAL; -+ iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(le16_to_cpu(atom->sl)); -+ iwe.u.qual.noise = -+ HFA384X_LEVEL_TO_dBm(le16_to_cpu(atom->anl)); -+ iwe.len = IW_EV_QUAL_LEN; -+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, -+ IW_EV_QUAL_LEN); -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWENCODE; -+ if (capabilities & WLAN_CAPABILITY_PRIVACY) -+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; -+ else -+ iwe.u.data.flags = IW_ENCODE_DISABLED; -+ iwe.u.data.length = 0; -+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; -+ current_ev = iwe_stream_add_point( -+ current_ev, end_buf, &iwe, -+ atom->ssid /* memcpy 0 bytes */); -+ -+ memset(&iwe, 0, sizeof(iwe)); -+ iwe.cmd = SIOCGIWRATE; -+ current_val = current_ev + IW_EV_LCP_LEN; -+ for (i = 0; i < sizeof(atom->sup_rates); i++) { -+ if (atom->sup_rates[i] == 0) -+ break; -+ /* Bit rate given in 500 kb/s units (+ 0x80) */ -+ iwe.u.bitrate.value = -+ ((atom->sup_rates[i] & 0x7f) * 500000); -+ current_val = iwe_stream_add_value( -+ current_ev, current_val, end_buf, &iwe, -+ IW_EV_PARAM_LEN); -+ } -+ /* Check if we added any event */ -+ if ((current_val - current_ev) > IW_EV_LCP_LEN) -+ current_ev = current_val; -+ -+ /* Could add beacon_interval and rate (of the received -+ * ProbeResp) to scan results. */ -+ -+ atom++; -+ left -= sizeof(*atom); -+ } -+ -+#if 0 -+ { -+ u8 *pos = buffer; -+ left = (current_ev - buffer); -+ printk(KERN_DEBUG "IW SCAN (len=%d):", left); -+ while (left > 0) { -+ printk(" %02x", *pos++); -+ left--; -+ } -+ printk("\n"); -+ } -+#endif -+ -+ return current_ev - buffer; -+} -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ -+static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *extra) -+{ -+#ifdef PRISM2_NO_STATION_MODES -+ return -EOPNOTSUPP; -+#else /* PRISM2_NO_STATION_MODES */ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res, maxlen, len, free_buffer = 1, offset; -+ char *buffer; -+ -+ /* Wait until the scan is finished. We can probably do better -+ * than that - Jean II */ -+ if (local->scan_timestamp && -+ time_before(jiffies, local->scan_timestamp + 3 * HZ)) { -+ /* Important note : we don't want to block the caller -+ * until results are ready for various reasons. -+ * First, managing wait queues is complex and racy -+ * (there may be multiple simultaneous callers). -+ * Second, we grab some rtnetlink lock before comming -+ * here (in dev_ioctl()). -+ * Third, the caller can wait on the Wireless Event -+ * - Jean II */ -+ return -EAGAIN; -+ } -+ local->scan_timestamp = 0; -+ -+ /* Maximum number of scan results on Prism2 is 32. This reserves -+ * enough buffer for all results. Other option would be to modify -+ * local->func->get_rid() to be able to allocate just the correct -+ * amount of memory based on RID header. */ -+ maxlen = sizeof(struct hfa384x_scan_result_hdr) + -+ sizeof(struct hfa384x_scan_result) * HFA384X_SCAN_MAX_RESULTS; -+ buffer = kmalloc(maxlen, GFP_KERNEL); -+ if (buffer == NULL) -+ return -ENOMEM; -+ -+ len = local->func->get_rid(dev, HFA384X_RID_SCANRESULTSTABLE, -+ buffer, maxlen, 0); -+ offset = sizeof(struct hfa384x_scan_result_hdr); -+ PDEBUG(DEBUG_EXTRA, "Scan len = %d (entry=%d)\n", -+ len, sizeof(struct hfa384x_scan_result)); -+ if (len < 0 || len < sizeof(struct hfa384x_scan_result_hdr)) { -+ kfree(buffer); -+ if (local->last_scan_results) { -+ PDEBUG(DEBUG_EXTRA, "Using last received ScanResults " -+ "info frame instead of RID\n"); -+ offset = 0; -+ len = local->last_scan_results_count * -+ sizeof(struct hfa384x_scan_result); -+ free_buffer = 0; -+ buffer = (char *) local->last_scan_results; -+ } else -+ return -EINVAL; -+ } -+ -+ /* Translate to WE format */ -+ res = prism2_translate_scan(dev, extra, buffer + offset, -+ len - offset); -+ if (free_buffer) -+ kfree(buffer); -+ -+ if (res >= 0) { -+ printk(KERN_DEBUG "Scan result translation succeeded " -+ "(length=%d)\n", res); -+ data->length = res; -+ return 0; -+ } else { -+ printk(KERN_DEBUG "Scan result translation failed (res=%d)\n", -+ res); -+ data->length = 0; -+ return res; -+ } -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+ -+static int prism2_ioctl_giwscan(struct net_device *dev, -+ struct iw_request_info *info, -+ struct iw_point *data, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int res; -+ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ /* In MASTER mode, it doesn't make sense to go around -+ * scanning the frequencies and make the stations we serve -+ * wait when what the user is really interested about is the -+ * list of stations and access points we are talking to. -+ * So, just extract results from our cache... -+ * Jean II */ -+ -+ /* Translate to WE format */ -+ res = prism2_ap_translate_scan(dev, extra); -+ if (res >= 0) { -+ printk(KERN_DEBUG "Scan result translation succeeded " -+ "(length=%d)\n", res); -+ data->length = res; -+ return 0; -+ } else { -+ printk(KERN_DEBUG -+ "Scan result translation failed (res=%d)\n", -+ res); -+ data->length = 0; -+ return res; -+ } -+ } else { -+ /* Station mode */ -+ return prism2_ioctl_giwscan_sta(dev, info, data, extra); -+ } -+} -+#endif /* WIRELESS_EXT > 13 */ -+ -+ -+#if WIRELESS_EXT > 8 -+static const struct iw_priv_args prism2_priv[] = { -+ { PRISM2_IOCTL_MONITOR, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" }, -+ { PRISM2_IOCTL_READMIF, -+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, -+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" }, -+ { PRISM2_IOCTL_WRITEMIF, -+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" }, -+ { PRISM2_IOCTL_RESET, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" }, -+ { PRISM2_IOCTL_INQUIRE, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" }, -+ { PRISM2_IOCTL_SET_RID_WORD, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" }, -+ { PRISM2_IOCTL_MACCMD, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" }, -+#ifdef PRISM2_USE_WE_TYPE_ADDR -+ { PRISM2_IOCTL_WDS_ADD, -+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" }, -+ { PRISM2_IOCTL_WDS_DEL, -+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" }, -+ { PRISM2_IOCTL_ADDMAC, -+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" }, -+ { PRISM2_IOCTL_DELMAC, -+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" }, -+ { PRISM2_IOCTL_KICKMAC, -+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" }, -+#else /* PRISM2_USE_WE_TYPE_ADDR */ -+ { PRISM2_IOCTL_WDS_ADD, -+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_add" }, -+ { PRISM2_IOCTL_WDS_DEL, -+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_del" }, -+ { PRISM2_IOCTL_ADDMAC, -+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "addmac" }, -+ { PRISM2_IOCTL_DELMAC, -+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "delmac" }, -+ { PRISM2_IOCTL_KICKMAC, -+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "kickmac" }, -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+ /* --- raw access to sub-ioctls --- */ -+ { PRISM2_IOCTL_PRISM2_PARAM, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" }, -+#if WIRELESS_EXT >= 12 -+ { PRISM2_IOCTL_GET_PRISM2_PARAM, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" }, -+#ifdef PRISM2_USE_WE_SUB_IOCTLS -+ /* --- sub-ioctls handlers --- */ -+ { PRISM2_IOCTL_PRISM2_PARAM, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, -+ { PRISM2_IOCTL_GET_PRISM2_PARAM, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, -+ /* --- sub-ioctls definitions --- */ -+ { PRISM2_PARAM_PTYPE, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ptype" }, -+ { PRISM2_PARAM_PTYPE, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getptype" }, -+ { PRISM2_PARAM_TXRATECTRL, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" }, -+ { PRISM2_PARAM_TXRATECTRL, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" }, -+ { PRISM2_PARAM_BEACON_INT, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" }, -+ { PRISM2_PARAM_BEACON_INT, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" }, -+#ifndef PRISM2_NO_STATION_MODES -+ { PRISM2_PARAM_PSEUDO_IBSS, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" }, -+ { PRISM2_PARAM_PSEUDO_IBSS, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" }, -+#endif /* PRISM2_NO_STATION_MODES */ -+ { PRISM2_PARAM_ALC, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" }, -+ { PRISM2_PARAM_ALC, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" }, -+ { PRISM2_PARAM_TXPOWER, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txpower" }, -+ { PRISM2_PARAM_TXPOWER, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getxpower" }, -+ { PRISM2_PARAM_DUMP, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" }, -+ { PRISM2_PARAM_DUMP, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" }, -+ { PRISM2_PARAM_OTHER_AP_POLICY, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" }, -+ { PRISM2_PARAM_OTHER_AP_POLICY, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" }, -+ { PRISM2_PARAM_AP_MAX_INACTIVITY, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" }, -+ { PRISM2_PARAM_AP_MAX_INACTIVITY, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" }, -+ { PRISM2_PARAM_AP_BRIDGE_PACKETS, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" }, -+ { PRISM2_PARAM_AP_BRIDGE_PACKETS, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" }, -+ { PRISM2_PARAM_DTIM_PERIOD, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" }, -+ { PRISM2_PARAM_DTIM_PERIOD, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" }, -+ { PRISM2_PARAM_AP_NULLFUNC_ACK, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" }, -+ { PRISM2_PARAM_AP_NULLFUNC_ACK, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" }, -+ { PRISM2_PARAM_MAX_WDS, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" }, -+ { PRISM2_PARAM_MAX_WDS, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" }, -+ { PRISM2_PARAM_AP_AUTOM_AP_WDS, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" }, -+ { PRISM2_PARAM_AP_AUTOM_AP_WDS, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" }, -+ { PRISM2_PARAM_AP_AUTH_ALGS, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" }, -+ { PRISM2_PARAM_AP_AUTH_ALGS, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" }, -+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" }, -+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" }, -+ { PRISM2_PARAM_HOST_ENCRYPT, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" }, -+ { PRISM2_PARAM_HOST_ENCRYPT, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" }, -+ { PRISM2_PARAM_HOST_DECRYPT, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" }, -+ { PRISM2_PARAM_HOST_DECRYPT, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" }, -+ { PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_rx" }, -+ { PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_rx" }, -+ { PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_tx" }, -+ { PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_tx" }, -+#ifndef PRISM2_NO_STATION_MODES -+ { PRISM2_PARAM_HOST_ROAMING, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" }, -+ { PRISM2_PARAM_HOST_ROAMING, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" }, -+#endif /* PRISM2_NO_STATION_MODES */ -+ { PRISM2_PARAM_BCRX_STA_KEY, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" }, -+ { PRISM2_PARAM_BCRX_STA_KEY, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" }, -+ { PRISM2_PARAM_IEEE_802_1X, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" }, -+ { PRISM2_PARAM_IEEE_802_1X, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" }, -+ { PRISM2_PARAM_ANTSEL_TX, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" }, -+ { PRISM2_PARAM_ANTSEL_TX, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" }, -+ { PRISM2_PARAM_ANTSEL_RX, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" }, -+ { PRISM2_PARAM_ANTSEL_RX, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" }, -+ { PRISM2_PARAM_MONITOR_TYPE, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" }, -+ { PRISM2_PARAM_MONITOR_TYPE, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" }, -+ { PRISM2_PARAM_WDS_TYPE, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" }, -+ { PRISM2_PARAM_WDS_TYPE, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" }, -+ { PRISM2_PARAM_HOSTSCAN, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" }, -+ { PRISM2_PARAM_HOSTSCAN, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" }, -+ { PRISM2_PARAM_AP_SCAN, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" }, -+ { PRISM2_PARAM_AP_SCAN, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" }, -+ { PRISM2_PARAM_ENH_SEC, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" }, -+ { PRISM2_PARAM_ENH_SEC, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" }, -+#ifdef PRISM2_IO_DEBUG -+ { PRISM2_PARAM_IO_DEBUG, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" }, -+ { PRISM2_PARAM_IO_DEBUG, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" }, -+#endif /* PRISM2_IO_DEBUG */ -+ { PRISM2_PARAM_BASIC_RATES, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" }, -+ { PRISM2_PARAM_BASIC_RATES, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" }, -+ { PRISM2_PARAM_OPER_RATES, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" }, -+ { PRISM2_PARAM_OPER_RATES, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" }, -+ { PRISM2_PARAM_HOSTAPD, -+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" }, -+ { PRISM2_PARAM_HOSTAPD, -+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" }, -+#endif /* PRISM2_USE_WE_SUB_IOCTLS */ -+#endif /* WIRELESS_EXT >= 12 */ -+}; -+ -+ -+#if WIRELESS_EXT <= 12 -+static int prism2_ioctl_giwpriv(struct net_device *dev, struct iw_point *data) -+{ -+ -+ if (!data->pointer || -+ verify_area(VERIFY_WRITE, data->pointer, sizeof(prism2_priv))) -+ return -EINVAL; -+ -+ data->length = sizeof(prism2_priv) / sizeof(prism2_priv[0]); -+ if (copy_to_user(data->pointer, prism2_priv, sizeof(prism2_priv))) -+ return -EINVAL; -+ return 0; -+} -+#endif /* WIRELESS_EXT <= 12 */ -+#endif /* WIRELESS_EXT > 8 */ -+#endif /* WIRELESS_EXT */ -+ -+ -+static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL)) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_priv_prism2_param(struct net_device *dev, -+ struct iw_request_info *info, -+ void *wrqu, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int *i = (int *) extra; -+ int param = *i; -+ int value = *(i + 1); -+ int ret = 0; -+ u16 val; -+ -+ switch (param) { -+ case PRISM2_PARAM_PTYPE: -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, value)) { -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ if (local->func->reset_port(dev)) -+ ret = -EINVAL; -+ break; -+ -+ case PRISM2_PARAM_TXRATECTRL: -+ local->fw_tx_rate_control = value; -+ break; -+ -+ case PRISM2_PARAM_BEACON_INT: -+ if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) || -+ local->func->reset_port(dev)) -+ ret = -EINVAL; -+ else -+ local->beacon_int = value; -+ break; -+ -+#ifndef PRISM2_NO_STATION_MODES -+ case PRISM2_PARAM_PSEUDO_IBSS: -+ if (value == local->pseudo_adhoc) -+ break; -+ -+ if (value != 0 && value != 1) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n", -+ dev->name, local->pseudo_adhoc, value); -+ local->pseudo_adhoc = value; -+ if (local->iw_mode != IW_MODE_ADHOC) -+ break; -+ -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, -+ hostap_get_porttype(local))) { -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ if (local->func->reset_port(dev)) -+ ret = -EINVAL; -+ break; -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ case PRISM2_PARAM_ALC: -+ printk(KERN_DEBUG "%s: %s ALC\n", dev->name, -+ value == 0 ? "Disabling" : "Enabling"); -+ val = HFA384X_TEST_CFG_BIT_ALC; -+ local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_CFG_BITS << 8), -+ value == 0 ? 0 : 1, &val, NULL); -+ break; -+ -+ case PRISM2_PARAM_TXPOWER: -+ val = value; -+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL)) -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_DUMP: -+ local->frame_dump = value; -+ break; -+ -+ case PRISM2_PARAM_OTHER_AP_POLICY: -+ if (value < 0 || value > 3) { -+ ret = -EINVAL; -+ break; -+ } -+ if (local->ap != NULL) -+ local->ap->ap_policy = value; -+ break; -+ -+ case PRISM2_PARAM_AP_MAX_INACTIVITY: -+ if (value < 0 || value > 7 * 24 * 60 * 60) { -+ ret = -EINVAL; -+ break; -+ } -+ if (local->ap != NULL) -+ local->ap->max_inactivity = value * HZ; -+ break; -+ -+ case PRISM2_PARAM_AP_BRIDGE_PACKETS: -+ if (local->ap != NULL) -+ local->ap->bridge_packets = value; -+ break; -+ -+ case PRISM2_PARAM_DTIM_PERIOD: -+ if (value < 0 || value > 65535) { -+ ret = -EINVAL; -+ break; -+ } -+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value) -+ || local->func->reset_port(dev)) -+ ret = -EINVAL; -+ else -+ local->dtim_period = value; -+ break; -+ -+ case PRISM2_PARAM_AP_NULLFUNC_ACK: -+ if (local->ap != NULL) -+ local->ap->nullfunc_ack = value; -+ break; -+ -+ case PRISM2_PARAM_MAX_WDS: -+ local->wds_max_connections = value; -+ break; -+ -+ case PRISM2_PARAM_AP_AUTOM_AP_WDS: -+ if (local->ap != NULL) { -+ if (!local->ap->autom_ap_wds && value) { -+ /* add WDS link to all APs in STA table */ -+ hostap_add_wds_links(local); -+ } -+ local->ap->autom_ap_wds = value; -+ } -+ break; -+ -+ case PRISM2_PARAM_AP_AUTH_ALGS: -+ if (local->ap != NULL) -+ local->ap->auth_algs = value; -+ break; -+ -+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR: -+ local->monitor_allow_fcserr = value; -+ break; -+ -+ case PRISM2_PARAM_HOST_ENCRYPT: -+ local->host_encrypt = value; -+ if (hostap_set_encryption(local) || -+ local->func->reset_port(dev)) -+ ret = -EINVAL; -+ break; -+ -+ case PRISM2_PARAM_HOST_DECRYPT: -+ local->host_decrypt = value; -+ if (hostap_set_encryption(local) || -+ local->func->reset_port(dev)) -+ ret = -EINVAL; -+ break; -+ -+ case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX: -+ local->bus_master_threshold_rx = value; -+ break; -+ -+ case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX: -+ local->bus_master_threshold_tx = value; -+ break; -+ -+#ifndef PRISM2_NO_STATION_MODES -+ case PRISM2_PARAM_HOST_ROAMING: -+ local->host_roaming = value; -+ if (hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, -+ value ? HFA384X_ROAMING_HOST : -+ HFA384X_ROAMING_FIRMWARE) || -+ local->func->reset_port(dev)) -+ ret = -EINVAL; -+ else -+ local->host_roaming = value; -+ break; -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ case PRISM2_PARAM_BCRX_STA_KEY: -+ local->bcrx_sta_key = value; -+ break; -+ -+ case PRISM2_PARAM_IEEE_802_1X: -+ local->ieee_802_1x = value; -+ break; -+ -+ case PRISM2_PARAM_ANTSEL_TX: -+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) { -+ ret = -EINVAL; -+ break; -+ } -+ local->antsel_tx = value; -+ hostap_set_antsel(local); -+ break; -+ -+ case PRISM2_PARAM_ANTSEL_RX: -+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) { -+ ret = -EINVAL; -+ break; -+ } -+ local->antsel_rx = value; -+ hostap_set_antsel(local); -+ break; -+ -+ case PRISM2_PARAM_MONITOR_TYPE: -+ if (value != PRISM2_MONITOR_80211 && -+ value != PRISM2_MONITOR_CAPHDR && -+ value != PRISM2_MONITOR_PRISM) { -+ ret = -EINVAL; -+ break; -+ } -+ local->monitor_type = value; -+ if (local->iw_mode == IW_MODE_MONITOR) -+ hostap_monitor_set_type(local); -+ break; -+ -+ case PRISM2_PARAM_WDS_TYPE: -+ local->wds_type = value; -+ break; -+ -+ case PRISM2_PARAM_HOSTSCAN: -+ { -+ struct hfa384x_hostscan_request scan_req; -+ u16 rate; -+ -+ memset(&scan_req, 0, sizeof(scan_req)); -+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff); -+ switch (value) { -+ case 1: rate = HFA384X_RATES_1MBPS; break; -+ case 2: rate = HFA384X_RATES_2MBPS; break; -+ case 3: rate = HFA384X_RATES_5MBPS; break; -+ case 4: rate = HFA384X_RATES_11MBPS; break; -+ default: rate = HFA384X_RATES_1MBPS; break; -+ } -+ scan_req.txrate = cpu_to_le16(rate); -+ /* leave SSID empty to accept all SSIDs */ -+ -+ if (local->iw_mode == IW_MODE_MASTER) { -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, -+ HFA384X_PORTTYPE_BSS) || -+ local->func->reset_port(dev)) -+ printk(KERN_DEBUG "Leaving Host AP mode " -+ "for HostScan failed\n"); -+ } -+ -+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req, -+ sizeof(scan_req))) { -+ printk(KERN_DEBUG "HOSTSCAN failed\n"); -+ ret = -EINVAL; -+ } -+ if (local->iw_mode == IW_MODE_MASTER) { -+ wait_queue_t __wait; -+ init_waitqueue_entry(&__wait, current); -+ add_wait_queue(&local->hostscan_wq, &__wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ); -+ if (signal_pending(current)) -+ ret = -EINTR; -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&local->hostscan_wq, &__wait); -+ -+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, -+ HFA384X_PORTTYPE_HOSTAP) || -+ local->func->reset_port(dev)) -+ printk(KERN_DEBUG "Returning to Host AP mode " -+ "after HostScan failed\n"); -+ } -+ break; -+ } -+ -+ case PRISM2_PARAM_AP_SCAN: -+ local->passive_scan_interval = value; -+ if (timer_pending(&local->passive_scan_timer)) -+ del_timer(&local->passive_scan_timer); -+ if (value > 0) { -+ local->passive_scan_timer.expires = jiffies + -+ local->passive_scan_interval * HZ; -+ add_timer(&local->passive_scan_timer); -+ } -+ break; -+ -+ case PRISM2_PARAM_ENH_SEC: -+ if (value < 0 || value > 3) { -+ ret = -EINVAL; -+ break; -+ } -+ local->enh_sec = value; -+ if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, -+ local->enh_sec)) { -+ printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w " -+ "1.6.3 or newer\n", dev->name); -+ ret = -EOPNOTSUPP; -+ } -+ break; -+ -+#ifdef PRISM2_IO_DEBUG -+ case PRISM2_PARAM_IO_DEBUG: -+ local->io_debug_enabled = value; -+ break; -+#endif /* PRISM2_IO_DEBUG */ -+ -+ case PRISM2_PARAM_BASIC_RATES: -+ local->basic_rates = value; -+ if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES, -+ local->basic_rates) || -+ local->func->reset_port(dev)) -+ ret = -EINVAL; -+ break; -+ -+ case PRISM2_PARAM_OPER_RATES: -+ local->tx_rate_control = value; -+ if (hostap_set_rate(dev)) -+ ret = -EINVAL; -+ break; -+ -+ case PRISM2_PARAM_HOSTAPD: -+ ret = hostap_set_hostapd(local, value, 1); -+ break; -+ -+ default: -+ printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n", -+ dev->name, param); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ return ret; -+} -+ -+ -+#if WIRELESS_EXT >= 12 -+static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev, -+ struct iw_request_info *info, -+ void *wrqu, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ int *param = (int *) extra; -+ int ret = 0; -+ u16 val; -+ -+ switch (*param) { -+ case PRISM2_PARAM_PTYPE: -+ if (local->func->get_rid(dev, HFA384X_RID_CNFPORTTYPE, -+ &val, 2, 1) < 0) -+ ret = -EINVAL; -+ else -+ *param = le16_to_cpu(val); -+ break; -+ -+ case PRISM2_PARAM_TXRATECTRL: -+ *param = local->fw_tx_rate_control; -+ break; -+ -+ case PRISM2_PARAM_BEACON_INT: -+ *param = local->beacon_int; -+ break; -+ -+ case PRISM2_PARAM_PSEUDO_IBSS: -+ *param = local->pseudo_adhoc; -+ break; -+ -+ case PRISM2_PARAM_ALC: -+ ret = -EOPNOTSUPP; /* FIX */ -+ break; -+ -+ case PRISM2_PARAM_TXPOWER: -+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, -+ HFA386X_CR_MANUAL_TX_POWER, NULL, &val)) -+ ret = -EOPNOTSUPP; -+ *param = val; -+ break; -+ -+ case PRISM2_PARAM_DUMP: -+ *param = local->frame_dump; -+ break; -+ -+ case PRISM2_PARAM_OTHER_AP_POLICY: -+ if (local->ap != NULL) -+ *param = local->ap->ap_policy; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_AP_MAX_INACTIVITY: -+ if (local->ap != NULL) -+ *param = local->ap->max_inactivity / HZ; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_AP_BRIDGE_PACKETS: -+ if (local->ap != NULL) -+ *param = local->ap->bridge_packets; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_DTIM_PERIOD: -+ *param = local->dtim_period; -+ break; -+ -+ case PRISM2_PARAM_AP_NULLFUNC_ACK: -+ if (local->ap != NULL) -+ *param = local->ap->nullfunc_ack; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_MAX_WDS: -+ *param = local->wds_max_connections; -+ break; -+ -+ case PRISM2_PARAM_AP_AUTOM_AP_WDS: -+ if (local->ap != NULL) -+ *param = local->ap->autom_ap_wds; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_AP_AUTH_ALGS: -+ if (local->ap != NULL) -+ *param = local->ap->auth_algs; -+ else -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR: -+ *param = local->monitor_allow_fcserr; -+ break; -+ -+ case PRISM2_PARAM_HOST_ENCRYPT: -+ *param = local->host_encrypt; -+ break; -+ -+ case PRISM2_PARAM_HOST_DECRYPT: -+ *param = local->host_decrypt; -+ break; -+ -+ case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX: -+ *param = local->bus_master_threshold_rx; -+ break; -+ -+ case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX: -+ *param = local->bus_master_threshold_tx; -+ break; -+ -+ case PRISM2_PARAM_HOST_ROAMING: -+ *param = local->host_roaming; -+ break; -+ -+ case PRISM2_PARAM_BCRX_STA_KEY: -+ *param = local->bcrx_sta_key; -+ break; -+ -+ case PRISM2_PARAM_IEEE_802_1X: -+ *param = local->ieee_802_1x; -+ break; -+ -+ case PRISM2_PARAM_ANTSEL_TX: -+ *param = local->antsel_tx; -+ break; -+ -+ case PRISM2_PARAM_ANTSEL_RX: -+ *param = local->antsel_rx; -+ break; -+ -+ case PRISM2_PARAM_MONITOR_TYPE: -+ *param = local->monitor_type; -+ break; -+ -+ case PRISM2_PARAM_WDS_TYPE: -+ *param = local->wds_type; -+ break; -+ -+ case PRISM2_PARAM_HOSTSCAN: -+ ret = -EOPNOTSUPP; -+ break; -+ -+ case PRISM2_PARAM_AP_SCAN: -+ *param = local->passive_scan_interval; -+ break; -+ -+ case PRISM2_PARAM_ENH_SEC: -+ *param = local->enh_sec; -+ break; -+ -+#ifdef PRISM2_IO_DEBUG -+ case PRISM2_PARAM_IO_DEBUG: -+ *param = local->io_debug_enabled; -+ break; -+#endif /* PRISM2_IO_DEBUG */ -+ -+ case PRISM2_PARAM_BASIC_RATES: -+ *param = local->basic_rates; -+ break; -+ -+ case PRISM2_PARAM_OPER_RATES: -+ *param = local->tx_rate_control; -+ break; -+ -+ case PRISM2_PARAM_HOSTAPD: -+ *param = local->hostapd; -+ break; -+ -+ default: -+ printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n", -+ dev->name, *param); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ return ret; -+} -+#endif /* WIRELESS_EXT >= 12 */ -+ -+ -+static int prism2_ioctl_priv_readmif(struct net_device *dev, -+ struct iw_request_info *info, -+ void *wrqu, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 resp0; -+ -+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL, -+ &resp0)) -+ return -EOPNOTSUPP; -+ else -+ *extra = resp0; -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_priv_writemif(struct net_device *dev, -+ struct iw_request_info *info, -+ void *wrqu, char *extra) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u16 cr, val; -+ -+ cr = *extra; -+ val = *(extra + 1); -+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL)) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) -+{ -+#if WIRELESS_EXT > 8 -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret = 0; -+ u32 mode; -+ -+ printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor " -+ "- update software to use iwconfig mode monitor\n", -+ dev->name, current->pid, current->comm); -+ -+ /* Backward compatibility code - this can be removed at some point */ -+ -+ if (*i == 0) { -+ /* Disable monitor mode - old mode was not saved, so go to -+ * Master mode */ -+ mode = IW_MODE_MASTER; -+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); -+ } else if (*i == 1) { -+ /* netlink socket mode is not supported anymore since it did -+ * not separate different devices from each other and was not -+ * best method for delivering large amount of packets to -+ * user space */ -+ ret = -EOPNOTSUPP; -+ } else if (*i == 2 || *i == 3) { -+ switch (*i) { -+ case 2: -+ local->monitor_type = PRISM2_MONITOR_80211; -+ break; -+ case 3: -+ local->monitor_type = PRISM2_MONITOR_PRISM; -+ break; -+ } -+ mode = IW_MODE_MONITOR; -+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); -+ hostap_monitor_mode_enable(local); -+ } else -+ ret = -EINVAL; -+ -+ return ret; -+#else /* WIRELESS_EXT > 8 */ -+ return -EOPNOTSUPP; -+#endif /* WIRELESS_EXT > 8 */ -+} -+ -+ -+static int prism2_ioctl_priv_reset(struct net_device *dev, int *i) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i); -+ switch (*i) { -+ case 0: -+ /* Disable and enable card */ -+ local->func->hw_shutdown(dev, 1); -+ local->func->hw_config(dev, 0); -+ break; -+ -+ case 1: -+ /* COR sreset */ -+ local->func->hw_reset(dev); -+ break; -+ -+ case 2: -+ /* Disable and enable port 0 */ -+ local->func->reset_port(dev); -+ break; -+ -+ case 3: -+ if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, -+ NULL)) -+ return -EINVAL; -+ break; -+ -+ case 4: -+ if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, -+ NULL)) -+ return -EINVAL; -+ break; -+ -+ default: -+ printk(KERN_DEBUG "Unknown reset request %d\n", *i); -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+ -+#ifndef PRISM2_USE_WE_TYPE_ADDR -+static inline int hex2int(char c) -+{ -+ if (c >= '0' && c <= '9') -+ return (c - '0'); -+ if (c >= 'a' && c <= 'f') -+ return (c - 'a' + 10); -+ if (c >= 'A' && c <= 'F') -+ return (c - 'A' + 10); -+ return -1; -+} -+ -+static int macstr2addr(char *macstr, u8 *addr) -+{ -+ int i, val, val2; -+ char *pos = macstr; -+ -+ for (i = 0; i < 6; i++) { -+ val = hex2int(*pos++); -+ if (val < 0) -+ return -1; -+ val2 = hex2int(*pos++); -+ if (val2 < 0) -+ return -1; -+ addr[i] = (val * 16 + val2) & 0xff; -+ -+ if (i < 5 && *pos++ != ':') -+ return -1; -+ } -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_priv_wds(struct net_device *dev, int add, char *macstr) -+{ -+ local_info_t *local = (local_info_t *) dev->priv; -+ u8 addr[6]; -+ -+ if (macstr2addr(macstr, addr)) { -+ printk(KERN_DEBUG "Invalid MAC address\n"); -+ return -EINVAL; -+ } -+ -+ if (add) -+ return prism2_wds_add(local, addr, 1); -+ else -+ return prism2_wds_del(local, addr, 1, 0); -+} -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+ -+ -+static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i) -+{ -+ int rid = *i; -+ int value = *(i + 1); -+ -+ printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value); -+ -+ if (hostap_set_word(dev, rid, value)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd) -+{ -+ int ret = 0; -+ -+ switch (*cmd) { -+ case AP_MAC_CMD_POLICY_OPEN: -+ local->ap->mac_restrictions.policy = MAC_POLICY_OPEN; -+ break; -+ case AP_MAC_CMD_POLICY_ALLOW: -+ local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW; -+ break; -+ case AP_MAC_CMD_POLICY_DENY: -+ local->ap->mac_restrictions.policy = MAC_POLICY_DENY; -+ break; -+ case AP_MAC_CMD_FLUSH: -+ ap_control_flush_macs(&local->ap->mac_restrictions); -+ break; -+ case AP_MAC_CMD_KICKALL: -+ ap_control_kickall(local->ap); -+ hostap_deauth_all_stas(local->dev, local->ap, 0); -+ break; -+ default: -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ return ret; -+} -+ -+ -+enum { AP_CTRL_MAC_ADD, AP_CTRL_MAC_DEL, AP_CTRL_MAC_KICK }; -+ -+#ifndef PRISM2_USE_WE_TYPE_ADDR -+static int ap_mac_ioctl(local_info_t *local, char *macstr, int cmd) -+{ -+ u8 addr[6]; -+ -+ if (macstr2addr(macstr, addr)) { -+ printk(KERN_DEBUG "Invalid MAC address '%s'\n", macstr); -+ return -EINVAL; -+ } -+ -+ switch (cmd) { -+ case AP_CTRL_MAC_ADD: -+ return ap_control_add_mac(&local->ap->mac_restrictions, addr); -+ case AP_CTRL_MAC_DEL: -+ return ap_control_del_mac(&local->ap->mac_restrictions, addr); -+ case AP_CTRL_MAC_KICK: -+ return ap_control_kick_mac(local->ap, local->dev, addr); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+#if defined(PRISM2_DOWNLOAD_SUPPORT) && WIRELESS_EXT > 8 -+static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p) -+{ -+ struct prism2_download_param *param; -+ int ret = 0; -+ -+ if (p->length < sizeof(struct prism2_download_param) || -+ p->length > 1024 || !p->pointer) -+ return -EINVAL; -+ -+ param = (struct prism2_download_param *) -+ kmalloc(p->length, GFP_KERNEL); -+ if (param == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(param, p->pointer, p->length)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ if (p->length < sizeof(struct prism2_download_param) + -+ param->num_areas * sizeof(struct prism2_download_area)) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = local->func->download(local, param); -+ -+ out: -+ if (param != NULL) -+ kfree(param); -+ -+ return ret; -+} -+#endif /* PRISM2_DOWNLOAD_SUPPORT and WIRELESS_EXT > 8 */ -+ -+ -+static int prism2_ioctl_set_encryption(local_info_t *local, -+ struct prism2_hostapd_param *param, -+ int param_len) -+{ -+ int ret = 0; -+ struct hostap_crypto_ops *ops; -+ struct prism2_crypt_data **crypt; -+ void *sta_ptr; -+ -+ param->u.crypt.err = 0; -+ param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0'; -+ -+ if (param_len != -+ (int) ((char *) param->u.crypt.key - (char *) param) + -+ param->u.crypt.key_len) -+ return -EINVAL; -+ -+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && -+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && -+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { -+ sta_ptr = NULL; -+ crypt = &local->crypt; -+ } else { -+ sta_ptr = ap_crypt_get_ptrs( -+ local->ap, param->sta_addr, -+ (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT), -+ &crypt); -+ -+ if (sta_ptr == NULL) { -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; -+ return -EINVAL; -+ } -+ } -+ -+ if (strcmp(param->u.crypt.alg, "none") == 0) { -+ prism2_crypt_delayed_deinit(local, crypt); -+ goto done; -+ } -+ -+ ops = hostap_get_crypto_ops(param->u.crypt.alg); -+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { -+ request_module("hostap_crypt_wep"); -+ ops = hostap_get_crypto_ops(param->u.crypt.alg); -+ } -+ if (ops == NULL) { -+ printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", -+ local->dev->name, param->u.crypt.alg); -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG; -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ /* station based encryption and other than WEP algorithms require -+ * host-based encryption, so force them on automatically */ -+ local->host_decrypt = local->host_encrypt = 1; -+ -+ if (*crypt == NULL || (*crypt)->ops != ops) { -+ struct prism2_crypt_data *new_crypt; -+ -+ prism2_crypt_delayed_deinit(local, crypt); -+ -+ new_crypt = (struct prism2_crypt_data *) -+ kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL); -+ if (new_crypt == NULL) { -+ ret = -ENOMEM; -+ goto done; -+ } -+ memset(new_crypt, 0, sizeof(struct prism2_crypt_data)); -+ new_crypt->ops = ops; -+ new_crypt->priv = new_crypt->ops->init(); -+ if (new_crypt->priv == NULL) { -+ kfree(new_crypt); -+ param->u.crypt.err = -+ HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED; -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ *crypt = new_crypt; -+ } -+ -+ if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) || -+ param->u.crypt.key_len > 0) && (*crypt)->ops->set_key && -+ (*crypt)->ops->set_key(param->u.crypt.idx, param->u.crypt.key, -+ param->u.crypt.key_len, (*crypt)->priv) < 0) { -+ printk(KERN_DEBUG "%s: key setting failed\n", -+ local->dev->name); -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ if ((param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) && -+ (*crypt)->ops->set_key_idx && -+ (*crypt)->ops->set_key_idx(param->u.crypt.idx, (*crypt)->priv) < 0) -+ { -+ printk(KERN_DEBUG "%s: TX key idx setting failed\n", -+ local->dev->name); -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED; -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ done: -+ if (sta_ptr) -+ hostap_handle_sta_release(sta_ptr); -+ -+ if (ret == 0 && -+ (hostap_set_encryption(local) || -+ local->func->reset_port(local->dev))) { -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED; -+ return -EINVAL; -+ } -+ -+ return ret; -+} -+ -+ -+static int prism2_ioctl_get_encryption(local_info_t *local, -+ struct prism2_hostapd_param *param, -+ int param_len) -+{ -+ struct prism2_crypt_data **crypt; -+ void *sta_ptr; -+ int max_key_len; -+ -+ param->u.crypt.err = 0; -+ -+ max_key_len = param_len - -+ (int) ((char *) param->u.crypt.key - (char *) param); -+ if (max_key_len < 0) -+ return -EINVAL; -+ -+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && -+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && -+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { -+ sta_ptr = NULL; -+ crypt = &local->crypt; -+ } else { -+ sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0, -+ &crypt); -+ -+ if (sta_ptr == NULL) { -+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; -+ return -EINVAL; -+ } -+ } -+ -+ if (*crypt == NULL || (*crypt)->ops == NULL) { -+ memcpy(param->u.crypt.alg, "none", 5); -+ param->u.crypt.key_len = 0; -+ param->u.crypt.idx = 0xff; -+ } else { -+ strncpy(param->u.crypt.alg, (*crypt)->ops->name, -+ HOSTAP_CRYPT_ALG_NAME_LEN); -+ param->u.crypt.key_len = 0; -+ if (param->u.crypt.idx >= WEP_KEYS && -+ (*crypt)->ops->get_key_idx) -+ param->u.crypt.idx = -+ (*crypt)->ops->get_key_idx((*crypt)->priv); -+ -+ if (param->u.crypt.idx < WEP_KEYS && (*crypt)->ops->get_key) -+ param->u.crypt.key_len = -+ (*crypt)->ops->get_key(param->u.crypt.idx, -+ param->u.crypt.key, -+ max_key_len, -+ (*crypt)->priv); -+ } -+ -+ if (sta_ptr) -+ hostap_handle_sta_release(sta_ptr); -+ -+ return 0; -+} -+ -+ -+static int prism2_ioctl_get_rid(local_info_t *local, -+ struct prism2_hostapd_param *param, -+ int param_len) -+{ -+ int max_len, res; -+ -+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN; -+ if (max_len < 0) -+ return -EINVAL; -+ -+ res = local->func->get_rid(local->dev, param->u.rid.rid, -+ param->u.rid.data, param->u.rid.len, 0); -+ if (res >= 0) { -+ param->u.rid.len = res; -+ return 0; -+ } -+ -+ return res; -+} -+ -+ -+static int prism2_ioctl_set_rid(local_info_t *local, -+ struct prism2_hostapd_param *param, -+ int param_len) -+{ -+ int max_len; -+ -+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN; -+ if (max_len < 0 || max_len < param->u.rid.len) -+ return -EINVAL; -+ -+ return local->func->set_rid(local->dev, param->u.rid.rid, -+ param->u.rid.data, param->u.rid.len); -+} -+ -+ -+static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local, -+ struct prism2_hostapd_param *param, -+ int param_len) -+{ -+ printk(KERN_DEBUG "%ssta: associated as client with AP " MACSTR "\n", -+ local->dev->name, MAC2STR(param->sta_addr)); -+ memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN); -+ return 0; -+} -+ -+ -+static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p) -+{ -+ struct prism2_hostapd_param *param; -+ int ret = 0; -+ int ap_ioctl = 0; -+ -+ if (p->length < sizeof(struct prism2_hostapd_param) || -+ p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) -+ return -EINVAL; -+ -+ param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); -+ if (param == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(param, p->pointer, p->length)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ switch (param->cmd) { -+ case PRISM2_SET_ENCRYPTION: -+ ret = prism2_ioctl_set_encryption(local, param, p->length); -+ break; -+ case PRISM2_GET_ENCRYPTION: -+ ret = prism2_ioctl_get_encryption(local, param, p->length); -+ break; -+ case PRISM2_HOSTAPD_GET_RID: -+ ret = prism2_ioctl_get_rid(local, param, p->length); -+ break; -+ case PRISM2_HOSTAPD_SET_RID: -+ ret = prism2_ioctl_set_rid(local, param, p->length); -+ break; -+ case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR: -+ ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length); -+ break; -+ default: -+ ret = prism2_hostapd(local->ap, param); -+ ap_ioctl = 1; -+ break; -+ } -+ -+ if (ret == 1 || !ap_ioctl) { -+ if (copy_to_user(p->pointer, param, p->length)) { -+ ret = -EFAULT; -+ goto out; -+ } else if (ap_ioctl) -+ ret = 0; -+ } -+ -+ out: -+ if (param != NULL) -+ kfree(param); -+ -+ return ret; -+} -+ -+ -+#if WIRELESS_EXT > 12 -+/* Structures to export the Wireless Handlers */ -+ -+static const iw_handler prism2_handler[] = -+{ -+ (iw_handler) NULL, /* SIOCSIWCOMMIT */ -+ (iw_handler) prism2_get_name, /* SIOCGIWNAME */ -+ (iw_handler) NULL, /* SIOCSIWNWID */ -+ (iw_handler) NULL, /* SIOCGIWNWID */ -+ (iw_handler) prism2_ioctl_siwfreq, /* SIOCSIWFREQ */ -+ (iw_handler) prism2_ioctl_giwfreq, /* SIOCGIWFREQ */ -+ (iw_handler) prism2_ioctl_siwmode, /* SIOCSIWMODE */ -+ (iw_handler) prism2_ioctl_giwmode, /* SIOCGIWMODE */ -+ (iw_handler) prism2_ioctl_siwsens, /* SIOCSIWSENS */ -+ (iw_handler) prism2_ioctl_giwsens, /* SIOCGIWSENS */ -+ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ -+ (iw_handler) prism2_ioctl_giwrange, /* SIOCGIWRANGE */ -+ (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ -+ (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ -+ (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ -+ (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ -+#if WIRELESS_EXT > 15 -+ iw_handler_set_spy, /* SIOCSIWSPY */ -+ iw_handler_get_spy, /* SIOCGIWSPY */ -+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ -+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ -+#else /* WIRELESS_EXT > 15 */ -+ (iw_handler) NULL, /* SIOCSIWSPY */ -+ (iw_handler) prism2_ioctl_giwspy, /* SIOCGIWSPY */ -+ (iw_handler) NULL, /* -- hole -- */ -+ (iw_handler) NULL, /* -- hole -- */ -+#endif /* WIRELESS_EXT > 15 */ -+ (iw_handler) prism2_ioctl_siwap, /* SIOCSIWAP */ -+ (iw_handler) prism2_ioctl_giwap, /* SIOCGIWAP */ -+ (iw_handler) NULL, /* -- hole -- */ -+ (iw_handler) prism2_ioctl_giwaplist, /* SIOCGIWAPLIST */ -+#if WIRELESS_EXT > 13 -+ (iw_handler) prism2_ioctl_siwscan, /* SIOCSIWSCAN */ -+ (iw_handler) prism2_ioctl_giwscan, /* SIOCGIWSCAN */ -+#else /* WIRELESS_EXT > 13 */ -+ (iw_handler) NULL, /* SIOCSIWSCAN */ -+ (iw_handler) NULL, /* SIOCGIWSCAN */ -+#endif /* WIRELESS_EXT > 13 */ -+ (iw_handler) prism2_ioctl_siwessid, /* SIOCSIWESSID */ -+ (iw_handler) prism2_ioctl_giwessid, /* SIOCGIWESSID */ -+ (iw_handler) prism2_ioctl_siwnickn, /* SIOCSIWNICKN */ -+ (iw_handler) prism2_ioctl_giwnickn, /* SIOCGIWNICKN */ -+ (iw_handler) NULL, /* -- hole -- */ -+ (iw_handler) NULL, /* -- hole -- */ -+ (iw_handler) prism2_ioctl_siwrate, /* SIOCSIWRATE */ -+ (iw_handler) prism2_ioctl_giwrate, /* SIOCGIWRATE */ -+ (iw_handler) prism2_ioctl_siwrts, /* SIOCSIWRTS */ -+ (iw_handler) prism2_ioctl_giwrts, /* SIOCGIWRTS */ -+ (iw_handler) prism2_ioctl_siwfrag, /* SIOCSIWFRAG */ -+ (iw_handler) prism2_ioctl_giwfrag, /* SIOCGIWFRAG */ -+ (iw_handler) prism2_ioctl_siwtxpow, /* SIOCSIWTXPOW */ -+ (iw_handler) prism2_ioctl_giwtxpow, /* SIOCGIWTXPOW */ -+ (iw_handler) prism2_ioctl_siwretry, /* SIOCSIWRETRY */ -+ (iw_handler) prism2_ioctl_giwretry, /* SIOCGIWRETRY */ -+ (iw_handler) prism2_ioctl_siwencode, /* SIOCSIWENCODE */ -+ (iw_handler) prism2_ioctl_giwencode, /* SIOCGIWENCODE */ -+ (iw_handler) prism2_ioctl_siwpower, /* SIOCSIWPOWER */ -+ (iw_handler) prism2_ioctl_giwpower, /* SIOCGIWPOWER */ -+}; -+ -+static const iw_handler prism2_private_handler[] = -+{ /* SIOCIWFIRSTPRIV + */ -+ (iw_handler) prism2_ioctl_priv_prism2_param, /* 0 */ -+ (iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */ -+ (iw_handler) prism2_ioctl_priv_writemif, /* 2 */ -+ (iw_handler) prism2_ioctl_priv_readmif, /* 3 */ -+}; -+ -+static const struct iw_handler_def hostap_iw_handler_def = -+{ -+ .num_standard = sizeof(prism2_handler) / sizeof(iw_handler), -+ .num_private = sizeof(prism2_private_handler) / sizeof(iw_handler), -+ .num_private_args = sizeof(prism2_priv) / sizeof(struct iw_priv_args), -+ .standard = (iw_handler *) prism2_handler, -+ .private = (iw_handler *) prism2_private_handler, -+ .private_args = (struct iw_priv_args *) prism2_priv, -+#if WIRELESS_EXT > 15 -+ .spy_offset = ((void *) (&((local_info_t *) NULL)->spy_data) - -+ (void *) NULL), -+#endif /* WIRELESS_EXT > 15 */ -+}; -+#endif /* WIRELESS_EXT > 12 */ -+ -+ -+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+#ifdef WIRELESS_EXT -+ struct iwreq *wrq = (struct iwreq *) ifr; -+#endif -+ local_info_t *local = (local_info_t *) dev->priv; -+ int ret = 0; -+ -+ switch (cmd) { -+ -+#ifdef WIRELESS_EXT -+#if WIRELESS_EXT <= 12 -+ case SIOCGIWNAME: -+ ret = prism2_get_name(dev, NULL, (char *) &wrq->u, NULL); -+ break; -+ -+ case SIOCSIWFREQ: -+ ret = prism2_ioctl_siwfreq(dev, NULL, &wrq->u.freq, NULL); -+ break; -+ case SIOCGIWFREQ: -+ ret = prism2_ioctl_giwfreq(dev, NULL, &wrq->u.freq, NULL); -+ break; -+ -+ case SIOCSIWAP: -+ ret = prism2_ioctl_siwap(dev, NULL, &wrq->u.ap_addr, NULL); -+ break; -+ case SIOCGIWAP: -+ ret = prism2_ioctl_giwap(dev, NULL, &wrq->u.ap_addr, NULL); -+ break; -+ -+#if WIRELESS_EXT > 8 -+ case SIOCSIWESSID: -+ if (!wrq->u.essid.pointer) -+ ret = -EINVAL; -+ else if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) -+ ret = -E2BIG; -+ else { -+ char ssid[IW_ESSID_MAX_SIZE]; -+ if (copy_from_user(ssid, wrq->u.essid.pointer, -+ wrq->u.essid.length)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = prism2_ioctl_siwessid(dev, NULL, &wrq->u.essid, -+ ssid); -+ } -+ break; -+ case SIOCGIWESSID: -+ if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) -+ ret = -E2BIG; -+ else if (wrq->u.essid.pointer) { -+ char ssid[IW_ESSID_MAX_SIZE]; -+ ret = prism2_ioctl_giwessid(dev, NULL, &wrq->u.essid, -+ ssid); -+ if (copy_to_user(wrq->u.essid.pointer, ssid, -+ wrq->u.essid.length)) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCSIWRATE: -+ ret = prism2_ioctl_siwrate(dev, NULL, &wrq->u.bitrate, NULL); -+ break; -+ case SIOCGIWRATE: -+ ret = prism2_ioctl_giwrate(dev, NULL, &wrq->u.bitrate, NULL); -+ break; -+ -+ case SIOCSIWRTS: -+ ret = prism2_ioctl_siwrts(dev, NULL, &wrq->u.rts, NULL); -+ break; -+ case SIOCGIWRTS: -+ ret = prism2_ioctl_giwrts(dev, NULL, &wrq->u.rts, NULL); -+ break; -+ -+ case SIOCSIWFRAG: -+ ret = prism2_ioctl_siwfrag(dev, NULL, &wrq->u.rts, NULL); -+ break; -+ case SIOCGIWFRAG: -+ ret = prism2_ioctl_giwfrag(dev, NULL, &wrq->u.rts, NULL); -+ break; -+ -+ case SIOCSIWENCODE: -+ { -+ char keybuf[WEP_KEY_LEN]; -+ if (wrq->u.encoding.pointer) { -+ if (wrq->u.encoding.length > WEP_KEY_LEN) { -+ ret = -E2BIG; -+ break; -+ } -+ if (copy_from_user(keybuf, -+ wrq->u.encoding.pointer, -+ wrq->u.encoding.length)) { -+ ret = -EFAULT; -+ break; -+ } -+ } else if (wrq->u.encoding.length != 0) { -+ ret = -EINVAL; -+ break; -+ } -+ ret = prism2_ioctl_siwencode(dev, NULL, -+ &wrq->u.encoding, keybuf); -+ } -+ break; -+ case SIOCGIWENCODE: -+ if (!capable(CAP_NET_ADMIN)) -+ ret = -EPERM; -+ else if (wrq->u.encoding.pointer) { -+ char keybuf[WEP_KEY_LEN]; -+ ret = prism2_ioctl_giwencode(dev, NULL, -+ &wrq->u.encoding, keybuf); -+ if (copy_to_user(wrq->u.encoding.pointer, keybuf, -+ wrq->u.encoding.length)) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCSIWNICKN: -+ if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) -+ ret = -E2BIG; -+ else if (wrq->u.essid.pointer) { -+ char nickbuf[IW_ESSID_MAX_SIZE + 1]; -+ if (copy_from_user(nickbuf, wrq->u.essid.pointer, -+ wrq->u.essid.length)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = prism2_ioctl_siwnickn(dev, NULL, &wrq->u.essid, -+ nickbuf); -+ } -+ break; -+ case SIOCGIWNICKN: -+ if (wrq->u.essid.pointer) { -+ char nickbuf[IW_ESSID_MAX_SIZE + 1]; -+ ret = prism2_ioctl_giwnickn(dev, NULL, &wrq->u.essid, -+ nickbuf); -+ if (copy_to_user(wrq->u.essid.pointer, nickbuf, -+ wrq->u.essid.length)) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCGIWSPY: -+ { -+ char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) + -+ sizeof(struct iw_quality))]; -+ ret = prism2_ioctl_giwspy(dev, NULL, &wrq->u.data, -+ buffer); -+ if (ret == 0 && wrq->u.data.pointer && -+ copy_to_user(wrq->u.data.pointer, buffer, -+ wrq->u.data.length * -+ (sizeof(struct sockaddr) + -+ sizeof(struct iw_quality)))) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCGIWRANGE: -+ { -+ struct iw_range range; -+ ret = prism2_ioctl_giwrange(dev, NULL, &wrq->u.data, -+ (char *) &range); -+ if (copy_to_user(wrq->u.data.pointer, &range, -+ sizeof(struct iw_range))) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCSIWSENS: -+ ret = prism2_ioctl_siwsens(dev, NULL, &wrq->u.sens, NULL); -+ break; -+ case SIOCGIWSENS: -+ ret = prism2_ioctl_giwsens(dev, NULL, &wrq->u.sens, NULL); -+ break; -+ -+ case SIOCGIWAPLIST: -+ if (wrq->u.data.pointer) { -+ char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + -+ sizeof(struct iw_quality))]; -+ ret = prism2_ioctl_giwaplist(dev, NULL, &wrq->u.data, -+ buffer); -+ if (copy_to_user(wrq->u.data.pointer, buffer, -+ (wrq->u.data.length * -+ (sizeof(struct sockaddr) + -+ sizeof(struct iw_quality))))) -+ ret = -EFAULT; -+ } -+ break; -+ -+ case SIOCSIWMODE: -+ ret = prism2_ioctl_siwmode(dev, NULL, &wrq->u.mode, NULL); -+ break; -+ case SIOCGIWMODE: -+ ret = prism2_ioctl_giwmode(dev, NULL, &wrq->u.mode, NULL); -+ break; -+ -+ case SIOCSIWPOWER: -+ ret = prism2_ioctl_siwpower(dev, NULL, &wrq->u.power, NULL); -+ break; -+ case SIOCGIWPOWER: -+ ret = prism2_ioctl_giwpower(dev, NULL, &wrq->u.power, NULL); -+ break; -+ -+ case SIOCGIWPRIV: -+ ret = prism2_ioctl_giwpriv(dev, &wrq->u.data); -+ break; -+#endif /* WIRELESS_EXT > 8 */ -+ -+#if WIRELESS_EXT > 9 -+ case SIOCSIWTXPOW: -+ ret = prism2_ioctl_siwtxpow(dev, NULL, &wrq->u.txpower, NULL); -+ break; -+ case SIOCGIWTXPOW: -+ ret = prism2_ioctl_giwtxpow(dev, NULL, &wrq->u.txpower, NULL); -+ break; -+#endif /* WIRELESS_EXT > 9 */ -+ -+#if WIRELESS_EXT > 10 -+ case SIOCSIWRETRY: -+ ret = prism2_ioctl_siwretry(dev, NULL, &wrq->u.retry, NULL); -+ break; -+ case SIOCGIWRETRY: -+ ret = prism2_ioctl_giwretry(dev, NULL, &wrq->u.retry, NULL); -+ break; -+#endif /* WIRELESS_EXT > 10 */ -+ -+ /* not supported wireless extensions */ -+ case SIOCSIWNWID: -+ case SIOCGIWNWID: -+ ret = -EOPNOTSUPP; -+ break; -+ -+ /* FIX: add support for this: */ -+ case SIOCSIWSPY: -+ printk(KERN_DEBUG "%s unsupported WIRELESS_EXT ioctl(0x%04x)\n" -+ , dev->name, cmd); -+ ret = -EOPNOTSUPP; -+ break; -+ -+ -+ /* Private ioctls (iwpriv); these are in SIOCDEVPRIVATE range -+ * if WIRELESS_EXT < 12, so better check privileges */ -+ -+ case PRISM2_IOCTL_PRISM2_PARAM: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_prism2_param(dev, NULL, &wrq->u, -+ (char *) &wrq->u); -+ break; -+#if WIRELESS_EXT >= 12 -+ case PRISM2_IOCTL_GET_PRISM2_PARAM: -+ ret = prism2_ioctl_priv_get_prism2_param(dev, NULL, &wrq->u, -+ (char *) &wrq->u); -+ break; -+#endif /* WIRELESS_EXT >= 12 */ -+ -+ case PRISM2_IOCTL_WRITEMIF: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_writemif(dev, NULL, &wrq->u, -+ (char *) &wrq->u); -+ break; -+ -+ case PRISM2_IOCTL_READMIF: -+ ret = prism2_ioctl_priv_readmif(dev, NULL, &wrq->u, -+ (char *) &wrq->u); -+ break; -+ -+#endif /* WIRELESS_EXT <= 12 */ -+ -+ -+ /* Private ioctls (iwpriv) that have not yet been converted -+ * into new wireless extensions API */ -+ -+ case PRISM2_IOCTL_INQUIRE: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name); -+ break; -+ -+ case PRISM2_IOCTL_MONITOR: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name); -+ break; -+ -+ case PRISM2_IOCTL_RESET: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name); -+ break; -+ -+#ifdef PRISM2_USE_WE_TYPE_ADDR -+ case PRISM2_IOCTL_WDS_ADD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1); -+ break; -+ -+ case PRISM2_IOCTL_WDS_DEL: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0); -+ break; -+#else /* PRISM2_USE_WE_TYPE_ADDR */ -+ case PRISM2_IOCTL_WDS_ADD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else if (wrq->u.data.pointer) { -+ char addrbuf[18]; -+ if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = prism2_ioctl_priv_wds(dev, 1, addrbuf); -+ } -+ break; -+ -+ case PRISM2_IOCTL_WDS_DEL: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else if (wrq->u.data.pointer) { -+ char addrbuf[18]; -+ if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = prism2_ioctl_priv_wds(dev, 0, addrbuf); -+ } -+ break; -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+ -+ case PRISM2_IOCTL_SET_RID_WORD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_set_rid_word(dev, -+ (int *) wrq->u.name); -+ break; -+ -+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -+ case PRISM2_IOCTL_MACCMD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name); -+ break; -+ -+#ifdef PRISM2_USE_WE_TYPE_ADDR -+ case PRISM2_IOCTL_ADDMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = ap_control_add_mac(&local->ap->mac_restrictions, -+ wrq->u.ap_addr.sa_data); -+ break; -+ case PRISM2_IOCTL_DELMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = ap_control_del_mac(&local->ap->mac_restrictions, -+ wrq->u.ap_addr.sa_data); -+ break; -+ case PRISM2_IOCTL_KICKMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = ap_control_kick_mac(local->ap, local->dev, -+ wrq->u.ap_addr.sa_data); -+ break; -+#else /* PRISM2_USE_WE_TYPE_ADDR */ -+ case PRISM2_IOCTL_ADDMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else if (wrq->u.data.pointer) { -+ char addrbuf[18]; -+ if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_ADD); -+ } -+ break; -+ -+ case PRISM2_IOCTL_DELMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else if (wrq->u.data.pointer) { -+ char addrbuf[18]; -+ if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_DEL); -+ } -+ break; -+ -+ case PRISM2_IOCTL_KICKMAC: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else if (wrq->u.data.pointer) { -+ char addrbuf[18]; -+ if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) { -+ ret = -EFAULT; -+ break; -+ } -+ ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_KICK); -+ } -+ break; -+#endif /* PRISM2_USE_WE_TYPE_ADDR */ -+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -+ -+ -+ /* Private ioctls that are not used with iwpriv; -+ * in SIOCDEVPRIVATE range */ -+ -+#if defined(PRISM2_DOWNLOAD_SUPPORT) && WIRELESS_EXT > 8 -+ case PRISM2_IOCTL_DOWNLOAD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+ else ret = prism2_ioctl_priv_download(local, &wrq->u.data); -+ break; -+#endif /* PRISM2_DOWNLOAD_SUPPORT and WIRELESS_EXT > 8 */ -+ -+ case PRISM2_IOCTL_HOSTAPD: -+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM; -+#if WIRELESS_EXT > 8 -+ else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data); -+#else /* WIRELESS_EXT > 8 */ -+ else ret = prism2_ioctl_priv_hostapd( -+ local, (struct iw_point *) &wrq->u.data); -+#endif /* WIRELESS_EXT > 8 */ -+ break; -+ -+#endif /* WIRELESS_EXT */ -+ -+ default: -+#if WIRELESS_EXT > 12 -+ if (cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) { -+ /* unsupport wireless extensions get through here - do -+ * not report these to debug log */ -+ ret = -EOPNOTSUPP; -+ break; -+ } -+#endif /* WIRELESS_EXT > 12 */ -+ printk(KERN_DEBUG "%s unsupported ioctl(0x%04x)\n", -+ dev->name, cmd); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ return ret; -+} - -Index: drivers/net/wireless/hostap_pci.c ---- drivers/net/wireless/hostap_pci.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_pci.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,415 @@ -+#define PRISM2_PCI -+ -+/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on -+ * driver patches from Reyk Floeter and -+ * Andy Warner */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+#include -+#else -+#include -+#endif -+#include -+#if WIRELESS_EXT > 12 -+#include -+#endif /* WIRELESS_EXT > 12 */ -+ -+#include -+#include -+ -+#include "hostap_wlan.h" -+ -+ -+static char *version = PRISM2_VERSION " (Jouni Malinen )"; -+static char *dev_info = "hostap_pci"; -+ -+ -+MODULE_AUTHOR("SSH Communications Security Corp, Jouni Malinen"); -+MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN " -+ "PCI cards."); -+MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) -+/* PCI initialization uses Linux 2.4.x version and older kernels do not support -+ * this */ -+#error Prism2.5 PCI version requires at least Linux kernel version 2.4.0 -+#endif /* kernel < 2.4.0 */ -+ -+ -+/* FIX: do we need mb/wmb/rmb with memory operations? */ -+ -+ -+static struct pci_device_id prism2_pci_id_table[] __devinitdata = { -+ /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */ -+ { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID }, -+ /* Samsung MagicLAN SWL-2210P */ -+ { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID }, -+ { 0 } -+}; -+ -+ -+#ifdef PRISM2_IO_DEBUG -+ -+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); -+ writeb(v, dev->mem_start + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u8 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = readb(dev->mem_start + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); -+ writew(v, dev->mem_start + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u16 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = readw(dev->mem_start + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v))) -+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a))) -+ -+#else /* PRISM2_IO_DEBUG */ -+ -+#define HFA384X_OUTB(v,a) writeb((v), dev->mem_start + (a)) -+#define HFA384X_INB(a) (u8) readb(dev->mem_start + (a)) -+#define HFA384X_OUTW(v,a) writew((v), dev->mem_start + (a)) -+#define HFA384X_INW(a) (u16) readw(dev->mem_start + (a)) -+#define HFA384X_OUTW_DATA(v,a) writew(cpu_to_le16(v), dev->mem_start + (a)) -+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(readw(dev->mem_start + (a))) -+ -+#endif /* PRISM2_IO_DEBUG */ -+ -+ -+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, -+ int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ for ( ; len > 1; len -= 2) -+ *pos++ = HFA384X_INW_DATA(d_off); -+ -+ if (len & 1) -+ *((char *) pos) = HFA384X_INB(d_off); -+ -+ return 0; -+} -+ -+ -+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ for ( ; len > 1; len -= 2) -+ HFA384X_OUTW_DATA(*pos++, d_off); -+ -+ if (len & 1) -+ HFA384X_OUTB(*((char *) pos), d_off); -+ -+ return 0; -+} -+ -+ -+/* FIX: This might change at some point.. */ -+#include "hostap_hw.c" -+ -+static void prism2_pci_cor_sreset(local_info_t *local) -+{ -+ struct net_device *dev = local->dev; -+ -+ /* linux-wlan-ng uses extremely long hold and settle times for -+ * COR sreset. A comment in the driver code mentions that the long -+ * delays appear to be necessary. However, at least IBM 22P6901 seems -+ * to work fine with shorter delays. -+ * -+ * Longer delays can be configured by uncommenting following line: */ -+/* #define PRISM2_PCI_USE_LONG_DELAYS */ -+ -+#ifdef PRISM2_PCI_USE_LONG_DELAYS -+ int i; -+ -+ HFA384X_OUTW(0x0080, HFA384X_PCICOR_OFF); -+ mdelay(250); -+ -+ HFA384X_OUTW(0x0, HFA384X_PCICOR_OFF); -+ mdelay(500); -+ -+ /* Wait for f/w to complete initialization (CMD:BUSY == 0) */ -+ i = 2000000 / 10; -+ while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i) -+ udelay(10); -+ -+#else /* PRISM2_PCI_USE_LONG_DELAYS */ -+ -+ HFA384X_OUTW(0x0080, HFA384X_PCICOR_OFF); -+ mdelay(1); -+ HFA384X_OUTW(0x0, HFA384X_PCICOR_OFF); -+ mdelay(1); -+ -+#endif /* PRISM2_PCI_USE_LONG_DELAYS */ -+ -+ if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) { -+ printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name); -+ } -+} -+ -+ -+static struct prism2_helper_functions prism2_pci_funcs = -+{ -+ .card_present = NULL, -+ .cor_sreset = prism2_pci_cor_sreset, -+ .dev_open = NULL, -+ .dev_close = NULL -+}; -+ -+ -+static int prism2_pci_probe(struct pci_dev *pdev, -+ const struct pci_device_id *id) -+{ -+ unsigned long phymem; -+ unsigned long mem = 0; -+ local_info_t *local = NULL; -+ struct net_device *dev = NULL; -+ static int cards_found /* = 0 */; -+ int irq_registered = 0; -+ -+ if (pci_enable_device(pdev)) -+ return -EIO; -+ -+ phymem = pci_resource_start(pdev, 0); -+ -+ if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { -+ printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); -+ goto err_out_disable; -+ } -+ -+ mem = (unsigned long) ioremap(phymem, pci_resource_len(pdev, 0)); -+ if (!mem) { -+ printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ; -+ goto fail; -+ } -+ -+#ifdef PRISM2_BUS_MASTER -+ pci_set_master(pdev); -+#endif /* PRISM2_BUS_MASTER */ -+ -+ local = prism2_init_local_data(&prism2_pci_funcs, cards_found); -+ if (local == NULL) -+ goto fail; -+ cards_found++; -+ -+ dev = local->dev; -+ -+ dev->irq = pdev->irq; -+ dev->mem_start = mem; -+ dev->mem_end = mem + pci_resource_len(pdev, 0); -+ -+ if (prism2_init_dev(local)) -+ goto fail; -+ -+ prism2_pci_cor_sreset(local); -+ -+ pci_set_drvdata(pdev, dev); -+ -+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name, -+ dev)) { -+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name); -+ goto fail; -+ } else -+ irq_registered = 1; -+ -+ if (prism2_hw_config(dev, 1)) { -+ printk(KERN_DEBUG "%s: hardware initialization failed\n", -+ dev_info); -+ goto fail; -+ } -+ -+ printk(KERN_INFO "%s: Intersil Prism2.5 PCI: " -+ "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq); -+ -+ return 0; -+ -+ fail: -+ prism2_free_local_data(local); -+ -+ if (irq_registered && dev) -+ free_irq(dev->irq, dev); -+ -+ if (mem) -+ iounmap((void *) mem); -+ -+ release_mem_region(phymem, pci_resource_len(pdev, 0)); -+ -+ err_out_disable: -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)) -+ pci_disable_device(pdev); -+#endif -+ -+ return -ENODEV; -+} -+ -+ -+static void prism2_pci_remove(struct pci_dev *pdev) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ local_info_t *local = (local_info_t *) dev->priv; -+ unsigned long mem_start; -+ -+ /* Reset the hardware, and ensure interrupts are disabled. */ -+ prism2_pci_cor_sreset(local); -+ hfa384x_disable_interrupts(dev); -+ -+ if (dev->irq) -+ free_irq(dev->irq, dev); -+ -+ mem_start = dev->mem_start; -+ prism2_free_local_data(local); -+ -+ iounmap((void *) mem_start); -+ -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)) -+ pci_disable_device(pdev); -+#endif -+} -+ -+ -+#ifdef CONFIG_PM -+static int prism2_pci_suspend(struct pci_dev *pdev, u32 state) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ if (netif_running(dev)) { -+ hostap_netif_stop_queues(dev); -+ netif_device_detach(dev); -+ } -+ prism2_hw_shutdown(dev, 0); -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6)) -+ pci_save_state(pdev, local->pci_save_state); -+#endif -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)) -+ pci_disable_device(pdev); -+#endif -+ pci_set_power_state(pdev, 3); -+ -+ return 0; -+} -+ -+static int prism2_pci_resume(struct pci_dev *pdev) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ pci_enable_device(pdev); -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6)) -+ pci_restore_state(pdev, local->pci_save_state); -+#endif -+ prism2_hw_config(dev, 0); -+ if (netif_running(dev)) { -+ netif_device_attach(dev); -+ netif_start_queue(dev); -+ } -+ -+ return 0; -+} -+#endif /* CONFIG_PM */ -+ -+ -+MODULE_DEVICE_TABLE(pci, prism2_pci_id_table); -+ -+static struct pci_driver prism2_pci_drv_id = { -+ .name = "prism2_pci", -+ .id_table = prism2_pci_id_table, -+ .probe = prism2_pci_probe, -+ .remove = prism2_pci_remove, -+#ifdef CONFIG_PM -+ .suspend = prism2_pci_suspend, -+ .resume = prism2_pci_resume, -+#endif /* CONFIG_PM */ -+ /* Linux 2.4.6 added save_state and enable_wake that are not used here -+ */ -+}; -+ -+ -+static int __init init_prism2_pci(void) -+{ -+ printk(KERN_INFO "%s: %s\n", dev_info, version); -+ -+ if (pci_register_driver(&prism2_pci_drv_id) <= 0) { -+ printk("hostap_pci: No devices found, driver not " -+ "installed.\n"); -+ pci_unregister_driver(&prism2_pci_drv_id); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+ -+static void __exit exit_prism2_pci(void) -+{ -+ pci_unregister_driver(&prism2_pci_drv_id); -+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -+} -+ -+ -+module_init(init_prism2_pci); -+module_exit(exit_prism2_pci); - -Index: drivers/net/wireless/hostap_plx.c ---- drivers/net/wireless/hostap_plx.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_plx.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,589 @@ -+#define PRISM2_PLX -+ -+/* Host AP driver's support for PC Cards on PCI adapters using PLX9052 is -+ * based on: -+ * - Host AP driver patch from james@madingley.org -+ * - linux-wlan-ng driver, Copyright (C) AbsoluteValue Systems, Inc. -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)) -+#include -+#else -+#include -+#endif -+#include -+#if WIRELESS_EXT > 12 -+#include -+#endif /* WIRELESS_EXT > 12 */ -+ -+#include -+#include -+ -+#include "hostap_wlan.h" -+ -+ -+static char *version = PRISM2_VERSION " (Jouni Malinen )"; -+static char *dev_info = "hostap_plx"; -+ -+ -+MODULE_AUTHOR("SSH Communications Security Corp, Jouni Malinen"); -+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " -+ "cards (PLX)."); -+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+ -+ -+static int ignore_cis = 0; -+MODULE_PARM(ignore_cis, "i"); -+MODULE_PARM_DESC(ignore_cis, "Do not verify manfid information in CIS"); -+ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) -+/* PCI initialization uses Linux 2.4.x version and older kernels do not support -+ * this */ -+#error PLX9052 version requires at least Linux kernel version 2.4.0 -+#endif /* kernel < 2.4.0 */ -+ -+ -+#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */ -+#define COR_SRESET 0x80 -+#define COR_LEVLREQ 0x40 -+#define COR_ENABLE_FUNC 0x01 -+/* PCI Configuration Registers */ -+#define PLX_PCIIPR 0x3d /* PCI Interrupt Pin */ -+/* Local Configuration Registers */ -+#define PLX_INTCSR 0x4c /* Interrupt Control/Status Register */ -+#define PLX_INTCSR_PCI_INTEN BIT(6) /* PCI Interrupt Enable */ -+#define PLX_CNTRL 0x50 -+#define PLX_CNTRL_SERIAL_EEPROM_PRESENT BIT(28) -+ -+ -+#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID } -+ -+static struct pci_device_id prism2_plx_id_table[] __devinitdata = { -+ PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"), -+ PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"), -+ PLXDEV(0x126c, 0x8030, "Nortel emobility"), -+ PLXDEV(0x1385, 0x4100, "Netgear MA301"), -+ PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"), -+ PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"), -+ PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"), -+ PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"), -+ PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"), -+ PLXDEV(0x16ab, 0x1103, "Longshine 8031"), -+ PLXDEV(0x16ec, 0x3685, "US Robotics USR2415"), -+ PLXDEV(0xec80, 0xec00, "Belkin F5D6000"), -+ { 0 } -+}; -+ -+ -+/* Array of known Prism2/2.5 PC Card manufactured ids. If your card's manfid -+ * is not listed here, you will need to add it here to get the driver -+ * initialized. */ -+static struct prism2_plx_manfid { -+ u16 manfid1, manfid2; -+} prism2_plx_known_manfids[] = { -+ { 0x000b, 0x7300 } /* Philips 802.11b WLAN PCMCIA */, -+ { 0x0101, 0x0777 } /* 3Com AirConnect PCI 777A */, -+ { 0x0126, 0x8000 } /* Proxim RangeLAN */, -+ { 0x0138, 0x0002 } /* Compaq WL100 */, -+ { 0x0156, 0x0002 } /* Intersil Prism II Ref. Design (and others) */, -+ { 0x026f, 0x030b } /* Buffalo WLI-CF-S11G */, -+ { 0x0274, 0x1612 } /* Linksys WPC11 Ver 2.5 */, -+ { 0x0274, 0x1613 } /* Linksys WPC11 Ver 3 */, -+ { 0x028a, 0x0002 } /* D-Link DRC-650 */, -+ { 0x0250, 0x0002 } /* Samsung SWL2000-N */, -+ { 0xc250, 0x0002 } /* EMTAC A2424i */, -+ { 0xd601, 0x0002 } /* Z-Com XI300 */, -+ { 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */, -+ { 0, 0} -+}; -+ -+ -+#ifdef PRISM2_IO_DEBUG -+ -+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); -+ outb(v, dev->base_addr + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u8 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = inb(dev->base_addr + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); -+ outw(v, dev->base_addr + a); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ u16 v; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ v = inw(dev->base_addr + a); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); -+ spin_unlock_irqrestore(&local->lock, flags); -+ return v; -+} -+ -+static inline void hfa384x_outsw_debug(struct net_device *dev, int a, -+ u8 *buf, int wc) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc); -+ outsw(dev->base_addr + a, buf, wc); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+static inline void hfa384x_insw_debug(struct net_device *dev, int a, -+ u8 *buf, int wc) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc); -+ insw(dev->base_addr + a, buf, wc); -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc)) -+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc)) -+ -+#else /* PRISM2_IO_DEBUG */ -+ -+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a)) -+#define HFA384X_INB(a) inb(dev->base_addr + (a)) -+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a)) -+#define HFA384X_INW(a) inw(dev->base_addr + (a)) -+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc) -+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc) -+ -+#endif /* PRISM2_IO_DEBUG */ -+ -+ -+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, -+ int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ if (len / 2) -+ HFA384X_INSW(d_off, buf, len / 2); -+ pos += len / 2; -+ -+ if (len & 1) -+ *((char *) pos) = HFA384X_INB(d_off); -+ -+ return 0; -+} -+ -+ -+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -+{ -+ u16 d_off; -+ u16 *pos; -+ -+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; -+ pos = (u16 *) buf; -+ -+ if (len / 2) -+ HFA384X_OUTSW(d_off, buf, len / 2); -+ pos += len / 2; -+ -+ if (len & 1) -+ HFA384X_OUTB(*((char *) pos), d_off); -+ -+ return 0; -+} -+ -+ -+/* FIX: This might change at some point.. */ -+#include "hostap_hw.c" -+ -+ -+static void prism2_plx_cor_sreset(local_info_t *local) -+{ -+ unsigned char corsave; -+ -+ printk(KERN_DEBUG "%s: Doing reset via direct COR access.\n", -+ dev_info); -+ -+ /* Set sreset bit of COR and clear it after hold time */ -+ -+ if (local->attr_mem == 0) { -+ /* TMD7160 - COR at card's first I/O addr */ -+ corsave = inb(local->cor_offset); -+ outb(corsave | COR_SRESET, local->cor_offset); -+ mdelay(1); -+ outb(corsave & ~COR_SRESET, local->cor_offset); -+ mdelay(1); -+ } else { -+ /* PLX9052 */ -+ corsave = readb(local->attr_mem + local->cor_offset); -+ writeb(corsave | COR_SRESET, -+ local->attr_mem + local->cor_offset); -+ mdelay(1); -+ writeb(corsave & ~COR_SRESET, -+ local->attr_mem + local->cor_offset); -+ mdelay(1); -+ } -+} -+ -+ -+static struct prism2_helper_functions prism2_plx_funcs = -+{ -+ .card_present = NULL, -+ .cor_sreset = prism2_plx_cor_sreset, -+ .dev_open = NULL, -+ .dev_close = NULL -+}; -+ -+ -+static int prism2_plx_check_cis(unsigned long attr_mem, int attr_len, -+ unsigned int *cor_offset, -+ unsigned int *cor_index) -+{ -+#define CISTPL_CONFIG 0x1A -+#define CISTPL_MANFID 0x20 -+#define CISTPL_END 0xFF -+#define CIS_MAX_LEN 256 -+ u8 cis[CIS_MAX_LEN]; -+ int i, pos; -+ unsigned int rmsz, rasz, manfid1, manfid2; -+ struct prism2_plx_manfid *manfid; -+ -+ /* read CIS; it is in even offsets in the beginning of attr_mem */ -+ for (i = 0; i < CIS_MAX_LEN; i++) -+ cis[i] = readb(attr_mem + 2 * i); -+ printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n", -+ dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]); -+ -+ /* set reasonable defaults for Prism2 cards just in case CIS parsing -+ * fails */ -+ *cor_offset = 0x3e0; -+ *cor_index = 0x01; -+ manfid1 = manfid2 = 0; -+ -+ pos = 0; -+ while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) { -+ if (pos + cis[pos + 1] >= CIS_MAX_LEN) -+ goto cis_error; -+ -+ switch (cis[pos]) { -+ case CISTPL_CONFIG: -+ if (cis[pos + 1] < 1) -+ goto cis_error; -+ rmsz = (cis[pos + 2] & 0x3c) >> 2; -+ rasz = cis[pos + 2] & 0x03; -+ if (4 + rasz + rmsz > cis[pos + 1]) -+ goto cis_error; -+ *cor_index = cis[pos + 3] & 0x3F; -+ *cor_offset = 0; -+ for (i = 0; i <= rasz; i++) -+ *cor_offset += cis[pos + 4 + i] << (8 * i); -+ printk(KERN_DEBUG "%s: cor_index=0x%x " -+ "cor_offset=0x%x\n", dev_info, -+ *cor_index, *cor_offset); -+ if (*cor_offset > attr_len) { -+ printk(KERN_ERR "%s: COR offset not within " -+ "attr_mem\n", dev_info); -+ return -1; -+ } -+ break; -+ -+ case CISTPL_MANFID: -+ if (cis[pos + 1] < 4) -+ goto cis_error; -+ manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); -+ manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); -+ printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n", -+ dev_info, manfid1, manfid2); -+ break; -+ } -+ -+ pos += cis[pos + 1] + 2; -+ } -+ -+ if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END) -+ goto cis_error; -+ -+ for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++) -+ if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) -+ return 0; -+ -+ printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is" -+ " not supported card\n", dev_info, manfid1, manfid2); -+ goto fail; -+ -+ cis_error: -+ printk(KERN_WARNING "%s: invalid CIS data\n", dev_info); -+ -+ fail: -+ if (ignore_cis) { -+ printk(KERN_INFO "%s: ignore_cis parameter set - ignoring " -+ "errors during CIS verification\n", dev_info); -+ return 0; -+ } -+ return -1; -+} -+ -+ -+static int prism2_plx_probe(struct pci_dev *pdev, -+ const struct pci_device_id *id) -+{ -+ unsigned int pccard_ioaddr, plx_ioaddr; -+ unsigned long pccard_attr_mem; -+ unsigned int pccard_attr_len; -+ unsigned long attr_mem = 0; -+ unsigned int cor_offset, cor_index; -+ u32 reg; -+ local_info_t *local = NULL; -+ struct net_device *dev = NULL; -+ static int cards_found /* = 0 */; -+ int irq_registered = 0; -+ int tmd7160; -+ -+ if (pci_enable_device(pdev)) -+ return -EIO; -+ -+ /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ -+ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); -+ -+ plx_ioaddr = pci_resource_start(pdev, 1); -+ pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3); -+ -+ if (tmd7160) { -+ /* TMD7160 */ -+ attr_mem = 0; /* no access to PC Card attribute memory */ -+ -+ printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, " -+ "irq=%d, pccard_io=0x%x\n", -+ plx_ioaddr, pdev->irq, pccard_ioaddr); -+ -+ cor_offset = plx_ioaddr; -+ cor_index = 0x04; -+ -+ outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr); -+ mdelay(1); -+ reg = inb(plx_ioaddr); -+ if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) { -+ printk(KERN_ERR "%s: Error setting COR (expected=" -+ "0x%02x, was=0x%02x)\n", dev_info, -+ cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg); -+ goto fail; -+ } -+ } else { -+ /* PLX9052 */ -+ pccard_attr_mem = pci_resource_start(pdev, 2); -+ pccard_attr_len = pci_resource_len(pdev, 2); -+ if (pccard_attr_len < PLX_MIN_ATTR_LEN) -+ goto fail; -+ -+ -+ attr_mem = (unsigned long) ioremap(pccard_attr_mem, -+ pccard_attr_len); -+ if (!attr_mem) { -+ printk(KERN_ERR "%s: cannot remap attr_mem\n", -+ dev_info); -+ goto fail; -+ } -+ -+ printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: " -+ "mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n", -+ pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr); -+ -+ if (prism2_plx_check_cis(attr_mem, pccard_attr_len, -+ &cor_offset, &cor_index)) { -+ printk(KERN_INFO "Unknown PC Card CIS - not a " -+ "Prism2/2.5 card?\n"); -+ goto fail; -+ } -+ -+ printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 " -+ "adapter\n"); -+ -+ /* Write COR to enable PC Card */ -+ writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, -+ attr_mem + cor_offset); -+ -+ /* Enable PCI interrupts if they are not already enabled */ -+ reg = inl(plx_ioaddr + PLX_INTCSR); -+ printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg); -+ if (!(reg & PLX_INTCSR_PCI_INTEN)) { -+ outl(reg | PLX_INTCSR_PCI_INTEN, -+ plx_ioaddr + PLX_INTCSR); -+ if (!(inl(plx_ioaddr + PLX_INTCSR) & -+ PLX_INTCSR_PCI_INTEN)) { -+ printk(KERN_WARNING "%s: Could not enable " -+ "Local Interrupts\n", dev_info); -+ goto fail; -+ } -+ } -+ -+ reg = inl(plx_ioaddr + PLX_CNTRL); -+ printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM " -+ "present=%d)\n", -+ reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0); -+ /* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is -+ * not present; but are there really such cards in use(?) */ -+ } -+ -+ local = prism2_init_local_data(&prism2_plx_funcs, cards_found); -+ if (local == NULL) -+ goto fail; -+ cards_found++; -+ -+ dev = local->dev; -+ -+ dev->irq = pdev->irq; -+ dev->base_addr = pccard_ioaddr; -+ local->attr_mem = attr_mem; -+ local->cor_offset = cor_offset; -+ -+ if (prism2_init_dev(local)) -+ goto fail; -+ -+ pci_set_drvdata(pdev, dev); -+ -+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name, -+ dev)) { -+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name); -+ goto fail; -+ } else -+ irq_registered = 1; -+ -+ if (prism2_hw_config(dev, 1)) { -+ printk(KERN_DEBUG "%s: hardware initialization failed\n", -+ dev_info); -+ goto fail; -+ } -+ -+ return 0; -+ -+ fail: -+ prism2_free_local_data(local); -+ -+ if (irq_registered && dev) -+ free_irq(dev->irq, dev); -+ -+ if (attr_mem) -+ iounmap((void *) attr_mem); -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)) -+ pci_disable_device(pdev); -+#endif -+ -+ return -ENODEV; -+} -+ -+ -+static void prism2_plx_remove(struct pci_dev *pdev) -+{ -+ struct net_device *dev = pci_get_drvdata(pdev); -+ local_info_t *local = (local_info_t *) dev->priv; -+ -+ /* Reset the hardware, and ensure interrupts are disabled. */ -+ prism2_plx_cor_sreset(local); -+ hfa384x_disable_interrupts(dev); -+ -+ if (local->attr_mem) -+ iounmap((void *) local->attr_mem); -+ if (dev->irq) -+ free_irq(dev->irq, dev); -+ -+ prism2_free_local_data(local); -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)) -+ pci_disable_device(pdev); -+#endif -+} -+ -+ -+MODULE_DEVICE_TABLE(pci, prism2_plx_id_table); -+ -+static struct pci_driver prism2_plx_drv_id = { -+ .name = "prism2_plx", -+ .id_table = prism2_plx_id_table, -+ .probe = prism2_plx_probe, -+ .remove = prism2_plx_remove, -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6)) -+ .save_state = NULL, -+ .suspend = NULL, -+ .resume = NULL, -+ .enable_wake = NULL -+#else /* Linux < 2.4.6 */ -+ .suspend = NULL, -+ .resume = NULL -+#endif /* Linux >= 2.4.6 */ -+}; -+ -+ -+static int __init init_prism2_plx(void) -+{ -+ printk(KERN_INFO "%s: %s\n", dev_info, version); -+ -+ if (pci_register_driver(&prism2_plx_drv_id) <= 0) { -+ printk("hostap_plx: No devices found, driver not " -+ "installed.\n"); -+ pci_unregister_driver(&prism2_plx_drv_id); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+ -+static void __exit exit_prism2_plx(void) -+{ -+ pci_unregister_driver(&prism2_plx_drv_id); -+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -+} -+ -+ -+module_init(init_prism2_plx); -+module_exit(exit_prism2_plx); - -Index: drivers/net/wireless/hostap_proc.c ---- drivers/net/wireless/hostap_proc.c.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_proc.c 2003-06-23 18:52:56.000000000 -0400 -@@ -0,0 +1,322 @@ -+/* /proc routines for Host AP driver */ -+ -+#define PROC_LIMIT (PAGE_SIZE - 80) -+ -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+static int prism2_debug_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ local_info_t *local = (local_info_t *) data; -+ int i; -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+ p += sprintf(p, "next_txfid=%d next_alloc=%d\n", -+ local->next_txfid, local->next_alloc); -+ for (i = 0; i < PRISM2_TXFID_COUNT; i++) -+ p += sprintf(p, "FID: tx=%04X intransmit=%04X\n", -+ local->txfid[i], local->intransmitfid[i]); -+ p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control); -+ p += sprintf(p, "beacon_int=%d\n", local->beacon_int); -+ p += sprintf(p, "dtim_period=%d\n", local->dtim_period); -+ p += sprintf(p, "wds_max_connections=%d\n", -+ local->wds_max_connections); -+ p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled); -+ p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck); -+ if (local->crypt && local->crypt->ops) -+ p += sprintf(p, "crypt=%s\n", local->crypt->ops->name); -+ -+ return (p - page); -+} -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ -+ -+static int prism2_stats_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ local_info_t *local = (local_info_t *) data; -+ struct comm_tallies_sums *sums = (struct comm_tallies_sums *) -+ &local->comm_tallies; -+ -+ if (off != 0) { -+ *eof = 1; -+ return 0; -+ } -+ -+ p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames); -+ p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames); -+ p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments); -+ p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets); -+ p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets); -+ p += sprintf(p, "TxDeferredTransmissions=%u\n", -+ sums->tx_deferred_transmissions); -+ p += sprintf(p, "TxSingleRetryFrames=%u\n", -+ sums->tx_single_retry_frames); -+ p += sprintf(p, "TxMultipleRetryFrames=%u\n", -+ sums->tx_multiple_retry_frames); -+ p += sprintf(p, "TxRetryLimitExceeded=%u\n", -+ sums->tx_retry_limit_exceeded); -+ p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards); -+ p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames); -+ p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames); -+ p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments); -+ p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets); -+ p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets); -+ p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors); -+ p += sprintf(p, "RxDiscardsNoBuffer=%u\n", -+ sums->rx_discards_no_buffer); -+ p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa); -+ p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n", -+ sums->rx_discards_wep_undecryptable); -+ p += sprintf(p, "RxMessageInMsgFragments=%u\n", -+ sums->rx_message_in_msg_fragments); -+ p += sprintf(p, "RxMessageInBadMsgFragments=%u\n", -+ sums->rx_message_in_bad_msg_fragments); -+ /* FIX: this may grow too long for one page(?) */ -+ -+ return (p - page); -+} -+ -+ -+static int prism2_wds_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ local_info_t *local = (local_info_t *) data; -+ prism2_wds_info_t *wds; -+ unsigned long flags; -+ -+ if (off > PROC_LIMIT) { -+ *eof = 1; -+ return 0; -+ } -+ -+ spin_lock_irqsave(&local->wdslock, flags); -+ wds = local->wds; -+ while (wds != NULL) { -+ p += sprintf(p, "%s\t" MACSTR "\n", -+ wds->dev.name, MAC2STR(wds->remote_addr)); -+ if ((p - page) > PROC_LIMIT) { -+ printk(KERN_DEBUG "%s: wds proc did not fit\n", -+ local->dev->name); -+ break; -+ } -+ wds = wds->next; -+ } -+ spin_unlock_irqrestore(&local->wdslock, flags); -+ -+ if ((p - page) <= off) { -+ *eof = 1; -+ return 0; -+ } -+ -+ *start = page + off; -+ -+ return (p - page - off); -+} -+ -+ -+static int prism2_pda_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ -+ if (local->pda == NULL || off >= PRISM2_PDA_SIZE) { -+ *eof = 1; -+ return 0; -+ } -+ -+ if (off + count > PRISM2_PDA_SIZE) -+ count = PRISM2_PDA_SIZE - off; -+ -+ memcpy(page, local->pda + off, count); -+ return count; -+} -+ -+ -+#ifdef PRISM2_IO_DEBUG -+static int prism2_io_debug_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ local_info_t *local = (local_info_t *) data; -+ int head = local->io_debug_head; -+ int start_bytes, left, copy, copied; -+ -+ if (off + count > PRISM2_IO_DEBUG_SIZE * 4) { -+ *eof = 1; -+ if (off >= PRISM2_IO_DEBUG_SIZE * 4) -+ return 0; -+ count = PRISM2_IO_DEBUG_SIZE * 4 - off; -+ } -+ -+ copied = 0; -+ start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4; -+ left = count; -+ -+ if (off < start_bytes) { -+ copy = start_bytes - off; -+ if (copy > count) -+ copy = count; -+ memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy); -+ left -= copy; -+ if (left > 0) -+ memcpy(&page[copy], local->io_debug, left); -+ } else { -+ memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes), -+ left); -+ } -+ -+ *start = page; -+ -+ return count; -+} -+#endif /* PRISM2_IO_DEBUG */ -+ -+ -+#ifndef PRISM2_NO_STATION_MODES -+static int prism2_scan_results_proc_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ char *p = page; -+ local_info_t *local = (local_info_t *) data; -+ int entry, i, len, total = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ p += sprintf(p, "Total ScanResults: %d\n", -+ local->last_scan_results_count); -+ for (entry = 0; entry < local->last_scan_results_count; entry++) { -+ struct hfa384x_scan_result *scanres = -+ &local->last_scan_results[entry]; -+ -+ if (total + (p - page) <= off) { -+ total += p - page; -+ p = page; -+ } -+ if (total + (p - page) > off + count) -+ break; -+ if ((p - page) > (PAGE_SIZE - 200)) -+ break; -+ -+ p += sprintf(p, "ScanResult %d:\n" -+ " CHID=%d ANL=%d SL=%d BcnInt=%d Capab=0x%02x " -+ "Rate=%d\n" -+ " bssid=" MACSTR " SSID='", -+ entry, -+ le16_to_cpu(scanres->chid), -+ le16_to_cpu(scanres->anl), -+ le16_to_cpu(scanres->sl), -+ le16_to_cpu(scanres->beacon_interval), -+ le16_to_cpu(scanres->capability), -+ le16_to_cpu(scanres->rate), -+ MAC2STR(scanres->bssid)); -+ len = le16_to_cpu(scanres->ssid_len); -+ if (len > 32) -+ len = 32; -+ for (i = 0; i < len; i++) { -+ unsigned char c = scanres->ssid[i]; -+ if (c >= 32 && c < 127) -+ p += sprintf(p, "%c", c); -+ else -+ p += sprintf(p, "<%02x>", c); -+ } -+ p += sprintf(p, "'\n" -+ " SupRates="); -+ for (i = 0; i < sizeof(scanres->sup_rates); i++) { -+ if (scanres->sup_rates[i] == 0) -+ break; -+ p += sprintf(p, "%02x ", scanres->sup_rates[i]); -+ } -+ p += sprintf(p, "\n"); -+ } -+ spin_unlock_irqrestore(&local->lock, flags); -+ -+ total += (p - page); -+ if (total >= off + count) -+ *eof = 1; -+ -+ if (total < off) { -+ *eof = 1; -+ return 0; -+ } -+ -+ len = total - off; -+ if (len > (p - page)) -+ len = p - page; -+ *start = p - len; -+ if (len > count) -+ len = count; -+ -+ return len; -+} -+#endif /* PRISM2_NO_STATION_MODES */ -+ -+ -+void hostap_init_proc(local_info_t *local) -+{ -+ local->proc = NULL; -+ -+ if (hostap_proc == NULL) { -+ printk(KERN_WARNING "%s: hostap proc directory not created\n", -+ local->dev->name); -+ return; -+ } -+ -+ local->proc = proc_mkdir(local->dev->name, hostap_proc); -+ if (local->proc == NULL) { -+ printk(KERN_INFO "/proc/net/hostap/%s creation failed\n", -+ local->dev->name); -+ return; -+ } -+ -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ create_proc_read_entry("debug", 0, local->proc, -+ prism2_debug_proc_read, local); -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ create_proc_read_entry("stats", 0, local->proc, -+ prism2_stats_proc_read, local); -+ create_proc_read_entry("wds", 0, local->proc, -+ prism2_wds_proc_read, local); -+ create_proc_read_entry("pda", 0, local->proc, -+ prism2_pda_proc_read, local); -+#ifdef PRISM2_IO_DEBUG -+ create_proc_read_entry("io_debug", 0, local->proc, -+ prism2_io_debug_proc_read, local); -+#endif /* PRISM2_IO_DEBUG */ -+#ifndef PRISM2_NO_STATION_MODES -+ create_proc_read_entry("scan_results", 0, local->proc, -+ prism2_scan_results_proc_read, local); -+#endif /* PRISM2_NO_STATION_MODES */ -+} -+ -+ -+void hostap_remove_proc(local_info_t *local) -+{ -+ if (local->proc != NULL) { -+#ifndef PRISM2_NO_STATION_MODES -+ remove_proc_entry("scan_results", local->proc); -+#endif /* PRISM2_NO_STATION_MODES */ -+#ifdef PRISM2_IO_DEBUG -+ remove_proc_entry("io_debug", local->proc); -+#endif /* PRISM2_IO_DEBUG */ -+ remove_proc_entry("pda", local->proc); -+ remove_proc_entry("wds", local->proc); -+ remove_proc_entry("stats", local->proc); -+#ifndef PRISM2_NO_PROCFS_DEBUG -+ remove_proc_entry("debug", local->proc); -+#endif /* PRISM2_NO_PROCFS_DEBUG */ -+ if (local->dev != NULL && local->dev->name != NULL && -+ hostap_proc != NULL) -+ remove_proc_entry(local->dev->name, hostap_proc); -+ } -+} -+ -+ -+EXPORT_SYMBOL(hostap_init_proc); -+EXPORT_SYMBOL(hostap_remove_proc); - -Index: drivers/net/wireless/hostap_wlan.h ---- drivers/net/wireless/hostap_wlan.h.orig 2003-08-12 14:39:16.000000000 -0400 -+++ drivers/net/wireless/hostap_wlan.h 2003-07-21 02:00:22.000000000 -0400 -@@ -0,0 +1,1487 @@ -+#ifndef HOSTAP_WLAN_H -+#define HOSTAP_WLAN_H -+ -+#include "hostap_config.h" -+#ifdef __KERNEL__ -+#include "hostap_compat.h" -+#endif -+#include "hostap_crypt.h" -+ -+#define MAX_PARM_DEVICES 8 -+#define PARM_MIN_MAX "1-" __MODULE_STRING(MAX_PARM_DEVICES) -+#define DEF_INTS -1, -1, -1, -1, -1, -1, -1 -+#define GET_INT_PARM(var,idx) var[var[idx] < 0 ? 0 : idx] -+ -+ -+#define BIT(x) (1 << (x)) -+ -+/* Specific skb->protocol value that indicates that the packet already contains -+ * txdesc header. -+ * FIX: This might need own value that would be allocated especially for Prism2 -+ * txdesc; ETH_P_CONTROL is commented as "Card specific control frames". -+ * However, these skb's should have only minimal path in the kernel side since -+ * prism2_send_mgmt() sends these with dev_queue_xmit() to prism2_tx(). */ -+#define ETH_P_HOSTAP ETH_P_CONTROL -+ -+#ifndef ETH_P_PAE -+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -+#endif /* ETH_P_PAE */ -+ -+#ifndef ARPHRD_IEEE80211 -+#define ARPHRD_IEEE80211 801 -+#endif -+#ifndef ARPHRD_IEEE80211_PRISM -+#define ARPHRD_IEEE80211_PRISM 802 -+#endif -+ -+/* ARPHRD_IEEE80211_PRISM uses a bloated version of Prism2 RX frame header -+ * (from linux-wlan-ng) */ -+struct linux_wlan_ng_val { -+ u32 did; -+ u16 status, len; -+ u32 data; -+} __attribute__ ((packed)); -+ -+struct linux_wlan_ng_prism_hdr { -+ u32 msgcode, msglen; -+ char devname[16]; -+ struct linux_wlan_ng_val hosttime, mactime, channel, rssi, sq, signal, -+ noise, rate, istx, frmlen; -+} __attribute__ ((packed)); -+ -+struct linux_wlan_ng_cap_hdr { -+ u32 version; -+ u32 length; -+ u64 mactime; -+ u64 hosttime; -+ u32 phytype; -+ u32 channel; -+ u32 datarate; -+ u32 antenna; -+ u32 priority; -+ u32 ssi_type; -+ s32 ssi_signal; -+ s32 ssi_noise; -+ u32 preamble; -+ u32 encoding; -+} __attribute__ ((packed)); -+ -+#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */ -+#define LWNG_CAPHDR_VERSION 0x80211001 -+ -+struct hostap_ieee80211_hdr { -+ u16 frame_control; -+ u16 duration_id; -+ u8 addr1[6]; -+ u8 addr2[6]; -+ u8 addr3[6]; -+ u16 seq_ctrl; -+ u8 addr4[6]; -+} __attribute__ ((packed)); -+ -+ -+struct hfa384x_rx_frame { -+ /* HFA384X RX frame descriptor */ -+ u16 status; /* HFA384X_RX_STATUS_ flags */ -+ u32 time; /* timestamp, 1 microsecond resolution */ -+ u8 silence; /* 27 .. 154; seems to be 0 */ -+ u8 signal; /* 27 .. 154 */ -+ u8 rate; /* 10, 20, 55, or 110 */ -+ u8 rxflow; -+ u32 reserved; -+ -+ /* 802.11 */ -+ u16 frame_control; -+ u16 duration_id; -+ u8 addr1[6]; -+ u8 addr2[6]; -+ u8 addr3[6]; -+ u16 seq_ctrl; -+ u8 addr4[6]; -+ u16 data_len; -+ -+ /* 802.3 */ -+ u8 dst_addr[6]; -+ u8 src_addr[6]; -+ u16 len; -+ -+ /* followed by frame data; max 2304 bytes */ -+} __attribute__ ((packed)); -+ -+ -+struct hfa384x_tx_frame { -+ /* HFA384X TX frame descriptor */ -+ u16 status; /* HFA384X_TX_STATUS_ flags */ -+ u16 reserved1; -+ u16 reserved2; -+ u32 sw_support; -+ u8 retry_count; /* not yet implemented */ -+ u8 tx_rate; /* Host AP only; 0 = firmware, or 10, 20, 55, 110 */ -+ u16 tx_control; /* HFA384X_TX_CTRL_ flags */ -+ -+ /* 802.11 */ -+ u16 frame_control; /* parts not used */ -+ u16 duration_id; -+ u8 addr1[6]; -+ u8 addr2[6]; /* filled by firmware */ -+ u8 addr3[6]; -+ u16 seq_ctrl; /* filled by firmware */ -+ u8 addr4[6]; -+ u16 data_len; -+ -+ /* 802.3 */ -+ u8 dst_addr[6]; -+ u8 src_addr[6]; -+ u16 len; -+ -+ /* followed by frame data; max 2304 bytes */ -+} __attribute__ ((packed)); -+ -+ -+struct hfa384x_rid_hdr -+{ -+ u16 len; -+ u16 rid; -+} __attribute__ ((packed)); -+ -+ -+struct hfa384x_comp_ident -+{ -+ u16 id; -+ u16 variant; -+ u16 major; -+ u16 minor; -+} __attribute__ ((packed)); -+ -+#define HFA384X_COMP_ID_PRI 0x15 -+#define HFA384X_COMP_ID_STA 0x1f -+#define HFA384X_COMP_ID_FW_AP 0x14b -+ -+struct hfa384x_sup_range -+{ -+ u16 role; -+ u16 id; -+ u16 variant; -+ u16 bottom; -+ u16 top; -+} __attribute__ ((packed)); -+ -+struct hfa384x_build_id -+{ -+ u16 pri_seq; -+ u16 sec_seq; -+} __attribute__ ((packed)); -+ -+/* FD01 - Download Buffer */ -+struct hfa384x_rid_download_buffer -+{ -+ u16 page; -+ u16 offset; -+ u16 length; -+} __attribute__ ((packed)); -+ -+/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */ -+struct hfa384x_comms_quality { -+ u16 comm_qual; /* 0 .. 92 */ -+ u16 signal_level; /* 27 .. 154 */ -+ u16 noise_level; /* 27 .. 154 */ -+} __attribute__ ((packed)); -+ -+/* Macro for converting signal levels (range 27 .. 154) to wireless ext -+ * dBm value with some accuracy */ -+#define HFA384X_LEVEL_TO_dBm(v) 0x100 + (v) * 100 / 255 - 100 -+ -+/* Macro for converting signal/silence levels (RSSI) from RX descriptor to -+ * dBm */ -+#define HFA384X_RSSI_LEVEL_TO_dBm(v) ((v) - 100) -+ -+struct hfa384x_scan_request { -+ u16 channel_list; -+ u16 txrate; /* HFA384X_RATES_* */ -+} __attribute__ ((packed)); -+ -+struct hfa384x_hostscan_request { -+ u16 channel_list; -+ u16 txrate; -+ u16 target_ssid_len; -+ u8 target_ssid[32]; -+} __attribute__ ((packed)); -+ -+struct hfa384x_join_request { -+ u8 bssid[6]; -+ u16 channel; -+} __attribute__ ((packed)); -+ -+struct hfa384x_info_frame { -+ u16 len; -+ u16 type; -+} __attribute__ ((packed)); -+ -+struct hfa384x_comm_tallies { -+ u16 tx_unicast_frames; -+ u16 tx_multicast_frames; -+ u16 tx_fragments; -+ u16 tx_unicast_octets; -+ u16 tx_multicast_octets; -+ u16 tx_deferred_transmissions; -+ u16 tx_single_retry_frames; -+ u16 tx_multiple_retry_frames; -+ u16 tx_retry_limit_exceeded; -+ u16 tx_discards; -+ u16 rx_unicast_frames; -+ u16 rx_multicast_frames; -+ u16 rx_fragments; -+ u16 rx_unicast_octets; -+ u16 rx_multicast_octets; -+ u16 rx_fcs_errors; -+ u16 rx_discards_no_buffer; -+ u16 tx_discards_wrong_sa; -+ u16 rx_discards_wep_undecryptable; -+ u16 rx_message_in_msg_fragments; -+ u16 rx_message_in_bad_msg_fragments; -+} __attribute__ ((packed)); -+ -+struct hfa384x_scan_result_hdr { -+ u16 reserved; -+ u16 scan_reason; -+#define HFA384X_SCAN_IN_PROGRESS 0 /* no results available yet */ -+#define HFA384X_SCAN_HOST_INITIATED 1 -+#define HFA384X_SCAN_FIRMWARE_INITIATED 2 -+#define HFA384X_SCAN_INQUIRY_FROM_HOST 3 -+} __attribute__ ((packed)); -+ -+#define HFA384X_SCAN_MAX_RESULTS 32 -+ -+struct hfa384x_scan_result { -+ u16 chid; -+ u16 anl; -+ u16 sl; -+ u8 bssid[6]; -+ u16 beacon_interval; -+ u16 capability; -+ u16 ssid_len; -+ u8 ssid[32]; -+ u8 sup_rates[10]; -+ u16 rate; -+} __attribute__ ((packed)); -+ -+struct hfa384x_hostscan_result { -+ u16 chid; -+ u16 anl; -+ u16 sl; -+ u8 bssid[6]; -+ u16 beacon_interval; -+ u16 capability; -+ u16 ssid_len; -+ u8 ssid[32]; -+ u8 sup_rates[10]; -+ u16 rate; -+ u16 atim; -+} __attribute__ ((packed)); -+ -+struct comm_tallies_sums { -+ unsigned int tx_unicast_frames; -+ unsigned int tx_multicast_frames; -+ unsigned int tx_fragments; -+ unsigned int tx_unicast_octets; -+ unsigned int tx_multicast_octets; -+ unsigned int tx_deferred_transmissions; -+ unsigned int tx_single_retry_frames; -+ unsigned int tx_multiple_retry_frames; -+ unsigned int tx_retry_limit_exceeded; -+ unsigned int tx_discards; -+ unsigned int rx_unicast_frames; -+ unsigned int rx_multicast_frames; -+ unsigned int rx_fragments; -+ unsigned int rx_unicast_octets; -+ unsigned int rx_multicast_octets; -+ unsigned int rx_fcs_errors; -+ unsigned int rx_discards_no_buffer; -+ unsigned int tx_discards_wrong_sa; -+ unsigned int rx_discards_wep_undecryptable; -+ unsigned int rx_message_in_msg_fragments; -+ unsigned int rx_message_in_bad_msg_fragments; -+}; -+ -+ -+struct hfa384x_regs { -+ u16 cmd; -+ u16 evstat; -+ u16 offset0; -+ u16 offset1; -+ u16 swsupport0; -+}; -+ -+ -+#if defined(PRISM2_PCCARD) || defined(PRISM2_PLX) -+/* I/O ports for HFA384X Controller access */ -+#define HFA384X_CMD_OFF 0x00 -+#define HFA384X_PARAM0_OFF 0x02 -+#define HFA384X_PARAM1_OFF 0x04 -+#define HFA384X_PARAM2_OFF 0x06 -+#define HFA384X_STATUS_OFF 0x08 -+#define HFA384X_RESP0_OFF 0x0A -+#define HFA384X_RESP1_OFF 0x0C -+#define HFA384X_RESP2_OFF 0x0E -+#define HFA384X_INFOFID_OFF 0x10 -+#define HFA384X_CONTROL_OFF 0x14 -+#define HFA384X_SELECT0_OFF 0x18 -+#define HFA384X_SELECT1_OFF 0x1A -+#define HFA384X_OFFSET0_OFF 0x1C -+#define HFA384X_OFFSET1_OFF 0x1E -+#define HFA384X_RXFID_OFF 0x20 -+#define HFA384X_ALLOCFID_OFF 0x22 -+#define HFA384X_TXCOMPLFID_OFF 0x24 -+#define HFA384X_SWSUPPORT0_OFF 0x28 -+#define HFA384X_SWSUPPORT1_OFF 0x2A -+#define HFA384X_SWSUPPORT2_OFF 0x2C -+#define HFA384X_EVSTAT_OFF 0x30 -+#define HFA384X_INTEN_OFF 0x32 -+#define HFA384X_EVACK_OFF 0x34 -+#define HFA384X_DATA0_OFF 0x36 -+#define HFA384X_DATA1_OFF 0x38 -+#define HFA384X_AUXPAGE_OFF 0x3A -+#define HFA384X_AUXOFFSET_OFF 0x3C -+#define HFA384X_AUXDATA_OFF 0x3E -+#endif /* PRISM2_PCCARD || PRISM2_PLX */ -+ -+#ifdef PRISM2_PCI -+/* Memory addresses for ISL3874 controller access */ -+#define HFA384X_CMD_OFF 0x00 -+#define HFA384X_PARAM0_OFF 0x04 -+#define HFA384X_PARAM1_OFF 0x08 -+#define HFA384X_PARAM2_OFF 0x0C -+#define HFA384X_STATUS_OFF 0x10 -+#define HFA384X_RESP0_OFF 0x14 -+#define HFA384X_RESP1_OFF 0x18 -+#define HFA384X_RESP2_OFF 0x1C -+#define HFA384X_INFOFID_OFF 0x20 -+#define HFA384X_CONTROL_OFF 0x28 -+#define HFA384X_SELECT0_OFF 0x30 -+#define HFA384X_SELECT1_OFF 0x34 -+#define HFA384X_OFFSET0_OFF 0x38 -+#define HFA384X_OFFSET1_OFF 0x3C -+#define HFA384X_RXFID_OFF 0x40 -+#define HFA384X_ALLOCFID_OFF 0x44 -+#define HFA384X_TXCOMPLFID_OFF 0x48 -+#define HFA384X_PCICOR_OFF 0x4C -+#define HFA384X_SWSUPPORT0_OFF 0x50 -+#define HFA384X_SWSUPPORT1_OFF 0x54 -+#define HFA384X_SWSUPPORT2_OFF 0x58 -+#define HFA384X_PCIHCR_OFF 0x5C -+#define HFA384X_EVSTAT_OFF 0x60 -+#define HFA384X_INTEN_OFF 0x64 -+#define HFA384X_EVACK_OFF 0x68 -+#define HFA384X_DATA0_OFF 0x6C -+#define HFA384X_DATA1_OFF 0x70 -+#define HFA384X_AUXPAGE_OFF 0x74 -+#define HFA384X_AUXOFFSET_OFF 0x78 -+#define HFA384X_AUXDATA_OFF 0x7C -+#define HFA384X_PCI_M0_ADDRH_OFF 0x80 -+#define HFA384X_PCI_M0_ADDRL_OFF 0x84 -+#define HFA384X_PCI_M0_LEN_OFF 0x88 -+#define HFA384X_PCI_M0_CTL_OFF 0x8C -+#define HFA384X_PCI_STATUS_OFF 0x98 -+#define HFA384X_PCI_M1_ADDRH_OFF 0xA0 -+#define HFA384X_PCI_M1_ADDRL_OFF 0xA4 -+#define HFA384X_PCI_M1_LEN_OFF 0xA8 -+#define HFA384X_PCI_M1_CTL_OFF 0xAC -+ -+/* PCI bus master control bits (these are undocumented; based on guessing and -+ * experimenting..) */ -+#define HFA384X_PCI_CTL_FROM_BAP (BIT(5) | BIT(1) | BIT(0)) -+#define HFA384X_PCI_CTL_TO_BAP (BIT(5) | BIT(0)) -+ -+#endif /* PRISM2_PCI */ -+ -+ -+/* Command codes for CMD reg. */ -+#define HFA384X_CMDCODE_INIT 0x00 -+#define HFA384X_CMDCODE_ENABLE 0x01 -+#define HFA384X_CMDCODE_DISABLE 0x02 -+#define HFA384X_CMDCODE_ALLOC 0x0A -+#define HFA384X_CMDCODE_TRANSMIT 0x0B -+#define HFA384X_CMDCODE_INQUIRE 0x11 -+#define HFA384X_CMDCODE_ACCESS 0x21 -+#define HFA384X_CMDCODE_ACCESS_WRITE (0x21 | BIT(8)) -+#define HFA384X_CMDCODE_DOWNLOAD 0x22 -+#define HFA384X_CMDCODE_READMIF 0x30 -+#define HFA384X_CMDCODE_WRITEMIF 0x31 -+#define HFA384X_CMDCODE_TEST 0x38 -+ -+#define HFA384X_CMDCODE_MASK 0x3F -+ -+/* Test mode operations */ -+#define HFA384X_TEST_CHANGE_CHANNEL 0x08 -+#define HFA384X_TEST_MONITOR 0x0B -+#define HFA384X_TEST_STOP 0x0F -+#define HFA384X_TEST_CFG_BITS 0x15 -+#define HFA384X_TEST_CFG_BIT_ALC BIT(3) -+ -+#define HFA384X_CMD_BUSY BIT(15) -+ -+#define HFA384X_CMD_TX_RECLAIM BIT(8) -+ -+#define HFA384X_OFFSET_ERR BIT(14) -+#define HFA384X_OFFSET_BUSY BIT(15) -+ -+ -+/* ProgMode for download command */ -+#define HFA384X_PROGMODE_DISABLE 0 -+#define HFA384X_PROGMODE_ENABLE_VOLATILE 1 -+#define HFA384X_PROGMODE_ENABLE_NON_VOLATILE 2 -+#define HFA384X_PROGMODE_PROGRAM_NON_VOLATILE 3 -+ -+#define HFA384X_AUX_MAGIC0 0xfe01 -+#define HFA384X_AUX_MAGIC1 0xdc23 -+#define HFA384X_AUX_MAGIC2 0xba45 -+ -+#define HFA384X_AUX_PORT_DISABLED 0 -+#define HFA384X_AUX_PORT_DISABLE BIT(14) -+#define HFA384X_AUX_PORT_ENABLE BIT(15) -+#define HFA384X_AUX_PORT_ENABLED (BIT(14) | BIT(15)) -+#define HFA384X_AUX_PORT_MASK (BIT(14) | BIT(15)) -+ -+#define PRISM2_PDA_SIZE 1024 -+ -+ -+/* Events; EvStat, Interrupt mask (IntEn), and acknowledge bits (EvAck) */ -+#define HFA384X_EV_TICK BIT(15) -+#define HFA384X_EV_WTERR BIT(14) -+#define HFA384X_EV_INFDROP BIT(13) -+#ifdef PRISM2_PCI -+#define HFA384X_EV_PCI_M1 BIT(9) -+#define HFA384X_EV_PCI_M0 BIT(8) -+#endif /* PRISM2_PCI */ -+#define HFA384X_EV_INFO BIT(7) -+#define HFA384X_EV_DTIM BIT(5) -+#define HFA384X_EV_CMD BIT(4) -+#define HFA384X_EV_ALLOC BIT(3) -+#define HFA384X_EV_TXEXC BIT(2) -+#define HFA384X_EV_TX BIT(1) -+#define HFA384X_EV_RX BIT(0) -+ -+ -+/* HFA384X Configuration RIDs */ -+#define HFA384X_RID_CNFPORTTYPE 0xFC00 -+#define HFA384X_RID_CNFOWNMACADDR 0xFC01 -+#define HFA384X_RID_CNFDESIREDSSID 0xFC02 -+#define HFA384X_RID_CNFOWNCHANNEL 0xFC03 -+#define HFA384X_RID_CNFOWNSSID 0xFC04 -+#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05 -+#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06 -+#define HFA384X_RID_CNFMAXDATALEN 0xFC07 -+#define HFA384X_RID_CNFWDSADDRESS 0xFC08 -+#define HFA384X_RID_CNFPMENABLED 0xFC09 -+#define HFA384X_RID_CNFPMEPS 0xFC0A -+#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B -+#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C -+#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D -+#define HFA384X_RID_CNFOWNNAME 0xFC0E -+#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10 -+#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */ -+#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */ -+#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */ -+#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */ -+#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */ -+#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */ -+#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */ -+#define HFA384X_RID_UNKNOWN1 0xFC20 -+#define HFA384X_RID_UNKNOWN2 0xFC21 -+#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23 -+#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24 -+#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25 -+#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26 -+#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27 -+#define HFA384X_RID_CNFWEPFLAGS 0xFC28 -+#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29 -+#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A -+#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */ -+#define HFA384X_RID_CNFTXCONTROL 0xFC2C -+#define HFA384X_RID_CNFROAMINGMODE 0xFC2D -+#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */ -+#define HFA384X_RID_CNFRCVCRCERROR 0xFC30 -+#define HFA384X_RID_CNFMMLIFE 0xFC31 -+#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32 -+#define HFA384X_RID_CNFBEACONINT 0xFC33 -+#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */ -+#define HFA384X_RID_CNFSTAPCFINFO 0xFC35 -+#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37 -+#define HFA384X_RID_CNFTIMCTRL 0xFC40 -+#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */ -+#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */ -+#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */ -+#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */ -+#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0; -+ * write only */ -+#define HFA384X_RID_GROUPADDRESSES 0xFC80 -+#define HFA384X_RID_CREATEIBSS 0xFC81 -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82 -+#define HFA384X_RID_RTSTHRESHOLD 0xFC83 -+#define HFA384X_RID_TXRATECONTROL 0xFC84 -+#define HFA384X_RID_PROMISCUOUSMODE 0xFC85 -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */ -+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */ -+#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */ -+#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */ -+#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0 -+#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1 -+#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2 -+#define HFA384X_RID_CNFBASICRATES 0xFCB3 -+#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4 -+#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */ -+#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */ -+#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */ -+#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */ -+#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */ -+#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */ -+#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */ -+#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */ -+#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */ -+#define HFA384X_RID_TICKTIME 0xFCE0 -+#define HFA384X_RID_SCANREQUEST 0xFCE1 -+#define HFA384X_RID_JOINREQUEST 0xFCE2 -+#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */ -+#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */ -+#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */ -+ -+/* HFA384X Information RIDs */ -+#define HFA384X_RID_MAXLOADTIME 0xFD00 -+#define HFA384X_RID_DOWNLOADBUFFER 0xFD01 -+#define HFA384X_RID_PRIID 0xFD02 -+#define HFA384X_RID_PRISUPRANGE 0xFD03 -+#define HFA384X_RID_CFIACTRANGES 0xFD04 -+#define HFA384X_RID_NICSERNUM 0xFD0A -+#define HFA384X_RID_NICID 0xFD0B -+#define HFA384X_RID_MFISUPRANGE 0xFD0C -+#define HFA384X_RID_CFISUPRANGE 0xFD0D -+#define HFA384X_RID_CHANNELLIST 0xFD10 -+#define HFA384X_RID_REGULATORYDOMAINS 0xFD11 -+#define HFA384X_RID_TEMPTYPE 0xFD12 -+#define HFA384X_RID_CIS 0xFD13 -+#define HFA384X_RID_STAID 0xFD20 -+#define HFA384X_RID_STASUPRANGE 0xFD21 -+#define HFA384X_RID_MFIACTRANGES 0xFD22 -+#define HFA384X_RID_CFIACTRANGES2 0xFD23 -+#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1; -+ * only Prism2.5(?) */ -+#define HFA384X_RID_PORTSTATUS 0xFD40 -+#define HFA384X_RID_CURRENTSSID 0xFD41 -+#define HFA384X_RID_CURRENTBSSID 0xFD42 -+#define HFA384X_RID_COMMSQUALITY 0xFD43 -+#define HFA384X_RID_CURRENTTXRATE 0xFD44 -+#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45 -+#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46 -+#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47 -+#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48 -+#define HFA384X_RID_LONGRETRYLIMIT 0xFD49 -+#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A -+#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B -+#define HFA384X_RID_CFPOLLABLE 0xFD4C -+#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D -+#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F -+#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */ -+#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */ -+#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */ -+#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */ -+#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */ -+#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */ -+#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */ -+#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */ -+#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */ -+#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */ -+#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */ -+#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */ -+#define HFA384X_RID_PHYTYPE 0xFDC0 -+#define HFA384X_RID_CURRENTCHANNEL 0xFDC1 -+#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2 -+#define HFA384X_RID_CCAMODE 0xFDC3 -+#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6 -+#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */ -+#define HFA384X_RID_BUILDSEQ 0xFFFE -+#define HFA384X_RID_FWID 0xFFFF -+ -+/* HFA384X Information frames */ -+#define HFA384X_INFO_HANDOVERADDR 0xF000 /* AP f/w ? */ -+#define HFA384X_INFO_HANDOVERDEAUTHADDR 0xF001 /* AP f/w 1.3.7 */ -+#define HFA384X_INFO_COMMTALLIES 0xF100 -+#define HFA384X_INFO_SCANRESULTS 0xF101 -+#define HFA384X_INFO_CHANNELINFORESULTS 0xF102 /* AP f/w only */ -+#define HFA384X_INFO_HOSTSCANRESULTS 0xF103 -+#define HFA384X_INFO_LINKSTATUS 0xF200 -+#define HFA384X_INFO_ASSOCSTATUS 0xF201 /* ? */ -+#define HFA384X_INFO_AUTHREQ 0xF202 /* ? */ -+#define HFA384X_INFO_PSUSERCNT 0xF203 /* ? */ -+#define HFA384X_INFO_KEYIDCHANGED 0xF204 /* ? */ -+ -+enum { HFA384X_LINKSTATUS_CONNECTED = 1, -+ HFA384X_LINKSTATUS_DISCONNECTED = 2, -+ HFA384X_LINKSTATUS_AP_CHANGE = 3, -+ HFA384X_LINKSTATUS_AP_OUT_OF_RANGE = 4, -+ HFA384X_LINKSTATUS_AP_IN_RANGE = 5, -+ HFA384X_LINKSTATUS_ASSOC_FAILED = 6 }; -+ -+enum { HFA384X_PORTTYPE_BSS = 1, HFA384X_PORTTYPE_WDS = 2, -+ HFA384X_PORTTYPE_PSEUDO_IBSS = 3, HFA384X_PORTTYPE_IBSS = 0, -+ HFA384X_PORTTYPE_HOSTAP = 6 }; -+ -+#define HFA384X_RATES_1MBPS BIT(0) -+#define HFA384X_RATES_2MBPS BIT(1) -+#define HFA384X_RATES_5MBPS BIT(2) -+#define HFA384X_RATES_11MBPS BIT(3) -+ -+#define HFA384X_ROAMING_FIRMWARE 1 -+#define HFA384X_ROAMING_HOST 2 -+#define HFA384X_ROAMING_DISABLED 3 -+ -+#define HFA384X_WEPFLAGS_PRIVACYINVOKED BIT(0) -+#define HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED BIT(1) -+#define HFA384X_WEPFLAGS_HOSTENCRYPT BIT(4) -+#define HFA384X_WEPFLAGS_HOSTDECRYPT BIT(7) -+ -+#define HFA384X_RX_STATUS_MSGTYPE (BIT(15) | BIT(14) | BIT(13)) -+#define HFA384X_RX_STATUS_PCF BIT(12) -+#define HFA384X_RX_STATUS_MACPORT (BIT(10) | BIT(9) | BIT(8)) -+#define HFA384X_RX_STATUS_UNDECR BIT(1) -+#define HFA384X_RX_STATUS_FCSERR BIT(0) -+ -+#define HFA384X_RX_STATUS_GET_MSGTYPE(s) \ -+(((s) & HFA384X_RX_STATUS_MSGTYPE) >> 13) -+#define HFA384X_RX_STATUS_GET_MACPORT(s) \ -+(((s) & HFA384X_RX_STATUS_MACPORT) >> 8) -+ -+enum { HFA384X_RX_MSGTYPE_NORMAL = 0, HFA384X_RX_MSGTYPE_RFC1042 = 1, -+ HFA384X_RX_MSGTYPE_BRIDGETUNNEL = 2, HFA384X_RX_MSGTYPE_MGMT = 4 }; -+ -+ -+#define HFA384X_TX_CTRL_ALT_RTRY BIT(5) -+#define HFA384X_TX_CTRL_802_11 BIT(3) -+#define HFA384X_TX_CTRL_802_3 0 -+#define HFA384X_TX_CTRL_TX_EX BIT(2) -+#define HFA384X_TX_CTRL_TX_OK BIT(1) -+ -+#define HFA384X_TX_STATUS_RETRYERR BIT(0) -+#define HFA384X_TX_STATUS_AGEDERR BIT(1) -+#define HFA384X_TX_STATUS_DISCON BIT(2) -+#define HFA384X_TX_STATUS_FORMERR BIT(3) -+ -+/* HFA3861/3863 (BBP) Control Registers */ -+#define HFA386X_CR_TX_CONFIGURE 0x12 -+#define HFA386X_CR_RX_CONFIGURE 0x14 -+#define HFA386X_CR_A_D_TEST_MODES2 0x1A -+#define HFA386X_CR_MANUAL_TX_POWER 0x3E -+ -+/* IEEE 802.11 defines */ -+ -+#define WLAN_FC_PVER (BIT(1) | BIT(0)) -+#define WLAN_FC_TODS BIT(8) -+#define WLAN_FC_FROMDS BIT(9) -+#define WLAN_FC_MOREFRAG BIT(10) -+#define WLAN_FC_RETRY BIT(11) -+#define WLAN_FC_PWRMGT BIT(12) -+#define WLAN_FC_MOREDATA BIT(13) -+#define WLAN_FC_ISWEP BIT(14) -+#define WLAN_FC_ORDER BIT(15) -+ -+#define WLAN_FC_GET_TYPE(fc) (((fc) & (BIT(3) | BIT(2))) >> 2) -+#define WLAN_FC_GET_STYPE(fc) \ -+ (((fc) & (BIT(7) | BIT(6) | BIT(5) | BIT(4))) >> 4) -+ -+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) -+#define WLAN_GET_SEQ_SEQ(seq) \ -+ (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) -+ -+#define WLAN_FC_TYPE_MGMT 0 -+#define WLAN_FC_TYPE_CTRL 1 -+#define WLAN_FC_TYPE_DATA 2 -+ -+/* management */ -+#define WLAN_FC_STYPE_ASSOC_REQ 0 -+#define WLAN_FC_STYPE_ASSOC_RESP 1 -+#define WLAN_FC_STYPE_REASSOC_REQ 2 -+#define WLAN_FC_STYPE_REASSOC_RESP 3 -+#define WLAN_FC_STYPE_PROBE_REQ 4 -+#define WLAN_FC_STYPE_PROBE_RESP 5 -+#define WLAN_FC_STYPE_BEACON 8 -+#define WLAN_FC_STYPE_ATIM 9 -+#define WLAN_FC_STYPE_DISASSOC 10 -+#define WLAN_FC_STYPE_AUTH 11 -+#define WLAN_FC_STYPE_DEAUTH 12 -+ -+/* control */ -+#define WLAN_FC_STYPE_PSPOLL 10 -+#define WLAN_FC_STYPE_RTS 11 -+#define WLAN_FC_STYPE_CTS 12 -+#define WLAN_FC_STYPE_ACK 13 -+#define WLAN_FC_STYPE_CFEND 14 -+#define WLAN_FC_STYPE_CFENDACK 15 -+ -+/* data */ -+#define WLAN_FC_STYPE_DATA 0 -+#define WLAN_FC_STYPE_DATA_CFACK 1 -+#define WLAN_FC_STYPE_DATA_CFPOLL 2 -+#define WLAN_FC_STYPE_DATA_CFACKPOLL 3 -+#define WLAN_FC_STYPE_NULLFUNC 4 -+#define WLAN_FC_STYPE_CFACK 5 -+#define WLAN_FC_STYPE_CFPOLL 6 -+#define WLAN_FC_STYPE_CFACKPOLL 7 -+ -+/* Authentication algorithms */ -+#define WLAN_AUTH_OPEN 0 -+#define WLAN_AUTH_SHARED_KEY 1 -+ -+#define WLAN_AUTH_CHALLENGE_LEN 128 -+ -+#define WLAN_CAPABILITY_ESS BIT(0) -+#define WLAN_CAPABILITY_IBSS BIT(1) -+#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) -+#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) -+#define WLAN_CAPABILITY_PRIVACY BIT(4) -+ -+/* Status codes */ -+#define WLAN_STATUS_SUCCESS 0 -+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -+#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -+#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -+#define WLAN_STATUS_CHALLENGE_FAIL 15 -+#define WLAN_STATUS_AUTH_TIMEOUT 16 -+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 -+#define WLAN_STATUS_ASSOC_DENIED_RATES 18 -+/* 802.11b */ -+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -+ -+/* Reason codes */ -+#define WLAN_REASON_UNSPECIFIED 1 -+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -+#define WLAN_REASON_DEAUTH_LEAVING 3 -+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -+#define WLAN_REASON_DISASSOC_AP_BUSY 5 -+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 -+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 -+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 -+ -+ -+/* Information Element IDs */ -+#define WLAN_EID_SSID 0 -+#define WLAN_EID_SUPP_RATES 1 -+#define WLAN_EID_FH_PARAMS 2 -+#define WLAN_EID_DS_PARAMS 3 -+#define WLAN_EID_CF_PARAMS 4 -+#define WLAN_EID_TIM 5 -+#define WLAN_EID_IBSS_PARAMS 6 -+#define WLAN_EID_CHALLENGE 16 -+ -+ -+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" -+ -+ -+/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ -+ -+#if WIRELESS_EXT >= 12 -+ -+/* New wireless extensions API - SET/GET convention (even ioctl numbers are -+ * root only) -+ */ -+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -+#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -+#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -+#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -+#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -+#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -+#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -+#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -+#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -+#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -+#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -+#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -+#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) -+ -+/* following are not in SIOCGIWPRIV list; check permission in the driver code -+ */ -+#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -+#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) -+ -+#else /* WIRELESS_EXT >= 12 */ -+ -+/* Old wireless extensions API - check permission in the driver code */ -+#define PRISM2_IOCTL_MONITOR (SIOCDEVPRIVATE) -+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCDEVPRIVATE + 1) -+#define PRISM2_IOCTL_READMIF (SIOCDEVPRIVATE + 2) -+#define PRISM2_IOCTL_WRITEMIF (SIOCDEVPRIVATE + 3) -+#define PRISM2_IOCTL_RESET (SIOCDEVPRIVATE + 4) -+#define PRISM2_IOCTL_INQUIRE (SIOCDEVPRIVATE + 5) -+#define PRISM2_IOCTL_WDS_ADD (SIOCDEVPRIVATE + 6) -+#define PRISM2_IOCTL_WDS_DEL (SIOCDEVPRIVATE + 7) -+#define PRISM2_IOCTL_SET_RID_WORD (SIOCDEVPRIVATE + 8) -+#define PRISM2_IOCTL_MACCMD (SIOCDEVPRIVATE + 9) -+#define PRISM2_IOCTL_ADDMAC (SIOCDEVPRIVATE + 10) -+#define PRISM2_IOCTL_DELMAC (SIOCDEVPRIVATE + 11) -+#define PRISM2_IOCTL_KICKMAC (SIOCDEVPRIVATE + 12) -+#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -+#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) -+ -+#endif /* WIRELESS_EXT >= 12 */ -+ -+ -+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -+enum { -+ PRISM2_PARAM_PTYPE = 1, -+ PRISM2_PARAM_TXRATECTRL = 2, -+ PRISM2_PARAM_BEACON_INT = 3, -+ PRISM2_PARAM_PSEUDO_IBSS = 4, -+ PRISM2_PARAM_ALC = 5, -+ PRISM2_PARAM_TXPOWER = 6, -+ PRISM2_PARAM_DUMP = 7, -+ PRISM2_PARAM_OTHER_AP_POLICY = 8, -+ PRISM2_PARAM_AP_MAX_INACTIVITY = 9, -+ PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, -+ PRISM2_PARAM_DTIM_PERIOD = 11, -+ PRISM2_PARAM_AP_NULLFUNC_ACK = 12, -+ PRISM2_PARAM_MAX_WDS = 13, -+ PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, -+ PRISM2_PARAM_AP_AUTH_ALGS = 15, -+ PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, -+ PRISM2_PARAM_HOST_ENCRYPT = 17, -+ PRISM2_PARAM_HOST_DECRYPT = 18, -+ PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, -+ PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, -+ PRISM2_PARAM_HOST_ROAMING = 21, -+ PRISM2_PARAM_BCRX_STA_KEY = 22, -+ PRISM2_PARAM_IEEE_802_1X = 23, -+ PRISM2_PARAM_ANTSEL_TX = 24, -+ PRISM2_PARAM_ANTSEL_RX = 25, -+ PRISM2_PARAM_MONITOR_TYPE = 26, -+ PRISM2_PARAM_WDS_TYPE = 27, -+ PRISM2_PARAM_HOSTSCAN = 28, -+ PRISM2_PARAM_AP_SCAN = 29, -+ PRISM2_PARAM_ENH_SEC = 30, -+ PRISM2_PARAM_IO_DEBUG = 31, -+ PRISM2_PARAM_BASIC_RATES = 32, -+ PRISM2_PARAM_OPER_RATES = 33, -+ PRISM2_PARAM_HOSTAPD = 34, -+}; -+ -+enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, -+ HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; -+ -+ -+/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -+enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, -+ AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, -+ AP_MAC_CMD_KICKALL = 4 }; -+ -+ -+/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -+enum { -+ PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, -+ /* Note! Old versions of prism2_srec have a fatal error in CRC-16 -+ * calculation, which will corrupt all non-volatile downloads. -+ * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to -+ * prevent use of old versions of prism2_srec for non-volatile -+ * download. */ -+ PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */ -+}; -+ -+struct prism2_download_param { -+ u32 dl_cmd; -+ u32 start_addr; -+ u32 num_areas; -+ struct prism2_download_area { -+ u32 addr; /* wlan card address */ -+ u32 len; -+ caddr_t ptr; /* pointer to data in user space */ -+ } data[0]; -+}; -+ -+#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -+#define PRISM2_MAX_DOWNLOAD_LEN 262144 -+ -+ -+/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -+enum { -+ PRISM2_HOSTAPD_FLUSH = 1, -+ PRISM2_HOSTAPD_ADD_STA = 2, -+ PRISM2_HOSTAPD_REMOVE_STA = 3, -+ PRISM2_HOSTAPD_GET_INFO_STA = 4, -+ PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, -+ PRISM2_SET_ENCRYPTION = 6, -+ PRISM2_GET_ENCRYPTION = 7, -+ PRISM2_HOSTAPD_SET_FLAGS_STA = 8, -+ PRISM2_HOSTAPD_GET_RID = 9, -+ PRISM2_HOSTAPD_SET_RID = 10, -+ PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, -+}; -+ -+#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -+#define PRISM2_HOSTAPD_RID_HDR_LEN \ -+((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -+ -+struct prism2_hostapd_param { -+ u32 cmd; -+ u8 sta_addr[ETH_ALEN]; -+ union { -+ struct { -+ u16 aid; -+ u16 capability; -+ u8 tx_supp_rates; -+ } add_sta; -+ struct { -+ u32 inactive_sec; -+ u32 txexc; -+ } get_info_sta; -+ struct { -+ u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; -+ u32 flags; -+ u32 err; -+ u8 idx; -+ u16 key_len; -+ u8 key[0]; -+ } crypt; -+ struct { -+ u32 flags_and; -+ u32 flags_or; -+ } set_flags_sta; -+ struct { -+ u16 rid; -+ u16 len; -+ u8 data[0]; -+ } rid; -+ } u; -+}; -+ -+#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -+#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) -+ -+#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -+#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -+#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -+#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -+#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -+#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 -+ -+ -+#ifdef __KERNEL__ -+ -+#define PRISM2_TXFID_COUNT 7 -+#define PRISM2_TXSKB_COUNT 100 -+#define PRISM2_DATA_MAXLEN 2304 -+#define PRISM2_TXFID_LEN (PRISM2_DATA_MAXLEN + sizeof(struct hfa384x_tx_frame)) -+#define PRISM2_TXFID_EMPTY 0xffff -+#define PRISM2_TXFID_RESERVED 0xfffe -+#define PRISM2_DUMMY_FID 0xffff -+#define MAX_SSID_LEN 32 -+#define MAX_NAME_LEN 32 /* this is assumed to be equal to MAX_SSID_LEN */ -+ -+#define PRISM2_DUMP_RX_HDR BIT(0) -+#define PRISM2_DUMP_TX_HDR BIT(1) -+#define PRISM2_DUMP_TXEXC_HDR BIT(2) -+ -+typedef struct prism2_wds_info prism2_wds_info_t; -+ -+struct prism2_wds_info { -+ /* must start with dev, since it is used also as a pointer to whole -+ * prism2_wds_info structure */ -+ struct net_device dev; -+ u8 remote_addr[6]; -+ struct net_device_stats stats; -+ prism2_wds_info_t *next; -+}; -+ -+ -+struct hostap_tx_callback_info { -+ u16 idx; -+ void (*func)(struct sk_buff *, int ok, void *); -+ void *data; -+ struct hostap_tx_callback_info *next; -+}; -+ -+ -+/* IEEE 802.11 requires that STA supports concurrent reception of at least -+ * three fragmented frames. This define can be increased to support more -+ * concurrent frames, but it should be noted that each entry can consume about -+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -+#define PRISM2_FRAG_CACHE_LEN 4 -+ -+struct prism2_frag_entry { -+ unsigned long first_frag_time; -+ unsigned int seq; -+ unsigned int last_frag; -+ struct sk_buff *skb; -+ u8 src_addr[ETH_ALEN]; -+ u8 dst_addr[ETH_ALEN]; -+}; -+ -+ -+struct prism2_crypt_data { -+ struct list_head list; /* delayed deletion list */ -+ struct hostap_crypto_ops *ops; -+ void *priv; -+ atomic_t refcnt; -+}; -+ -+struct hostap_cmd_queue { -+ struct list_head list; -+ wait_queue_head_t compl; -+ volatile enum { CMD_SLEEP, CMD_CALLBACK, CMD_COMPLETED } type; -+ void (*callback)(struct net_device *dev, void *context, u16 resp0, -+ u16 res); -+ void *context; -+ u16 cmd, param0, param1; -+ u16 resp0, res; -+ volatile int issued, issuing; -+ -+ atomic_t usecnt; -+ int del_req; -+}; -+ -+/* prism2_rx_80211 'type' argument */ -+enum { -+ PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC, -+ PRISM2_RX_NULLFUNC_ACK -+}; -+ -+/* options for hw_shutdown */ -+#define HOSTAP_HW_NO_DISABLE BIT(0) -+#define HOSTAP_HW_ENABLE_CMDCOMPL BIT(1) -+ -+typedef struct local_info local_info_t; -+ -+struct prism2_helper_functions { -+ /* these functions are defined in hardware model specific files -+ * (hostap_{cs,plx,pci}.c */ -+ int (*card_present)(local_info_t *local); -+ void (*cor_sreset)(local_info_t *local); -+ int (*dev_open)(local_info_t *local); -+ int (*dev_close)(local_info_t *local); -+ -+ /* the following functions are from hostap_hw.c, but they may have some -+ * hardware model specific code */ -+ -+ /* FIX: low-level commands like cmd might disappear at some point to -+ * make it easier to change them if needed (e.g., cmd would be replaced -+ * with write_mif/read_mif/testcmd/inquire); at least get_rid and -+ * set_rid might move to hostap_{cs,plx,pci}.c */ -+ int (*cmd)(struct net_device *dev, u16 cmd, u16 param0, u16 *param1, -+ u16 *resp0); -+ void (*read_regs)(struct net_device *dev, struct hfa384x_regs *regs); -+ int (*get_rid)(struct net_device *dev, u16 rid, void *buf, int len, -+ int exact_len); -+ int (*set_rid)(struct net_device *dev, u16 rid, void *buf, int len); -+ int (*hw_enable)(struct net_device *dev, int initial); -+ int (*hw_config)(struct net_device *dev, int initial); -+ void (*hw_reset)(struct net_device *dev); -+ void (*hw_shutdown)(struct net_device *dev, int no_disable); -+ int (*reset_port)(struct net_device *dev); -+ int (*tx)(struct sk_buff *skb, struct net_device *dev); -+ void (*schedule_reset)(local_info_t *local); -+#ifdef PRISM2_DOWNLOAD_SUPPORT -+ int (*download)(local_info_t *local, -+ struct prism2_download_param *param); -+#endif /* PRISM2_DOWNLOAD_SUPPORT */ -+ int (*rx_80211)(struct net_device *dev, struct sk_buff *skb, -+ int type, char *extra, int extra_len); -+ int (*tx_80211)(struct sk_buff *skb, struct net_device *dev); -+}; -+ -+struct local_info { -+ struct module *hw_module; -+ int card_idx; -+ int dev_enabled; -+ struct net_device *dev; -+ spinlock_t cmdlock, baplock, wdslock, lock; -+ struct semaphore rid_bap_sem; -+ u16 infofid; /* MAC buffer id for info frame */ -+ /* txfid, intransmitfid, next_txtid, and next_alloc are protected by -+ * txfidlock */ -+ spinlock_t txfidlock; -+ int txfid_len; /* length of allocated TX buffers */ -+ u16 txfid[PRISM2_TXFID_COUNT]; /* buffer IDs for TX frames */ -+ /* buffer IDs for intransmit frames or PRISM2_TXFID_EMPTY if -+ * corresponding txfid is free for next TX frame */ -+ u16 intransmitfid[PRISM2_TXFID_COUNT]; -+ int next_txfid; /* index to the next txfid to be checked for -+ * availability */ -+ int next_alloc; /* index to the next intransmitfid to be checked for -+ * allocation events */ -+ /* start click tx cb */ -+ struct sk_buff *txskb[PRISM2_TXSKB_COUNT]; -+ /* endclick tx cb */ -+ -+ /* bitfield for atomic bitops */ -+#define HOSTAP_BITS_TRANSMIT 0 -+#define HOSTAP_BITS_BAP_TASKLET 1 -+#define HOSTAP_BITS_BAP_TASKLET2 2 -+ long bits; -+ -+ struct ap_data *ap; -+ -+ char essid[MAX_SSID_LEN + 1]; -+ char name[MAX_NAME_LEN + 1]; -+ int name_set; -+ u16 channel_mask; -+ struct comm_tallies_sums comm_tallies; -+ struct net_device_stats stats; -+ struct proc_dir_entry *proc; -+ int iw_mode; /* operating mode (IW_MODE_*) */ -+ int pseudo_adhoc; /* 0: IW_MODE_ADHOC is real 802.11 compliant IBSS -+ * 1: IW_MODE_ADHOC is "pseudo IBSS" */ -+ char bssid[ETH_ALEN]; -+ int channel; -+ int beacon_int; -+ int dtim_period; -+ int disable_on_close; -+ int mtu; -+ int frame_dump; /* dump RX/TX frame headers, PRISM2_DUMP_ flags */ -+ int fw_tx_rate_control; -+ u16 tx_rate_control; -+ u16 basic_rates; -+ int hw_resetting; -+ int hw_ready; -+ int hw_reset_tries; /* how many times reset has been tried */ -+ int hw_downloading; -+ int shutdown; -+ -+ enum { -+ PRISM2_TXPOWER_AUTO = 0, PRISM2_TXPOWER_OFF, -+ PRISM2_TXPOWER_FIXED, PRISM2_TXPOWER_UNKNOWN -+ } txpower_type; -+ u16 txpower; /* if txpower_type == PRISM2_TXPOWER_FIXED */ -+ -+ /* command queue for hfa384x_cmd(); protected with cmdlock */ -+ struct list_head cmd_queue; -+ /* max_len for cmd_queue; in addition, cmd_callback can use two -+ * additional entries to prevent sleeping commands from stopping -+ * transmits */ -+#define HOSTAP_CMD_QUEUE_MAX_LEN 16 -+ int cmd_queue_len; /* number of entries in cmd_queue */ -+ -+ /* if card timeout is detected in interrupt context, reset_queue is -+ * used to schedule card reseting to be done in user context */ -+ HOSTAP_QUEUE reset_queue; -+ -+ /* For scheduling a change of the promiscuous mode RID */ -+ int is_promisc; -+ HOSTAP_QUEUE set_multicast_list_queue; -+ -+ prism2_wds_info_t *wds; /* list of established wds connections */ -+ int wds_max_connections; -+ int wds_connections; -+#define HOSTAP_WDS_BROADCAST_RA BIT(0) -+#define HOSTAP_WDS_AP_CLIENT BIT(1) -+#define HOSTAP_WDS_STANDARD_FRAME BIT(2) -+ u32 wds_type; -+ u16 tx_control; /* flags to be used in TX description */ -+ int manual_retry_count; /* -1 = use f/w default; otherwise retry count -+ * to be used with all frames */ -+ -+#ifdef WIRELESS_EXT -+ struct iw_statistics wstats; -+#if WIRELESS_EXT > 13 -+ unsigned long scan_timestamp; /* Time started to scan */ -+#endif /* WIRELESS_EXT > 13 */ -+#if WIRELESS_EXT > 15 -+ struct iw_spy_data spy_data; /* iwspy support */ -+#endif /* WIRELESS_EXT > 15 */ -+#endif /* WIRELESS_EXT */ -+ enum { -+ PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1, -+ PRISM2_MONITOR_CAPHDR = 2 -+ } monitor_type; -+ int (*saved_eth_header_parse)(struct sk_buff *skb, -+ unsigned char *haddr); -+ int monitor_allow_fcserr; -+ -+ int hostapd; /* whether user space daemon, hostapd, is used for AP -+ * management */ -+ struct net_device *apdev; -+ struct net_device_stats apdevstats; -+ -+ char assoc_ap_addr[ETH_ALEN]; -+ struct net_device *stadev; -+ struct net_device_stats stadevstats; -+ -+ struct prism2_crypt_data *crypt; -+ struct timer_list crypt_deinit_timer; -+ struct list_head crypt_deinit_list; -+ -+#define WEP_KEYS 4 -+#define WEP_KEY_LEN 13 -+ int open_wep; /* allow unencrypted frames */ -+ int host_encrypt; -+ int host_decrypt; -+ int fw_encrypt_ok; /* whether firmware-based WEP encrypt is working -+ * in Host AP mode (STA f/w 1.4.9 or newer) */ -+ int bcrx_sta_key; /* use individual keys to override default keys even -+ * with RX of broad/multicast frames */ -+ -+ struct prism2_frag_entry frag_cache[PRISM2_FRAG_CACHE_LEN]; -+ unsigned int frag_next_idx; -+ -+ int ieee_802_1x; /* is IEEE 802.1X used */ -+ -+ int antsel_tx, antsel_rx; -+ -+ int enh_sec; /* cnfEnhSecurity options (broadcast SSID hide/ignore) */ -+ -+ struct prism2_helper_functions *func; -+ -+ int bus_master_threshold_tx; -+ int bus_master_threshold_rx; -+ u8 *bus_m1_buf; -+ -+ u8 *pda; -+ int fw_ap; -+#define PRISM2_FW_VER(major, minor, variant) \ -+(((major) << 16) | ((minor) << 8) | variant) -+ u32 sta_fw_ver; -+ -+ /* Tasklets for handling hardware IRQ related operations outside hw IRQ -+ * handler */ -+ HOSTAP_TASKLET bap_tasklet; -+ -+ HOSTAP_TASKLET info_tasklet; -+ struct sk_buff_head info_list; /* info frames as skb's for -+ * info_tasklet */ -+ -+ HOSTAP_TASKLET tx_callback_tasklet; -+ struct sk_buff_head tx_callback_list; /* queued TX ACK/no-ACK data -+ * frames for tx_callback_tasklet -+ */ -+ struct hostap_tx_callback_info *tx_callback; /* registered TX callbacks -+ */ -+ -+ HOSTAP_TASKLET rx_tasklet; -+ struct sk_buff_head rx_list; -+ -+ HOSTAP_TASKLET sta_tx_exc_tasklet; -+ struct sk_buff_head sta_tx_exc_list; -+ -+ int host_roaming; -+ unsigned long last_join_time; /* time of last JoinRequest */ -+ struct hfa384x_scan_result *last_scan_results; -+ int last_scan_results_count; -+ HOSTAP_QUEUE info_queue; -+ long pending_info; /* bit field of pending info_queue items */ -+#define PRISM2_INFO_PENDING_LINKSTATUS 0 -+#define PRISM2_INFO_PENDING_SCANRESULTS 1 -+ int prev_link_status; /* previous received LinkStatus info */ -+ u8 preferred_ap[6]; /* use this AP if possible */ -+ -+#ifdef PRISM2_CALLBACK -+ void *callback_data; /* Can be used in callbacks; e.g., allocate -+ * on enable event and free on disable event. -+ * Host AP driver code does not touch this. */ -+#endif /* PRISM2_CALLBACK */ -+ -+ wait_queue_head_t hostscan_wq; -+ -+ /* Passive scan in Host AP mode */ -+ struct timer_list passive_scan_timer; -+ int passive_scan_interval; /* in seconds, 0 = disabled */ -+ int passive_scan_channel; -+ enum { PASSIVE_SCAN_WAIT, PASSIVE_SCAN_LISTEN } passive_scan_state; -+ -+ struct timer_list tick_timer; -+ unsigned long last_tick_timer; -+ unsigned int sw_tick_stuck; -+ -+#ifdef PRISM2_IO_DEBUG -+#define PRISM2_IO_DEBUG_SIZE 10000 -+ u32 io_debug[PRISM2_IO_DEBUG_SIZE]; -+ int io_debug_head; -+ int io_debug_enabled; -+#endif /* PRISM2_IO_DEBUG */ -+ -+ /* struct local_info is used also in hostap.o that does not define -+ * any PRISM2_{PCCARD,PLX,PCI}. Make sure that the hardware version -+ * specific fields are in the end of the struct (these could also be -+ * moved to void *priv or something like that). */ -+#ifdef PRISM2_PCCARD -+ dev_node_t node; -+ dev_link_t *link; -+#endif /* PRISM2_PCCARD */ -+ -+#ifdef PRISM2_PLX -+ unsigned long attr_mem; -+ unsigned int cor_offset; -+#endif /* PRISM2_PLX */ -+ -+#ifdef PRISM2_PCI -+ unsigned long attr_mem; -+ unsigned int cor_offset; -+#ifdef PRISM2_BUS_MASTER -+ /* bus master for BAP0 (TX) */ -+ int bus_m0_tx_idx; -+ u8 *bus_m0_buf; -+ -+ /* bus master for BAP1 (RX) */ -+ struct sk_buff *rx_skb; -+#endif /* PRISM2_BUS_MASTER */ -+#ifdef CONFIG_PM -+ u32 pci_save_state[16]; -+#endif /* CONFIG_PM */ -+#endif /* PRISM2_PCI */ -+ -+ /* NOTE! Do not add common entries here after hardware version -+ * specific blocks. */ -+}; -+ -+/* if wireless ext is not supported */ -+#ifndef IW_MODE_ADHOC -+#define IW_MODE_ADHOC 1 -+#endif -+#ifndef IW_MODE_INFRA -+#define IW_MODE_INFRA 2 -+#endif -+#ifndef IW_MODE_MASTER -+#define IW_MODE_MASTER 3 -+#endif -+#ifndef IW_MODE_REPEAT -+#define IW_MODE_REPEAT 4 -+#endif -+#ifndef IW_MODE_SECOND -+#define IW_MODE_SECOND 5 -+#endif -+#ifndef IW_MODE_MONITOR -+#define IW_MODE_MONITOR 6 -+#endif -+ -+#ifndef PRISM2_NO_DEBUG -+ -+#define DEBUG_FID BIT(0) -+#define DEBUG_PS BIT(1) -+#define DEBUG_FLOW BIT(2) -+#define DEBUG_AP BIT(3) -+#define DEBUG_HW BIT(4) -+#define DEBUG_EXTRA BIT(5) -+#define DEBUG_EXTRA2 BIT(6) -+#define DEBUG_PS2 BIT(7) -+#define DEBUG_MASK (DEBUG_PS | DEBUG_FLOW | DEBUG_AP | DEBUG_HW | \ -+ DEBUG_EXTRA) -+#define PDEBUG(n, args...) \ -+do { if ((n) & DEBUG_MASK) printk(KERN_DEBUG args); } while (0) -+#define PDEBUG2(n, args...) \ -+do { if ((n) & DEBUG_MASK) printk(args); } while (0) -+ -+#else /* PRISM2_NO_DEBUG */ -+ -+#define PDEBUG(n, args...) -+#define PDEBUG2(n, args...) -+ -+#endif /* PRISM2_NO_DEBUG */ -+ -+enum { BAP0 = 0, BAP1 = 1 }; -+ -+#define PRISM2_IO_DEBUG_CMD_INB 0 -+#define PRISM2_IO_DEBUG_CMD_INW 1 -+#define PRISM2_IO_DEBUG_CMD_INSW 2 -+#define PRISM2_IO_DEBUG_CMD_OUTB 3 -+#define PRISM2_IO_DEBUG_CMD_OUTW 4 -+#define PRISM2_IO_DEBUG_CMD_OUTSW 5 -+#define PRISM2_IO_DEBUG_CMD_ERROR 6 -+#define PRISM2_IO_DEBUG_CMD_INTERRUPT 7 -+ -+#ifdef PRISM2_IO_DEBUG -+ -+#define PRISM2_IO_DEBUG_ENTRY(cmd, reg, value) \ -+(((cmd) << 24) | ((reg) << 16) | value) -+ -+static inline void prism2_io_debug_add(struct net_device *dev, int cmd, -+ int reg, int value) -+{ -+ local_info_t *local = dev->priv; -+ -+ if (!local->io_debug_enabled) -+ return; -+ -+ local->io_debug[local->io_debug_head] = jiffies & 0xffffffff; -+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE) -+ local->io_debug_head = 0; -+ local->io_debug[local->io_debug_head] = -+ PRISM2_IO_DEBUG_ENTRY(cmd, reg, value); -+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE) -+ local->io_debug_head = 0; -+} -+ -+ -+static inline void prism2_io_debug_error(struct net_device *dev, int err) -+{ -+ local_info_t *local = dev->priv; -+ unsigned long flags; -+ -+ if (!local->io_debug_enabled) -+ return; -+ -+ spin_lock_irqsave(&local->lock, flags); -+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_ERROR, 0, err); -+ if (local->io_debug_enabled == 1) { -+ local->io_debug_enabled = 0; -+ printk(KERN_DEBUG "%s: I/O debug stopped\n", dev->name); -+ } -+ spin_unlock_irqrestore(&local->lock, flags); -+} -+ -+#else /* PRISM2_IO_DEBUG */ -+ -+static inline void prism2_io_debug_add(struct net_device *dev, int cmd, -+ int reg, int value) -+{ -+} -+ -+static inline void prism2_io_debug_error(struct net_device *dev, int err) -+{ -+} -+ -+#endif /* PRISM2_IO_DEBUG */ -+ -+ -+#ifdef PRISM2_CALLBACK -+enum { -+ /* Called when card is enabled */ -+ PRISM2_CALLBACK_ENABLE, -+ -+ /* Called when card is disabled */ -+ PRISM2_CALLBACK_DISABLE, -+ -+ /* Called when RX/TX starts/ends */ -+ PRISM2_CALLBACK_RX_START, PRISM2_CALLBACK_RX_END, -+ PRISM2_CALLBACK_TX_START, PRISM2_CALLBACK_TX_END -+}; -+void prism2_callback(local_info_t *local, int event); -+#else /* PRISM2_CALLBACK */ -+#define prism2_callback(d, e) do { } while (0) -+#endif /* PRISM2_CALLBACK */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* HOSTAP_WLAN_H */ - -Index: Documentation/Configure.help ---- Documentation/Configure.help.orig 2003-08-12 14:43:15.000000000 -0400 -+++ Documentation/Configure.help 2003-06-09 13:28:05.000000000 -0400 -@@ -9377,6 +9377,53 @@ - say M here and read . The module - will be called orinoco_cs.o. - -+Host AP support for Prism2/2.5/3 IEEE 802.11b -+CONFIG_HOSTAP -+ A driver for 802.11b wireless cards based on Intersil Prism2/2.5/3 -+ chipset. This driver supports so called Host AP mode that allows -+ the card to act as an IEEE 802.11 access point. -+ -+ See for more information about the -+ Host AP driver configuration and tools. -+ -+ This option includes the base Host AP driver code that is shared by -+ different hardware models. You will also need to enable support for -+ PLX/PCI/CS version of the driver to actually use the driver. -+ -+ The driver can be compiled as modules and they will be called -+ "hostap.o", "hostap_crypt.o", and "hostap_crypt_wep.o". -+ -+Host AP driver for Prism2/2.5/3 in PLX9052 based PCI adaptors -+CONFIG_HOSTAP_PLX -+ Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based -+ PCI adaptors. -+ -+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this -+ driver and its help text includes more information about the Host AP -+ driver. -+ -+ The driver can be compiled as a module and will be named "hostap_plx.o". -+ -+Host AP driver for Prism2.5 PCI adaptors -+CONFIG_HOSTAP_PCI -+ Host AP driver's version for Prism2.5 PCI adaptors. -+ -+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this -+ driver and its help text includes more information about the Host AP -+ driver. -+ -+ The driver can be compiled as a module and will be named "hostap_pci.o". -+ -+Host AP driver for Prism2/2.5/3 PC Cards -+CONFIG_HOSTAP_CS -+ Host AP driver's version for Prism2/2.5/3 PC Cards. -+ -+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this -+ driver and its help text includes more information about the Host AP -+ driver. -+ -+ The driver can be compiled as a module and will be named "hostap_cs.o". -+ - Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards - CONFIG_AIRO - This is the standard Linux driver to support Cisco/Aironet ISA and - -Index: MAINTAINERS ---- MAINTAINERS.orig 2003-08-12 14:42:54.000000000 -0400 -+++ MAINTAINERS 2003-06-09 13:23:17.000000000 -0400 -@@ -664,6 +664,13 @@ - L: linux-hippi@sunsite.dk - S: Maintained - -+HOST AP DRIVER -+P: Jouni Malinen -+M: jkmaline@cc.hut.fi -+L: hostap@lists.ssh.com -+W: http://hostap.epitest.fi/ -+S: Maintained -+ - HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series - P: Jaroslav Kysela - M: perex@suse.cz diff --git a/etc/linux-2.4.21-patch b/etc/linux-2.4.21-patch deleted file mode 100644 index 1c580bf98c..0000000000 --- a/etc/linux-2.4.21-patch +++ /dev/null @@ -1,2980 +0,0 @@ -Index: drivers/net/typhoon.c -=================================================================== ---- drivers/net/typhoon.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ drivers/net/typhoon.c (working copy) -@@ -1709,7 +1709,7 @@ - vlan_hwaccel_receive_skb(new_skb, tp->vlgrp, - ntohl(rx->vlanTag) & 0xffff); - else -- netif_receive_skb(new_skb); -+ netif_receive_skb(new_skb, new_skb->protocol, 0); - spin_unlock(&tp->state_lock); - - tp->dev->last_rx = jiffies; -Index: drivers/net/tulip/tulip_core.c -=================================================================== ---- drivers/net/tulip/tulip_core.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ drivers/net/tulip/tulip_core.c (working copy) -@@ -265,7 +265,17 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); - -+ - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) - { -@@ -710,6 +720,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -745,13 +766,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -760,6 +781,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -822,8 +856,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -902,10 +940,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1723,6 +1765,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1931,3 +1984,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -Index: drivers/net/tulip/interrupt.c -=================================================================== ---- drivers/net/tulip/interrupt.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ drivers/net/tulip/interrupt.c (working copy) -@@ -311,6 +311,10 @@ - #endif - } - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -320,7 +324,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -328,6 +331,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -341,14 +345,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -357,7 +380,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -425,16 +454,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -456,7 +486,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -547,7 +580,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -570,12 +605,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: - } -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; -+} -Index: drivers/net/tg3.c -=================================================================== ---- drivers/net/tg3.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ drivers/net/tg3.c (working copy) -@@ -2023,7 +2023,7 @@ - desc->err_vlan & RXD_VLAN_MASK); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - tp->dev->last_rx = jiffies; - received++; -Index: drivers/net/eepro100.c -=================================================================== ---- drivers/net/eepro100.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ drivers/net/eepro100.c (working copy) -@@ -549,6 +549,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -880,6 +890,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1130,7 +1151,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* -@@ -1395,7 +1417,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1442,6 +1465,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1499,7 +1530,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1508,6 +1538,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1571,6 +1607,11 @@ - long ioaddr, boguscnt = max_interrupt_work; - unsigned short status; - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1599,13 +1640,15 @@ - break; - - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - - spin_lock(&sp->lock); - /* -@@ -1630,7 +1673,7 @@ - - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - speedo_tx_buffer_gc(dev); - if (sp->tx_full - && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -@@ -1748,6 +1791,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1764,6 +1813,12 @@ - - if (netif_msg_intr(sp)) - printk(KERN_DEBUG " In speedo_rx().\n"); -+ if (dev->polling) { -+ printk(KERN_ERR "%s: In speedo_rx() while polling.\n", -+ dev->name); -+ return 0; -+ } -+ - /* If we own the next entry, it's a new packet. Send it up. */ - while (sp->rx_ringp[entry] != NULL) { - int status; -@@ -2455,3 +2510,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (netif_msg_rx_err(sp)) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -Index: kernel/ksyms.c -=================================================================== ---- kernel/ksyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ kernel/ksyms.c (working copy) -@@ -539,6 +539,8 @@ - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); - EXPORT_SYMBOL(__inode_dir_notify); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -Index: include/asm-ia64/delay.h -=================================================================== ---- include/asm-ia64/delay.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/delay.h (working copy) -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -Index: include/asm-ia64/sn/rw_mmr.h -=================================================================== ---- include/asm-ia64/sn/rw_mmr.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/sn/rw_mmr.h (working copy) -@@ -51,7 +51,7 @@ - "st8.rel [%0]=%1;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr), "r"(val) -+ : : "r"(mmr), "r"(val) - : "r2", "memory"); - } - -@@ -66,7 +66,7 @@ - "st8.rel [%2]=%3;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) -+ : : "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) - : "r2", "memory"); - } - -Index: include/asm-ia64/io.h -=================================================================== ---- include/asm-ia64/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/io.h (working copy) -@@ -85,7 +85,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -Index: include/asm-ia64/processor.h -=================================================================== ---- include/asm-ia64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/processor.h (working copy) -@@ -413,14 +413,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - -@@ -447,8 +447,8 @@ - extern void ia32_load_state (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -477,25 +477,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -509,7 +509,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -523,7 +523,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -538,7 +538,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -550,7 +550,7 @@ - ia64_clear_ic (void) - { - __u64 psr; -- asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) :: "memory"); -+ asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) : : "memory"); - return psr; - } - -@@ -560,7 +560,7 @@ - static inline void - ia64_set_psr (__u64 psr) - { -- asm volatile (";; mov psr.l=%0;; srlz.d" :: "r" (psr) : "memory"); -+ asm volatile (";; mov psr.l=%0;; srlz.d" : : "r" (psr) : "memory"); - } - - /* -@@ -572,14 +572,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -590,13 +590,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -607,16 +607,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -624,7 +624,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -639,13 +639,13 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #define cpu_relax() do { } while (0) -@@ -654,13 +654,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -675,7 +675,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -690,7 +690,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -758,7 +758,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - /* -@@ -769,7 +769,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -784,7 +784,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -798,7 +798,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -815,7 +815,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -832,7 +832,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -849,7 +849,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -875,13 +875,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -Index: include/asm-ia64/spinlock.h -=================================================================== ---- include/asm-ia64/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/spinlock.h (working copy) -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -93,7 +93,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -156,7 +156,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ -+ : : "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ - } while(0) - - #define write_unlock(x) \ -Index: include/asm-ia64/system.h -=================================================================== ---- include/asm-ia64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/system.h (working copy) -@@ -57,7 +57,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -82,7 +82,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -121,7 +121,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -133,7 +133,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -147,7 +147,7 @@ - __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (psr) :: "memory"); \ -+ : "=r" (psr) : : "memory"); \ - (x) = psr; \ - } while (0) - -@@ -171,25 +171,25 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_set(x) __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (x) :: "memory") -+ : "=r" (x) : : "memory") - # define local_irq_restore(x) __asm__ __volatile__ ("cmp.ne p6,p7=%0,r0;;" \ - "(p6) ssm psr.i;" \ - "(p7) rsm psr.i;;" \ - "srlz.d" \ -- :: "r"((x) & IA64_PSR_I) \ -+ : : "r"((x) & IA64_PSR_I) \ - : "p6", "p7", "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define __save_and_sti(flags) local_irq_set(flags) - #define save_and_cli(flags) __save_and_cli(flags) -@@ -324,7 +324,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -Index: include/asm-ia64/pgalloc.h -=================================================================== ---- include/asm-ia64/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ia64/pgalloc.h (working copy) -@@ -209,7 +209,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - else - vma->vm_mm->context = 0; - #endif -Index: include/asm-sparc/system.h -=================================================================== ---- include/asm-sparc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-sparc/system.h (working copy) -@@ -299,9 +299,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - - #define nop() __asm__ __volatile__ ("nop"); - -Index: include/asm-mips/processor.h -=================================================================== ---- include/asm-mips/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips/processor.h (working copy) -@@ -256,6 +256,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips/system.h -=================================================================== ---- include/asm-mips/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips/system.h (working copy) -@@ -248,17 +248,17 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - #endif /* !__ASSEMBLY__ */ - - #define prepare_to_switch() do { } while(0) - - struct task_struct; - --extern asmlinkage void lazy_fpu_switch(void *); --extern asmlinkage void init_fpu(void); --extern asmlinkage void save_fp(struct task_struct *); --extern asmlinkage void restore_fp(struct task_struct *); -+asmlinkage void lazy_fpu_switch(void *); -+asmlinkage void init_fpu(void); -+asmlinkage void save_fp(struct task_struct *); -+asmlinkage void restore_fp(struct task_struct *); - - #define switch_to(prev,next,last) \ - do { \ -Index: include/asm-mips/watch.h -=================================================================== ---- include/asm-mips/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips/watch.h (working copy) -@@ -20,9 +20,9 @@ - - extern char watch_available; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (watch_available) \ -Index: include/asm-mips/sibyte/64bit.h -=================================================================== ---- include/asm-mips/sibyte/64bit.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips/sibyte/64bit.h (working copy) -@@ -51,7 +51,7 @@ - " or $1, $1, $2 \n" - " sd $1, (%2)\n" - ".set pop\n" -- ::"r" (high), "r" (low), "r" (addr) -+ : :"r" (high), "r" (low), "r" (addr) - :"$1", "$2"); - __restore_flags(flags); - } -Index: include/net/route.h -=================================================================== ---- include/net/route.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/net/route.h (working copy) -@@ -140,7 +140,13 @@ - static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) - { -+#ifdef __cplusplus -+ struct rt_key key = { daddr, saddr }; -+ key.oif = oif; -+ key.tos = tos; -+#else - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; -+#endif - - return ip_route_output_key(rp, &key); - } -Index: include/net/checksum.h -=================================================================== ---- include/net/checksum.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/net/checksum.h (working copy) -@@ -111,7 +111,7 @@ - static __inline__ unsigned int csum_and_copy_to_user - (const char *src, char *dst, int len, unsigned int sum, int *err_ptr) - { -- sum = csum_partial(src, len, sum); -+ sum = csum_partial((const unsigned char *) src, len, sum); - - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len) == 0) -Index: include/net/ax25.h -=================================================================== ---- include/net/ax25.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/net/ax25.h (working copy) -@@ -176,7 +176,7 @@ - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - ax25_digi *digipeat; -- ax25_dev *ax25_dev; -+ struct ax25_dev *ax25_dev; - unsigned char iamdigi; - unsigned char state, modulus, pidincl; - unsigned short vs, vr, va; -Index: include/asm-arm/mmu.h -=================================================================== ---- include/asm-arm/mmu.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-arm/mmu.h (working copy) -@@ -2,6 +2,6 @@ - #define __ARM_MMU_H - - /* The ARM doesn't have a mmu context */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -Index: include/asm-arm/system.h -=================================================================== ---- include/asm-arm/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-arm/system.h (working copy) -@@ -29,7 +29,7 @@ - - #define tas(ptr) (xchg((ptr),1)) - --extern asmlinkage void __backtrace(void); -+asmlinkage void __backtrace(void); - - /* - * Include processor dependent parts -Index: include/asm-arm/proc-armo/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armo/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-arm/proc-armo/pgalloc.h (working copy) -@@ -20,7 +20,7 @@ - */ - static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) - { -- return kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ return (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - } - - /* -Index: include/asm-arm/proc-armv/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armv/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-arm/proc-armv/pgalloc.h (working copy) -@@ -22,7 +22,7 @@ - { - pte_t *pte; - -- pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ pte = (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - if (pte) - pte += PTRS_PER_PTE; - return pte; -Index: include/asm-parisc/system.h -=================================================================== ---- include/asm-parisc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-parisc/system.h (working copy) -@@ -138,7 +138,7 @@ - ** The __asm__ op below simple prevents gcc/ld from reordering - ** instructions across the mb() "call". - */ --#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */ -+#define mb() __asm__ __volatile__("": : :"memory"); /* barrier() */ - #define rmb() mb() - #define wmb() mb() - #define smp_mb() mb() -Index: include/linux/list.h -=================================================================== ---- include/linux/list.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/list.h (working copy) -@@ -91,8 +91,8 @@ - static inline void list_del(struct list_head *entry) - { - __list_del(entry->prev, entry->next); -- entry->next = (void *) 0; -- entry->prev = (void *) 0; -+ entry->next = (struct list_head *) 0; -+ entry->prev = (struct list_head *) 0; - } - - /** -Index: include/linux/sysctl.h -=================================================================== ---- include/linux/sysctl.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/sysctl.h (working copy) -@@ -643,7 +643,7 @@ - - #ifdef __KERNEL__ - --extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+asmlinkage long sys_sysctl(struct __sysctl_args *); - extern void sysctl_init(void); - - typedef struct ctl_table ctl_table; -Index: include/linux/spinlock.h -=================================================================== ---- include/linux/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/spinlock.h (working copy) -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - /* - * These are the generic versions of the spinlocks and read-write -@@ -71,13 +72,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 95) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -135,13 +131,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -Index: include/linux/netdevice.h -=================================================================== ---- include/linux/netdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/netdevice.h (working copy) -@@ -438,6 +438,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - -@@ -480,6 +520,9 @@ - extern int unregister_netdevice(struct net_device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -@@ -593,7 +636,7 @@ - #define HAVE_NETIF_RX 1 - extern int netif_rx(struct sk_buff *skb); - #define HAVE_NETIF_RECEIVE_SKB 1 --extern int netif_receive_skb(struct sk_buff *skb); -+extern int netif_receive_skb(struct sk_buff *skb, unsigned short, int ignore_notifiers); - extern int dev_ioctl(unsigned int cmd, void *); - extern int dev_change_flags(struct net_device *, unsigned); - extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); -Index: include/linux/intermezzo_kml.h -=================================================================== ---- include/linux/intermezzo_kml.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/intermezzo_kml.h (working copy) -@@ -70,8 +70,7 @@ - int gid; - }; - --struct kml_open { --}; -+EMPTY_STRUCT_DECL(kml_open); - - struct kml_mkdir { - char *path; -Index: include/linux/skbuff.h -=================================================================== ---- include/linux/skbuff.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/skbuff.h (working copy) -@@ -126,15 +126,31 @@ - skb_frag_t frags[MAX_SKB_FRAGS]; - }; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -165,8 +181,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; -- - /* - * This is the control buffer. It is free to use for every - * layer. Please put your private variables there. If you -@@ -175,24 +189,18 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -+ struct dst_entry *dst; -+ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ - unsigned int data_len; - unsigned int csum; /* Checksum */ -- unsigned char __unused, /* Dead field, may be reused */ -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ - -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -- - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER - /* Can be used for communication between hooks. */ -@@ -233,6 +241,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -823,7 +833,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -851,7 +861,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -Index: include/linux/atalk.h -=================================================================== ---- include/linux/atalk.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/atalk.h (working copy) -@@ -163,7 +163,7 @@ - - static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) - { -- return dev->atalk_ptr; -+ return (struct atalk_iface *) dev->atalk_ptr; - } - - extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); -Index: include/linux/types.h -=================================================================== ---- include/linux/types.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/types.h (working copy) -@@ -134,4 +134,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -Index: include/linux/inetdevice.h -=================================================================== ---- include/linux/inetdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/inetdevice.h (working copy) -@@ -124,7 +124,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -Index: include/linux/if_vlan.h -=================================================================== ---- include/linux/if_vlan.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/if_vlan.h (working copy) -@@ -183,7 +183,7 @@ - break; - }; - -- return (polling ? netif_receive_skb(skb) : netif_rx(skb)); -+ return (polling ? netif_receive_skb(skb, skb->protocol, 0) : netif_rx(skb)); - } - - static inline int vlan_hwaccel_rx(struct sk_buff *skb, -Index: include/linux/nfsd/syscall.h -=================================================================== ---- include/linux/nfsd/syscall.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/nfsd/syscall.h (working copy) -@@ -133,7 +133,7 @@ - * Kernel syscall implementation. - */ - #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) --extern asmlinkage long sys_nfsservctl(int, void *, void *); -+asmlinkage long sys_nfsservctl(int, void *, void *); - #else - #define sys_nfsservctl sys_ni_syscall - #endif -Index: include/linux/highmem.h -=================================================================== ---- include/linux/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/highmem.h (working copy) -@@ -17,7 +17,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -103,7 +103,7 @@ - - if (offset + size > PAGE_SIZE) - out_of_line_bug(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -114,8 +114,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -Index: include/linux/mtd/compatmac.h -=================================================================== ---- include/linux/mtd/compatmac.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/mtd/compatmac.h (working copy) -@@ -133,8 +133,8 @@ - #endif /* !(__BIT_TYPES_DEFINED__) */ - - #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } -+ typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+ #define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - #else - typedef struct { int gcc_is_buggy; } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } -Index: include/linux/netfilter_ipv4/ip_conntrack_irc.h -=================================================================== ---- include/linux/netfilter_ipv4/ip_conntrack_irc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/netfilter_ipv4/ip_conntrack_irc.h (working copy) -@@ -27,8 +27,7 @@ - }; - - /* This structure exists only once per master */ --struct ip_ct_irc_master { --}; -+EMPTY_STRUCT_DECL(ip_ct_irc_master); - - - #ifdef __KERNEL__ -Index: include/linux/mm.h -=================================================================== ---- include/linux/mm.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/mm.h (working copy) -@@ -577,7 +577,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -Index: include/linux/reiserfs_fs_sb.h -=================================================================== ---- include/linux/reiserfs_fs_sb.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/reiserfs_fs_sb.h (working copy) -@@ -405,8 +405,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -Index: include/linux/swap.h -=================================================================== ---- include/linux/swap.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/linux/swap.h (working copy) -@@ -100,7 +100,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -Index: include/asm-mips64/processor.h -=================================================================== ---- include/asm-mips64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips64/processor.h (working copy) -@@ -307,6 +307,6 @@ - * functions. We avoid the overhead of a function call by forcing the - * compiler to save the return address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips64/system.h -=================================================================== ---- include/asm-mips64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips64/system.h (working copy) -@@ -221,16 +221,16 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - - struct task_struct; - --extern asmlinkage void lazy_fpu_switch(void *, void *); --extern asmlinkage void init_fpu(void); --extern asmlinkage void save_fp(struct task_struct *); --extern asmlinkage void restore_fp(struct task_struct *); -+asmlinkage void lazy_fpu_switch(void *, void *); -+asmlinkage void init_fpu(void); -+asmlinkage void save_fp(struct task_struct *); -+asmlinkage void restore_fp(struct task_struct *); - - #ifdef CONFIG_SMP - #define SWITCH_DO_LAZY_FPU \ -Index: include/asm-mips64/watch.h -=================================================================== ---- include/asm-mips64/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips64/watch.h (working copy) -@@ -20,9 +20,9 @@ - - extern char watch_available; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (watch_available) \ -Index: include/asm-mips64/sibyte/64bit.h -=================================================================== ---- include/asm-mips64/sibyte/64bit.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-mips64/sibyte/64bit.h (working copy) -@@ -51,7 +51,7 @@ - " or $1, $1, $2 \n" - " sd $1, (%2)\n" - ".set pop\n" -- ::"r" (high), "r" (low), "r" (addr) -+ : :"r" (high), "r" (low), "r" (addr) - :"$1", "$2"); - __restore_flags(flags); - } -Index: include/asm-sparc64/system.h -=================================================================== ---- include/asm-sparc64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-sparc64/system.h (working copy) -@@ -121,9 +121,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -Index: include/asm-alpha/core_tsunami.h -=================================================================== ---- include/asm-alpha/core_tsunami.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-alpha/core_tsunami.h (working copy) -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -Index: include/asm-s390x/uaccess.h -=================================================================== ---- include/asm-s390x/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-s390x/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-i386/pgtable.h -=================================================================== ---- include/asm-i386/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-i386/pgtable.h (working copy) -@@ -43,7 +43,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-i386/rwlock.h -=================================================================== ---- include/asm-i386/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-i386/rwlock.h (working copy) -@@ -28,7 +28,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -58,7 +58,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -Index: include/asm-i386/string.h -=================================================================== ---- include/asm-i386/string.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-i386/string.h (working copy) -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -Index: include/asm-i386/desc.h -=================================================================== ---- include/asm-i386/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-i386/desc.h (working copy) -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -Index: include/asm-i386/highmem.h -=================================================================== ---- include/asm-i386/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-i386/highmem.h (working copy) -@@ -94,7 +94,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -110,7 +110,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -Index: include/asm-ppc64/delay.h -=================================================================== ---- include/asm-ppc64/delay.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-ppc64/delay.h (working copy) -@@ -19,7 +19,7 @@ - /* define these here to prevent circular dependencies */ - #define __HMT_low() asm volatile("or 1,1,1") - #define __HMT_medium() asm volatile("or 2,2,2") --#define __barrier() asm volatile("":::"memory") -+#define __barrier() asm volatile("": : :"memory") - - static inline unsigned long __get_tb(void) - { -Index: include/asm-s390/uaccess.h -=================================================================== ---- include/asm-s390/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-s390/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4)); \ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-x86_64/uaccess.h -=================================================================== ---- include/asm-x86_64/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/uaccess.h (working copy) -@@ -283,13 +283,13 @@ - case 10: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2); - return ret; - case 16: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8); - return ret; - default: -Index: include/asm-x86_64/pgtable.h -=================================================================== ---- include/asm-x86_64/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/pgtable.h (working copy) -@@ -49,7 +49,7 @@ - "movq %%cr3, %0; # flush TLB \n" \ - "movq %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-x86_64/rwlock.h -=================================================================== ---- include/asm-x86_64/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/rwlock.h (working copy) -@@ -31,7 +31,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -44,7 +44,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile int *)rw))::"memory") -+ :"=m" (*((volatile int *)rw)): :"memory") - - #define __build_read_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -@@ -61,7 +61,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -@@ -74,7 +74,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile long *)rw))::"memory") -+ :"=m" (*((volatile long *)rw)): :"memory") - - #define __build_write_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -Index: include/asm-x86_64/pda.h -=================================================================== ---- include/asm-x86_64/pda.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/pda.h (working copy) -@@ -41,9 +41,9 @@ - - #define pda_to_op(op,field,val) do { \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %0,%%gs:%c1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 4: asm volatile(op "l %0,%%gs:%c1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 8: asm volatile(op "q %0,%%gs:%c1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 2: asm volatile(op "w %0,%%gs:%c1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 4: asm volatile(op "l %0,%%gs:%c1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 8: asm volatile(op "q %0,%%gs:%c1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ - default: __bad_pda_field(); \ - } \ - } while (0) -Index: include/asm-x86_64/page.h -=================================================================== ---- include/asm-x86_64/page.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/page.h (working copy) -@@ -87,9 +87,9 @@ - char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */ - unsigned short line; - } __attribute__((packed)); --#define BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" :: "i"(__LINE__), \ -+#define BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" : : "i"(__LINE__), \ - "i" (__stringify(KBUILD_BASENAME))) --#define HEADER_BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" :: "i"(__LINE__), \ -+#define HEADER_BUG() asm volatile("ud2 ; .quad %c1 ; .short %c0" : : "i"(__LINE__), \ - "i" (__stringify(__FILE__))) - #define PAGE_BUG(page) BUG() - -Index: include/asm-x86_64/desc.h -=================================================================== ---- include/asm-x86_64/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/desc.h (working copy) -@@ -73,9 +73,9 @@ - #define __CPU_DESC_INDEX(x,field) \ - ((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + __GDT_HEAD_SIZE) - --#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss))); --#define __load_LDT(cpu) asm volatile("lldt %w0"::"r" (__CPU_DESC_INDEX(cpu, ldt))); --#define clear_LDT(n) asm volatile("lldt %w0"::"r" (0)) -+#define load_TR(cpu) asm volatile("ltr %w0": :"r" (__CPU_DESC_INDEX(cpu, tss))); -+#define __load_LDT(cpu) asm volatile("lldt %w0": :"r" (__CPU_DESC_INDEX(cpu, ldt))); -+#define clear_LDT(n) asm volatile("lldt %w0": :"r" (0)) - - extern struct gate_struct idt_table[]; - -Index: include/asm-x86_64/system.h -=================================================================== ---- include/asm-x86_64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-x86_64/system.h (working copy) -@@ -248,9 +248,9 @@ - * but I'd also expect them to finally get their act together - * and add some real memory barriers if so. - */ --#define mb() asm volatile("mfence":::"memory") --#define rmb() asm volatile("lfence":::"memory") --#define wmb() asm volatile("sfence":::"memory") -+#define mb() asm volatile("mfence": : :"memory") -+#define rmb() asm volatile("lfence": : :"memory") -+#define wmb() asm volatile("sfence": : :"memory") - #define set_mb(var, value) do { xchg(&var, value); } while (0) - #define set_wmb(var, value) do { var = value; wmb(); } while (0) - -@@ -299,7 +299,7 @@ - #endif - - /* Default simics "magic" breakpoint */ --#define icebp() asm volatile("xchg %%bx,%%bx" ::: "ebx") -+#define icebp() asm volatile("xchg %%bx,%%bx" : : : "ebx") - - /* - * disable hlt during certain critical i/o operations -Index: include/asm-cris/io.h -=================================================================== ---- include/asm-cris/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ include/asm-cris/io.h (working copy) -@@ -26,8 +26,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -Index: net/netsyms.c -=================================================================== ---- net/netsyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ net/netsyms.c (working copy) -@@ -278,6 +278,11 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - -Index: net/core/dev.c -=================================================================== ---- net/core/dev.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ net/core/dev.c (working copy) -@@ -182,6 +182,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1423,6 +1426,22 @@ - } - - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1456,11 +1475,10 @@ - } - #endif /* CONFIG_NET_DIVERT */ - --int netif_receive_skb(struct sk_buff *skb) -+int netif_receive_skb(struct sk_buff *skb, unsigned short type, int notifier_data) - { - struct packet_type *ptype, *pt_prev; - int ret = NET_RX_DROP; -- unsigned short type = skb->protocol; - - if (skb->stamp.tv_sec == 0) - do_gettimeofday(&skb->stamp); -@@ -1478,6 +1496,14 @@ - - skb->h.raw = skb->nh.raw = skb->data; - -+ /* Click: may want to steal the packet */ -+ if (notifier_data >= 0 -+ && notifier_call_chain(&net_in_chain, -+ notifier_data, -+ skb) & NOTIFY_STOP_MASK) { -+ return ret; -+ } -+ - pt_prev = NULL; - for (ptype = ptype_all; ptype; ptype = ptype->next) { - if (!ptype->dev || ptype->dev == skb->dev) { -@@ -1557,7 +1583,7 @@ - - dev = skb->dev; - -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, skb_queue_len(&queue->input_pkt_queue)); - - dev_put(dev); - -Index: net/core/skbuff.c -=================================================================== ---- net/core/skbuff.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ net/core/skbuff.c (working copy) -@@ -443,6 +443,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -Index: net/ipv4/arp.c -=================================================================== ---- net/ipv4/arp.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ net/ipv4/arp.c (working copy) -@@ -318,6 +318,7 @@ - { - u32 saddr; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -330,8 +331,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -341,8 +342,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) -Index: fs/proc/inode.c -=================================================================== ---- fs/proc/inode.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.21) (revision 23) -+++ fs/proc/inode.c (working copy) -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { diff --git a/etc/linux-2.4.26-patch b/etc/linux-2.4.26-patch deleted file mode 100644 index b3e065609d..0000000000 --- a/etc/linux-2.4.26-patch +++ /dev/null @@ -1,3268 +0,0 @@ -Index: drivers/net/e1000/e1000_main.c -=================================================================== ---- drivers/net/e1000/e1000_main.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/e1000/e1000_main.c (working copy) -@@ -2348,7 +2348,7 @@ - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); - } else { -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - } - #else /* CONFIG_E1000_NAPI */ - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { -Index: drivers/net/8139cp.c -=================================================================== ---- drivers/net/8139cp.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/8139cp.c (working copy) -@@ -472,7 +472,7 @@ - be16_to_cpu(desc->opts2 & 0xffff)); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - } - - static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, -Index: drivers/net/mv64340_eth.c -=================================================================== ---- drivers/net/mv64340_eth.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/mv64340_eth.c (working copy) -@@ -529,7 +529,7 @@ - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, dev); - #ifdef MV64340_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - #else - netif_rx(skb); - #endif -Index: drivers/net/gt64240eth.c -=================================================================== ---- drivers/net/gt64240eth.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/gt64240eth.c (working copy) -@@ -1520,7 +1520,7 @@ - /* NIC performed some checksum computation */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - #ifdef GT64240_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - #else - netif_rx(skb); /* pass the packet to upper layers */ - #endif -Index: drivers/net/b44.c -=================================================================== ---- drivers/net/b44.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/b44.c (working copy) -@@ -743,7 +743,7 @@ - } - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, bp->dev); -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - bp->dev->last_rx = jiffies; - received++; - budget--; -Index: drivers/net/typhoon.c -=================================================================== ---- drivers/net/typhoon.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/typhoon.c (working copy) -@@ -1729,7 +1729,7 @@ - vlan_hwaccel_receive_skb(new_skb, tp->vlgrp, - ntohl(rx->vlanTag) & 0xffff); - else -- netif_receive_skb(new_skb); -+ netif_receive_skb(new_skb, new_skb->protocol, 0); - spin_unlock(&tp->state_lock); - - tp->dev->last_rx = jiffies; -Index: drivers/net/tulip/tulip_core.c -=================================================================== ---- drivers/net/tulip/tulip_core.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/tulip/tulip_core.c (working copy) -@@ -268,7 +268,17 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); - -+ - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) - { -@@ -713,6 +723,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -748,13 +769,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -763,6 +784,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -825,8 +859,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -905,10 +943,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1729,6 +1771,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1937,3 +1990,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -Index: drivers/net/tulip/interrupt.c -=================================================================== ---- drivers/net/tulip/interrupt.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/tulip/interrupt.c (working copy) -@@ -311,6 +311,10 @@ - #endif - } - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -320,7 +324,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -328,6 +331,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -341,14 +345,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -357,7 +380,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -425,16 +454,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -456,7 +486,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -547,7 +580,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -570,12 +605,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: - } -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; -+} -Index: drivers/net/tg3.c -=================================================================== ---- drivers/net/tg3.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/tg3.c (working copy) -@@ -2302,7 +2302,7 @@ - desc->err_vlan & RXD_VLAN_MASK); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - tp->dev->last_rx = jiffies; - received++; -Index: drivers/net/eepro100.c -=================================================================== ---- drivers/net/eepro100.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ drivers/net/eepro100.c (working copy) -@@ -549,6 +549,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -880,6 +890,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1130,7 +1151,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* -@@ -1395,7 +1417,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1442,6 +1465,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1499,7 +1530,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1508,6 +1538,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1571,6 +1607,11 @@ - long ioaddr, boguscnt = max_interrupt_work; - unsigned short status; - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1599,13 +1640,15 @@ - break; - - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - - spin_lock(&sp->lock); - /* -@@ -1630,7 +1673,7 @@ - - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - speedo_tx_buffer_gc(dev); - if (sp->tx_full - && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -@@ -1748,6 +1791,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1764,6 +1813,12 @@ - - if (netif_msg_intr(sp)) - printk(KERN_DEBUG " In speedo_rx().\n"); -+ if (dev->polling) { -+ printk(KERN_ERR "%s: In speedo_rx() while polling.\n", -+ dev->name); -+ return 0; -+ } -+ - /* If we own the next entry, it's a new packet. Send it up. */ - while (sp->rx_ringp[entry] != NULL) { - int status; -@@ -2456,3 +2511,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (netif_msg_rx_err(sp)) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -Index: kernel/ksyms.c -=================================================================== ---- kernel/ksyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ kernel/ksyms.c (working copy) -@@ -558,6 +558,8 @@ - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); - EXPORT_SYMBOL(__inode_dir_notify); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -Index: include/asm-ia64/intrinsics.h -=================================================================== ---- include/asm-ia64/intrinsics.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/intrinsics.h (working copy) -@@ -131,7 +131,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -Index: include/asm-ia64/delay.h -=================================================================== ---- include/asm-ia64/delay.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/delay.h (working copy) -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -Index: include/asm-ia64/sn/sn2/io.h -=================================================================== ---- include/asm-ia64/sn/sn2/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/sn/sn2/io.h (working copy) -@@ -12,7 +12,7 @@ - extern void * sn_io_addr(unsigned long port) __attribute__ ((__const__)); /* Forward definition */ - extern void sn_mmiob(void); /* Forward definition */ - --#define __sn_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __sn_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - extern void sn_dma_flush(unsigned long); - -Index: include/asm-ia64/sn/rw_mmr.h -=================================================================== ---- include/asm-ia64/sn/rw_mmr.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/sn/rw_mmr.h (working copy) -@@ -51,7 +51,7 @@ - "st8.rel [%0]=%1;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr), "r"(val) -+ : : "r"(mmr), "r"(val) - : "r2", "memory"); - } - -@@ -66,7 +66,7 @@ - "st8.rel [%2]=%3;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) -+ : : "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) - : "r2", "memory"); - } - -Index: include/asm-ia64/io.h -=================================================================== ---- include/asm-ia64/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/io.h (working copy) -@@ -85,7 +85,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -Index: include/asm-ia64/processor.h -=================================================================== ---- include/asm-ia64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/processor.h (working copy) -@@ -424,14 +424,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - /* Return TRUE if task T owns the fph partition of the CPU we're running on. */ -@@ -463,8 +463,8 @@ - extern void ia32_load_state (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -493,25 +493,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -525,7 +525,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -539,7 +539,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -554,7 +554,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -566,7 +566,7 @@ - ia64_clear_ic (void) - { - __u64 psr; -- asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) :: "memory"); -+ asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) : : "memory"); - return psr; - } - -@@ -576,7 +576,7 @@ - static inline void - ia64_set_psr (__u64 psr) - { -- asm volatile (";; mov psr.l=%0;; srlz.d" :: "r" (psr) : "memory"); -+ asm volatile (";; mov psr.l=%0;; srlz.d" : : "r" (psr) : "memory"); - } - - /* -@@ -588,14 +588,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -606,13 +606,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -623,16 +623,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -640,7 +640,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -655,20 +655,20 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #ifdef GAS_HAS_HINT_INSN - static inline void - ia64_hint_pause (void) - { -- asm volatile ("hint @pause" ::: "memory"); -+ asm volatile ("hint @pause" : : : "memory"); - } - - #define cpu_relax() ia64_hint_pause() -@@ -679,13 +679,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -700,7 +700,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -715,7 +715,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -780,7 +780,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -788,7 +788,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -803,7 +803,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -817,7 +817,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -834,7 +834,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -851,7 +851,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -868,7 +868,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -894,13 +894,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -Index: include/asm-ia64/spinlock.h -=================================================================== ---- include/asm-ia64/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/spinlock.h (working copy) -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -100,7 +100,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -165,7 +165,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ -+ : : "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ - } while(0) - - #define write_unlock(x) \ -Index: include/asm-ia64/system.h -=================================================================== ---- include/asm-ia64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/system.h (working copy) -@@ -57,7 +57,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -82,7 +82,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -121,7 +121,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -133,7 +133,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -147,7 +147,7 @@ - __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (psr) :: "memory"); \ -+ : "=r" (psr) : : "memory"); \ - (x) = psr; \ - } while (0) - -@@ -171,25 +171,25 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_set(x) __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (x) :: "memory") -+ : "=r" (x) : : "memory") - # define local_irq_restore(x) __asm__ __volatile__ ("cmp.ne p6,p7=%0,r0;;" \ - "(p6) ssm psr.i;" \ - "(p7) rsm psr.i;;" \ - "srlz.d" \ -- :: "r"((x) & IA64_PSR_I) \ -+ : : "r"((x) & IA64_PSR_I) \ - : "p6", "p7", "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define __save_and_sti(flags) local_irq_set(flags) - #define save_and_cli(flags) __save_and_cli(flags) -Index: include/asm-ia64/pgalloc.h -=================================================================== ---- include/asm-ia64/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ia64/pgalloc.h (working copy) -@@ -209,7 +209,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - else - vma->vm_mm->context = 0; - #endif -Index: include/asm-mips/irq.h -=================================================================== ---- include/asm-mips/irq.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/irq.h (working copy) -@@ -30,7 +30,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -Index: include/asm-mips/time.h -=================================================================== ---- include/asm-mips/time.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/time.h (working copy) -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -Index: include/asm-mips/processor.h -=================================================================== ---- include/asm-mips/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/processor.h (working copy) -@@ -314,6 +314,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips/system.h -=================================================================== ---- include/asm-mips/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/system.h (working copy) -@@ -260,7 +260,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -Index: include/asm-mips/watch.h -=================================================================== ---- include/asm-mips/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/watch.h (working copy) -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -Index: include/asm-mips/fpu.h -=================================================================== ---- include/asm-mips/fpu.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips/fpu.h (working copy) -@@ -22,8 +22,8 @@ - - struct sigcontext; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -Index: include/asm-sparc/system.h -=================================================================== ---- include/asm-sparc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-sparc/system.h (working copy) -@@ -295,9 +295,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - - #define nop() __asm__ __volatile__ ("nop"); - -Index: include/net/route.h -=================================================================== ---- include/net/route.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/net/route.h (working copy) -@@ -142,7 +142,13 @@ - static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) - { -+#ifdef __cplusplus -+ struct rt_key key = { daddr, saddr }; -+ key.oif = oif; -+ key.tos = tos; -+#else - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; -+#endif - - return ip_route_output_key(rp, &key); - } -Index: include/net/checksum.h -=================================================================== ---- include/net/checksum.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/net/checksum.h (working copy) -@@ -111,7 +111,7 @@ - static __inline__ unsigned int csum_and_copy_to_user - (const char *src, char *dst, int len, unsigned int sum, int *err_ptr) - { -- sum = csum_partial(src, len, sum); -+ sum = csum_partial((const unsigned char *) src, len, sum); - - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len) == 0) -Index: include/net/ax25.h -=================================================================== ---- include/net/ax25.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/net/ax25.h (working copy) -@@ -176,7 +176,7 @@ - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - ax25_digi *digipeat; -- ax25_dev *ax25_dev; -+ struct ax25_dev *ax25_dev; - unsigned char iamdigi; - unsigned char state, modulus, pidincl; - unsigned short vs, vr, va; -Index: include/asm-arm/mmu.h -=================================================================== ---- include/asm-arm/mmu.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-arm/mmu.h (working copy) -@@ -4,6 +4,6 @@ - /* - * The ARM doesn't have a mmu context - */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -Index: include/asm-arm/system.h -=================================================================== ---- include/asm-arm/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-arm/system.h (working copy) -@@ -36,7 +36,7 @@ - - #define tas(ptr) (xchg((ptr),1)) - --extern asmlinkage void __backtrace(void); -+asmlinkage void __backtrace(void); - - /* - * Include processor dependent parts -Index: include/asm-arm/proc-armo/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armo/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-arm/proc-armo/pgalloc.h (working copy) -@@ -20,7 +20,7 @@ - */ - static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) - { -- return kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ return (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - } - - /* -Index: include/asm-arm/proc-armv/pgalloc.h -=================================================================== ---- include/asm-arm/proc-armv/pgalloc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-arm/proc-armv/pgalloc.h (working copy) -@@ -22,7 +22,7 @@ - { - pte_t *pte; - -- pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ pte = (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - if (pte) - pte += PTRS_PER_PTE; - return pte; -Index: include/asm-parisc/system.h -=================================================================== ---- include/asm-parisc/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-parisc/system.h (working copy) -@@ -138,7 +138,7 @@ - ** The __asm__ op below simple prevents gcc/ld from reordering - ** instructions across the mb() "call". - */ --#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */ -+#define mb() __asm__ __volatile__("": : :"memory"); /* barrier() */ - #define rmb() mb() - #define wmb() mb() - #define smp_mb() mb() -Index: include/linux/list.h -=================================================================== ---- include/linux/list.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/list.h (working copy) -@@ -91,8 +91,8 @@ - static inline void list_del(struct list_head *entry) - { - __list_del(entry->prev, entry->next); -- entry->next = (void *) 0; -- entry->prev = (void *) 0; -+ entry->next = (struct list_head *) 0; -+ entry->prev = (struct list_head *) 0; - } - - /** -Index: include/linux/sysctl.h -=================================================================== ---- include/linux/sysctl.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/sysctl.h (working copy) -@@ -713,7 +713,7 @@ - - #ifdef __KERNEL__ - --extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+asmlinkage long sys_sysctl(struct __sysctl_args *); - extern void sysctl_init(void); - - typedef struct ctl_table ctl_table; -Index: include/linux/spinlock.h -=================================================================== ---- include/linux/spinlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/spinlock.h (working copy) -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - #include - -@@ -73,13 +74,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 95) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -137,13 +133,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -Index: include/linux/dqblk_v1.h -=================================================================== ---- include/linux/dqblk_v1.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/dqblk_v1.h (working copy) -@@ -12,7 +12,6 @@ - #define V1_DQF_RSQUASH 1 - - /* Special information about quotafile */ --struct v1_mem_dqinfo { --}; -+EMPTY_STRUCT_DECL(v1_mem_dqinfo); - - #endif /* _LINUX_DQBLK_V1_H */ -Index: include/linux/netdevice.h -=================================================================== ---- include/linux/netdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/netdevice.h (working copy) -@@ -452,6 +452,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - /* 2.6 compatibility */ -@@ -496,6 +536,9 @@ - extern int unregister_netdevice(struct net_device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -@@ -609,7 +652,7 @@ - #define HAVE_NETIF_RX 1 - extern int netif_rx(struct sk_buff *skb); - #define HAVE_NETIF_RECEIVE_SKB 1 --extern int netif_receive_skb(struct sk_buff *skb); -+extern int netif_receive_skb(struct sk_buff *skb, unsigned short, int ignore_notifiers); - extern int dev_ioctl(unsigned int cmd, void *); - extern int dev_ethtool(struct ifreq *); - extern int dev_change_flags(struct net_device *, unsigned); -Index: include/linux/intermezzo_kml.h -=================================================================== ---- include/linux/intermezzo_kml.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/intermezzo_kml.h (working copy) -@@ -70,8 +70,7 @@ - int gid; - }; - --struct kml_open { --}; -+EMPTY_STRUCT_DECL(kml_open); - - struct kml_mkdir { - char *path; -Index: include/linux/skbuff.h -=================================================================== ---- include/linux/skbuff.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/skbuff.h (working copy) -@@ -126,19 +126,31 @@ - skb_frag_t frags[MAX_SKB_FRAGS]; - }; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -- struct net_device *real_dev; /* For support of point to point protocols -- (e.g. 802.3ad) over bonding, we must save the -- physical device that got the packet before -- replacing skb->dev with the virtual device. */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -169,8 +181,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; -- - /* - * This is the control buffer. It is free to use for every - * layer. Please put your private variables there. If you -@@ -179,24 +189,22 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -+ struct dst_entry *dst; -+ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ struct net_device *real_dev; /* For support of point to point protocols -+ (e.g. 802.3ad) over bonding, we must save the -+ physical device that got the packet before -+ replacing skb->dev with the virtual device. */ -+ - unsigned int data_len; - unsigned int csum; /* Checksum */ -- unsigned char __unused, /* Dead field, may be reused */ -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ - -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ -- - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER - /* Can be used for communication between hooks. */ -@@ -234,6 +242,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -824,7 +834,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -852,7 +862,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -Index: include/linux/atalk.h -=================================================================== ---- include/linux/atalk.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/atalk.h (working copy) -@@ -163,7 +163,7 @@ - - static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) - { -- return dev->atalk_ptr; -+ return (struct atalk_iface *) dev->atalk_ptr; - } - - extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); -Index: include/linux/types.h -=================================================================== ---- include/linux/types.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/types.h (working copy) -@@ -134,4 +134,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -Index: include/linux/inetdevice.h -=================================================================== ---- include/linux/inetdevice.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/inetdevice.h (working copy) -@@ -140,7 +140,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -Index: include/linux/if_vlan.h -=================================================================== ---- include/linux/if_vlan.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/if_vlan.h (working copy) -@@ -184,7 +184,7 @@ - break; - }; - -- return (polling ? netif_receive_skb(skb) : netif_rx(skb)); -+ return (polling ? netif_receive_skb(skb, skb->protocol, 0) : netif_rx(skb)); - } - - static inline int vlan_hwaccel_rx(struct sk_buff *skb, -Index: include/linux/nfsd/syscall.h -=================================================================== ---- include/linux/nfsd/syscall.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/nfsd/syscall.h (working copy) -@@ -133,7 +133,7 @@ - * Kernel syscall implementation. - */ - #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) --extern asmlinkage long sys_nfsservctl(int, void *, void *); -+asmlinkage long sys_nfsservctl(int, void *, void *); - #else - #define sys_nfsservctl sys_ni_syscall - #endif -Index: include/linux/highmem.h -=================================================================== ---- include/linux/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/highmem.h (working copy) -@@ -17,7 +17,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -103,7 +103,7 @@ - - if (offset + size > PAGE_SIZE) - out_of_line_bug(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -114,8 +114,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -@@ -125,8 +125,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_page(vto, vfrom); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -Index: include/linux/mtd/compatmac.h -=================================================================== ---- include/linux/mtd/compatmac.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/mtd/compatmac.h (working copy) -@@ -133,8 +133,8 @@ - #endif /* !(__BIT_TYPES_DEFINED__) */ - - #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } -+ typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+ #define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - #else - typedef struct { int gcc_is_buggy; } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } -Index: include/linux/netfilter_ipv4/ip_conntrack_irc.h -=================================================================== ---- include/linux/netfilter_ipv4/ip_conntrack_irc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/netfilter_ipv4/ip_conntrack_irc.h (working copy) -@@ -27,8 +27,7 @@ - }; - - /* This structure exists only once per master */ --struct ip_ct_irc_master { --}; -+EMPTY_STRUCT_DECL(ip_ct_irc_master); - - - #ifdef __KERNEL__ -Index: include/linux/mm.h -=================================================================== ---- include/linux/mm.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/mm.h (working copy) -@@ -589,7 +589,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -Index: include/linux/reiserfs_fs_sb.h -=================================================================== ---- include/linux/reiserfs_fs_sb.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/reiserfs_fs_sb.h (working copy) -@@ -352,8 +352,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -Index: include/linux/swap.h -=================================================================== ---- include/linux/swap.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/linux/swap.h (working copy) -@@ -101,7 +101,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -Index: include/asm-mips64/irq.h -=================================================================== ---- include/asm-mips64/irq.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/irq.h (working copy) -@@ -48,7 +48,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -Index: include/asm-mips64/time.h -=================================================================== ---- include/asm-mips64/time.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/time.h (working copy) -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -Index: include/asm-mips64/processor.h -=================================================================== ---- include/asm-mips64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/processor.h (working copy) -@@ -357,6 +357,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -Index: include/asm-mips64/system.h -=================================================================== ---- include/asm-mips64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/system.h (working copy) -@@ -238,7 +238,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -Index: include/asm-mips64/watch.h -=================================================================== ---- include/asm-mips64/watch.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/watch.h (working copy) -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -Index: include/asm-mips64/fpu.h -=================================================================== ---- include/asm-mips64/fpu.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-mips64/fpu.h (working copy) -@@ -23,11 +23,11 @@ - struct sigcontext; - struct sigcontext32; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - --extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); --extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -Index: include/asm-sparc64/system.h -=================================================================== ---- include/asm-sparc64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-sparc64/system.h (working copy) -@@ -121,9 +121,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory"); --#define smp_rmb() __asm__ __volatile__("":::"memory"); --#define smp_wmb() __asm__ __volatile__("":::"memory"); -+#define smp_mb() __asm__ __volatile__("": : :"memory"); -+#define smp_rmb() __asm__ __volatile__("": : :"memory"); -+#define smp_wmb() __asm__ __volatile__("": : :"memory"); - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -Index: include/asm-alpha/core_tsunami.h -=================================================================== ---- include/asm-alpha/core_tsunami.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-alpha/core_tsunami.h (working copy) -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -Index: include/asm-s390x/uaccess.h -=================================================================== ---- include/asm-s390x/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-s390x/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-i386/pgtable.h -=================================================================== ---- include/asm-i386/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/pgtable.h (working copy) -@@ -43,7 +43,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-i386/save_state.h -=================================================================== ---- include/asm-i386/save_state.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/save_state.h (working copy) -@@ -160,24 +160,24 @@ - * first restore %ds, so we can access our data properly - */ - asm volatile (".align 4"); -- asm volatile ("movw %0, %%ds" :: "r" ((u16)__KERNEL_DS)); -+ asm volatile ("movw %0, %%ds" : : "r" ((u16)__KERNEL_DS)); - - - /* - * control registers - */ -- asm volatile ("movl %0, %%cr4" :: "r" (saved_context.cr4)); -- asm volatile ("movl %0, %%cr3" :: "r" (saved_context.cr3)); -- asm volatile ("movl %0, %%cr2" :: "r" (saved_context.cr2)); -- asm volatile ("movl %0, %%cr0" :: "r" (saved_context.cr0)); -+ asm volatile ("movl %0, %%cr4" : : "r" (saved_context.cr4)); -+ asm volatile ("movl %0, %%cr3" : : "r" (saved_context.cr3)); -+ asm volatile ("movl %0, %%cr2" : : "r" (saved_context.cr2)); -+ asm volatile ("movl %0, %%cr0" : : "r" (saved_context.cr0)); - - /* - * segment registers - */ -- asm volatile ("movw %0, %%es" :: "r" (saved_context.es)); -- asm volatile ("movw %0, %%fs" :: "r" (saved_context.fs)); -- asm volatile ("movw %0, %%gs" :: "r" (saved_context.gs)); -- asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); -+ asm volatile ("movw %0, %%es" : : "r" (saved_context.es)); -+ asm volatile ("movw %0, %%fs" : : "r" (saved_context.fs)); -+ asm volatile ("movw %0, %%gs" : : "r" (saved_context.gs)); -+ asm volatile ("movw %0, %%ss" : : "r" (saved_context.ss)); - - /* - * the other general registers -@@ -188,21 +188,21 @@ - * bad since we don't have a stack set up when we enter, and we - * want to preserve the values on exit. So, we set them manually. - */ -- asm volatile ("movl %0, %%esp" :: "m" (saved_context.esp)); -- asm volatile ("movl %0, %%ebp" :: "m" (saved_context.ebp)); -- asm volatile ("movl %0, %%eax" :: "m" (saved_context.eax)); -- asm volatile ("movl %0, %%ebx" :: "m" (saved_context.ebx)); -- asm volatile ("movl %0, %%ecx" :: "m" (saved_context.ecx)); -- asm volatile ("movl %0, %%edx" :: "m" (saved_context.edx)); -- asm volatile ("movl %0, %%esi" :: "m" (saved_context.esi)); -- asm volatile ("movl %0, %%edi" :: "m" (saved_context.edi)); -+ asm volatile ("movl %0, %%esp" : : "m" (saved_context.esp)); -+ asm volatile ("movl %0, %%ebp" : : "m" (saved_context.ebp)); -+ asm volatile ("movl %0, %%eax" : : "m" (saved_context.eax)); -+ asm volatile ("movl %0, %%ebx" : : "m" (saved_context.ebx)); -+ asm volatile ("movl %0, %%ecx" : : "m" (saved_context.ecx)); -+ asm volatile ("movl %0, %%edx" : : "m" (saved_context.edx)); -+ asm volatile ("movl %0, %%esi" : : "m" (saved_context.esi)); -+ asm volatile ("movl %0, %%edi" : : "m" (saved_context.edi)); - - /* - * now restore the descriptor tables to their proper values - */ -- asm volatile ("lgdt (%0)" :: "m" (saved_context.gdt_limit)); -- asm volatile ("lidt (%0)" :: "m" (saved_context.idt_limit)); -- asm volatile ("lldt (%0)" :: "m" (saved_context.ldt)); -+ asm volatile ("lgdt (%0)" : : "m" (saved_context.gdt_limit)); -+ asm volatile ("lidt (%0)" : : "m" (saved_context.idt_limit)); -+ asm volatile ("lldt (%0)" : : "m" (saved_context.ldt)); - - fix_processor_context(); - do_fpu_end(); -Index: include/asm-i386/rwlock.h -=================================================================== ---- include/asm-i386/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/rwlock.h (working copy) -@@ -28,7 +28,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -58,7 +58,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -Index: include/asm-i386/string.h -=================================================================== ---- include/asm-i386/string.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/string.h (working copy) -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -Index: include/asm-i386/desc.h -=================================================================== ---- include/asm-i386/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/desc.h (working copy) -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -Index: include/asm-i386/processor.h -=================================================================== ---- include/asm-i386/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/processor.h (working copy) -@@ -493,7 +493,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - static inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop" ::: "memory"); -+ __asm__ __volatile__("rep;nop" : : : "memory"); - } - - #define cpu_relax() rep_nop() -Index: include/asm-i386/highmem.h -=================================================================== ---- include/asm-i386/highmem.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-i386/highmem.h (working copy) -@@ -94,7 +94,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -110,7 +110,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -Index: include/asm-ppc64/delay.h -=================================================================== ---- include/asm-ppc64/delay.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ppc64/delay.h (working copy) -@@ -19,7 +19,7 @@ - /* define these here to prevent circular dependencies */ - #define __HMT_low() asm volatile("or 1,1,1") - #define __HMT_medium() asm volatile("or 2,2,2") --#define __barrier() asm volatile("":::"memory") -+#define __barrier() asm volatile("": : :"memory") - - static inline unsigned long __get_tb(void) - { -Index: include/asm-ppc64/mmu_context.h -=================================================================== ---- include/asm-ppc64/mmu_context.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-ppc64/mmu_context.h (working copy) -@@ -138,7 +138,7 @@ - "\tdssall\n" - "\tsync\n" - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) -- ::); -+ : :); - #endif - flush_stab(); - } -Index: include/asm-s390/uaccess.h -=================================================================== ---- include/asm-s390/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-s390/uaccess.h (working copy) -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4)); \ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -Index: include/asm-x86_64/uaccess.h -=================================================================== ---- include/asm-x86_64/uaccess.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/uaccess.h (working copy) -@@ -284,13 +284,13 @@ - case 10: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2); - return ret; - case 16: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8); - return ret; - default: -Index: include/asm-x86_64/pgtable.h -=================================================================== ---- include/asm-x86_64/pgtable.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/pgtable.h (working copy) -@@ -49,7 +49,7 @@ - "movq %%cr3, %0; # flush TLB \n" \ - "movq %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -Index: include/asm-x86_64/rwlock.h -=================================================================== ---- include/asm-x86_64/rwlock.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/rwlock.h (working copy) -@@ -31,7 +31,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -44,7 +44,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile int *)rw))::"memory") -+ :"=m" (*((volatile int *)rw)): :"memory") - - #define __build_read_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -@@ -61,7 +61,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -@@ -74,7 +74,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile long *)rw))::"memory") -+ :"=m" (*((volatile long *)rw)): :"memory") - - #define __build_write_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -Index: include/asm-x86_64/pda.h -=================================================================== ---- include/asm-x86_64/pda.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/pda.h (working copy) -@@ -41,9 +41,9 @@ - - #define pda_to_op(op,field,val) do { \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 4: asm volatile(op "l %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 8: asm volatile(op "q %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 2: asm volatile(op "w %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 4: asm volatile(op "l %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 8: asm volatile(op "q %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ - default: __bad_pda_field(); \ - } \ - } while (0) -Index: include/asm-x86_64/page.h -=================================================================== ---- include/asm-x86_64/page.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/page.h (working copy) -@@ -91,9 +91,9 @@ - char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */ - unsigned short line; - } __attribute__((packed)); --#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(KBUILD_BASENAME))) --#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(__FILE__))) - #define PAGE_BUG(page) BUG() - -Index: include/asm-x86_64/desc.h -=================================================================== ---- include/asm-x86_64/desc.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/desc.h (working copy) -@@ -73,9 +73,9 @@ - #define __CPU_DESC_INDEX(x,field) \ - ((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + __GDT_HEAD_SIZE) - --#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss))); --#define __load_LDT(cpu) asm volatile("lldt %w0"::"r" (__CPU_DESC_INDEX(cpu, ldt))); --#define clear_LDT(n) asm volatile("lldt %w0"::"r" (0)) -+#define load_TR(cpu) asm volatile("ltr %w0": :"r" (__CPU_DESC_INDEX(cpu, tss))); -+#define __load_LDT(cpu) asm volatile("lldt %w0": :"r" (__CPU_DESC_INDEX(cpu, ldt))); -+#define clear_LDT(n) asm volatile("lldt %w0": :"r" (0)) - - extern struct gate_struct idt_table[]; - -Index: include/asm-x86_64/processor.h -=================================================================== ---- include/asm-x86_64/processor.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/processor.h (working copy) -@@ -389,7 +389,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - extern inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop":::"memory"); -+ __asm__ __volatile__("rep;nop": : :"memory"); - } - - /* Avoid speculative execution by the CPU */ -Index: include/asm-x86_64/system.h -=================================================================== ---- include/asm-x86_64/system.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-x86_64/system.h (working copy) -@@ -248,9 +248,9 @@ - * but I'd also expect them to finally get their act together - * and add some real memory barriers if so. - */ --#define mb() asm volatile("mfence":::"memory") --#define rmb() asm volatile("lfence":::"memory") --#define wmb() asm volatile("sfence":::"memory") -+#define mb() asm volatile("mfence": : :"memory") -+#define rmb() asm volatile("lfence": : :"memory") -+#define wmb() asm volatile("sfence": : :"memory") - #define set_mb(var, value) do { xchg(&var, value); } while (0) - #define set_wmb(var, value) do { var = value; wmb(); } while (0) - -@@ -299,7 +299,7 @@ - #endif - - /* Default simics "magic" breakpoint */ --#define icebp() asm volatile("xchg %%bx,%%bx" ::: "ebx") -+#define icebp() asm volatile("xchg %%bx,%%bx" : : : "ebx") - - /* - * disable hlt during certain critical i/o operations -Index: include/asm-cris/io.h -=================================================================== ---- include/asm-cris/io.h (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ include/asm-cris/io.h (working copy) -@@ -26,8 +26,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -Index: net/netsyms.c -=================================================================== ---- net/netsyms.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ net/netsyms.c (working copy) -@@ -291,6 +291,11 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - -Index: net/core/dev.c -=================================================================== ---- net/core/dev.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ net/core/dev.c (working copy) -@@ -182,6 +182,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1425,6 +1428,22 @@ - } - - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1458,11 +1477,10 @@ - } - #endif /* CONFIG_NET_DIVERT */ - --int netif_receive_skb(struct sk_buff *skb) -+int netif_receive_skb(struct sk_buff *skb, unsigned short type, int notifier_data) - { - struct packet_type *ptype, *pt_prev; - int ret = NET_RX_DROP; -- unsigned short type; - - if (skb->stamp.tv_sec == 0) - do_gettimeofday(&skb->stamp); -@@ -1480,6 +1498,14 @@ - - skb->h.raw = skb->nh.raw = skb->data; - -+ /* Click: may want to steal the packet */ -+ if (notifier_data >= 0 -+ && notifier_call_chain(&net_in_chain, -+ notifier_data, -+ skb) & NOTIFY_STOP_MASK) { -+ return ret; -+ } -+ - pt_prev = NULL; - for (ptype = ptype_all; ptype; ptype = ptype->next) { - if (!ptype->dev || ptype->dev == skb->dev) { -@@ -1507,7 +1533,6 @@ - } - #endif - -- type = skb->protocol; - for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { - if (ptype->type == type && - (!ptype->dev || ptype->dev == skb->dev)) { -@@ -1560,7 +1585,7 @@ - - dev = skb->dev; - -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, skb_queue_len(&queue->input_pkt_queue)); - - dev_put(dev); - -Index: net/core/skbuff.c -=================================================================== ---- net/core/skbuff.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ net/core/skbuff.c (working copy) -@@ -446,6 +446,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -Index: net/ipv4/arp.c -=================================================================== ---- net/ipv4/arp.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ net/ipv4/arp.c (working copy) -@@ -323,6 +323,7 @@ - { - u32 saddr = 0; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -360,8 +361,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -371,8 +372,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_ignore(struct in_device *in_dev, struct net_device *dev, -Index: fs/proc/inode.c -=================================================================== ---- fs/proc/inode.c (.../svn+ssh://eddietwo@amsterdam.lcs.mit.edu/home/am0/click/svn/linux/tags/PURE/linux-2.4.26) (revision 23) -+++ fs/proc/inode.c (working copy) -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { diff --git a/etc/linux-2.4.32-patch b/etc/linux-2.4.32-patch deleted file mode 100644 index 25b525323d..0000000000 --- a/etc/linux-2.4.32-patch +++ /dev/null @@ -1,3204 +0,0 @@ -diff -ru ../linux-2.4.32/drivers/net/8139cp.c ./drivers/net/8139cp.c ---- ../linux-2.4.32/drivers/net/8139cp.c 2005-01-19 06:09:56.000000000 -0800 -+++ ./drivers/net/8139cp.c 2006-05-13 10:37:50.000000000 -0700 -@@ -477,7 +477,7 @@ - be16_to_cpu(desc->opts2 & 0xffff)); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - } - - static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, -diff -ru ../linux-2.4.32/drivers/net/b44.c ./drivers/net/b44.c ---- ../linux-2.4.32/drivers/net/b44.c 2004-08-07 16:26:05.000000000 -0700 -+++ ./drivers/net/b44.c 2006-05-13 10:37:50.000000000 -0700 -@@ -749,7 +749,7 @@ - } - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, bp->dev); -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - bp->dev->last_rx = jiffies; - received++; - budget--; -diff -ru ../linux-2.4.32/drivers/net/e1000/e1000_main.c ./drivers/net/e1000/e1000_main.c ---- ../linux-2.4.32/drivers/net/e1000/e1000_main.c 2005-04-03 18:42:19.000000000 -0700 -+++ ./drivers/net/e1000/e1000_main.c 2006-05-13 10:37:50.000000000 -0700 -@@ -2506,7 +2506,7 @@ - le16_to_cpu(rx_desc->special) & - E1000_RXD_SPC_VLAN_MASK); - } else { -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - } - #else /* CONFIG_E1000_NAPI */ - if(unlikely(adapter->vlgrp && -diff -ru ../linux-2.4.32/drivers/net/eepro100.c ./drivers/net/eepro100.c ---- ../linux-2.4.32/drivers/net/eepro100.c 2005-04-03 18:42:19.000000000 -0700 -+++ ./drivers/net/eepro100.c 2006-05-13 10:37:50.000000000 -0700 -@@ -549,6 +549,16 @@ - static void set_rx_mode(struct net_device *dev); - static void speedo_show_state(struct net_device *dev); - -+/* device polling stuff */ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int speedo_tx_eob(struct net_device *dev); -+static int speedo_tx_start(struct net_device *dev); -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **); -+static struct sk_buff *speedo_tx_clean(struct net_device *dev); -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want); -+static int speedo_poll_on(struct net_device *dev); -+static int speedo_poll_off(struct net_device *dev); -+ - - - #ifdef honor_default_port -@@ -880,6 +890,17 @@ - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &speedo_ioctl; - -+ /* Click: polling support */ -+ dev->polling = 0; -+ dev->poll_on = &speedo_poll_on; -+ dev->poll_off = &speedo_poll_off; -+ dev->rx_poll = &speedo_rx_poll; -+ dev->rx_refill = &speedo_rx_refill; -+ dev->tx_queue = &speedo_tx_queue; -+ dev->tx_clean = &speedo_tx_clean; -+ dev->tx_start = &speedo_tx_start; -+ dev->tx_eob = &speedo_tx_eob; -+ - return 0; - } - -@@ -1130,7 +1151,8 @@ - ioaddr + SCBPointer); - /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should - remain masked --Dragan */ -- outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); -+ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl | -+ (dev->polling ? SCBMaskAll : 0), ioaddr + SCBCmd); - } - - /* -@@ -1395,7 +1417,8 @@ - dev->name); - outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]), - ioaddr + SCBPointer); -- outw(CUStart, ioaddr + SCBCmd); -+ outw(CUStart | (dev->polling ? SCBMaskAll : 0), -+ ioaddr + SCBCmd); - reset_mii(dev); - } else { - #else -@@ -1442,6 +1465,14 @@ - /* Prevent interrupts from changing the Tx ring from underneath us. */ - unsigned long flags; - -+#if 0 -+ if (dev->polling) -+ { -+ printk(KERN_ERR "%s: start_xmit while polling\n", dev->name); -+ return 1; -+ } -+#endif -+ - spin_lock_irqsave(&sp->lock, flags); - - /* Check if there are enough space. */ -@@ -1499,7 +1530,6 @@ - spin_unlock_irqrestore(&sp->lock, flags); - - dev->trans_start = jiffies; -- - return 0; - } - -@@ -1508,6 +1538,12 @@ - unsigned int dirty_tx; - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_tx_buffer_gc while polling\n", -+ dev->name); -+ return; -+ } -+ - dirty_tx = sp->dirty_tx; - while ((int)(sp->cur_tx - dirty_tx) > 0) { - int entry = dirty_tx % TX_RING_SIZE; -@@ -1571,6 +1607,11 @@ - long ioaddr, boguscnt = max_interrupt_work; - unsigned short status; - -+#if 0 -+ if (dev->polling) -+ printk(KERN_ERR "%s: interrupt while polling\n", dev->name); -+#endif -+ - ioaddr = dev->base_addr; - sp = (struct speedo_private *)dev->priv; - -@@ -1599,13 +1640,15 @@ - break; - - -- if ((status & 0x5000) || /* Packet received, or Rx error. */ -- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) -+ if (!dev->polling && -+ ((status & 0x5000) || /* Packet received, or Rx error. */ -+ (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)) - /* Need to gather the postponed packet. */ - speedo_rx(dev); - - /* Always check if all rx buffers are allocated. --SAW */ -- speedo_refill_rx_buffers(dev, 0); -+ if (!dev->polling) -+ speedo_refill_rx_buffers(dev, 0); - - spin_lock(&sp->lock); - /* -@@ -1630,7 +1673,7 @@ - - - /* User interrupt, Command/Tx unit interrupt or CU not active. */ -- if (status & 0xA400) { -+ if (!dev->polling && (status & 0xA400)) { - speedo_tx_buffer_gc(dev); - if (sp->tx_full - && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -@@ -1748,6 +1791,12 @@ - { - struct speedo_private *sp = (struct speedo_private *)dev->priv; - -+ if (dev->polling) { -+ printk(KERN_ERR "%s: speedo_refill_rx_buffers called " -+ "while polling\n", dev->name); -+ return; -+ } -+ - /* Refill the RX ring. */ - while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && - speedo_refill_rx_buf(dev, force) != -1); -@@ -1764,6 +1813,12 @@ - - if (netif_msg_intr(sp)) - printk(KERN_DEBUG " In speedo_rx().\n"); -+ if (dev->polling) { -+ printk(KERN_ERR "%s: In speedo_rx() while polling.\n", -+ dev->name); -+ return 0; -+ } -+ - /* If we own the next entry, it's a new packet. Send it up. */ - while (sp->rx_ringp[entry] != NULL) { - int status; -@@ -2456,3 +2511,368 @@ - * tab-width: 4 - * End: - */ -+ -+/* -+ * Click: Polling extensions. Most of this code has been copied -+ * from various routines above with slight modifications. -+ */ -+ -+static int speedo_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_list; -+ int dirty_rx = sp->dirty_rx; -+ -+ /* If the list is empty, return the number of skb's we want */ -+ if (skbs == 0) -+ return sp->cur_rx - sp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* -+ * Refill the RX ring with supplied skb's. Unlike -+ * speedo_refill_rx_buf routine, we don't have to -+ * worry about failed allocations. -+ */ -+ while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && skb_list) { -+ int entry; -+ struct RxFD *rxf; -+ struct sk_buff *skb; -+ -+ entry = sp->dirty_rx % RX_RING_SIZE; -+ if (sp->rx_skbuff[entry] == NULL) { -+ skb = skb_list; -+ skb_list = skb->next; -+ skb->prev = skb->next = NULL; -+ skb->list = NULL; -+ -+ sp->rx_skbuff[entry] = skb; -+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; -+ sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->dev = dev; -+ skb_reserve(skb, sizeof(struct RxFD)); -+ rxf->rx_buf_addr = 0xffffffff; -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), -+ PCI_DMA_TODEVICE); -+ } else { -+ rxf = sp->rx_ringp[entry]; -+ } -+ speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); -+ sp->dirty_rx++; -+ } -+ -+ /* -+ * Check if the RU is stopped -- restart it, if so. -+ */ -+ if ((inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ /* -+ * If the RU stopped, it's because there aren't -+ * any DMA buffers left, so the first DMA buffer -+ * we've just refilled is where we should start -+ * receiving. -+ */ -+ outl(virt_to_bus(sp->rx_ringp[dirty_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ /* -+ * Clear error flags on the RX ring, write back the remaining -+ * skb's that we haven't used, and return the number of dirty -+ * buffers remaining. -+ */ -+ sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); -+ *skbs = skb_list; -+ return sp->cur_rx - sp->dirty_rx; -+} -+ -+static struct sk_buff *speedo_rx_poll(struct net_device *dev, int *want) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry = sp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ /* If we own the next entry, it's a new packet. Send it up. */ -+ while (sp->rx_ringp[entry] != NULL) { -+ int status; -+ int pkt_len; -+ -+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], -+ sizeof(struct RxFD), PCI_DMA_FROMDEVICE); -+ status = le32_to_cpu(sp->rx_ringp[entry]->status); -+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; -+ -+ if (!(status & RxComplete)) -+ break; -+ -+ if (--rx_work_limit < 0 || got == *want) -+ break; -+ -+ /* Check for a rare out-of-memory case: the current buffer is -+ the last buffer allocated in the RX ring. --SAW */ -+ if (sp->last_rxf == sp->rx_ringp[entry]) { -+ /* -+ * Postpone the packet. It'll be reaped next time -+ * when this packet is no longer the last packet -+ * in the ring. -+ */ -+ if (netif_msg_rx_err(sp)) -+ printk(KERN_DEBUG "%s: RX packet postponed!\n", -+ dev->name); -+ sp->rx_ring_state |= RrPostponed; -+ break; -+ } -+ -+ if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { -+ if (status & RxErrTooBig) { -+ printk(KERN_ERR "%s: Ethernet frame overran " -+ "the Rx buffer, status %8.8x!\n", -+ dev->name, status); -+ } else if (! (status & RxOK)) { -+ /* -+ * There was a fatal error. This *should* -+ * be impossible. -+ */ -+ sp->stats.rx_errors++; -+ printk(KERN_ERR "%s: Anomalous event in " -+ "speedo_rx_poll(), status %8.8x.\n", -+ dev->name, status); -+ } -+ } else { -+ struct sk_buff *skb = sp->rx_skbuff[entry]; -+ -+ if (skb == NULL) { -+ printk(KERN_ERR "%s: Inconsistent Rx " -+ "descriptor chain.\n", dev->name); -+ break; -+ } -+ -+ /* Remove skbuff from RX ring. */ -+ sp->rx_skbuff[entry] = NULL; -+ sp->rx_ringp[entry] = NULL; -+ skb_put(skb, pkt_len); -+ pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], -+ PKT_BUF_SZ + sizeof(struct RxFD), -+ PCI_DMA_FROMDEVICE); -+ -+ skb->protocol = eth_type_trans(skb, dev); -+ sp->stats.rx_packets++; -+ sp->stats.rx_bytes += pkt_len; -+ -+ /* Append the skb to the received list */ -+ if (got == 0) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ -+ got++; -+ } -+ -+ entry = (++sp->cur_rx) % RX_RING_SIZE; -+ sp->rx_ring_state &= ~RrPostponed; -+ } -+ -+ if (got == 0 && (inw(dev->base_addr + SCBStatus) & 0x003c) == 0x0008) { -+ wait_for_cmd_done(dev); -+ -+ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), -+ dev->base_addr + SCBPointer); -+ outb(RxStart, dev->base_addr + SCBCmd); -+ } -+ -+ sp->last_rx_time = jiffies; -+ *want = got; -+ return skb_head; -+} -+ -+static int speedo_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ int entry; -+ -+ unsigned flags; -+ spin_lock_irqsave(&sp->lock, flags); -+ -+ /* Check if there are enough space. */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", -+ dev->name); -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 1; -+ } -+ -+ /* Calculate the Tx descriptor entry. */ -+ entry = sp->cur_tx++ % TX_RING_SIZE; -+ -+ sp->tx_skbuff[entry] = skb; -+ sp->tx_ring[entry].status = -+ cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); -+ sp->tx_ring[entry].link = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); -+ sp->tx_ring[entry].tx_desc_addr = -+ cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); -+ -+ /* The data region is always in one buffer descriptor. */ -+ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); -+ sp->tx_ring[entry].tx_buf_addr0 = -+ cpu_to_le32(pci_map_single(sp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE)); -+ sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); -+ -+ /* Clear the suspend bit on the last command */ -+ clear_suspend(sp->last_cmd); -+ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; -+ -+ /* Leave room for set_rx_mode(). If there is no more space than -+ * reserved for multicast filter mark the ring as full. -+ */ -+ if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { -+ netif_stop_queue(dev); -+ sp->tx_full = 1; -+ } -+ -+ spin_unlock_irqrestore(&sp->lock, flags); -+ return 0; -+} -+ -+static int speedo_tx_eob(struct net_device *dev) -+{ -+ /* benjie: not sure what this is used for... */ -+ // wait_for_cmd_done(dev); -+ -+ /* benjie: i suspect this won't cause a race condition because eob -+ * is called right after the last tx_queue and also we batch a -+ * bunch of packets, so tx is probably not going to be as fast as -+ * we are. */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static int speedo_tx_start(struct net_device *dev) { -+ printk("hard tx_start\n"); -+ /* must have been suspended before the last queued DMA ring, so -+ * this mindless CUResume is probably okay */ -+ outb(CUResume, dev->base_addr + SCBCmd); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -+static struct sk_buff *speedo_tx_clean(struct net_device *dev) { -+ unsigned int dirty_tx; -+ struct speedo_private *sp = (struct speedo_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ -+ skb_head = skb_last = NULL; -+ dirty_tx = sp->dirty_tx; -+ while ((int)(sp->cur_tx - dirty_tx) > 0) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(sp->tx_ring[entry].status); -+ -+ if ((status & StatusComplete) == 0) -+ break; /* It still hasn't been processed. */ -+ -+ if (status & TxUnderrun) -+ if (sp->tx_threshold < 0x01e08000) { -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: TX underrun, " -+ "threshold adjusted.\n", -+ dev->name); -+ sp->tx_threshold += 0x00040000; -+ } -+ -+ /* Put the original skb on the return list. */ -+ if (sp->tx_skbuff[entry]) { -+ struct sk_buff *skb = sp->tx_skbuff[entry]; -+ -+ sp->stats.tx_packets++; /* Count only user packets. */ -+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; -+ pci_unmap_single(sp->pdev, -+ le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), -+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); -+ sp->tx_skbuff[entry] = 0; -+ -+ if (skb_head == NULL) { -+ skb_head = skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ dirty_tx++; -+ } -+ -+ if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { -+ printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," -+ " full=%d.\n", -+ dirty_tx, sp->cur_tx, sp->tx_full); -+ dirty_tx += TX_RING_SIZE; -+ } -+ -+ while (sp->mc_setup_head != NULL -+ && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { -+ struct speedo_mc_block *t; -+ if (netif_msg_tx_err(sp)) -+ printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); -+ pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, -+ sp->mc_setup_head->len, PCI_DMA_TODEVICE); -+ t = sp->mc_setup_head->next; -+ kfree(sp->mc_setup_head); -+ sp->mc_setup_head = t; -+ } -+ if (sp->mc_setup_head == NULL) -+ sp->mc_setup_tail = NULL; -+ -+ sp->dirty_tx = dirty_tx; -+ -+ if (sp->tx_full && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { -+ /* The ring is no longer full. */ -+ sp->tx_full = 0; -+ netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ -+ } -+ return skb_head; -+} -+ -+static int speedo_poll_on(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling == 0) { -+ /* Mask all interrupts */ -+ outw(SCBMaskAll, ioaddr + SCBCmd); -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int speedo_poll_off(struct net_device *dev) { -+ long ioaddr = dev->base_addr; -+ -+ if (dev->polling > 0) { -+ /* Enable interrupts */ -+ outw(0, ioaddr + SCBCmd); -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -diff -ru ../linux-2.4.32/drivers/net/gt64240eth.c ./drivers/net/gt64240eth.c ---- ../linux-2.4.32/drivers/net/gt64240eth.c 2005-01-19 06:09:56.000000000 -0800 -+++ ./drivers/net/gt64240eth.c 2006-05-13 10:37:50.000000000 -0700 -@@ -1459,7 +1459,7 @@ - /* NIC performed some checksum computation */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - #ifdef GT64240_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - #else - netif_rx(skb); /* pass the packet to upper layers */ - #endif -diff -ru ../linux-2.4.32/drivers/net/ibmveth.c ./drivers/net/ibmveth.c ---- ../linux-2.4.32/drivers/net/ibmveth.c 2004-08-07 16:26:05.000000000 -0700 -+++ ./drivers/net/ibmveth.c 2006-05-13 10:38:32.000000000 -0700 -@@ -730,7 +730,7 @@ - skb->dev = netdev; - skb->protocol = eth_type_trans(skb, netdev); - -- netif_receive_skb(skb); /* send it up */ -+ netif_receive_skb(skb, skb->protocol, 0); /* send it up */ - - adapter->stats.rx_packets++; - adapter->stats.rx_bytes += length; -diff -ru ../linux-2.4.32/drivers/net/mv64340_eth.c ./drivers/net/mv64340_eth.c ---- ../linux-2.4.32/drivers/net/mv64340_eth.c 2005-01-19 06:09:56.000000000 -0800 -+++ ./drivers/net/mv64340_eth.c 2006-05-13 10:37:50.000000000 -0700 -@@ -522,7 +522,7 @@ - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, dev); - #ifdef MV64340_NAPI -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - #else - netif_rx(skb); - #endif -diff -ru ../linux-2.4.32/drivers/net/tg3.c ./drivers/net/tg3.c ---- ../linux-2.4.32/drivers/net/tg3.c 2005-05-31 17:56:56.000000000 -0700 -+++ ./drivers/net/tg3.c 2006-05-13 10:37:50.000000000 -0700 -@@ -2825,7 +2825,7 @@ - desc->err_vlan & RXD_VLAN_MASK); - } else - #endif -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - tp->dev->last_rx = jiffies; - received++; -diff -ru ../linux-2.4.32/drivers/net/titan_ge.c ./drivers/net/titan_ge.c ---- ../linux-2.4.32/drivers/net/titan_ge.c 2005-01-19 06:09:56.000000000 -0800 -+++ ./drivers/net/titan_ge.c 2006-05-13 10:38:46.000000000 -0700 -@@ -1651,7 +1651,7 @@ - */ - skb_reserve(skb, 2); - skb->protocol = eth_type_trans(skb, netdev); -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, 0); - - #ifdef CONFIG_NET_FASTROUTE - gone: -diff -ru ../linux-2.4.32/drivers/net/tulip/interrupt.c ./drivers/net/tulip/interrupt.c ---- ../linux-2.4.32/drivers/net/tulip/interrupt.c 2005-04-03 18:42:19.000000000 -0700 -+++ ./drivers/net/tulip/interrupt.c 2006-05-13 10:37:50.000000000 -0700 -@@ -311,6 +311,10 @@ - #endif - } - -+/* Polling extensions -- interrupt stats */ -+void (*tulip_interrupt_hook)(struct net_device *, unsigned); -+ -+ - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ - void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -@@ -320,7 +324,6 @@ - long ioaddr = dev->base_addr; - int csr5; - int entry; -- int missed; - int rx = 0; - int tx = 0; - int oi = 0; -@@ -328,6 +331,7 @@ - int maxtx = TX_RING_SIZE; - int maxoi = TX_RING_SIZE; - unsigned int work_count = tulip_max_interrupt_work; -+ int first_time = 1; - - /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); -@@ -341,14 +345,33 @@ - tp->nir++; - - do { -+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { -+ if (dev->polling > 0) -+ goto out; -+ if (first_time) -+ goto out; -+ else -+ break; -+ } -+ first_time = 0; -+ - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - -+ /* Notify tulip_interrupt_hook */ -+ if (tulip_interrupt_hook) -+ tulip_interrupt_hook(dev, CSR5); -+ -+ if (dev->polling > 0) { -+ if ((csr5 & (TxDied|TimerInt|AbnormalIntr)) == 0) -+ goto out; -+ } -+ - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - -- if (csr5 & (RxIntr | RxNoBuf)) { -+ if ((csr5 & (RxIntr | RxNoBuf)) && (dev->polling == 0)) { - #ifdef CONFIG_NET_HW_FLOWCONTROL - if ((!tp->fc_bit) || - (!test_bit(tp->fc_bit, &netdev_fc_xoff))) -@@ -357,7 +380,13 @@ - tulip_refill_rx(dev); - } - -- if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { -+ if ((csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) && -+ (dev->polling == 0)) { -+ /* -+ * part of the following code is duplicated at the end -+ * in tulip_tx_clean for the polling driver; changes -+ * here should propagate to there as well. -+ */ - unsigned int dirty_tx; - - spin_lock(&tp->lock); -@@ -425,16 +454,17 @@ - netif_wake_queue(dev); - - tp->dirty_tx = dirty_tx; -- if (csr5 & TxDied) { -- if (tulip_debug > 2) -- printk(KERN_WARNING "%s: The transmitter stopped." -- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -- tulip_restart_rxtx(tp); -- } - spin_unlock(&tp->lock); - } - -+ if (csr5 & TxDied) { /* XXX move after loop? */ -+ if (tulip_debug > 2) -+ printk(KERN_WARNING "%s: The transmitter stopped." -+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", -+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); -+ tulip_restart_rxtx(tp); -+ } -+ - /* Log errors. */ - if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ - if (csr5 == 0xffffffff) -@@ -456,7 +486,10 @@ - } - } - if (csr5 & RxDied) { /* Missed a Rx frame. */ -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; -@@ -547,7 +580,9 @@ - csr5 = inl(ioaddr + CSR5); - } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); - -- tulip_refill_rx(dev); -+ if (dev->polling == 0) { -+ tulip_refill_rx(dev); -+ } - - /* check if the card is in suspend mode */ - entry = tp->dirty_rx % RX_RING_SIZE; -@@ -570,12 +605,230 @@ - } - } - -+#if 0 - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { - tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; - } -+#endif - - if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - -+out: -+} -+ -+/* Click: polling support routines */ -+ -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **skbs) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_list; -+ -+ if (skbs == NULL) -+ return tp->cur_rx - tp->dirty_rx; -+ -+ skb_list = *skbs; -+ -+ /* Refill the Rx ring buffers. */ -+ for (; tp->cur_rx - tp->dirty_rx > 0 && skb_list; tp->dirty_rx++) { -+ int entry = tp->dirty_rx % RX_RING_SIZE; -+ if (tp->rx_buffers[entry].skb == NULL) { -+ struct sk_buff *skb; -+ dma_addr_t mapping; -+ -+ /* Grab an skb from the list we were given */ -+ skb = skb_list; -+ skb_list = skb_list->next; -+ skb->prev = NULL; -+ skb->next = NULL; -+ skb->list = NULL; -+ -+ tp->rx_buffers[entry].skb = skb; -+ -+ mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, -+ PCI_DMA_FROMDEVICE); -+ tp->rx_buffers[entry].mapping = mapping; -+ -+ skb->dev = dev; /* Mark as being used by this device. */ -+ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ } -+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned); -+ } -+ if(tp->chip_id == LC82C168) { -+ if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { -+ /* Rx stopped due to out of buffers, -+ * restart it -+ */ -+ outl(0x01, dev->base_addr + CSR2); -+ } -+ } -+ -+ /* Return the unused skb's */ -+ *skbs = skb_list; -+ -+ return tp->cur_rx - tp->dirty_rx; -+} -+ -+struct sk_buff *tulip_tx_clean(struct net_device *dev) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ struct sk_buff *skb_head, *skb_last; -+ unsigned int dirty_tx; -+ -+ skb_head = skb_last = 0; -+ -+ spin_lock(&tp->lock); -+ -+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { -+ int entry = dirty_tx % TX_RING_SIZE; -+ int status = le32_to_cpu(tp->tx_ring[entry].status); -+ struct sk_buff *skb; -+ -+ if (status < 0) -+ break; /* It still has not been Txed */ -+ -+ /* Check for Rx filter setup frames. */ -+ if (tp->tx_buffers[entry].skb == NULL) { -+ /* test because dummy frames not mapped */ -+ if (tp->tx_buffers[entry].mapping) -+ pci_unmap_single(tp->pdev, -+ tp->tx_buffers[entry].mapping, -+ sizeof(tp->setup_frame), -+ PCI_DMA_TODEVICE); -+ continue; -+ } -+ -+ if (status & 0x8000) { -+ /* There was an major error, log it. */ -+#ifndef final_version -+ if (tulip_debug > 1) -+ printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", -+ dev->name, status); -+#endif -+ tp->stats.tx_errors++; -+ if (status & 0x4104) tp->stats.tx_aborted_errors++; -+ if (status & 0x0C00) tp->stats.tx_carrier_errors++; -+ if (status & 0x0200) tp->stats.tx_window_errors++; -+ if (status & 0x0002) tp->stats.tx_fifo_errors++; -+ if ((status & 0x0080) && tp->full_duplex == 0) -+ tp->stats.tx_heartbeat_errors++; -+ } else { -+ tp->stats.tx_bytes += -+ tp->tx_buffers[entry].skb->len; -+ tp->stats.collisions += (status >> 3) & 15; -+ tp->stats.tx_packets++; -+ } -+ -+ pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, -+ tp->tx_buffers[entry].skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Remove from buffer list */ -+ skb = tp->tx_buffers[entry].skb; -+ -+ tp->tx_buffers[entry].skb = NULL; -+ tp->tx_buffers[entry].mapping = 0; -+ -+ /* Put the skb onto the return list */ -+ if (skb_head == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb_last->next = NULL; -+ skb_last->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ } -+ -+#ifndef final_version -+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { -+ printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", -+ dev->name, dirty_tx, tp->cur_tx); -+ dirty_tx += TX_RING_SIZE; -+ } -+#endif -+ -+#if 0 -+ if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) -+ netif_wake_queue(dev); -+#endif -+ -+ tp->dirty_tx = dirty_tx; -+ spin_unlock(&tp->lock); -+ -+ return skb_head; -+} -+ -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry = tp->cur_rx % RX_RING_SIZE; -+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; -+ struct sk_buff *skb_head, *skb_last; -+ int got = 0; -+ -+ skb_head = skb_last = NULL; -+ -+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { -+ s32 status = le32_to_cpu(tp->rx_ring[entry].status); -+ -+ if (--rx_work_limit < 0 || got == *want) break; -+ -+ if ((status & 0x38008300) != 0x0300) { -+ if ((status & 0x38000300) != 0x0300) { -+ /* Ignore earlier buffers. */ -+ if ((status & 0xffff) != 0x7fff) { -+ if (tulip_debug > 1) -+ printk(KERN_WARNING "%s: Oversized Ethernet frame " -+ "spanned multiple buffers, status %8.8x!\n", -+ dev->name, status); -+ tp->stats.rx_length_errors++; -+ } -+ } else if (status & RxDescFatalErr) { -+ /* There was a fatal error. */ -+ if (tulip_debug > 2) -+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", -+ dev->name, status); -+ tp->stats.rx_errors++; /* end of a packet.*/ -+ if (status & 0x0890) tp->stats.rx_length_errors++; -+ if (status & 0x0004) tp->stats.rx_frame_errors++; -+ if (status & 0x0002) tp->stats.rx_crc_errors++; -+ if (status & 0x0001) tp->stats.rx_fifo_errors++; -+ } -+ } else { -+ /* Omit the four octet CRC from the length. */ -+ short pkt_len = ((status >> 16) & 0x7ff) - 4; -+ struct sk_buff *skb = tp->rx_buffers[entry].skb; -+ -+ pci_unmap_single(tp->pdev, -+ tp->rx_buffers[entry].mapping, -+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE); -+ -+ tp->rx_buffers[entry].skb = NULL; -+ tp->rx_buffers[entry].mapping = 0; -+ -+ skb_put(skb, pkt_len); -+ skb->protocol = eth_type_trans(skb, dev); -+ tp->stats.rx_packets++; -+ tp->stats.rx_bytes += pkt_len; -+ -+ if (got == 0) { -+ skb_head = skb; -+ skb_last = skb; -+ skb->next = skb->prev = NULL; -+ } else { -+ skb_last->next = skb; -+ skb->prev = skb_last; -+ skb->next = NULL; -+ skb_last = skb; -+ } -+ got++; -+ } -+ entry = (++tp->cur_rx) % RX_RING_SIZE; -+ } -+ -+ dev->last_rx = jiffies; -+ *want = got; -+ return skb_head; - } -diff -ru ../linux-2.4.32/drivers/net/tulip/tulip_core.c ./drivers/net/tulip/tulip_core.c ---- ../linux-2.4.32/drivers/net/tulip/tulip_core.c 2005-04-03 18:42:19.000000000 -0700 -+++ ./drivers/net/tulip/tulip_core.c 2006-05-13 10:37:50.000000000 -0700 -@@ -269,6 +269,16 @@ - static void set_rx_mode(struct net_device *dev); - - -+/* Click: polling support */ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb); -+static int tulip_tx_eob(struct net_device *dev); -+static int tulip_tx_start(struct net_device *dev); -+int tulip_rx_refill(struct net_device *dev, struct sk_buff **); -+struct sk_buff *tulip_tx_clean(struct net_device *dev); -+struct sk_buff *tulip_rx_poll(struct net_device *dev, int *want); -+static int tulip_poll_on(struct net_device *dev); -+static int tulip_poll_off(struct net_device *dev); -+ - - static void tulip_set_power_state (struct tulip_private *tp, - int sleep, int snooze) -@@ -714,6 +724,17 @@ - } - - static int -+tulip_tx_start(struct net_device *dev) { -+ /* Trigger an immediate transmit demand unless polling */ -+ if (dev->polling <= 0) -+ outl(0, dev->base_addr + CSR1); -+ -+ dev->trans_start = jiffies; -+ -+ return 0; -+} -+ -+static int - tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; -@@ -749,13 +770,13 @@ - tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); - /* if we were using Transmit Automatic Polling, we would need a - * wmb() here. */ -+ wmb(); - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); - wmb(); - - tp->cur_tx++; - -- /* Trigger an immediate transmit demand. */ -- outl(0, dev->base_addr + CSR1); -+ tulip_tx_start(dev); - - spin_unlock_irqrestore(&tp->lock, eflags); - -@@ -764,6 +785,19 @@ - return 0; - } - -+static __inline__ unsigned long long -+tulip_get_cycles(void) -+{ -+ unsigned long low, high; -+ unsigned long long x; -+ -+ __asm__ __volatile__("rdtsc":"=a" (low), "=d" (high)); -+ x = high; -+ x <<= 32; -+ x |= low; -+ return(x); -+} -+ - static void tulip_clean_tx_ring(struct tulip_private *tp) - { - unsigned int dirty_tx; -@@ -826,8 +860,12 @@ - if (tp->chip_id == DC21040) - outl (0x00000004, ioaddr + CSR13); - -- if (inl (ioaddr + CSR6) != 0xffffffff) -- tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; -+ if (inl (ioaddr + CSR6) != 0xffffffff) { -+ unsigned csr8status = inl(ioaddr + CSR8); -+ unsigned fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; -+ } - - spin_unlock_irqrestore (&tp->lock, flags); - -@@ -906,10 +944,14 @@ - - if (netif_running(dev)) { - unsigned long flags; -+ unsigned csr8status, fifostatus; - - spin_lock_irqsave (&tp->lock, flags); - -- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; -+ csr8status = inl(ioaddr + CSR8); -+ fifostatus = csr8status >> 17; -+ tp->stats.rx_missed_errors += csr8status & 0xffff; -+ tp->stats.rx_fifo_errors += fifostatus & 0x7ff; - - spin_unlock_irqrestore(&tp->lock, flags); - } -@@ -1730,6 +1772,17 @@ - dev->do_ioctl = private_ioctl; - dev->set_multicast_list = set_rx_mode; - -+ /* Click polling for this device */ -+ dev->polling = 0; -+ dev->rx_poll = tulip_rx_poll; -+ dev->rx_refill = tulip_rx_refill; -+ dev->tx_clean = tulip_tx_clean; -+ dev->tx_queue = tulip_tx_queue; -+ dev->tx_start = tulip_tx_start; -+ dev->tx_eob = tulip_tx_eob; -+ dev->poll_on = tulip_poll_on; -+ dev->poll_off = tulip_poll_off; -+ - if (register_netdev(dev)) - goto err_out_free_ring; - -@@ -1938,3 +1991,113 @@ - - module_init(tulip_init); - module_exit(tulip_cleanup); -+ -+/* -+ * Click polling extensions -+ */ -+ -+/* Demand polling - the TX DMA engine on some tulip cards can automatically -+ * poll the TX DMA ring for packets; with this feature the driver does not -+ * need to poke the TX DMA engine after packet transmission stopped. however -+ * it seems that on some cards this feature does not work, therefore by -+ * default it is disabled. the eob() function minimizes the number of such -+ * pokes already. */ -+ -+#define DEMAND_POLLTX 0 -+ -+static int -+tulip_poll_on(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling == 0) { -+ csr7 = inl(ioaddr + CSR7) & ~(NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = (inl(ioaddr + CSR0) & ~(7<<17)) | (4<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 2; -+ } -+ -+ return 0; -+} -+ -+static int -+tulip_poll_off(struct net_device *dev) -+{ -+ long ioaddr = dev->base_addr; -+ int csr7; -+#if DEMAND_POLLTX -+ int csr0; -+#endif -+ -+ if (dev->polling > 0) { -+ csr7 = inl(ioaddr + CSR7) | (NormalIntr|RxNoBuf|\ -+ RxIntr|TxIntr|TxNoBuf); -+ outl(csr7, ioaddr + CSR7); -+ -+#if DEMAND_POLLTX -+ csr0 = inl(ioaddr + CSR0) & ~(7<<17); -+ outl(csr0, ioaddr + CSR0); -+#endif -+ -+ dev->polling = 0; -+ } -+ -+ return 0; -+} -+ -+static int tulip_tx_queue(struct net_device *dev, struct sk_buff *skb) { -+ struct tulip_private *tp = (struct tulip_private *)dev->priv; -+ int entry; -+ u32 flag; -+ dma_addr_t mapping; -+ -+ spin_lock_irq(&tp->lock); -+ -+ /* Calculate the next Tx descriptor entry. */ -+ entry = tp->cur_tx % TX_RING_SIZE; -+ -+ tp->tx_buffers[entry].skb = skb; -+ mapping = pci_map_single(tp->pdev, skb->data, -+ skb->len, PCI_DMA_TODEVICE); -+ tp->tx_buffers[entry].mapping = mapping; -+ tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); -+ -+ flag = 0x60000000; /* No interrupt */ -+ -+ if (entry == TX_RING_SIZE-1) -+ flag = 0xe0000000 | DESC_RING_WRAP; -+ -+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); -+ /* if we were using Transmit Automatic Polling, we would need a -+ * wmb() here. */ -+ wmb(); -+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); -+ wmb(); -+ -+ tp->cur_tx++; -+ -+ /* If we've almost filled up the transmit ring, signal busy */ -+ if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) -+ netif_stop_queue(dev); -+ -+ spin_unlock_irq(&tp->lock); -+ -+ return 0; -+} -+ -+static int tulip_tx_eob(struct net_device *dev) { -+ outl(0, dev->base_addr + CSR1); -+ dev->trans_start = jiffies; -+ return 0; -+} -+ -diff -ru ../linux-2.4.32/drivers/net/typhoon.c ./drivers/net/typhoon.c ---- ../linux-2.4.32/drivers/net/typhoon.c 2004-04-14 06:05:30.000000000 -0700 -+++ ./drivers/net/typhoon.c 2006-05-13 10:37:50.000000000 -0700 -@@ -1729,7 +1729,7 @@ - vlan_hwaccel_receive_skb(new_skb, tp->vlgrp, - ntohl(rx->vlanTag) & 0xffff); - else -- netif_receive_skb(new_skb); -+ netif_receive_skb(new_skb, new_skb->protocol, 0); - spin_unlock(&tp->state_lock); - - tp->dev->last_rx = jiffies; -diff -ru ../linux-2.4.32/fs/proc/inode.c ./fs/proc/inode.c ---- ../linux-2.4.32/fs/proc/inode.c 2003-11-28 10:26:21.000000000 -0800 -+++ ./fs/proc/inode.c 2006-05-13 10:37:50.000000000 -0700 -@@ -147,6 +147,11 @@ - if (!inode) - goto out_fail; - -+ /* Click change: don't double-increment de's use count if the inode -+ * existed already */ -+ if (inode->u.generic_ip == (void *) de) -+ de_put(de); -+ - inode->u.generic_ip = (void *) de; - if (de) { - if (de->mode) { -diff -ru ../linux-2.4.32/include/asm-alpha/core_tsunami.h ./include/asm-alpha/core_tsunami.h ---- ../linux-2.4.32/include/asm-alpha/core_tsunami.h 2002-08-02 17:39:45.000000000 -0700 -+++ ./include/asm-alpha/core_tsunami.h 2006-05-13 10:37:50.000000000 -0700 -@@ -281,8 +281,7 @@ - /* - * Data structure for handling TSUNAMI machine checks: - */ --struct el_TSUNAMI_sysdata_mcheck { --}; -+EMPTY_STRUCT_DECL(el_TSUNAMI_sysdata_mcheck); - - - #ifdef __KERNEL__ -diff -ru ../linux-2.4.32/include/asm-arm/mmu.h ./include/asm-arm/mmu.h ---- ../linux-2.4.32/include/asm-arm/mmu.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-arm/mmu.h 2006-05-13 10:37:50.000000000 -0700 -@@ -4,6 +4,6 @@ - /* - * The ARM doesn't have a mmu context - */ --typedef struct { } mm_context_t; -+typedef EMPTY_STRUCT_DECL(/* unnamed */) mm_context_t; - - #endif -diff -ru ../linux-2.4.32/include/asm-arm/proc-armo/pgalloc.h ./include/asm-arm/proc-armo/pgalloc.h ---- ../linux-2.4.32/include/asm-arm/proc-armo/pgalloc.h 2001-04-12 12:20:31.000000000 -0700 -+++ ./include/asm-arm/proc-armo/pgalloc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -20,7 +20,7 @@ - */ - static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) - { -- return kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ return (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - } - - /* -diff -ru ../linux-2.4.32/include/asm-arm/proc-armv/pgalloc.h ./include/asm-arm/proc-armv/pgalloc.h ---- ../linux-2.4.32/include/asm-arm/proc-armv/pgalloc.h 2001-04-12 12:20:31.000000000 -0700 -+++ ./include/asm-arm/proc-armv/pgalloc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -22,7 +22,7 @@ - { - pte_t *pte; - -- pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); -+ pte = (pte_t *) kmem_cache_alloc(pte_cache, GFP_KERNEL); - if (pte) - pte += PTRS_PER_PTE; - return pte; -diff -ru ../linux-2.4.32/include/asm-arm/system.h ./include/asm-arm/system.h ---- ../linux-2.4.32/include/asm-arm/system.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-arm/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -36,7 +36,7 @@ - - #define tas(ptr) (xchg((ptr),1)) - --extern asmlinkage void __backtrace(void); -+asmlinkage void __backtrace(void); - - /* - * Include processor dependent parts -diff -ru ../linux-2.4.32/include/asm-cris/io.h ./include/asm-cris/io.h ---- ../linux-2.4.32/include/asm-cris/io.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-cris/io.h 2006-05-13 10:37:50.000000000 -0700 -@@ -26,8 +26,8 @@ - ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \ - (255)); _Foofoo; }) - --#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0) --#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0) -+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" : : "r" (254)); } while (0) -+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" : : "r" (28)); } while (0) - #define CRIS_CYCLES() __extension__ \ - ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;}) - #else /* ! defined CONFIG_SVINTO_SIM */ -diff -ru ../linux-2.4.32/include/asm-i386/desc.h ./include/asm-i386/desc.h ---- ../linux-2.4.32/include/asm-i386/desc.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-i386/desc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -56,9 +56,9 @@ - #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) - #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) - --#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -+#define load_TR(n) __asm__ __volatile__("ltr %%ax": :"a" (__TSS(n)<<3)) - --#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) -+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax": :"a" (__LDT(n)<<3)) - - /* - * This is the ldt that every process will get unless we need -diff -ru ../linux-2.4.32/include/asm-i386/highmem.h ./include/asm-i386/highmem.h ---- ../linux-2.4.32/include/asm-i386/highmem.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/asm-i386/highmem.h 2006-05-13 10:43:06.000000000 -0700 -@@ -94,7 +94,7 @@ - if (page < highmem_start_page) - return page_address(page); - -- idx = type + KM_TYPE_NR*smp_processor_id(); -+ idx = (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); - #if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) -@@ -110,7 +110,8 @@ - { - #if HIGHMEM_DEBUG - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; -- enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -+ enum fixed_addresses idx = -+ (enum fixed_addresses) (type + KM_TYPE_NR*smp_processor_id()); - - if (vaddr < FIXADDR_START) // FIXME - return; -diff -ru ../linux-2.4.32/include/asm-i386/pgtable.h ./include/asm-i386/pgtable.h ---- ../linux-2.4.32/include/asm-i386/pgtable.h 2002-11-28 15:53:15.000000000 -0800 -+++ ./include/asm-i386/pgtable.h 2006-05-13 10:43:06.000000000 -0700 -@@ -43,7 +43,7 @@ - "movl %%cr3, %0; # flush TLB \n" \ - "movl %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -diff -ru ../linux-2.4.32/include/asm-i386/processor.h ./include/asm-i386/processor.h ---- ../linux-2.4.32/include/asm-i386/processor.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-i386/processor.h 2006-05-13 10:43:06.000000000 -0700 -@@ -493,7 +493,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - static inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop" ::: "memory"); -+ __asm__ __volatile__("rep;nop" : : : "memory"); - } - - #define cpu_relax() rep_nop() -diff -ru ../linux-2.4.32/include/asm-i386/rwlock.h ./include/asm-i386/rwlock.h ---- ../linux-2.4.32/include/asm-i386/rwlock.h 2002-08-02 17:39:45.000000000 -0700 -+++ ./include/asm-i386/rwlock.h 2006-05-13 10:37:50.000000000 -0700 -@@ -28,7 +28,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -58,7 +58,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -diff -ru ../linux-2.4.32/include/asm-i386/save_state.h ./include/asm-i386/save_state.h ---- ../linux-2.4.32/include/asm-i386/save_state.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-i386/save_state.h 2006-05-13 10:55:58.000000000 -0700 -@@ -160,24 +160,24 @@ - * first restore %ds, so we can access our data properly - */ - asm volatile (".align 4"); -- asm volatile ("movw %0, %%ds" :: "r" ((u16)__KERNEL_DS)); -+ asm volatile ("movw %0, %%ds" : : "r" ((u16)__KERNEL_DS)); - - - /* - * control registers - */ -- asm volatile ("movl %0, %%cr4" :: "r" (saved_context.cr4)); -- asm volatile ("movl %0, %%cr3" :: "r" (saved_context.cr3)); -- asm volatile ("movl %0, %%cr2" :: "r" (saved_context.cr2)); -- asm volatile ("movl %0, %%cr0" :: "r" (saved_context.cr0)); -+ asm volatile ("movl %0, %%cr4" : : "r" (saved_context.cr4)); -+ asm volatile ("movl %0, %%cr3" : : "r" (saved_context.cr3)); -+ asm volatile ("movl %0, %%cr2" : : "r" (saved_context.cr2)); -+ asm volatile ("movl %0, %%cr0" : : "r" (saved_context.cr0)); - - /* - * segment registers - */ -- asm volatile ("movw %0, %%es" :: "r" (saved_context.es)); -- asm volatile ("movw %0, %%fs" :: "r" (saved_context.fs)); -- asm volatile ("movw %0, %%gs" :: "r" (saved_context.gs)); -- asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); -+ asm volatile ("movw %0, %%es" : : "r" (saved_context.es)); -+ asm volatile ("movw %0, %%fs" : : "r" (saved_context.fs)); -+ asm volatile ("movw %0, %%gs" : : "r" (saved_context.gs)); -+ asm volatile ("movw %0, %%ss" : : "r" (saved_context.ss)); - - /* - * the other general registers -@@ -188,21 +188,21 @@ - * bad since we don't have a stack set up when we enter, and we - * want to preserve the values on exit. So, we set them manually. - */ -- asm volatile ("movl %0, %%esp" :: "m" (saved_context.esp)); -- asm volatile ("movl %0, %%ebp" :: "m" (saved_context.ebp)); -- asm volatile ("movl %0, %%eax" :: "m" (saved_context.eax)); -- asm volatile ("movl %0, %%ebx" :: "m" (saved_context.ebx)); -- asm volatile ("movl %0, %%ecx" :: "m" (saved_context.ecx)); -- asm volatile ("movl %0, %%edx" :: "m" (saved_context.edx)); -- asm volatile ("movl %0, %%esi" :: "m" (saved_context.esi)); -- asm volatile ("movl %0, %%edi" :: "m" (saved_context.edi)); -+ asm volatile ("movl %0, %%esp" : : "m" (saved_context.esp)); -+ asm volatile ("movl %0, %%ebp" : : "m" (saved_context.ebp)); -+ asm volatile ("movl %0, %%eax" : : "m" (saved_context.eax)); -+ asm volatile ("movl %0, %%ebx" : : "m" (saved_context.ebx)); -+ asm volatile ("movl %0, %%ecx" : : "m" (saved_context.ecx)); -+ asm volatile ("movl %0, %%edx" : : "m" (saved_context.edx)); -+ asm volatile ("movl %0, %%esi" : : "m" (saved_context.esi)); -+ asm volatile ("movl %0, %%edi" : : "m" (saved_context.edi)); - - /* - * now restore the descriptor tables to their proper values - */ -- asm volatile ("lgdt (%0)" :: "m" (saved_context.gdt_limit)); -- asm volatile ("lidt (%0)" :: "m" (saved_context.idt_limit)); -- asm volatile ("lldt (%0)" :: "m" (saved_context.ldt)); -+ asm volatile ("lgdt (%0)" : : "m" (saved_context.gdt_limit)); -+ asm volatile ("lidt (%0)" : : "m" (saved_context.idt_limit)); -+ asm volatile ("lldt (%0)" : : "m" (saved_context.ldt)); - - fix_processor_context(); - do_fpu_end(); -diff -ru ../linux-2.4.32/include/asm-i386/string.h ./include/asm-i386/string.h ---- ../linux-2.4.32/include/asm-i386/string.h 2001-11-22 11:46:18.000000000 -0800 -+++ ./include/asm-i386/string.h 2006-05-13 10:43:06.000000000 -0700 -@@ -29,6 +29,7 @@ - * consider these trivial functions to be PD. - */ - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCPY - static inline char * strcpy(char * dest,const char *src) - { -@@ -42,6 +43,7 @@ - :"0" (src),"1" (dest) : "memory"); - return dest; - } -+#endif - - #define __HAVE_ARCH_STRNCPY - static inline char * strncpy(char * dest,const char *src,size_t count) -@@ -102,6 +104,7 @@ - return dest; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRCMP - static inline int strcmp(const char * cs,const char * ct) - { -@@ -122,6 +125,7 @@ - :"1" (cs),"2" (ct)); - return __res; - } -+#endif - - #define __HAVE_ARCH_STRNCMP - static inline int strncmp(const char * cs,const char * ct,size_t count) -@@ -182,6 +186,7 @@ - return __res; - } - -+#if __GNUC__ > 2 || __GNUC_MINOR__ != 96 || !defined(CLICK_LINUXMODULE) - #define __HAVE_ARCH_STRLEN - static inline size_t strlen(const char * s) - { -@@ -195,6 +200,7 @@ - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; - } -+#endif - - static inline void * __memcpy(void * to, const void * from, size_t n) - { -diff -ru ../linux-2.4.32/include/asm-ia64/delay.h ./include/asm-ia64/delay.h ---- ../linux-2.4.32/include/asm-ia64/delay.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/asm-ia64/delay.h 2006-05-13 10:37:50.000000000 -0700 -@@ -21,7 +21,7 @@ - static __inline__ void - ia64_set_itm (unsigned long val) - { -- __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -29,20 +29,20 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) : : "memory"); - return result; - } - - static __inline__ void - ia64_set_itv (unsigned long val) - { -- __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov cr.itv=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ void - ia64_set_itc (unsigned long val) - { -- __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); -+ __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" : : "r"(val) : "memory"); - } - - static __inline__ unsigned long -@@ -50,10 +50,10 @@ - { - unsigned long result; - -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #ifdef CONFIG_ITANIUM - while (__builtin_expect ((__s32) result == -1, 0)) -- __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); -+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) : : "memory"); - #endif - return result; - } -@@ -67,9 +67,9 @@ - return; - - __asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc)); -- __asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1)); -+ __asm__ __volatile__("mov ar.lc=%0;;" : : "r"(loops - 1)); - __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;"); -- __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); -+ __asm__ __volatile__("mov ar.lc=%0" : : "r"(saved_ar_lc)); - } - - static __inline__ void -diff -ru ../linux-2.4.32/include/asm-ia64/intrinsics.h ./include/asm-ia64/intrinsics.h ---- ../linux-2.4.32/include/asm-ia64/intrinsics.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-ia64/intrinsics.h 2006-05-13 10:37:50.000000000 -0700 -@@ -131,7 +131,7 @@ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ -- __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ -+ __asm__ __volatile__ ("mov ar.ccv=%0;;" : : "rO"(_o_)); \ - switch (size) { \ - case 1: \ - __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ -diff -ru ../linux-2.4.32/include/asm-ia64/io.h ./include/asm-ia64/io.h ---- ../linux-2.4.32/include/asm-ia64/io.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/asm-ia64/io.h 2006-05-13 10:37:50.000000000 -0700 -@@ -85,7 +85,7 @@ - * Memory fence w/accept. This should never be used in code that is - * not IA-64 specific. - */ --#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __ia64_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - static inline const unsigned long - __ia64_get_io_port_base (void) -diff -ru ../linux-2.4.32/include/asm-ia64/pgalloc.h ./include/asm-ia64/pgalloc.h ---- ../linux-2.4.32/include/asm-ia64/pgalloc.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/asm-ia64/pgalloc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -209,7 +209,7 @@ - flush_tlb_range(vma->vm_mm, (addr & PAGE_MASK), (addr & PAGE_MASK) + PAGE_SIZE); - #else - if (vma->vm_mm == current->active_mm) -- asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); -+ asm volatile ("ptc.l %0,%1" : : "r"(addr), "r"(PAGE_SHIFT << 2) : "memory"); - else - vma->vm_mm->context = 0; - #endif -diff -ru ../linux-2.4.32/include/asm-ia64/processor.h ./include/asm-ia64/processor.h ---- ../linux-2.4.32/include/asm-ia64/processor.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/asm-ia64/processor.h 2006-05-13 10:37:50.000000000 -0700 -@@ -424,14 +424,14 @@ - ia64_set_kr (unsigned long regnum, unsigned long r) - { - switch (regnum) { -- case 0: asm volatile ("mov ar.k0=%0" :: "r"(r)); break; -- case 1: asm volatile ("mov ar.k1=%0" :: "r"(r)); break; -- case 2: asm volatile ("mov ar.k2=%0" :: "r"(r)); break; -- case 3: asm volatile ("mov ar.k3=%0" :: "r"(r)); break; -- case 4: asm volatile ("mov ar.k4=%0" :: "r"(r)); break; -- case 5: asm volatile ("mov ar.k5=%0" :: "r"(r)); break; -- case 6: asm volatile ("mov ar.k6=%0" :: "r"(r)); break; -- case 7: asm volatile ("mov ar.k7=%0" :: "r"(r)); break; -+ case 0: asm volatile ("mov ar.k0=%0" : : "r"(r)); break; -+ case 1: asm volatile ("mov ar.k1=%0" : : "r"(r)); break; -+ case 2: asm volatile ("mov ar.k2=%0" : : "r"(r)); break; -+ case 3: asm volatile ("mov ar.k3=%0" : : "r"(r)); break; -+ case 4: asm volatile ("mov ar.k4=%0" : : "r"(r)); break; -+ case 5: asm volatile ("mov ar.k5=%0" : : "r"(r)); break; -+ case 6: asm volatile ("mov ar.k6=%0" : : "r"(r)); break; -+ case 7: asm volatile ("mov ar.k7=%0" : : "r"(r)); break; - } - } - /* Return TRUE if task T owns the fph partition of the CPU we're running on. */ -@@ -463,8 +463,8 @@ - extern void ia32_load_state (struct task_struct *task); - #endif - --#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); --#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" ::: "memory"); -+#define ia64_fph_enable() asm volatile (";; rsm psr.dfh;; srlz.d;;" : : : "memory"); -+#define ia64_fph_disable() asm volatile (";; ssm psr.dfh;; srlz.d;;" : : : "memory"); - - /* load fp 0.0 into fph */ - static inline void -@@ -493,25 +493,25 @@ - static inline void - ia64_fc (void *addr) - { -- asm volatile ("fc %0" :: "r"(addr) : "memory"); -+ asm volatile ("fc %0" : : "r"(addr) : "memory"); - } - - static inline void - ia64_sync_i (void) - { -- asm volatile (";; sync.i" ::: "memory"); -+ asm volatile (";; sync.i" : : : "memory"); - } - - static inline void - ia64_srlz_i (void) - { -- asm volatile (";; srlz.i ;;" ::: "memory"); -+ asm volatile (";; srlz.i ;;" : : : "memory"); - } - - static inline void - ia64_srlz_d (void) - { -- asm volatile (";; srlz.d" ::: "memory"); -+ asm volatile (";; srlz.d" : : : "memory"); - } - - static inline __u64 -@@ -525,7 +525,7 @@ - static inline void - ia64_set_rr (__u64 reg_bits, __u64 rr_val) - { -- asm volatile ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); -+ asm volatile ("mov rr[%0]=%1" : : "r"(reg_bits), "r"(rr_val) : "memory"); - } - - static inline __u64 -@@ -539,7 +539,7 @@ - static inline void - ia64_set_dcr (__u64 val) - { -- asm volatile ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.dcr=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -554,7 +554,7 @@ - static inline void - ia64_invala (void) - { -- asm volatile ("invala" ::: "memory"); -+ asm volatile ("invala" : : : "memory"); - } - - /* -@@ -566,7 +566,7 @@ - ia64_clear_ic (void) - { - __u64 psr; -- asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) :: "memory"); -+ asm volatile ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;" : "=r"(psr) : : "memory"); - return psr; - } - -@@ -576,7 +576,7 @@ - static inline void - ia64_set_psr (__u64 psr) - { -- asm volatile (";; mov psr.l=%0;; srlz.d" :: "r" (psr) : "memory"); -+ asm volatile (";; mov psr.l=%0;; srlz.d" : : "r" (psr) : "memory"); - } - - /* -@@ -588,14 +588,14 @@ - __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - if (target_mask & 0x1) - asm volatile ("itr.i itr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - if (target_mask & 0x2) - asm volatile (";;itr.d dtr[%0]=%1" -- :: "r"(tr_num), "r"(pte) : "memory"); -+ : : "r"(tr_num), "r"(pte) : "memory"); - } - - /* -@@ -606,13 +606,13 @@ - ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, - __u64 log_page_size) - { -- asm volatile ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory"); -- asm volatile ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory"); -+ asm volatile ("mov cr.itir=%0" : : "r"(log_page_size << 2) : "memory"); -+ asm volatile ("mov cr.ifa=%0;;" : : "r"(vmaddr) : "memory"); - /* as per EAS2.6, itc must be the last instruction in an instruction group */ - if (target_mask & 0x1) -- asm volatile ("itc.i %0;;" :: "r"(pte) : "memory"); -+ asm volatile ("itc.i %0;;" : : "r"(pte) : "memory"); - if (target_mask & 0x2) -- asm volatile (";;itc.d %0;;" :: "r"(pte) : "memory"); -+ asm volatile (";;itc.d %0;;" : : "r"(pte) : "memory"); - } - - /* -@@ -623,16 +623,16 @@ - ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) - { - if (target_mask & 0x1) -- asm volatile ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.i %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - if (target_mask & 0x2) -- asm volatile ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2)); -+ asm volatile ("ptr.d %0,%1" : : "r"(vmaddr), "r"(log_size << 2)); - } - - /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ - static inline void - ia64_set_iva (void *ivt_addr) - { -- asm volatile ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); -+ asm volatile ("mov cr.iva=%0;; srlz.i;;" : : "r"(ivt_addr) : "memory"); - } - - /* Set the page table address and control bits. */ -@@ -640,7 +640,7 @@ - ia64_set_pta (__u64 pta) - { - /* Note: srlz.i implies srlz.d */ -- asm volatile ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); -+ asm volatile ("mov cr.pta=%0;; srlz.i;;" : : "r"(pta) : "memory"); - } - - static inline __u64 -@@ -655,20 +655,20 @@ - static inline void - ia64_eoi (void) - { -- asm ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); -+ asm ("mov cr.eoi=r0;; srlz.d;;" : : : "memory"); - } - - static inline void - ia64_set_lrr0 (unsigned long val) - { -- asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr0=%0;; srlz.d" : : "r"(val) : "memory"); - } - - #ifdef GAS_HAS_HINT_INSN - static inline void - ia64_hint_pause (void) - { -- asm volatile ("hint @pause" ::: "memory"); -+ asm volatile ("hint @pause" : : : "memory"); - } - - #define cpu_relax() ia64_hint_pause() -@@ -679,13 +679,13 @@ - static inline void - ia64_set_lrr1 (unsigned long val) - { -- asm volatile ("mov cr.lrr1=%0;; srlz.d" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.lrr1=%0;; srlz.d" : : "r"(val) : "memory"); - } - - static inline void - ia64_set_pmv (__u64 val) - { -- asm volatile ("mov cr.pmv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.pmv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -700,7 +700,7 @@ - static inline void - ia64_set_pmc (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmc[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline __u64 -@@ -715,7 +715,7 @@ - static inline void - ia64_set_pmd (__u64 regnum, __u64 value) - { -- asm volatile ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov pmd[%0]=%1" : : "r"(regnum), "r"(value)); - } - - /* -@@ -780,7 +780,7 @@ - static inline void - ia64_set_cmcv (__u64 val) - { -- asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory"); -+ asm volatile ("mov cr.cmcv=%0" : : "r"(val) : "memory"); - } - - static inline __u64 -@@ -788,7 +788,7 @@ - { - __u64 val; - -- asm volatile ("mov %0=cr.cmcv" : "=r"(val) :: "memory"); -+ asm volatile ("mov %0=cr.cmcv" : "=r"(val) : : "memory"); - return val; - } - -@@ -803,7 +803,7 @@ - static inline void - ia64_set_tpr (__u64 val) - { -- asm volatile ("mov cr.tpr=%0" :: "r"(val)); -+ asm volatile ("mov cr.tpr=%0" : : "r"(val)); - } - - static inline __u64 -@@ -817,7 +817,7 @@ - static inline void - ia64_set_irr0 (__u64 val) - { -- asm volatile("mov cr.irr0=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr0=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -834,7 +834,7 @@ - static inline void - ia64_set_irr1 (__u64 val) - { -- asm volatile("mov cr.irr1=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr1=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -851,7 +851,7 @@ - static inline void - ia64_set_irr2 (__u64 val) - { -- asm volatile("mov cr.irr2=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr2=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -868,7 +868,7 @@ - static inline void - ia64_set_irr3 (__u64 val) - { -- asm volatile("mov cr.irr3=%0;;" :: "r"(val) : "memory"); -+ asm volatile("mov cr.irr3=%0;;" : : "r"(val) : "memory"); - ia64_srlz_d(); - } - -@@ -894,13 +894,13 @@ - static inline void - ia64_set_ibr (__u64 regnum, __u64 value) - { -- asm volatile ("mov ibr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov ibr[%0]=%1" : : "r"(regnum), "r"(value)); - } - - static inline void - ia64_set_dbr (__u64 regnum, __u64 value) - { -- asm volatile ("mov dbr[%0]=%1" :: "r"(regnum), "r"(value)); -+ asm volatile ("mov dbr[%0]=%1" : : "r"(regnum), "r"(value)); - #ifdef CONFIG_ITANIUM - asm volatile (";; srlz.d"); - #endif -diff -ru ../linux-2.4.32/include/asm-ia64/sn/rw_mmr.h ./include/asm-ia64/sn/rw_mmr.h ---- ../linux-2.4.32/include/asm-ia64/sn/rw_mmr.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-ia64/sn/rw_mmr.h 2006-05-13 10:37:50.000000000 -0700 -@@ -51,7 +51,7 @@ - "st8.rel [%0]=%1;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr), "r"(val) -+ : : "r"(mmr), "r"(val) - : "r2", "memory"); - } - -@@ -66,7 +66,7 @@ - "st8.rel [%2]=%3;;" - "mov psr.l=r2;;" - "srlz.i;;" -- :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) -+ : : "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) - : "r2", "memory"); - } - -diff -ru ../linux-2.4.32/include/asm-ia64/sn/sn2/io.h ./include/asm-ia64/sn/sn2/io.h ---- ../linux-2.4.32/include/asm-ia64/sn/sn2/io.h 2003-11-28 10:26:21.000000000 -0800 -+++ ./include/asm-ia64/sn/sn2/io.h 2006-05-13 10:37:50.000000000 -0700 -@@ -12,7 +12,7 @@ - extern void * sn_io_addr(unsigned long port) __attribute__ ((__const__)); /* Forward definition */ - extern void sn_mmiob(void); /* Forward definition */ - --#define __sn_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -+#define __sn_mf_a() __asm__ __volatile__ ("mf.a" : : : "memory") - - extern void sn_dma_flush(unsigned long); - -diff -ru ../linux-2.4.32/include/asm-ia64/spinlock.h ./include/asm-ia64/spinlock.h ---- ../linux-2.4.32/include/asm-ia64/spinlock.h 2003-11-28 10:26:21.000000000 -0800 -+++ ./include/asm-ia64/spinlock.h 2006-05-13 10:37:50.000000000 -0700 -@@ -45,7 +45,7 @@ - "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ - ";;\n" \ - "1:\n" /* force a new bundle */ \ -- :: "r"(addr) \ -+ : : "r"(addr) \ - : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ - } - -@@ -100,7 +100,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -+ : : "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") - - #define spin_is_locked(x) ((x)->lock != 0) - #define spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) -@@ -165,7 +165,7 @@ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ -- :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ -+ : : "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ - } while(0) - - #define write_unlock(x) \ -diff -ru ../linux-2.4.32/include/asm-ia64/system.h ./include/asm-ia64/system.h ---- ../linux-2.4.32/include/asm-ia64/system.h 2004-08-07 16:26:06.000000000 -0700 -+++ ./include/asm-ia64/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -57,7 +57,7 @@ - static inline void - ia64_insn_group_barrier (void) - { -- __asm__ __volatile__ (";;" ::: "memory"); -+ __asm__ __volatile__ (";;" : : : "memory"); - } - - /* -@@ -82,7 +82,7 @@ - * it's (presumably) much slower than mf and (b) mf.a is supported for - * sequential memory pages only. - */ --#define mb() __asm__ __volatile__ ("mf" ::: "memory") -+#define mb() __asm__ __volatile__ ("mf" : : : "memory") - #define rmb() mb() - #define wmb() mb() - -@@ -121,7 +121,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -133,7 +133,7 @@ - do { \ - unsigned long ip, psr; \ - \ -- __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory"); \ -+ __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) : : "memory"); \ - if (psr & IA64_PSR_I) { \ - __asm__ ("mov %0=ip" : "=r"(ip)); \ - last_cli_ip = ip; \ -@@ -147,7 +147,7 @@ - __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (psr) :: "memory"); \ -+ : "=r" (psr) : : "memory"); \ - (x) = psr; \ - } while (0) - -@@ -171,25 +171,25 @@ - #else /* !CONFIG_IA64_DEBUG_IRQ */ - /* clearing of psr.i is implicitly serialized (visible by next insn) */ - # define local_irq_save(x) __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" \ -- : "=r" (x) :: "memory") --# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory") -+ : "=r" (x) : : "memory") -+# define local_irq_disable() __asm__ __volatile__ (";; rsm psr.i;;" : : : "memory") - /* (potentially) setting psr.i requires data serialization: */ - # define local_irq_set(x) __asm__ __volatile__ ("mov %0=psr;;" \ - "ssm psr.i;;" \ - "srlz.d" \ -- : "=r" (x) :: "memory") -+ : "=r" (x) : : "memory") - # define local_irq_restore(x) __asm__ __volatile__ ("cmp.ne p6,p7=%0,r0;;" \ - "(p6) ssm psr.i;" \ - "(p7) rsm psr.i;;" \ - "srlz.d" \ -- :: "r"((x) & IA64_PSR_I) \ -+ : : "r"((x) & IA64_PSR_I) \ - : "p6", "p7", "memory") - #endif /* !CONFIG_IA64_DEBUG_IRQ */ - --#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") -+#define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" : : : "memory") - - #define __cli() local_irq_disable () --#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") -+#define __save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) : : "memory") - #define __save_and_cli(flags) local_irq_save(flags) - #define __save_and_sti(flags) local_irq_set(flags) - #define save_and_cli(flags) __save_and_cli(flags) -diff -ru ../linux-2.4.32/include/asm-mips/fpu.h ./include/asm-mips/fpu.h ---- ../linux-2.4.32/include/asm-mips/fpu.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-mips/fpu.h 2006-05-13 10:37:50.000000000 -0700 -@@ -22,8 +22,8 @@ - - struct sigcontext; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -diff -ru ../linux-2.4.32/include/asm-mips/irq.h ./include/asm-mips/irq.h ---- ../linux-2.4.32/include/asm-mips/irq.h 2003-08-25 04:44:43.000000000 -0700 -+++ ./include/asm-mips/irq.h 2006-05-13 10:37:50.000000000 -0700 -@@ -30,7 +30,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -diff -ru ../linux-2.4.32/include/asm-mips/processor.h ./include/asm-mips/processor.h ---- ../linux-2.4.32/include/asm-mips/processor.h 2005-01-19 06:10:12.000000000 -0800 -+++ ./include/asm-mips/processor.h 2006-05-13 10:37:50.000000000 -0700 -@@ -316,6 +316,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -ru ../linux-2.4.32/include/asm-mips/system.h ./include/asm-mips/system.h ---- ../linux-2.4.32/include/asm-mips/system.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-mips/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -260,7 +260,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -diff -ru ../linux-2.4.32/include/asm-mips/time.h ./include/asm-mips/time.h ---- ../linux-2.4.32/include/asm-mips/time.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-mips/time.h 2006-05-13 10:37:50.000000000 -0700 -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -diff -ru ../linux-2.4.32/include/asm-mips/watch.h ./include/asm-mips/watch.h ---- ../linux-2.4.32/include/asm-mips/watch.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-mips/watch.h 2006-05-13 10:37:50.000000000 -0700 -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -diff -ru ../linux-2.4.32/include/asm-mips64/fpu.h ./include/asm-mips64/fpu.h ---- ../linux-2.4.32/include/asm-mips64/fpu.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-mips64/fpu.h 2006-05-13 10:37:50.000000000 -0700 -@@ -23,11 +23,11 @@ - struct sigcontext; - struct sigcontext32; - --extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); --extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); -+asmlinkage int (*save_fp_context)(struct sigcontext *sc); -+asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - --extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); --extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); -+asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); - - extern void fpu_emulator_init_fpu(void); - extern void _init_fpu(void); -diff -ru ../linux-2.4.32/include/asm-mips64/irq.h ./include/asm-mips64/irq.h ---- ../linux-2.4.32/include/asm-mips64/irq.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-mips64/irq.h 2006-05-13 10:37:50.000000000 -0700 -@@ -48,7 +48,7 @@ - extern void enable_irq(unsigned int); - - struct pt_regs; --extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); - - /* Machine specific interrupt initialization */ - extern void (*irq_setup)(void); -diff -ru ../linux-2.4.32/include/asm-mips64/processor.h ./include/asm-mips64/processor.h ---- ../linux-2.4.32/include/asm-mips64/processor.h 2005-01-19 06:10:12.000000000 -0800 -+++ ./include/asm-mips64/processor.h 2006-05-13 10:37:50.000000000 -0700 -@@ -359,6 +359,6 @@ - * overhead of a function call by forcing the compiler to save the return - * address register on the stack. - */ --#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) -+#define return_address() ({__asm__ __volatile__("": : :"$31");__builtin_return_address(0);}) - - #endif /* _ASM_PROCESSOR_H */ -diff -ru ../linux-2.4.32/include/asm-mips64/system.h ./include/asm-mips64/system.h ---- ../linux-2.4.32/include/asm-mips64/system.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-mips64/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -238,7 +238,7 @@ - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - */ --extern asmlinkage void *resume(void *last, void *next); -+asmlinkage void *resume(void *last, void *next); - - #define prepare_to_switch() do { } while(0) - -diff -ru ../linux-2.4.32/include/asm-mips64/time.h ./include/asm-mips64/time.h ---- ../linux-2.4.32/include/asm-mips64/time.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-mips64/time.h 2006-05-13 10:37:50.000000000 -0700 -@@ -72,13 +72,13 @@ - /* - * the corresponding low-level timer interrupt routine. - */ --extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * profiling and process accouting is done separately in local_timer_interrupt - */ - extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); --extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); -+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); - - /* - * board specific routines required by time_init(). -diff -ru ../linux-2.4.32/include/asm-mips64/watch.h ./include/asm-mips64/watch.h ---- ../linux-2.4.32/include/asm-mips64/watch.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-mips64/watch.h 2006-05-13 10:37:50.000000000 -0700 -@@ -18,9 +18,9 @@ - wr_load = 2 - }; - --extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); --extern asmlinkage void __watch_clear(void); --extern asmlinkage void __watch_reenable(void); -+asmlinkage void __watch_set(unsigned long addr, enum wref_type ref); -+asmlinkage void __watch_clear(void); -+asmlinkage void __watch_reenable(void); - - #define watch_set(addr, ref) \ - if (cpu_has_watch) \ -diff -ru ../linux-2.4.32/include/asm-parisc/system.h ./include/asm-parisc/system.h ---- ../linux-2.4.32/include/asm-parisc/system.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/asm-parisc/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -138,7 +138,7 @@ - ** The __asm__ op below simple prevents gcc/ld from reordering - ** instructions across the mb() "call". - */ --#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */ -+#define mb() __asm__ __volatile__("": : :"memory"); /* barrier() */ - #define rmb() mb() - #define wmb() mb() - #define smp_mb() mb() -diff -ru ../linux-2.4.32/include/asm-ppc64/delay.h ./include/asm-ppc64/delay.h ---- ../linux-2.4.32/include/asm-ppc64/delay.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/asm-ppc64/delay.h 2006-05-13 10:37:50.000000000 -0700 -@@ -19,7 +19,7 @@ - /* define these here to prevent circular dependencies */ - #define __HMT_low() asm volatile("or 1,1,1") - #define __HMT_medium() asm volatile("or 2,2,2") --#define __barrier() asm volatile("":::"memory") -+#define __barrier() asm volatile("": : :"memory") - - static inline unsigned long __get_tb(void) - { -diff -ru ../linux-2.4.32/include/asm-ppc64/mmu_context.h ./include/asm-ppc64/mmu_context.h ---- ../linux-2.4.32/include/asm-ppc64/mmu_context.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/asm-ppc64/mmu_context.h 2006-05-13 10:37:50.000000000 -0700 -@@ -138,7 +138,7 @@ - "\tdssall\n" - "\tsync\n" - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) -- ::); -+ : :); - #endif - flush_stab(); - } -diff -ru ../linux-2.4.32/include/asm-s390/uaccess.h ./include/asm-s390/uaccess.h ---- ../linux-2.4.32/include/asm-s390/uaccess.h 2002-08-02 17:39:45.000000000 -0700 -+++ ./include/asm-s390/uaccess.h 2006-05-13 10:37:50.000000000 -0700 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4)); \ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -diff -ru ../linux-2.4.32/include/asm-s390x/uaccess.h ./include/asm-s390x/uaccess.h ---- ../linux-2.4.32/include/asm-s390x/uaccess.h 2002-08-02 17:39:45.000000000 -0700 -+++ ./include/asm-s390x/uaccess.h 2006-05-13 10:37:50.000000000 -0700 -@@ -36,7 +36,7 @@ - - #define get_ds() (KERNEL_DS) - #define get_fs() (current->addr_limit) --#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\ -+#define set_fs(x) ({asm volatile("sar 4,%0": :"a" ((x).ar4));\ - current->addr_limit = (x);}) - - #define segment_eq(a,b) ((a).ar4 == (b).ar4) -diff -ru ../linux-2.4.32/include/asm-sparc/system.h ./include/asm-sparc/system.h ---- ../linux-2.4.32/include/asm-sparc/system.h 2005-04-03 18:42:20.000000000 -0700 -+++ ./include/asm-sparc/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -295,9 +295,9 @@ - #define wmb() mb() - #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) - #define set_wmb(__var, __value) set_mb(__var, __value) --#define smp_mb() __asm__ __volatile__("":::"memory") --#define smp_rmb() __asm__ __volatile__("":::"memory") --#define smp_wmb() __asm__ __volatile__("":::"memory") -+#define smp_mb() __asm__ __volatile__("": : :"memory") -+#define smp_rmb() __asm__ __volatile__("": : :"memory") -+#define smp_wmb() __asm__ __volatile__("": : :"memory") - - #define nop() __asm__ __volatile__ ("nop") - -diff -ru ../linux-2.4.32/include/asm-sparc64/system.h ./include/asm-sparc64/system.h ---- ../linux-2.4.32/include/asm-sparc64/system.h 2005-04-03 18:42:20.000000000 -0700 -+++ ./include/asm-sparc64/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -121,9 +121,9 @@ - #define smp_rmb() rmb() - #define smp_wmb() wmb() - #else --#define smp_mb() __asm__ __volatile__("":::"memory") --#define smp_rmb() __asm__ __volatile__("":::"memory") --#define smp_wmb() __asm__ __volatile__("":::"memory") -+#define smp_mb() __asm__ __volatile__("": : :"memory") -+#define smp_rmb() __asm__ __volatile__("": : :"memory") -+#define smp_wmb() __asm__ __volatile__("": : :"memory") - #endif - - #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") -diff -ru ../linux-2.4.32/include/asm-x86_64/desc.h ./include/asm-x86_64/desc.h ---- ../linux-2.4.32/include/asm-x86_64/desc.h 2005-11-16 11:12:54.000000000 -0800 -+++ ./include/asm-x86_64/desc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -73,9 +73,9 @@ - #define __CPU_DESC_INDEX(x,field) \ - ((x) * sizeof(struct per_cpu_gdt) + offsetof(struct per_cpu_gdt, field) + __GDT_HEAD_SIZE) - --#define load_TR(cpu) asm volatile("ltr %w0"::"r" (__CPU_DESC_INDEX(cpu, tss))); --#define __load_LDT(cpu) asm volatile("lldt %w0"::"r" (__CPU_DESC_INDEX(cpu, ldt))); --#define clear_LDT(n) asm volatile("lldt %w0"::"r" (0)) -+#define load_TR(cpu) asm volatile("ltr %w0": :"r" (__CPU_DESC_INDEX(cpu, tss))); -+#define __load_LDT(cpu) asm volatile("lldt %w0": :"r" (__CPU_DESC_INDEX(cpu, ldt))); -+#define clear_LDT(n) asm volatile("lldt %w0": :"r" (0)) - - extern struct gate_struct idt_table[]; - -diff -ru ../linux-2.4.32/include/asm-x86_64/page.h ./include/asm-x86_64/page.h ---- ../linux-2.4.32/include/asm-x86_64/page.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-x86_64/page.h 2006-05-13 10:37:50.000000000 -0700 -@@ -91,9 +91,9 @@ - char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */ - unsigned short line; - } __attribute__((packed)); --#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(KBUILD_BASENAME))) --#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" :: "i"(__LINE__), \ -+#define HEADER_BUG() asm volatile("ud2 ; .quad %P1 ; .short %P0" : : "i"(__LINE__), \ - "i" (__stringify(__FILE__))) - #define PAGE_BUG(page) BUG() - -diff -ru ../linux-2.4.32/include/asm-x86_64/pda.h ./include/asm-x86_64/pda.h ---- ../linux-2.4.32/include/asm-x86_64/pda.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/asm-x86_64/pda.h 2006-05-13 10:37:50.000000000 -0700 -@@ -41,9 +41,9 @@ - - #define pda_to_op(op,field,val) do { \ - switch (sizeof_field(struct x8664_pda, field)) { \ -- case 2: asm volatile(op "w %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 4: asm volatile(op "l %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -- case 8: asm volatile(op "q %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 2: asm volatile(op "w %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 4: asm volatile(op "l %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ -+ case 8: asm volatile(op "q %0,%%gs:%P1" : : "r" (val), "i"(pda_offset(field)):"memory"); break; \ - default: __bad_pda_field(); \ - } \ - } while (0) -diff -ru ../linux-2.4.32/include/asm-x86_64/pgtable.h ./include/asm-x86_64/pgtable.h ---- ../linux-2.4.32/include/asm-x86_64/pgtable.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/asm-x86_64/pgtable.h 2006-05-13 10:37:50.000000000 -0700 -@@ -49,7 +49,7 @@ - "movq %%cr3, %0; # flush TLB \n" \ - "movq %0, %%cr3; \n" \ - : "=r" (tmpreg) \ -- :: "memory"); \ -+ : : "memory"); \ - } while (0) - - /* -diff -ru ../linux-2.4.32/include/asm-x86_64/processor.h ./include/asm-x86_64/processor.h ---- ../linux-2.4.32/include/asm-x86_64/processor.h 2005-11-16 11:12:54.000000000 -0800 -+++ ./include/asm-x86_64/processor.h 2006-05-13 10:37:50.000000000 -0700 -@@ -389,7 +389,7 @@ - /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ - extern inline void rep_nop(void) - { -- __asm__ __volatile__("rep;nop":::"memory"); -+ __asm__ __volatile__("rep;nop": : :"memory"); - } - - /* Avoid speculative execution by the CPU */ -diff -ru ../linux-2.4.32/include/asm-x86_64/rwlock.h ./include/asm-x86_64/rwlock.h ---- ../linux-2.4.32/include/asm-x86_64/rwlock.h 2002-11-28 15:53:15.000000000 -0800 -+++ ./include/asm-x86_64/rwlock.h 2006-05-13 10:37:50.000000000 -0700 -@@ -31,7 +31,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ -@@ -44,7 +44,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile int *)rw))::"memory") -+ :"=m" (*((volatile int *)rw)): :"memory") - - #define __build_read_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -@@ -61,7 +61,7 @@ - "2:\tcall " helper "\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- ::"a" (rw) : "memory") -+ : :"a" (rw) : "memory") - - #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ -@@ -74,7 +74,7 @@ - "popq %%rax\n\t" \ - "jmp 1b\n" \ - LOCK_SECTION_END \ -- :"=m" (*((volatile long *)rw))::"memory") -+ :"=m" (*((volatile long *)rw)): :"memory") - - #define __build_write_lock(rw, helper) do { \ - if (__builtin_constant_p(rw)) \ -diff -ru ../linux-2.4.32/include/asm-x86_64/system.h ./include/asm-x86_64/system.h ---- ../linux-2.4.32/include/asm-x86_64/system.h 2003-11-28 10:26:21.000000000 -0800 -+++ ./include/asm-x86_64/system.h 2006-05-13 10:37:50.000000000 -0700 -@@ -248,9 +248,9 @@ - * but I'd also expect them to finally get their act together - * and add some real memory barriers if so. - */ --#define mb() asm volatile("mfence":::"memory") --#define rmb() asm volatile("lfence":::"memory") --#define wmb() asm volatile("sfence":::"memory") -+#define mb() asm volatile("mfence": : :"memory") -+#define rmb() asm volatile("lfence": : :"memory") -+#define wmb() asm volatile("sfence": : :"memory") - #define set_mb(var, value) do { xchg(&var, value); } while (0) - #define set_wmb(var, value) do { var = value; wmb(); } while (0) - -@@ -299,7 +299,7 @@ - #endif - - /* Default simics "magic" breakpoint */ --#define icebp() asm volatile("xchg %%bx,%%bx" ::: "ebx") -+#define icebp() asm volatile("xchg %%bx,%%bx" : : : "ebx") - - /* - * disable hlt during certain critical i/o operations -diff -ru ../linux-2.4.32/include/asm-x86_64/uaccess.h ./include/asm-x86_64/uaccess.h ---- ../linux-2.4.32/include/asm-x86_64/uaccess.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/asm-x86_64/uaccess.h 2006-05-13 10:37:50.000000000 -0700 -@@ -284,13 +284,13 @@ - case 10: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2); - return ret; - case 16: - __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16); - if (ret) return ret; -- asm("":::"memory"); -+ asm("": : :"memory"); - __put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8); - return ret; - default: -diff -ru ../linux-2.4.32/include/linux/atalk.h ./include/linux/atalk.h ---- ../linux-2.4.32/include/linux/atalk.h 2001-11-22 11:47:11.000000000 -0800 -+++ ./include/linux/atalk.h 2006-05-13 10:46:55.000000000 -0700 -@@ -163,7 +163,7 @@ - - static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) - { -- return dev->atalk_ptr; -+ return (struct atalk_iface *) dev->atalk_ptr; - } - - extern struct at_addr *atalk_find_dev_addr(struct net_device *dev); -diff -ru ../linux-2.4.32/include/linux/dqblk_v1.h ./include/linux/dqblk_v1.h ---- ../linux-2.4.32/include/linux/dqblk_v1.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/linux/dqblk_v1.h 2006-05-13 10:37:50.000000000 -0700 -@@ -12,7 +12,6 @@ - #define V1_DQF_RSQUASH 1 - - /* Special information about quotafile */ --struct v1_mem_dqinfo { --}; -+EMPTY_STRUCT_DECL(v1_mem_dqinfo); - - #endif /* _LINUX_DQBLK_V1_H */ -diff -ru ../linux-2.4.32/include/linux/highmem.h ./include/linux/highmem.h ---- ../linux-2.4.32/include/linux/highmem.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/linux/highmem.h 2006-05-13 10:43:06.000000000 -0700 -@@ -17,7 +17,7 @@ - - static inline char *bh_kmap(struct buffer_head *bh) - { -- return kmap(bh->b_page) + bh_offset(bh); -+ return (char *)kmap(bh->b_page) + bh_offset(bh); - } - - static inline void bh_kunmap(struct buffer_head *bh) -@@ -103,7 +103,7 @@ - - if (offset + size > PAGE_SIZE) - out_of_line_bug(); -- kaddr = kmap(page); -+ kaddr = (char *) kmap(page); - memset(kaddr + offset, 0, size); - flush_dcache_page(page); - flush_page_to_ram(page); -@@ -114,8 +114,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -@@ -125,8 +125,8 @@ - { - char *vfrom, *vto; - -- vfrom = kmap_atomic(from, KM_USER0); -- vto = kmap_atomic(to, KM_USER1); -+ vfrom = (char *) kmap_atomic(from, KM_USER0); -+ vto = (char *) kmap_atomic(to, KM_USER1); - copy_page(vto, vfrom); - kunmap_atomic(vfrom, KM_USER0); - kunmap_atomic(vto, KM_USER1); -diff -ru ../linux-2.4.32/include/linux/if_vlan.h ./include/linux/if_vlan.h ---- ../linux-2.4.32/include/linux/if_vlan.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/linux/if_vlan.h 2006-05-13 10:55:19.000000000 -0700 -@@ -184,7 +184,7 @@ - break; - }; - -- return (polling ? netif_receive_skb(skb) : netif_rx(skb)); -+ return (polling ? netif_receive_skb(skb, skb->protocol, 0) : netif_rx(skb)); - } - - static inline int vlan_hwaccel_rx(struct sk_buff *skb, -diff -ru ../linux-2.4.32/include/linux/inetdevice.h ./include/linux/inetdevice.h ---- ../linux-2.4.32/include/linux/inetdevice.h 2004-04-14 06:05:40.000000000 -0700 -+++ ./include/linux/inetdevice.h 2006-05-13 10:37:50.000000000 -0700 -@@ -140,7 +140,7 @@ - struct in_device *in_dev; - - read_lock(&inetdev_lock); -- in_dev = dev->ip_ptr; -+ in_dev = (struct in_device *) dev->ip_ptr; - if (in_dev) - atomic_inc(&in_dev->refcnt); - read_unlock(&inetdev_lock); -diff -ru ../linux-2.4.32/include/linux/intermezzo_kml.h ./include/linux/intermezzo_kml.h ---- ../linux-2.4.32/include/linux/intermezzo_kml.h 2001-11-11 10:20:21.000000000 -0800 -+++ ./include/linux/intermezzo_kml.h 2006-05-13 10:37:50.000000000 -0700 -@@ -70,8 +70,7 @@ - int gid; - }; - --struct kml_open { --}; -+EMPTY_STRUCT_DECL(kml_open); - - struct kml_mkdir { - char *path; -diff -ru ../linux-2.4.32/include/linux/list.h ./include/linux/list.h ---- ../linux-2.4.32/include/linux/list.h 2004-02-18 05:36:32.000000000 -0800 -+++ ./include/linux/list.h 2006-05-13 10:43:06.000000000 -0700 -@@ -91,8 +91,8 @@ - static inline void list_del(struct list_head *entry) - { - __list_del(entry->prev, entry->next); -- entry->next = (void *) 0; -- entry->prev = (void *) 0; -+ entry->next = (struct list_head *) 0; -+ entry->prev = (struct list_head *) 0; - } - - /** -diff -ru ../linux-2.4.32/include/linux/mm.h ./include/linux/mm.h ---- ../linux-2.4.32/include/linux/mm.h 2005-01-19 06:10:12.000000000 -0800 -+++ ./include/linux/mm.h 2006-05-13 10:43:06.000000000 -0700 -@@ -592,7 +592,6 @@ - return 0; - } - --struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -diff -ru ../linux-2.4.32/include/linux/mtd/compatmac.h ./include/linux/mtd/compatmac.h ---- ../linux-2.4.32/include/linux/mtd/compatmac.h 2003-06-13 07:51:38.000000000 -0700 -+++ ./include/linux/mtd/compatmac.h 2006-05-13 10:37:50.000000000 -0700 -@@ -133,8 +133,8 @@ - #endif /* !(__BIT_TYPES_DEFINED__) */ - - #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } -+ typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+ #define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - #else - typedef struct { int gcc_is_buggy; } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } -diff -ru ../linux-2.4.32/include/linux/netdevice.h ./include/linux/netdevice.h ---- ../linux-2.4.32/include/linux/netdevice.h 2004-11-17 03:54:22.000000000 -0800 -+++ ./include/linux/netdevice.h 2006-05-13 10:46:44.000000000 -0700 -@@ -453,6 +453,46 @@ - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; - #endif /* CONFIG_NET_DIVERT */ -+ -+ /* Click polling support */ -+ /* -+ * polling is < 0 if the device does not support polling, == 0 if the -+ * device supports polling but interrupts are on, and > 0 if polling -+ * is on. -+ */ -+ int polling; -+ int (*poll_on)(struct net_device *); -+ int (*poll_off)(struct net_device *); -+ /* -+ * rx_poll returns to caller a linked list of sk_buff objects received -+ * by the device. on call, the want argument specifies the number of -+ * packets wanted. on return, the want argument specifies the number -+ * of packets actually returned. -+ */ -+ struct sk_buff * (*rx_poll)(struct net_device*, int *want); -+ /* refill rx dma ring using the given sk_buff list. returns 0 if -+ * successful, or if there are more entries need to be cleaned, -+ * returns the number of dirty entries. the ptr to the sk_buff list is -+ * updated by the driver to point to any unused skbs. -+ */ -+ int (*rx_refill)(struct net_device*, struct sk_buff**); -+ /* -+ * place sk_buff on the transmit ring. returns 0 if successful, 1 -+ * otherwise -+ */ -+ int (*tx_queue)(struct net_device *, struct sk_buff *); -+ /* -+ * clean tx dma ring. returns the list of skb objects cleaned -+ */ -+ struct sk_buff* (*tx_clean)(struct net_device *); -+ /* -+ * start transmission. returns 0 if successful, 1 otherwise -+ */ -+ int (*tx_start)(struct net_device *); -+ /* -+ * tell device the end of a batch of packets -+ */ -+ int (*tx_eob)(struct net_device *); - }; - - /* 2.6 compatibility */ -@@ -501,6 +541,9 @@ - extern int unregister_netdevice(struct net_device *dev); - extern int register_netdevice_notifier(struct notifier_block *nb); - extern int unregister_netdevice_notifier(struct notifier_block *nb); -+extern int register_net_in(struct notifier_block *nb); /* Click */ -+extern int unregister_net_in(struct notifier_block *nb); /* Click */ -+extern int ptype_dispatch(struct sk_buff *skb, unsigned short type); /* Click */ - extern int dev_new_index(void); - extern struct net_device *dev_get_by_index(int ifindex); - extern struct net_device *__dev_get_by_index(int ifindex); -@@ -614,7 +657,7 @@ - #define HAVE_NETIF_RX 1 - extern int netif_rx(struct sk_buff *skb); - #define HAVE_NETIF_RECEIVE_SKB 1 --extern int netif_receive_skb(struct sk_buff *skb); -+extern int netif_receive_skb(struct sk_buff *skb, unsigned short, int ignore_notifiers); - extern int dev_ioctl(unsigned int cmd, void *); - extern int dev_ethtool(struct ifreq *); - extern int dev_change_flags(struct net_device *, unsigned); -diff -ru ../linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_irc.h ./include/linux/netfilter_ipv4/ip_conntrack_irc.h ---- ../linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_irc.h 2004-11-17 03:54:22.000000000 -0800 -+++ ./include/linux/netfilter_ipv4/ip_conntrack_irc.h 2006-05-13 10:37:50.000000000 -0700 -@@ -27,8 +27,7 @@ - }; - - /* This structure exists only once per master */ --struct ip_ct_irc_master { --}; -+EMPTY_STRUCT_DECL(ip_ct_irc_master); - - - #ifdef __KERNEL__ -diff -ru ../linux-2.4.32/include/linux/nfsd/syscall.h ./include/linux/nfsd/syscall.h ---- ../linux-2.4.32/include/linux/nfsd/syscall.h 2001-11-22 11:47:52.000000000 -0800 -+++ ./include/linux/nfsd/syscall.h 2006-05-13 10:51:07.000000000 -0700 -@@ -133,7 +133,7 @@ - * Kernel syscall implementation. - */ - #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) --extern asmlinkage long sys_nfsservctl(int, void *, void *); -+asmlinkage long sys_nfsservctl(int, void *, void *); - #else - #define sys_nfsservctl sys_ni_syscall - #endif -diff -ru ../linux-2.4.32/include/linux/reiserfs_fs_sb.h ./include/linux/reiserfs_fs_sb.h ---- ../linux-2.4.32/include/linux/reiserfs_fs_sb.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/linux/reiserfs_fs_sb.h 2006-05-13 10:43:06.000000000 -0700 -@@ -352,8 +352,7 @@ - } journal; - } reiserfs_proc_info_data_t; - #else --typedef struct reiserfs_proc_info_data --{} reiserfs_proc_info_data_t; -+typedef EMPTY_STRUCT_DECL(reiserfs_proc_info_data) reiserfs_proc_info_data_t; - #endif - - /* reiserfs union of in-core super block data */ -diff -ru ../linux-2.4.32/include/linux/skbuff.h ./include/linux/skbuff.h ---- ../linux-2.4.32/include/linux/skbuff.h 2005-04-03 18:42:20.000000000 -0700 -+++ ./include/linux/skbuff.h 2006-05-13 10:44:31.000000000 -0700 -@@ -126,19 +126,31 @@ - skb_frag_t frags[MAX_SKB_FRAGS]; - }; - -+/* Click: overload sk_buff.pkt_type to contain information about whether -+ a packet is clean. Clean packets have the following fields zero: -+ dst, destructor, pkt_bridged, prev, list, sk, security, priority. */ -+#define PACKET_CLEAN 128 /* Is packet clean? */ -+#define PACKET_TYPE_MASK 127 /* Actual packet type */ -+ -+/* Click: change sk_buff structure so all fields used for router are grouped -+ * together on one cache line, we hope */ - struct sk_buff { - /* These two members must be first. */ - struct sk_buff * next; /* Next buffer in list */ - struct sk_buff * prev; /* Previous buffer in list */ - -- struct sk_buff_head * list; /* List we are on */ -- struct sock *sk; /* Socket we are owned by */ -- struct timeval stamp; /* Time we arrived */ -+ unsigned int len; /* Length of actual data */ -+ unsigned char *data; /* Data head pointer */ -+ unsigned char *tail; /* Tail pointer */ - struct net_device *dev; /* Device we arrived on/are leaving by */ -- struct net_device *real_dev; /* For support of point to point protocols -- (e.g. 802.3ad) over bonding, we must save the -- physical device that got the packet before -- replacing skb->dev with the virtual device. */ -+ unsigned char __unused, /* Dead field, may be reused */ -+ cloned, /* head may be cloned (check refcnt to be sure). */ -+ pkt_type, /* Packet class */ -+ ip_summed; /* Driver fed us an IP checksum */ -+ atomic_t users; /* User count - see datagram.c,tcp.c */ -+ unsigned int truesize; /* Buffer size */ -+ unsigned char *head; /* Head of buffer */ -+ unsigned char *end; /* End pointer */ - - /* Transport layer header */ - union -@@ -169,8 +181,6 @@ - unsigned char *raw; - } mac; - -- struct dst_entry *dst; -- - /* - * This is the control buffer. It is free to use for every - * layer. Please put your private variables there. If you -@@ -179,23 +189,21 @@ - */ - char cb[48]; - -- unsigned int len; /* Length of actual data */ -+ struct dst_entry *dst; -+ -+ struct sk_buff_head * list; /* List we are on */ -+ struct sock *sk; /* Socket we are owned by */ -+ struct timeval stamp; /* Time we arrived */ -+ struct net_device *real_dev; /* For support of point to point protocols -+ (e.g. 802.3ad) over bonding, we must save the -+ physical device that got the packet before -+ replacing skb->dev with the virtual device. */ -+ - unsigned int data_len; - unsigned int csum; /* Checksum */ -- unsigned char __unused, /* Dead field, may be reused */ -- cloned, /* head may be cloned (check refcnt to be sure). */ -- pkt_type, /* Packet class */ -- ip_summed; /* Driver fed us an IP checksum */ - __u32 priority; /* Packet queueing priority */ -- atomic_t users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short security; /* Security level of packet */ -- unsigned int truesize; /* Buffer size */ -- -- unsigned char *head; /* Head of buffer */ -- unsigned char *data; /* Data head pointer */ -- unsigned char *tail; /* Tail pointer */ -- unsigned char *end; /* End pointer */ - - void (*destructor)(struct sk_buff *); /* Destruct function */ - #ifdef CONFIG_NETFILTER -@@ -234,6 +242,8 @@ - extern void kfree_skbmem(struct sk_buff *skb); - extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); - extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); -+extern void skb_recycled_init(struct sk_buff *buf); -+extern struct sk_buff * skb_recycle(struct sk_buff *buf); - extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask); - extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask); - extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); -@@ -820,7 +830,7 @@ - return skb->data; - } - --static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) - { - skb->len-=len; - if (skb->len < skb->data_len) -@@ -848,7 +858,7 @@ - - extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta); - --static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len) -+static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) - { - if (len > skb_headlen(skb) && - __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL) -diff -ru ../linux-2.4.32/include/linux/spinlock.h ./include/linux/spinlock.h ---- ../linux-2.4.32/include/linux/spinlock.h 2005-01-19 06:10:12.000000000 -0800 -+++ ./include/linux/spinlock.h 2006-05-13 10:43:06.000000000 -0700 -@@ -2,6 +2,7 @@ - #define __LINUX_SPINLOCK_H - - #include -+#include - - #include - -@@ -73,13 +74,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 95) -- typedef struct { } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } spinlock_t; -- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) spinlock_t; -+#define SPIN_LOCK_UNLOCKED EMPTY_STRUCT_INIT(spinlock_t) - - #define spin_lock_init(lock) do { } while(0) - #define spin_lock(lock) (void)(lock) /* Not "unused variable". */ -@@ -137,13 +133,8 @@ - * Some older gcc versions had a nasty bug with empty initializers. - * (XXX: could someone please confirm whether egcs 1.1 still has this bug?) - */ --#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91) -- typedef struct { } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { } --#else -- typedef struct { int gcc_is_buggy; } rwlock_t; -- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } --#endif -+typedef EMPTY_STRUCT_DECL(/* unnamed */) rwlock_t; -+#define RW_LOCK_UNLOCKED EMPTY_STRUCT_INIT(rwlock_t) - - #define rwlock_init(lock) do { } while(0) - #define read_lock(lock) (void)(lock) /* Not "unused variable". */ -diff -ru ../linux-2.4.32/include/linux/swap.h ./include/linux/swap.h ---- ../linux-2.4.32/include/linux/swap.h 2005-01-19 06:10:12.000000000 -0800 -+++ ./include/linux/swap.h 2006-05-13 10:43:06.000000000 -0700 -@@ -101,7 +101,7 @@ - struct vm_area_struct; - struct sysinfo; - --struct zone_t; -+struct zone_struct; - - /* linux/mm/swap.c */ - extern void FASTCALL(lru_cache_add(struct page *)); -diff -ru ../linux-2.4.32/include/linux/sysctl.h ./include/linux/sysctl.h ---- ../linux-2.4.32/include/linux/sysctl.h 2005-04-03 18:42:20.000000000 -0700 -+++ ./include/linux/sysctl.h 2006-05-13 10:43:58.000000000 -0700 -@@ -728,7 +728,7 @@ - - #ifdef __KERNEL__ - --extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+asmlinkage long sys_sysctl(struct __sysctl_args *); - extern void sysctl_init(void); - - typedef struct ctl_table ctl_table; -diff -ru ../linux-2.4.32/include/linux/types.h ./include/linux/types.h ---- ../linux-2.4.32/include/linux/types.h 2003-06-13 07:51:39.000000000 -0700 -+++ ./include/linux/types.h 2006-05-13 10:43:05.000000000 -0700 -@@ -134,4 +134,23 @@ - char f_fpack[6]; - }; - -+/* -+ * Click: Macros for defining empty structures. Needed because GCC's C and C++ -+ * compilers have different ABIs for empty structures. -+ */ -+ -+#if 1 -+# define EMPTY_STRUCT_DECL(s) struct s { int gcc_is_buggy; } -+# define EMPTY_STRUCT_INIT(s) (s) { 0 } -+#else -+/* This code remains in case GCC ever gets an option to give empty structures -+ * zero size. */ -+# define EMPTY_STRUCT_DECL(s) struct s { } -+# ifdef __cplusplus -+# define EMPTY_STRUCT_INIT(s) s() -+# else -+# define EMPTY_STRUCT_INIT(s) (s) { } -+# endif -+#endif -+ - #endif /* _LINUX_TYPES_H */ -diff -ru ../linux-2.4.32/include/net/ax25.h ./include/net/ax25.h ---- ../linux-2.4.32/include/net/ax25.h 2005-11-16 11:12:54.000000000 -0800 -+++ ./include/net/ax25.h 2006-05-13 10:46:55.000000000 -0700 -@@ -176,7 +176,7 @@ - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - ax25_digi *digipeat; -- ax25_dev *ax25_dev; -+ struct ax25_dev *ax25_dev; - unsigned char iamdigi; - unsigned char state, modulus, pidincl; - unsigned short vs, vr, va; -diff -ru ../linux-2.4.32/include/net/checksum.h ./include/net/checksum.h ---- ../linux-2.4.32/include/net/checksum.h 2001-11-22 11:47:22.000000000 -0800 -+++ ./include/net/checksum.h 2006-05-13 10:51:30.000000000 -0700 -@@ -111,7 +111,7 @@ - static __inline__ unsigned int csum_and_copy_to_user - (const char *src, char *dst, int len, unsigned int sum, int *err_ptr) - { -- sum = csum_partial(src, len, sum); -+ sum = csum_partial((const unsigned char *) src, len, sum); - - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len) == 0) -diff -ru ../linux-2.4.32/include/net/route.h ./include/net/route.h ---- ../linux-2.4.32/include/net/route.h 2003-08-25 04:44:44.000000000 -0700 -+++ ./include/net/route.h 2006-05-13 10:51:30.000000000 -0700 -@@ -142,7 +142,13 @@ - static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) - { -+#ifdef __cplusplus -+ struct rt_key key = { daddr, saddr }; -+ key.oif = oif; -+ key.tos = tos; -+#else - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; -+#endif - - return ip_route_output_key(rp, &key); - } -diff -ru ../linux-2.4.32/kernel/ksyms.c ./kernel/ksyms.c ---- ../linux-2.4.32/kernel/ksyms.c 2004-02-18 05:36:32.000000000 -0800 -+++ ./kernel/ksyms.c 2006-05-13 10:37:50.000000000 -0700 -@@ -558,6 +558,8 @@ - EXPORT_SYMBOL(event); - EXPORT_SYMBOL(brw_page); - EXPORT_SYMBOL(__inode_dir_notify); -+EXPORT_SYMBOL(super_blocks); -+EXPORT_SYMBOL(sb_lock); - - #ifdef CONFIG_UID16 - EXPORT_SYMBOL(overflowuid); -diff -ru ../linux-2.4.32/net/core/dev.c ./net/core/dev.c ---- ../linux-2.4.32/net/core/dev.c 2005-04-03 18:42:20.000000000 -0700 -+++ ./net/core/dev.c 2006-05-13 10:37:50.000000000 -0700 -@@ -182,6 +182,9 @@ - - static struct notifier_block *netdev_chain=NULL; - -+/* Click: input packet handlers, might steal packets from net_rx_action. */ -+static struct notifier_block *net_in_chain = 0; -+ - /* - * Device drivers call our routines to queue packets here. We empty the - * queue in the local softnet handler. -@@ -1425,6 +1428,22 @@ - } - - -+/* -+ * Click: Allow Click to ask to intercept input packets. -+ */ -+int -+register_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&net_in_chain, nb); -+} -+ -+int -+unregister_net_in(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&net_in_chain, nb); -+} -+ -+ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; - #endif -@@ -1458,11 +1477,10 @@ - } - #endif /* CONFIG_NET_DIVERT */ - --int netif_receive_skb(struct sk_buff *skb) -+int netif_receive_skb(struct sk_buff *skb, unsigned short type, int notifier_data) - { - struct packet_type *ptype, *pt_prev; - int ret = NET_RX_DROP; -- unsigned short type; - - if (skb->stamp.tv_sec == 0) - do_gettimeofday(&skb->stamp); -@@ -1480,6 +1498,14 @@ - - skb->h.raw = skb->nh.raw = skb->data; - -+ /* Click: may want to steal the packet */ -+ if (notifier_data >= 0 -+ && notifier_call_chain(&net_in_chain, -+ notifier_data, -+ skb) & NOTIFY_STOP_MASK) { -+ return ret; -+ } -+ - pt_prev = NULL; - for (ptype = ptype_all; ptype; ptype = ptype->next) { - if (!ptype->dev || ptype->dev == skb->dev) { -@@ -1507,7 +1533,6 @@ - } - #endif - -- type = skb->protocol; - for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { - if (ptype->type == type && - (!ptype->dev || ptype->dev == skb->dev)) { -@@ -1560,7 +1585,7 @@ - - dev = skb->dev; - -- netif_receive_skb(skb); -+ netif_receive_skb(skb, skb->protocol, skb_queue_len(&queue->input_pkt_queue)); - - dev_put(dev); - -diff -ru ../linux-2.4.32/net/core/skbuff.c ./net/core/skbuff.c ---- ../linux-2.4.32/net/core/skbuff.c 2003-08-25 04:44:44.000000000 -0700 -+++ ./net/core/skbuff.c 2006-05-13 10:37:50.000000000 -0700 -@@ -446,6 +446,65 @@ - #endif - } - -+/* Click: attempts to recycle a sk_buff. if it can be recycled, return it -+ * without reinitializing any bits */ -+struct sk_buff *skb_recycle(struct sk_buff *skb) -+{ -+ if (atomic_dec_and_test(&skb->users)) { -+ -+ if (skb->list) { -+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still " -+ "on a list (from %p).\n", NET_CALLER(skb)); -+ BUG(); -+ } -+ -+ dst_release(skb->dst); -+ if(skb->destructor) { -+ if (in_irq()) { -+ printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", -+ NET_CALLER(skb)); -+ } -+ skb->destructor(skb); -+ } -+#ifdef CONFIG_NETFILTER -+ nf_conntrack_put(skb->nfct); -+#endif -+ skb_headerinit(skb, NULL, 0); -+ -+ if (!skb->cloned || -+ atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) { -+ if (skb_shinfo(skb)->nr_frags) { -+ int i; -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) -+ put_page(skb_shinfo(skb)->frags[i].page); -+ } -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_drop_fraglist(skb); -+ -+ /* Load the data pointers. */ -+ skb->data = skb->head; -+ skb->tail = skb->data; -+ /* end and truesize should have never changed */ -+ /* skb->end = skb->data + skb->truesize; */ -+ -+ /* set up other state */ -+ skb->len = 0; -+ skb->cloned = 0; -+ -+ atomic_set(&skb->users, 1); -+ atomic_set(&(skb_shinfo(skb)->dataref), 1); -+ -+ return skb; -+ } -+ -+ skb_head_to_pool(skb); -+ } -+ -+ return 0; -+} -+ -+ - /** - * skb_copy - create private copy of an sk_buff - * @skb: buffer to copy -diff -ru ../linux-2.4.32/net/ipv4/arp.c ./net/ipv4/arp.c ---- ../linux-2.4.32/net/ipv4/arp.c 2004-11-17 03:54:22.000000000 -0800 -+++ ./net/ipv4/arp.c 2006-05-13 10:37:50.000000000 -0700 -@@ -319,6 +319,7 @@ - { - u32 saddr = 0; - u8 *dst_ha = NULL; -+ u8 dst_ha_buf[MAX_ADDR_LEN+sizeof(unsigned long)]; - struct net_device *dev = neigh->dev; - u32 target = *(u32*)neigh->primary_key; - int probes = atomic_read(&neigh->probes); -@@ -356,8 +357,8 @@ - if ((probes -= neigh->parms->ucast_probes) < 0) { - if (!(neigh->nud_state&NUD_VALID)) - printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); -- dst_ha = neigh->ha; -- read_lock_bh(&neigh->lock); -+ memcpy(dst_ha_buf, neigh->ha, sizeof(neigh->ha)); -+ dst_ha = dst_ha_buf; - } else if ((probes -= neigh->parms->app_probes) < 0) { - #ifdef CONFIG_ARPD - neigh_app_ns(neigh); -@@ -367,8 +368,6 @@ - - arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, - dst_ha, dev->dev_addr, NULL); -- if (dst_ha) -- read_unlock_bh(&neigh->lock); - } - - static int arp_ignore(struct in_device *in_dev, struct net_device *dev, -diff -ru ../linux-2.4.32/net/netsyms.c ./net/netsyms.c ---- ../linux-2.4.32/net/netsyms.c 2005-04-03 18:42:20.000000000 -0700 -+++ ./net/netsyms.c 2006-05-13 10:37:50.000000000 -0700 -@@ -294,6 +294,11 @@ - EXPORT_SYMBOL(register_inetaddr_notifier); - EXPORT_SYMBOL(unregister_inetaddr_notifier); - -+/* Click */ -+EXPORT_SYMBOL(register_net_in); -+EXPORT_SYMBOL(unregister_net_in); -+EXPORT_SYMBOL(skb_recycle); -+ - /* needed for ip_gre -cw */ - EXPORT_SYMBOL(ip_statistics); - diff --git a/etc/pkg-linuxmodule.mk b/etc/pkg-linuxmodule.mk index cb1e45ff6c..6c8c532a8c 100644 --- a/etc/pkg-linuxmodule.mk +++ b/etc/pkg-linuxmodule.mk @@ -46,49 +46,6 @@ ifndef MINDRIVER PACKAGE_CLEANFILES += $(package)-kelem.conf endif -ifneq ($(CLICK_LINUXMODULE_2_6),1) - -CXXCOMPILE = $(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) $(PACKAGE_CXXFLAGS) $(DEFS) $(INCLUDES) -CXXLD = $(CXX) -CXXLINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ -COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(PACKAGE_CFLAGS) $(DEFS) $(INCLUDES) -CCLD = $(CC) -LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ -FIXDEP = @-sed 's/\.o:/\.ko:/' < $*.d > $*.kd; /bin/rm -f $*.d - -ifeq ($(V),1) -ccompile = $(COMPILE) $(DEPCFLAGS) $(1) -ccompile_nodep = $(COMPILE) $(1) -cxxcompile = $(CXXCOMPILE) $(DEPCFLAGS) $(1) -cxxcompile_nodep = $(CXXCOMPILE) $(1) -else -ccompile = @/bin/echo ' ' $(2) $< && $(COMPILE) $(DEPCFLAGS) $(1) -ccompile_nodep = @/bin/echo ' ' $(2) $< && $(COMPILE) $(1) -cxxcompile = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(DEPCFLAGS) $(1) -cxxcompile_nodep = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(1) -endif - -.SUFFIXES: -.SUFFIXES: .c .cc .ko .kii - -.c.ko: - $(call ccompile,-c $< -o $@,CC) - $(FIXDEP) -.cc.ko: - $(call cxxcompile,-c $< -o $@,CXX) - $(FIXDEP) -.cc.kii: - $(call cxxcompile_nodep,-E $< > $@,CXXCPP) - -ifneq ($(MAKECMDGOALS),clean) --include $(package)-kelem.mk -endif - -OBJS = $(ELEMENT_OBJS) $(PACKAGE_OBJS) kversion.ko - -endif - -ifeq ($(CLICK_LINUXMODULE_2_6),1) # Jump through hoops to avoid missing symbol warnings $(package).ko: Makefile Kbuild always $(PACKAGE_DEPS) @fifo=.$(package).ko.$$$$.$$RANDOM.errors; rm -f $$fifo; \ @@ -100,11 +57,6 @@ $(package).ko: Makefile Kbuild always $(PACKAGE_DEPS) Kbuild: $(CLICK_BUILDTOOL) echo 'include $$(obj)/Makefile' > Kbuild $(CLICK_BUILDTOOL) $(CLICK_BUILDTOOL_FLAGS) kbuild >> Kbuild -else -$(package).ko: $(clickbuild_datadir)/pkg-linuxmodule.mk $(OBJS) $(PACKAGE_DEPS) - $(LD) -r -o $(package).ko $(OBJS) - $(STRIP) -g $(package).ko -endif ifdef MINDRIVER elemlist: diff --git a/lib/master.cc b/lib/master.cc index 96fd99ddea..dd62473365 100644 --- a/lib/master.cc +++ b/lib/master.cc @@ -204,7 +204,7 @@ Master::kill_router(Router *router) // Fix stopper request_stop(); -#if CLICK_LINUXMODULE && HAVE_LINUXMODULE_2_6 +#if CLICK_LINUXMODULE preempt_disable(); #endif unlock_master(); @@ -233,7 +233,7 @@ Master::kill_router(Router *router) #endif unpause(); -#if CLICK_LINUXMODULE && HAVE_LINUXMODULE_2_6 +#if CLICK_LINUXMODULE preempt_enable_no_resched(); #endif diff --git a/linuxmodule/Makefile.in b/linuxmodule/Makefile.in index dc491db447..38972f0229 100644 --- a/linuxmodule/Makefile.in +++ b/linuxmodule/Makefile.in @@ -59,10 +59,8 @@ endif INSTALLOBJS = $(DRIVER).o proclikefs.o -ifeq (@LINUXMODULE_2_6@,1) - ########################################################################## -## LINUX 2.6 ## +## LINUX RULES ## KERNELPATH = @linux_builddir@ @@ -94,7 +92,7 @@ CLICKmkinstalldirs = $(conf_auxdir)/mkinstalldirs CLICK_BUILDTOOL = $(top_builddir)/click-buildtool MD5SUM = @MD5SUM@ -CLICK_ELEM2MAKE = $(CLICK_BUILDTOOL) elem2make --linux26 +CLICK_ELEM2MAKE = $(CLICK_BUILDTOOL) elem2make --linux CLICKCC = @KERNEL_CC@ CLICKCXX = @KERNEL_CXX@ @@ -219,114 +217,9 @@ uninstall: for i in $(patsubst %.o,%.ko,$(INSTALLOBJS)); do /bin/rm -f $(DESTDIR)$(libdir)/$$i; done (cd $(top_builddir)/include/click-linuxmodule; find . -type f -print) | grep / | sed 's ^\.\(.*\) '"$(top_builddir)/include/click-linuxmodule"'\1'" $(DESTDIR)$(includedir)/click-linuxmodule"'\1 ' | xargs -L 1 rm -f -else - -########################################################################## -## LINUX 2.4 ## - -top_srcdir := @top_srcdir@ -srcdir := @srcdir@ -top_builddir := .. - -VPATH = .:$(top_srcdir)/lib:$(top_srcdir)/$(subdir):$(top_srcdir)/elements/standard - -CC = @KERNEL_CC@ -CPP = @CPP@ -CXX = @KERNEL_CXX@ -CXXCPP = @CXXCPP@ -LD = @LD@ -STRIP = @STRIP@ -INSTALL = @INSTALL@ -INSTALL_DATA = $(INSTALL) -m 644 -mkinstalldirs = $(conf_auxdir)/mkinstalldirs -CLICK_ELEM2MAKE = $(top_builddir)/click-buildtool elem2make - -ifeq ($(V),1) -ccompile = $(COMPILE) $(DEPCFLAGS) $(1) -ccompile_nodep = $(COMPILE) $(1) -cxxcompile = $(CXXCOMPILE) $(DEPCFLAGS) $(1) -cxxcompile_nodep = $(CXXCOMPILE) $(1) -else -ccompile = @/bin/echo ' ' $(2) $< && $(COMPILE) $(DEPCFLAGS) $(1) -ccompile_nodep = @/bin/echo ' ' $(2) $< && $(COMPILE) $(1) -cxxcompile = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(DEPCFLAGS) $(1) -cxxcompile_nodep = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(1) -endif - -.SUFFIXES: -.SUFFIXES: .c .cc .o .S .s .i .ii - -.c.o: - $(call ccompile,-c $< -o $@,CC) -.c.i: - $(call ccompile_nodep,-E $< > $@,CPP) -.s.o: - $(call ccompile,-c $< -o $@,ASM) -.S.o: - $(call ccompile,-c $< -o $@,ASM) -.cc.o: - $(call cxxcompile,-c $< -o $@,CXX) -.cc.s: - $(call cxxcompile_nodep,-S $< -o $@,CXX -S) -.cc.ii: - $(call cxxcompile_nodep,-E $< > $@,CXXCPP) - - -OBJS = $(LIB_CXX_OBJS) $(LIB_C_OBJS) $(STD_ELEMENT_OBJS) $(ELEMENT_OBJS) \ - $(LINUXMODULE_CXX_OBJS) $(LINUXMODULE_C_OBJS) $(ELEMENTSCONF).o - -CPPFLAGS = @CPPFLAGS@ -DCLICK_LINUXMODULE -CFLAGS = @KERNEL_CFLAGS@ -CXXFLAGS = @KERNEL_CXXFLAGS@ -DEPCFLAGS = @DEPCFLAGS@ - -DEFS = @DEFS@ -INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(srcdir) -I$(top_srcdir) -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ - -CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -CXXLD = $(CXX) -CXXLINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ -COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ - -all: $(INSTALLOBJS) - -ifneq ($(MAKECMDGOALS),clean) --include $(ELEMENTSCONF).mk -endif - -$(DRIVER).o: Makefile $(OBJS) - $(LD) -r -o $(DRIVER).o $(OBJS) - $(STRIP) -g $(DRIVER).o - -proclikefs.o: proclikefs.c Makefile - $(COMPILE) -D__KERNEL__ -DMODULE $(DEPCFLAGS) -c $< -o $@ - -DEPFILES := $(wildcard *.d) -ifneq ($(DEPFILES),) -include $(DEPFILES) -endif - -install: install-local -install-local: $(INSTALLOBJS) - $(mkinstalldirs) $(DESTDIR)$(libdir) - for i in $(INSTALLOBJS); do $(INSTALL_DATA) $$i $(DESTDIR)$(libdir)/$$i; done -install-include: - @: -install-man: - @: -uninstall: - for i in $(INSTALLOBJS); do /bin/rm -f $(DESTDIR)$(libdir)/$$i; done - -endif - ########################################################################## -## ANY LINUX ## +## GENERIC RULES ## elemlist: @/bin/rm -f elements.conf elements.csmk diff --git a/linuxmodule/clickfs.cc b/linuxmodule/clickfs.cc index 8acda47624..fbda5b4ae0 100644 --- a/linuxmodule/clickfs.cc +++ b/linuxmodule/clickfs.cc @@ -33,11 +33,7 @@ #include CLICK_CXX_PROTECT #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -# include -#else -# include -#endif +#include #include CLICK_CXX_UNPROTECT #include @@ -76,21 +72,12 @@ static inline void lock_config(const char *file, int line, int iswrite) { wait_queue_t wait; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) # define private linux_private init_wait(&wait); # undef private -#else - init_waitqueue_entry(&wait, current); - add_wait_queue(&clickfs_waitq, &wait); -#endif for (;;) { SPIN_LOCK(&clickfs_lock, file, line); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) prepare_to_wait(&clickfs_waitq, &wait, TASK_UNINTERRUPTIBLE); -#else - set_current_state(TASK_UNINTERRUPTIBLE); -#endif int reads = atomic_read(&clickfs_read_count); if (iswrite ? reads == 0 : reads >= 0) break; @@ -102,12 +89,7 @@ lock_config(const char *file, int line, int iswrite) else atomic_inc(&clickfs_read_count); SPIN_UNLOCK(&clickfs_lock, file, line); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) finish_wait(&clickfs_waitq, &wait); -#else - __set_current_state(TASK_RUNNING); - remove_wait_queue(&clickfs_waitq, &wait); -#endif clickfs_task = current; } @@ -132,11 +114,7 @@ unlock_config_write(const char *file, int line) /*************************** Inode constants ********************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) #define INODE_INFO(inode) (*((ClickInodeInfo *)(&(inode)->i_private))) -#else -#define INODE_INFO(inode) (*((ClickInodeInfo *)(&(inode)->u))) -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) #define set_nlink(inode, nlink) ((inode)->i_nlink = (nlink)) #endif @@ -242,10 +220,8 @@ extern "C" { static struct dentry * #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) click_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -click_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *) #else -click_dir_lookup(struct inode *dir, struct dentry *dentry) +click_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *) #endif { LOCK_CONFIG_READ(); @@ -279,7 +255,6 @@ click_dir_lookup(struct inode *dir, struct dentry *dentry) } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) static int click_dentry_revalidate(struct dentry *dentry, unsigned flags) { @@ -307,27 +282,12 @@ click_dentry_revalidate(struct dentry *dentry, unsigned flags) return r; } -# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) static int click_dentry_revalidate_nd(struct dentry *dentry, struct nameidata *nd) { return click_dentry_revalidate(dentry, nd->flags); } -# endif -#else -static int -click_dir_revalidate(struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - MDEBUG("click_dir_revalidate %lx", (inode ? inode->i_ino : 0)); - if (!inode) - return -EINVAL; - - LOCK_CONFIG_READ(); - int error = click_ino_check(inode, -EIO); - UNLOCK_CONFIG_READ(); - return error; -} #endif @@ -377,11 +337,7 @@ click_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) done: UNLOCK_CONFIG_READ(); filp->f_pos = f_pos; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) return (error ? error : stored); -#else - return error; -#endif } } // extern "C" @@ -436,32 +392,30 @@ click_read_super(struct super_block *sb, void * /* data */, int) return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) static int click_fill_super(struct super_block *sb, void *data, int flags) { return click_read_super(sb, data, flags) ? 0 : -ENOMEM; } -# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) static struct dentry * click_get_sb(struct file_system_type *fs_type, int flags, const char *, void *data) { return mount_single(fs_type, flags, data, click_fill_super); } -# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) static int click_get_sb(struct file_system_type *fs_type, int flags, const char *, void *data, struct vfsmount *vfsmount) { return get_sb_single(fs_type, flags, data, click_fill_super, vfsmount); } -# else +#else static struct super_block * click_get_sb(struct file_system_type *fs_type, int flags, const char *, void *data) { return get_sb_single(fs_type, flags, data, click_fill_super); } -# endif #endif static void @@ -730,12 +684,7 @@ handler_llseek(struct file* filp, loff_t offset, int origin) if (offset >= 0 && offset <= 0x7FFFFFFF) { if (offset != filp->f_pos) { filp->f_pos = offset; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) filp->f_version = 0; -#else - filp->f_reada = 0; - filp->f_version = ++event; -#endif } return offset; } else @@ -1061,15 +1010,8 @@ read_ino_info(Element *, void *) struct file_operations * click_new_file_operations() { - if (!clickfs) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + if (!clickfs) clickfs = proclikefs_register_filesystem("click", 0, click_get_sb); -#else - // NB: remove FS_SINGLE if it will ever make sense to have different - // Click superblocks -- if we introduce mount options, for example - clickfs = proclikefs_register_filesystem("click", FS_SINGLE, click_read_super); -#endif - } if (clickfs) return proclikefs_new_file_operations(clickfs); else @@ -1079,9 +1021,6 @@ click_new_file_operations() int init_clickfs() { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) - static_assert(sizeof(((struct inode *)0)->u) >= sizeof(ClickInodeInfo), "The file-system-specific data in struct inode isn't big enough."); -#endif static_assert(HANDLER_DIRECT + HANDLER_WRITE_UNLIMITED < Handler::USER_FLAG_0, "Too few driver handler flags available."); static_assert(((HS_DIRECT | HS_WRITE_UNLIMITED) & (HS_READING | HS_DONE | HS_RAW)) == 0, "Handler flag overlap."); @@ -1100,25 +1039,19 @@ init_clickfs() return -EINVAL; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) - click_superblock_ops.put_inode = force_delete; -#endif click_superblock_ops.put_super = proclikefs_put_super; // XXX statfs click_dentry_ops.d_delete = click_delete_dentry; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) click_dentry_ops.d_revalidate = click_dentry_revalidate; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#else click_dentry_ops.d_revalidate = click_dentry_revalidate_nd; #endif click_dir_file_ops->read = generic_read_dir; click_dir_file_ops->readdir = click_dir_readdir; click_dir_inode_ops->lookup = click_dir_lookup; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) - click_dir_inode_ops->revalidate = click_dir_revalidate; -#endif click_handler_file_ops->llseek = handler_llseek; click_handler_file_ops->read = handler_read; diff --git a/linuxmodule/kernelversion.c b/linuxmodule/kernelversion.c index 0a5ad2976b..e09c7883ef 100644 --- a/linuxmodule/kernelversion.c +++ b/linuxmodule/kernelversion.c @@ -28,11 +28,7 @@ #include #include "moduleparm.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 52) -# define CLICK_INT_MODULE_PARAM(param) MODULE_PARM(param, "i") -#else -# define CLICK_INT_MODULE_PARAM(param) module_param(param, int, 0) -#endif +#define CLICK_INT_MODULE_PARAM(param) module_param(param, int, 0) static int accessible = 1; CLICK_INT_MODULE_PARAM(accessible); @@ -59,11 +55,9 @@ static int greedy = 0; CLICK_INT_MODULE_PARAM(greedy); MODULE_PARM_DESC(greedy, "Click takes a whole CPU [0]"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 21) static int cpu = -1; CLICK_INT_MODULE_PARAM(cpu); MODULE_PARM_DESC(cpu, "Click thread preferred CPU [-1=any]"); -#endif int click_parm(int which) @@ -77,10 +71,8 @@ click_parm(int which) return gid; case CLICKPARM_GREEDY: return greedy; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 21) case CLICKPARM_CPU: return cpu; -#endif #if HAVE_MULTITHREAD case CLICKPARM_THREADS: return threads; diff --git a/linuxmodule/modulepriv.hh b/linuxmodule/modulepriv.hh index c7fe7b9245..c760509dc5 100644 --- a/linuxmodule/modulepriv.hh +++ b/linuxmodule/modulepriv.hh @@ -13,7 +13,7 @@ CLICK_CXX_PROTECT CLICK_CXX_UNPROTECT #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) # error "Linux version too old" #endif diff --git a/linuxmodule/proclikefs.c b/linuxmodule/proclikefs.c index 77fd7d92d7..78b7bb95c0 100644 --- a/linuxmodule/proclikefs.c +++ b/linuxmodule/proclikefs.c @@ -29,21 +29,13 @@ #endif #ifdef CONFIG_MODVERSIONS # define MODVERSIONS -# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -# include -# endif #endif #include #include "proclikefs.h" #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -# include -#endif #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -# include -#endif +#include #include #define CLICK_CONFIG_LINUXMODULE_SYMBOLS_ONLY 1 #include @@ -136,16 +128,6 @@ EXPORT_SYMBOL(proclikefs_put_super); EXPORT_SYMBOL(proclikefs_new_file_operations); EXPORT_SYMBOL(proclikefs_new_inode_operations); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -static struct super_block * -proclikefs_null_read_super(struct super_block *sb, void *data, int silent) -{ - DEBUG("null_read_super"); - sb->s_dev = 0; - return 0; -} -#endif - static struct dentry * #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) proclikefs_null_root_lookup(struct inode *dir, struct dentry *dentry, unsigned flags) @@ -174,14 +156,10 @@ proclikefs_register_filesystem(const char *name, int fs_flags, if (!name || strlen(name) >= PROCLIKEFS_NAME_LEN) return 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) if (!try_module_get(THIS_MODULE)) { printk(KERN_ALERT "proclikefs: error using module\n"); return 0; } -#else - MOD_INC_USE_COUNT; -#endif mutex_lock(&fslist_lock); @@ -209,11 +187,9 @@ proclikefs_register_filesystem(const char *name, int fs_flags, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) newfs->fs.mount = mountfunc; newfs->fs.kill_sb = kill_anon_super; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#else newfs->fs.get_sb = mountfunc; newfs->fs.kill_sb = kill_anon_super; -#else - newfs->fs.read_super = mountfunc; #endif if (!proclikefs_defined(newfs)) { @@ -387,9 +363,6 @@ proclikefs_unregister_filesystem(struct proclikefs_file_system *pfs) unlock_sb(); pfs->live = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) - pfs->fs.read_super = proclikefs_null_read_super; -#endif MOD_DEC_USE_COUNT; mutex_unlock(&pfs->lock); @@ -402,12 +375,8 @@ proclikefs_read_super(struct super_block *sb) struct proclikefs_file_system *pfs = (struct proclikefs_file_system *) (sb->s_type); atomic_inc(&pfs->nsuper); DEBUG("pfs[%p]: read_super for %s", pfs, pfs->fs.name); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) if (!try_module_get(THIS_MODULE)) printk(KERN_ALERT "proclikefs: error using module\n"); -#else - MOD_INC_USE_COUNT; -#endif } void diff --git a/linuxmodule/proclikefs.h b/linuxmodule/proclikefs.h index 65f58e717a..cb30d7d69e 100644 --- a/linuxmodule/proclikefs.h +++ b/linuxmodule/proclikefs.h @@ -14,10 +14,8 @@ struct proclikefs_file_system; typedef struct dentry *(*proclikefs_mountfunc)(struct file_system_type *, int, const char *, void *); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) typedef int (*proclikefs_mountfunc)(struct file_system_type *, int, const char *, void *, struct vfsmount *); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -typedef struct super_block *(*proclikefs_mountfunc)(struct file_system_type *, int, const char *, void *); #else -typedef struct super_block *(*proclikefs_mountfunc)(struct super_block *, void *, int); +typedef struct super_block *(*proclikefs_mountfunc)(struct file_system_type *, int, const char *, void *); #endif diff --git a/linuxmodule/sched.cc b/linuxmodule/sched.cc index 365ca5de90..d92abf2dd5 100644 --- a/linuxmodule/sched.cc +++ b/linuxmodule/sched.cc @@ -38,30 +38,19 @@ CLICK_CXX_PROTECT #include #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -# include -#endif +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) # include #endif CLICK_CXX_UNPROTECT #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -# define MIN_PRIO MAX_RT_PRIO +#define MIN_PRIO MAX_RT_PRIO /* MAX_PRIO already defined */ -# define PRIO2NICE(p) ((p) - MIN_PRIO - 20) -# define NICE2PRIO(n) (MIN_PRIO + (n) + 20) -# define DEF_PRIO NICE2PRIO(0) -# define TASK_PRIO(t) ((t)->static_prio) -#else -# define MIN_PRIO (-20) -# define MAX_PRIO 20 -# define PRIO2NICE(p) (p) -# define NICE2PRIO(n) (n) -# define DEF_PRIO DEF_NICE -# define TASK_PRIO(t) ((t)->nice) -#endif +#define PRIO2NICE(p) ((p) - MIN_PRIO - 20) +#define NICE2PRIO(n) (MIN_PRIO + (n) + 20) +#define DEF_PRIO NICE2PRIO(0) +#define TASK_PRIO(t) ((t)->static_prio) #define SOFT_SPIN_LOCK(l) do { /*MDEBUG("soft_lock %s", #l);*/ soft_spin_lock((l)); } while (0) #define SPIN_UNLOCK(l) do { /*MDEBUG("unlock %s", #l);*/ spin_unlock((l)); } while (0) @@ -87,11 +76,8 @@ click_sched(void *thunk) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) /* daemonize seems to be unnecessary */ -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - daemonize("kclick"); #else - daemonize(); - strcpy(current->comm, "kclick"); + daemonize("kclick"); #endif TASK_PRIO(current) = click_thread_priority; @@ -105,21 +91,14 @@ click_sched(void *thunk) int mycpu = click_parm(CLICKPARM_CPU); if (mycpu >= 0) { mycpu += rt->thread_id(); -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) if (mycpu < num_possible_cpus() && cpu_online(mycpu)) { -# if CONFIG_CPUMASK_OFFSTACK +# if CONFIG_CPUMASK_OFFSTACK set_cpus_allowed_ptr(current, cpumask_of(mycpu)); -# else +# else set_cpus_allowed(current, cpumask_of_cpu(mycpu)); -# endif +# endif } else printk(KERN_WARNING "click: warning: cpu %d for thread %d offline\n", mycpu, rt->thread_id()); -# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 21) - if (mycpu < smp_num_cpus && (cpu_online_map & (1UL << cpu_logical_map(mycpu)))) - set_cpus_allowed(current, 1UL << cpu_logical_map(mycpu)); - else - printk(KERN_WARNING "click: warning: cpu %d for thread %d offline\n", mycpu, rt->thread_id()); -# endif } #endif diff --git a/tools/click-install/click-install.cc b/tools/click-install/click-install.cc index f9b91d9873..197c449b29 100644 --- a/tools/click-install/click-install.cc +++ b/tools/click-install/click-install.cc @@ -56,7 +56,6 @@ #define EXPRESSION_OPT 304 #define UNINSTALL_OPT 305 #define HOTSWAP_OPT 306 -#define MAP_OPT 307 #define VERBOSE_OPT 308 #define THREADS_OPT 309 #define PRIVATE_OPT 310 @@ -76,7 +75,6 @@ static const Clp_Option options[] = { { "hotswap", 'h', HOTSWAP_OPT, 0, Clp_Negate }, { "priority", 'n', PRIORITY_OPT, Clp_ValInt, 0 }, #if FOR_LINUXMODULE - { "map", 'm', MAP_OPT, 0, 0 }, { "private", 'p', PRIVATE_OPT, 0, Clp_Negate }, { "threads", 'j', THREADS_OPT, Clp_ValUnsigned, 0 }, { 0, 't', THREADS_OPT, Clp_ValUnsigned, 0 }, // deprecated @@ -92,9 +90,6 @@ static const Clp_Option options[] = { }; static const char *program_name; -#if FOR_LINUXMODULE -static bool output_map; -#endif static String tmpdir; @@ -128,10 +123,6 @@ Options:\n\ -j, --threads N Use N threads (multithreaded Click only).\n\ -G, --greedy Make Click thread take up an entire CPU.\n\ --cpu N Click thread runs on CPU N.\n"); -# if HAVE_LINUXMODULE_2_6 - printf("\ - -m, --map Print load map to the standard output.\n"); -# endif #endif printf("\ -V, --verbose Print information about files installed.\n\ @@ -199,10 +190,7 @@ install_module(const String &filename, const String &options, ErrorHandler *errh) { #if FOR_LINUXMODULE - String cmdline = "/sbin/insmod "; - if (output_map) - cmdline += "-m "; - cmdline += filename; + String cmdline = "/sbin/insmod " + filename; if (options) cmdline += " " + options; int retval = system(cmdline.c_str()); @@ -322,7 +310,6 @@ main(int argc, char **argv) bool accessible = true; int threads = 1; bool greedy = false; - output_map = false; uid_t uid = 0; gid_t gid = 0; int cpu = -1; @@ -386,14 +373,6 @@ particular purpose.\n"); priority = clp->val.i; break; - case MAP_OPT: -# if HAVE_LINUXMODULE_2_6 - errh->warning("'%s' ignored on 2.6 kernels", Clp_CurOptionName(clp)); -# else - output_map = !clp->negated; -# endif - break; - case GREEDY_OPT: greedy = !clp->negated; break; @@ -488,13 +467,8 @@ particular purpose.\n"); // find and install proclikefs.o StringMap modules(-1); if (read_active_modules(modules, errh) && modules["proclikefs"] < 0) { -# if HAVE_LINUXMODULE_2_6 String proclikefs_o = clickpath_find_file("proclikefs.ko", "lib", CLICK_LIBDIR, errh); -# else - String proclikefs_o = - clickpath_find_file("proclikefs.o", "lib", CLICK_LIBDIR, errh); -# endif if (verbose) errh->message("Installing proclikefs (%s)", proclikefs_o.c_str()); install_module(proclikefs_o, String(), errh); @@ -502,12 +476,9 @@ particular purpose.\n"); #endif // find loadable module -#if FOR_BSDMODULE || (FOR_LINUXMODULE && HAVE_LINUXMODULE_2_6) +#if FOR_BSDMODULE || FOR_LINUXMODULE String click_o = clickpath_find_file("click.ko", "lib", CLICK_LIBDIR, errh); -#elif FOR_LINUXMODULE - String click_o = - clickpath_find_file("click.o", "lib", CLICK_LIBDIR, errh); #endif if (verbose) errh->message("Installing Click module (%s)", click_o.c_str());