This patch has been created from AVM's opensrc packages for 3490.06.20 and 3490.06.31
by applying to the kernel sources they contain the following command:

    diff -durN --no-dereference 3490.06.20 3490.06.31 > this.patch

--- linux-2.6.32/arch/mips/atheros/avm_hw_config.c
+++ linux-2.6.32/arch/mips/atheros/avm_hw_config.c
@@ -273,7 +273,7 @@
     { .name = "gpio_avm_uart_tx",               .value = 10  },
 
     { .name = "gpio_avm_extphy1_reset",         .value = 11  },
-    { .name = "gpio_avm_mdio_clk",              .value = 12, },
+    { .name = "gpio_avm_mdio_clk",              .value = 12,  },
     { .name = "gpio_avm_mdio_data",             .value = 19  },
 
     { .name = "gpio_avm_peregrine_reset",       .value = 17 },
--- linux-2.6.32/arch/mips/include/asm/mach-infineon/ifx_gpio.h
+++ linux-2.6.32/arch/mips/include/asm/mach-infineon/ifx_gpio.h
@@ -118,6 +118,7 @@
     IFX_GPIO_MODULE_WLAN_PEACOCK_RESET,
     IFX_GPIO_MODULE_PLL,
     IFX_GPIO_MODULE_SHIFT_REG,
+    IFX_GPIO_MODULE_WLAN_OFFLOAD_SCRPN_UART,
     //  add more component in the future
     IFX_GPIO_MODULE_MAX,
     //  flag to init module during system bootup no matter whether this module is loaded or not
@@ -170,7 +171,8 @@
         "WLAN_OFFLOAD_WASP_RESET",          \
         "WLAN_PEACOCK_RESET",               \
         "PLL",                              \
-        "SHIFT_REG"                         \
+        "SHIFT_REG",                        \
+        "WLAN_OFFLOAD_SCRPN_UART"           \
     }
 
 
--- linux-2.6.32/arch/mips/kernel/yield_context.c
+++ linux-2.6.32/arch/mips/kernel/yield_context.c
@@ -490,7 +490,7 @@
 \*--------------------------------------------------------------------------------*/
 void yield_context_dump(void)
 {
-	char buf[256];
+	char buf[512];
 	struct seq_file s = {
 		.buf = buf,
 		.size = sizeof(buf),
@@ -807,7 +807,7 @@
 	stackpointer = regs ? regs->regs[29] : 0L;
 	if((stackpointer < (unsigned long)&per_tc->yield_sp[0]) || (stackpointer >= (unsigned long)&per_tc->yield_sp[YIELD_MAX_STACK_ELEMENTS])) {
 		printk(KERN_EMERG"Fatal Error: Stackpointer %08lx exceed stack!\n", stackpointer);
-	} else {
+	} else if(stackpointer) {
 		unsigned int linenefeed = 0;
 		unsigned int *p      = (unsigned int *)stackpointer;
 		printk(KERN_EMERG"Stack:\n");
--- linux-2.6.32/arch/mips/mach-infineon/vr9/avm_hw_config_hw185.h
+++ linux-2.6.32/arch/mips/mach-infineon/vr9/avm_hw_config_hw185.h
@@ -464,6 +464,15 @@
             .config    = IFX_GPIO_IOCTL_PIN_CONFIG_DIR_OUT | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL0_CLEAR | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL1_CLEAR| IFX_GPIO_IOCTL_PIN_CONFIG_OD_SET | IFX_GPIO_IOCTL_PIN_CONFIG_PUDSEL_SET
         }
     },
+    {
+        .name   = "gpio_avm_offload_scrpn_uart",
+        .value  =  31,
+        .param  = avm_hw_param_gpio_out_active_high,
+        .manufactor_hw_config.manufactor_lantiq_gpio_config = {
+            .module_id = IFX_GPIO_MODULE_WLAN_OFFLOAD_SCRPN_UART,
+            .config    = IFX_GPIO_IOCTL_PIN_CONFIG_DIR_OUT | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL0_CLEAR | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL1_CLEAR| IFX_GPIO_IOCTL_PIN_CONFIG_OD_SET | IFX_GPIO_IOCTL_PIN_CONFIG_PUDSEL_SET
+        }
+    },
     /*----
     {
         .name   = "gpio_avm_offload_mac",
--- linux-2.6.32/arch/mips/mach-infineon/vr9/avm_hw_config_hw212.h
+++ linux-2.6.32/arch/mips/mach-infineon/vr9/avm_hw_config_hw212.h
@@ -302,6 +302,15 @@
             .config    = IFX_GPIO_IOCTL_PIN_CONFIG_DIR_OUT | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL0_CLEAR | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL1_CLEAR| IFX_GPIO_IOCTL_PIN_CONFIG_OD_SET | IFX_GPIO_IOCTL_PIN_CONFIG_PUDSEL_SET
         }
     },
+    {
+        .name   = "gpio_avm_offload_scrpn_uart",
+        .value  =  31,
+        .param  = avm_hw_param_gpio_out_active_high,
+        .manufactor_hw_config.manufactor_lantiq_gpio_config = {
+            .module_id = IFX_GPIO_MODULE_WLAN_OFFLOAD_SCRPN_UART,
+            .config    = IFX_GPIO_IOCTL_PIN_CONFIG_DIR_OUT | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL0_CLEAR | IFX_GPIO_IOCTL_PIN_CONFIG_ALTSEL1_CLEAR| IFX_GPIO_IOCTL_PIN_CONFIG_OD_SET | IFX_GPIO_IOCTL_PIN_CONFIG_PUDSEL_SET
+        }
+    },
     /*----
     {
         .name   = "gpio_avm_offload_mac",
--- linux-2.6.32/.config
+++ linux-2.6.32/.config
@@ -1152,6 +1152,7 @@
 CONFIG_UBIK2=n
 CONFIG_UBIK2_DEVELOPMENT_SUPPORT=0
 CONFIG_UBIK2_MSEC_PER_IRQ=4
+CONFIG_UBIK2_ISDNSTACK_ON_CPU=1
 CONFIG_IFX_PMCU=y
 # CONFIG_IFX_CPUFREQ is not set
 CONFIG_IFX_PMU=y
--- linux-2.6.32/drivers/block/nbd.c
+++ linux-2.6.32/drivers/block/nbd.c
@@ -655,7 +655,8 @@
 
 		mutex_unlock(&lo->tx_lock);
 
-		thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
+		thread = kthread_create(nbd_thread, lo, "%s",
+					lo->disk->disk_name);
 		if (IS_ERR(thread)) {
 			mutex_lock(&lo->tx_lock);
 			return PTR_ERR(thread);
--- linux-2.6.32/drivers/char/avm_new/ar7wdt_main.c
+++ linux-2.6.32/drivers/char/avm_new/ar7wdt_main.c
@@ -982,6 +982,30 @@
 	}
 }
 #endif
+
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+int __get_userinfo(char *buf, unsigned int maxbuflen, struct mm_struct *mmm, unsigned long addr) {
+    struct vm_area_struct *vm;
+    unsigned int i = 0;
+    if(mmm == NULL) {
+        return 1;
+    }
+    vm = mmm->mmap;
+    while(vm) {
+        /*--- printk(KERN_INFO"%s[%x]:%p %x -%x\n", __func__, addr, vm, vm->vm_start, vm->vm_end); ---*/
+        if((addr >= vm->vm_start) && (addr < vm->vm_end)) {
+            snprintf(buf, maxbuflen,"seg=%3u of=0x%08lx [%s]", i, addr - (unsigned long)vm->vm_start, 
+                         (vm->vm_file && vm->vm_file->f_path.dentry) ? (char *)vm->vm_file->f_path.dentry->d_name.name : "");
+            /*--- printk(KERN_INFO"%s", buf); ---*/
+            return 0;
+        }
+        vm = vm->vm_next;
+        i++;
+    }
+    return 1;
+}
+
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static void __sched_show_user_task(struct task_struct *task){
--- linux-2.6.32/drivers/char/avm_new/avm_debug.c
+++ linux-2.6.32/drivers/char/avm_new/avm_debug.c
@@ -432,7 +432,7 @@
     return idx;
 }
 
-inline void avm_debug_enable_avm_printk(void)
+void avm_debug_enable_avm_printk(void)
 {
 #ifdef CONFIG_PRINTK
 
@@ -448,7 +448,7 @@
 #endif /* CONFIG_PRINTK */
 }
 
-inline void avm_debug_disable_avm_printk(void)
+void avm_debug_disable_avm_printk(void)
 {
 #ifdef CONFIG_PRINTK
 
@@ -474,7 +474,7 @@
 
     /* Always use original Linux printk */
     printk_linux(KERN_ERR "\nblock cpu%x for %lu ms\n",
-		smp_processor_id(), timer);
+		raw_smp_processor_id(), timer);
 
     while(timer--) {
         udelay(1000);
@@ -490,7 +490,7 @@
 static void torture_function(unsigned long context)
 {
 	printk_linux(KERN_ERR "\nblock timer on cpu%x for %lu ms\n",
-		     smp_processor_id(), context);
+		     raw_smp_processor_id(), context);
 
 	while (context--)
 		udelay(1000);
@@ -646,7 +646,7 @@
                 add_timer_on(&torture_Timer[cpu], cpu);
             } else 
 #if defined(CONFIG_SMP)
-            if(cpu != smp_processor_id()) {
+            if(cpu != raw_smp_processor_id()) {
                 smp_call_function_single(cpu, torture, (void *)val, 0);
             } else 
 #endif /*--- #if defined(CONFIG_SMP) ---*/
@@ -1219,7 +1219,7 @@
     if(pud->NextIsLong == TRUE) {
         signed long long lValue;
         lValue = va_arg(*marker, long long);
-        sprintf(Data, "%llx", lValue);
+        snprintf(Data, sizeof(Data), "%llx", lValue);
     } else {
         Val = va_arg(*marker, int); 
         if((mode == 1) && (Val == 0)) {
@@ -1369,7 +1369,7 @@
         return;
     }
     if(check_memory_pointer(B)){
-        sprintf(tmp, "(inval=0x%x)", (unsigned int)B);
+        snprintf(tmp, sizeof(tmp), "(inval=0x%x)", (unsigned int)B);
         B = tmp;
     }
     if(pud->Leftjust == TRUE) { /*--- reverse ---*/
@@ -1408,7 +1408,7 @@
         pstring = "(null)";
     }
     if(check_memory_pointer(pstring)){
-        sprintf(tmp, "(inval=0x%x)", (unsigned int)pstring);
+        snprintf(tmp, sizeof(tmp), "(inval=0x%x)", (unsigned int)pstring);
         pstring = tmp;
     }
     if (pud->field_prec == 0) {
@@ -1472,7 +1472,7 @@
 
 #if defined(CONFIG_SMP)
 #define CPU_ARGUMENT_STRING()  "[%x] "
-#define CPU_ID()    ,smp_processor_id()
+#define CPU_ID()    ,raw_smp_processor_id()
 #else
 #define CPU_ARGUMENT_STRING() " "
 #define CPU_ID()    
@@ -1505,7 +1505,7 @@
 #if defined(CONFIG_PRINTK_TIME)
         /* Follow the token with the time */
         unsigned long clk_rem;
-        unsigned long long clk = cpu_clock(smp_processor_id());
+        unsigned long long clk = cpu_clock(raw_smp_processor_id());
         clk_rem = do_div(clk, 1000000000);
 #endif /*--- #if defined(CONFIG_PRINTK_TIME) ---*/
         if(lost) {
@@ -1546,6 +1546,8 @@
 #ifdef CONFIG_KALLSYMS
    if(Mode && (*Mode & 0x2)) {
 #else
+       /*--- wir benoetigen Modul-Textaufloesung: ---*/
+#endif/*--- #ifdef CONFIG_KALLSYMS ---*/
         if(Mode && (*Mode & 0x1)) {
             len = debug_prefix(DebugData, 0);
             if(len > 0) {
@@ -1553,8 +1555,6 @@
                 pud->Sum = len;
             }
         }
-       /*--- wir benoetigen Modul-Textaufloesung: ---*/
-#endif/*--- #ifdef CONFIG_KALLSYMS ---*/
         pud->Pos        = 0;
         pud->NextIsLong = FALSE;
         pud->p_ext = no_extension;
@@ -1730,13 +1730,17 @@
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
 void avm_DebugPrintf(const char *format, ...) {
-    int print_time = 0x1| 0x2;
+    int print_time = 0x2;
+	const char *start_format = format;
     va_list marker;
 
     int level = skip_loglevel(&format, 0);
     if (console_loglevel < level) {
         return;
     }
+	if(start_format != format) {
+		print_time |= 0x1;	/*--- Loglevel gefunden -> Timestamp davor ---*/
+    }
     va_start(marker,format);
     if(likely(avm_debug.init)) {
         avm_DebugvPrintf(&print_time, format, marker);
--- linux-2.6.32/drivers/char/avm_new/avm_proc_profile.c
+++ linux-2.6.32/drivers/char/avm_new/avm_proc_profile.c
@@ -572,28 +572,6 @@
 
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
-int __get_userinfo(char *buf, unsigned int maxbuflen, struct mm_struct *mmm, unsigned long addr) {
-    struct vm_area_struct *vm;
-    unsigned int i = 0;
-    if(mmm == NULL) {
-        return 1;
-    }
-    vm = mmm->mmap;
-    while(vm) {
-        /*--- printk(KERN_INFO"%s[%x]:%p %x -%x\n", __func__, addr, vm, vm->vm_start, vm->vm_end); ---*/
-        if((addr >= vm->vm_start) && (addr < vm->vm_end)) {
-            snprintf(buf, maxbuflen,"seg=%3u of=0x%08lx [%s]", i, addr - (unsigned long)vm->vm_start, 
-                         (vm->vm_file && vm->vm_file->f_path.dentry) ? (char *)vm->vm_file->f_path.dentry->d_name.name : "");
-            /*--- printk(KERN_INFO"%s", buf); ---*/
-            return 0;
-        }
-        vm = vm->vm_next;
-        i++;
-    }
-    return 1;
-}
-/*--------------------------------------------------------------------------------*\
-\*--------------------------------------------------------------------------------*/
 int get_user_info(char *buf, unsigned int maxbuflen, pid_t pid, unsigned long addr) {
     struct pid *ppid;
     unsigned int pc_value __attribute__((unused)), ret = 1;
@@ -1075,15 +1053,17 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static void performance_counter_action(char *p __attribute__((unused))) {
-		char *p1  __attribute__((unused));
 #if defined(CONFIG_MIPS) && !defined(CONFIG_MIPS_UR8)
         unsigned int perf_reg_number = 0;
         int perf_reg_flags = 0;
         int perf_reg_index = 0;
         unsigned int i;
         unsigned int perf_max_registers;
+#if defined(CONFIG_CPU_MIPS_34K)
+		char *p1  __attribute__((unused));
         int perf_vpeid = -1;
         int perf_tcid = -1;
+#endif
         int new_perf_ctl = 0;
 
 #if defined(CONFIG_CPU_MIPS_34K)
@@ -1224,6 +1204,7 @@
         SKIP_NON_SPACE(p);
         SKIP_SPACE(p);
 
+#if defined(CONFIG_CPU_MIPS_34K)
         if((p1 = strstr(p, "examine_vpe="))){
 			unsigned int param;
             sscanf(p1, "examine_vpe=%x", &param);
@@ -1239,7 +1220,6 @@
             SKIP_NON_SPACE(p);
             SKIP_SPACE(p);
         }
-#if defined(CONFIG_CPU_MIPS_34K)
         if((p1 = strstr(p, "counting_tc_mask="))) {
 			unsigned int param;
             sscanf(p1 , "counting_tc_mask=%x", &param);
--- linux-2.6.32/drivers/char/avm_new/avm_sammel.c
+++ linux-2.6.32/drivers/char/avm_new/avm_sammel.c
@@ -107,10 +107,6 @@
             *p++ = ' ';
             *p   = '\0';
         }
-
-        if(strstr(AVM_NEW_HWREV_LIST, buff)) {
-            avm_event_enable_push_button = 1;
-        }
     }
 
     /*--------------------------------------------------------------------------------------*\
--- linux-2.6.32/drivers/char/avm_new/init_avm
+++ linux-2.6.32/drivers/char/avm_new/init_avm
@@ -25,20 +25,6 @@
     KERNEL_CLASS=26
 fi
 
-tmp=`grep 'BUTTON=y' $FRITZ_BOX_BUILD_DIR/arch/etc/init.d/rc.${KERNEL_LAYOUT}.init`
-
-AVM_NEW_HWREV_LIST=""
-for i in $tmp ; do
-    case $i in
-        HW=*)
-            HWREV=${i##HW=}
-            AVM_NEW_HWREV_LIST="$AVM_NEW_HWREV_LIST ${HWREV%%[a-zA-Z]*}"
-            ;;
-        *)
-            ;;
-    esac
-done
-
 for i in `find . -name Makefile.$KERNEL_CLASS` ; do
     dest=${i%.$KERNEL_CLASS}
     source="`pwd`/$i"
@@ -49,7 +35,6 @@
     echo -e "#############################################" >>$dest
     echo -e "" >>$dest
     cat  $source >> $dest
-    echo "EXTRA_CFLAGS	+= -DAVM_NEW_HWREV_LIST=\"\\\"$AVM_NEW_HWREV_LIST \\\"\"" >>$dest
 done
 
 ln -fs `pwd`/linux_avm_event.h ../../../include/linux/avm_event.h 
--- linux-2.6.32/drivers/char/avm_new/Makefile
+++ linux-2.6.32/drivers/char/avm_new/Makefile
@@ -1,6 +1,6 @@
 #############################################
 # Makefile: automaticly generated by ./init_avm
-#           Mi 17. Sep 11:27:25 CEST 2014
+#           Di 9. Feb 14:46:06 CET 2016
 #############################################
 
 #############################################
@@ -104,5 +104,3 @@
 
 EXTRA_CFLAGS	+= -Wall -Wextra
 # EXTRA_CFLAGS	+= -g -ggdb -save-temps
-EXTRA_CFLAGS	+= -DAVM_NEW_HWREV_LIST="\" 156 191 171 137 168 197 139 145 167 141 144 170 175 177 181 183 196 202 203 209 185 193 212 192 198 210 211 189 179 188 180 96 184 195 207 190 201 194 200 205 206 172 173 \""
-EXTRA_CFLAGS	+= -DAVM_NEW_HWREV_LIST="\" 156 191 171 137 168 197 139 145 167 141 144 170 175 177 181 183 196 202 203 209 185 193 212 192 198 210 211 189 179 188 180 96 184 195 207 190 201 194 200 205 206 214 172 173 \""
--- linux-2.6.32/drivers/char/avm_new/Makefile.26
+++ linux-2.6.32/drivers/char/avm_new/Makefile.26
@@ -99,4 +99,3 @@
 
 EXTRA_CFLAGS	+= -Wall -Wextra
 # EXTRA_CFLAGS	+= -g -ggdb -save-temps
-EXTRA_CFLAGS	+= -DAVM_NEW_HWREV_LIST="\" 156 191 171 137 168 197 139 145 167 141 144 170 175 177 181 183 196 202 203 209 185 193 212 192 198 210 211 189 179 188 180 96 184 195 207 190 201 194 200 205 206 172 173 \""
--- linux-2.6.32/drivers/char/avm_power/avm_power.h
+++ linux-2.6.32/drivers/char/avm_power/avm_power.h
@@ -80,6 +80,7 @@
     struct _power_managment_clients *next;
     char *client_name;
     int (*CallBackPowerManagmentControl)(int state);
+    atomic_t link;
 };
 
 /*--------------------------------------------------------------------------------*\
--- linux-2.6.32/drivers/char/avm_power/avm_power_if.c
+++ linux-2.6.32/drivers/char/avm_power/avm_power_if.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/avm_power.h>
+#include <linux/sched.h>
 #include "avm_power.h"
 #if defined(DECTSYNC_PATCH)
 #include "dectsync.h"
@@ -42,6 +43,8 @@
 #define DEB_TRC_PT(args...)
 #endif/*--- #else ---*//*--- #if defined(DEBUG_TRACE_POWERTAB) ---*/
 
+static DEFINE_SPINLOCK(gpw_client_lock);
+
 /*-------------------------------------------------------------------------------------*\
  * Liste von registrierten Treibern, die den PowermanagmentCallback-Befehl bekommen
 \*-------------------------------------------------------------------------------------*/
@@ -375,17 +378,38 @@
     }
     return NULL;
 }
+/*--------------------------------------------------------------------------------*\
+ * ret: 0 freigegeben 
+\*--------------------------------------------------------------------------------*/
+static inline int put_pwclient(struct _power_managment_clients *client) {
+	if(atomic_read(&client->link) == 0) {
+		printk(KERN_ERR"%s error link already zero\n", __func__);
+		return 0;
+	}
+	if (atomic_dec_and_test(&client->link)) {
+		/*--- printk(KERN_INFO"%s free\n", __func__); ---*/
+		kfree(client);
+		return 0;
+	}
+	return 1;
+}
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-struct _power_managment_clients *find_pwclient_by_name(char *client_name) {
-    struct _power_managment_clients *client = (struct _power_managment_clients *)PwClientAnker;
+struct _power_managment_clients *get_pwclient_by_name(char *client_name) {
+    struct _power_managment_clients *client;
+	unsigned long flags;
 
+	spin_lock_irqsave(&gpw_client_lock, flags);
+    client = (struct _power_managment_clients *)PwClientAnker;
     while(client) {
         if(strcmp(client_name, client->client_name) == 0) {
+			atomic_add(1, &client->link);
+			spin_unlock_irqrestore(&gpw_client_lock, flags);
             return client;
         }
         client = client->next;
     }
+	spin_unlock_irqrestore(&gpw_client_lock, flags);
     return NULL; 
 }
 /*-------------------------------------------------------------------------------------*\
@@ -398,22 +422,26 @@
     if(new == NULL) {
         return NULL;
     }
+	atomic_set(&new->link, 1);
     new->client_name = (char *)new + sizeof(struct _power_managment_clients);
     strcpy(new->client_name, client_name);
     new->CallBackPowerManagmentControl = CallBackPowerManagmentControl;
-    new->next = NULL;
-    flags = avm_power_lock();
+
+	spin_lock_irqsave(&gpw_client_lock, flags);
     new->next     = (struct _power_managment_clients *)PwClientAnker;
     PwClientAnker = new;
-    avm_power_unlock(flags);
+	spin_unlock_irqrestore(&gpw_client_lock, flags);
     return new; 
 }
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-static void del_pwclient(struct _power_managment_clients *delclient) {
+static int del_pwclient(struct _power_managment_clients *delclient) {
+	unsigned long flags;
     struct _power_managment_clients *prevclient = NULL; 
-    unsigned long flags = avm_power_lock();
-    struct _power_managment_clients *client = (struct _power_managment_clients *)PwClientAnker;
+    struct _power_managment_clients *client;
+
+	spin_lock_irqsave(&gpw_client_lock, flags);
+    client = (struct _power_managment_clients *)PwClientAnker;
     while(client) {
         if(client == delclient) {
             if(prevclient == NULL) {
@@ -422,14 +450,14 @@
             } else {
                 prevclient->next = client->next;
             }
-            avm_power_unlock(flags);
-            kfree(client);
-            return;
+			spin_unlock_irqrestore(&gpw_client_lock, flags);
+            return put_pwclient(client);
         }
         prevclient = client;
         client     = client->next;
     }
-    avm_power_unlock(flags);
+	spin_unlock_irqrestore(&gpw_client_lock, flags);
+	return 0;
 }
 /*-------------------------------------------------------------------------------------*\
  * Powermanagment des Treibers anmelden
@@ -439,13 +467,13 @@
 void *PowerManagmentRegister(char *client_name, int (*CallBackPowerManagmentControl)(int state)){
     struct _power_managment_clients *client;
     DEB_INFO("[avm_power] PowerManagmentRegister(\"%s\", 0x%p)\n", client_name, CallBackPowerManagmentControl);
-
     if(client_name == NULL || CallBackPowerManagmentControl == NULL) {
         DEB_ERR("[avm_power]PowerManagmentRegister: invalid param %p %p\n", client_name, CallBackPowerManagmentControl);
         return NULL;
     }
-    client = find_pwclient_by_name(client_name);
+    client = get_pwclient_by_name(client_name);
     if(client) {
+		put_pwclient(client);
         return client;
     }
     return add_pwclient(client_name, CallBackPowerManagmentControl);
@@ -456,11 +484,14 @@
 \*-------------------------------------------------------------------------------------*/
 void PowerManagmentRelease(void *Handle){
     struct _power_managment_clients *delclient = (struct _power_managment_clients *)Handle;
+    printk(KERN_ERR"[avm_power] PowerManagmentRelease(0x%p)\n", Handle);
     if(Handle == NULL) {
         DEB_ERR("[avm_power]%s: invalid Handle\n", __func__);
         return;
     }
-    del_pwclient(delclient);
+    if(del_pwclient(delclient)) {
+		schedule_timeout(HZ/10); /*--- er scheint noch in CallBackPowerManagmentControl zu haengen: hier warten ! ---*/
+	}
 }
 EXPORT_SYMBOL(PowerManagmentRelease);
 
@@ -509,7 +540,7 @@
         return 1;
     }
     while(powermodetab[i].client_name) {
-        registered_client = find_pwclient_by_name(powermodetab[i].client_name);
+        registered_client = get_pwclient_by_name(powermodetab[i].client_name);
         if(registered_client == NULL) {
             if(powermodetab[i].mandatory & AVM_PM_CB_UNINSTALLED_OR_FAILED) {
                 DEB_TRC_PT("[avm_power] '%s' not registered can't execute powermanagment ->stop\n", powermodetab[i].client_name);
@@ -519,6 +550,7 @@
             }
         } else {
             if((async_context == 0) && (powermodetab[i].mandatory & AVM_PM_ASYNC)) {
+				put_pwclient(registered_client);
                 return powermode_action_async(&powermodetab[i]);
             }
             if((powermodetab[i].mandatory & AVM_PM_LOCK) && (locked == 0)) {
@@ -535,6 +567,7 @@
             } else {
                 /*--- DEB_TRC_PT("[avm_power] '%s'=0x%x powermanagment ok\n", powermodetab[i].client_name, powermodetab[i].state); ---*/
             }
+			put_pwclient(registered_client);
         }
         if(ret) {
             break;
@@ -553,14 +586,14 @@
 \*--------------------------------------------------------------------------------*/
 int powermode_action_nolist(char *client_name, int State) {
     struct _power_managment_clients *registered_client;
-    registered_client = find_pwclient_by_name(client_name);
+	int ret;
+    registered_client = get_pwclient_by_name(client_name);
     if(registered_client == NULL) {
         return 2;
     }
-    if(registered_client->CallBackPowerManagmentControl(State)) {
-        return 1;
-    }
-    return 0;
+    ret = registered_client->CallBackPowerManagmentControl(State);
+	put_pwclient(registered_client);
+    return ret ? 1 : 0;
 }
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
--- linux-2.6.32/drivers/char/Kconfig
+++ linux-2.6.32/drivers/char/Kconfig
@@ -1369,6 +1369,13 @@
 	help
         only 4 or 8 ms supported
 
+config UBIK2_ISDNSTACK_ON_CPU
+	int "interrupt on cpuX"
+	depends on UBIK2 && SMP
+	default 1
+	help
+	  ISDN-Stack have to bind on fixed cpu
+
 source "drivers/s390/char/Kconfig"
 
 source "drivers/char/Kconfig.ifx"
--- linux-2.6.32/drivers/char/tffs-2.0/tffs_panic.c
+++ linux-2.6.32/drivers/char/tffs-2.0/tffs_panic.c
@@ -43,6 +43,9 @@
 #include <linux/seq_file.h>
 #endif /*--- #if defined(CONFIG_PROC_FS) ---*/
 #include "tffs_local.h"
+#if defined(CONFIG_AVM_WATCHDOG)
+#include <linux/ar7wdt.h>
+#endif/*--- #if defined(CONFIG_AVM_WATCHDOG) ---*/
 
 #define ARRAY_EL(a) (sizeof(a) / sizeof(a[0]))
 
@@ -52,6 +55,8 @@
 #endif/*--- #if defined(CONFIG_MACH_AR934x) ---*/
 
 unsigned int tffs_spi_mode = 0;
+unsigned int tffs_panic_log_suppress = 0;
+EXPORT_SYMBOL(tffs_panic_log_suppress);
 
 #if !defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE)
 static struct file tffs_panic_file;
@@ -61,7 +66,7 @@
 /*--------------------------------------------------------------------------------*\
  * Schreiben im Panic-Kontext
 \*--------------------------------------------------------------------------------*/
-void tffs_panic_log_open(void) {
+static void tffs_panic_log_open(void) {
     int ret __attribute__((unused));
     if(tffs_panic_open_flag == 1)
         return;
@@ -73,20 +78,21 @@
     tffs_panic_inode.i_rdev = MKDEV(0, FLASH_FS_ID_PANIC_LOG);   /*--- major muss 0 sein fuer Kernel Mode ---*/
 
     ret = tffs_open(&tffs_panic_inode, &tffs_panic_file);
-    if(ret)
+    if(ret) {
         return;
+	}
 #endif/*--- #if !defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE) ---*/
     tffs_panic_open_flag = 1;
 }
 /*--------------------------------------------------------------------------------*\
  * Schreiben im Panic-Kontext
 \*--------------------------------------------------------------------------------*/
-void tffs_panic_log_write(char *buffer, unsigned int len) {
+static void tffs_panic_log_write(char *buffer, unsigned int len) {
     static loff_t off __attribute__((unused));
     if(tffs_panic_open_flag == 0)
         return;
 #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE)
-    avm_event_send_log(remote_panic, 1, buffer, len);
+    avm_event_send_log(remote_panic, FLAG_REMOTELOG_APPEND, buffer, len);
 #else /*--- #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE) ---*/
     tffs_write(&tffs_panic_file, buffer, len, &off);
 #endif/*--- #else  ---*//*--- #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE) ---*/
@@ -94,10 +100,11 @@
 /*--------------------------------------------------------------------------------*\
  * Schreiben im Panic-Kontext
 \*--------------------------------------------------------------------------------*/
-void tffs_panic_log_close(void) {
+static void tffs_panic_log_close(void) {
     if(tffs_panic_open_flag == 0)
         return;
 #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE)
+    avm_event_send_log(remote_panic, FLAG_REMOTELOG_APPEND_FINISHED | FLAG_REMOTELOG_REBOOT, NULL, 0);
     printk("%s wait on reboot from host-cpu\n", __func__);
     for(;;) ;   /*--- ... der arm soll booten - ansonsten auf Watchdog warten ---*/
 #else/*--- #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE) ---*/
@@ -106,6 +113,78 @@
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
+static unsigned int get_act_time(void) {
+    struct timeval now;
+    do_gettimeofday(&now);
+    return (unsigned int)(now.tv_sec);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static char *time_to_ascii(unsigned long local_time, char *buf, int len, char *prefix) {
+    static char *month[] = { "Jan",  "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+    static char *day[]   = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+    struct rtc_time tm;
+    rtc_time_to_tm(local_time, &tm);
+    snprintf(buf, len, "%s %s %02d %02d:%02d:%02d %02d UTC %s", day[tm.tm_wday],  month[tm.tm_mon], tm.tm_mday, 
+                                                  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900,
+                                                  prefix
+                                                  );
+    return buf;
+}
+/*--------------------------------------------------------------------------------*\
+ * maxsize of buf: 14 + 10 + 2 + 2 + 2  = 30
+\*--------------------------------------------------------------------------------*/
+static char *human_readable_time(char *buf, unsigned long buf_size, unsigned long time) {
+	unsigned long seconds, minutes, hours, days;
+
+	seconds = time % 60; time /= 60;
+	minutes = time % 60; time /= 60; 
+	hours	= time % 24; time /= 24;
+	days	= time;
+	snprintf(buf, buf_size, "%lu d %lu h %lu min %lu s", days, hours, minutes, seconds);
+    return buf;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+void tffs_panic_log_printkbuf(void) {
+    if(tffs_panic_log_suppress == 0) {
+        unsigned long printk_get_buffer(char **p_log_buf, unsigned long *p_log_end, unsigned long *p_anzahl);
+        char *buf;
+        unsigned long end;
+        unsigned long anzahl;
+        unsigned long len = printk_get_buffer(&buf, &end, &anzahl);
+        struct timespec uptime;
+		char htime[32], huptime[128];
+        char time_stamp_buf[sizeof("UPTIME: \n") + sizeof(htime) + sizeof(huptime) + 10 + sizeof("\n( - panic on )\nPANIC LOG VERSION 2.0\n")];
+        unsigned long time_stamp_buf_len;
+
+        tffs_panic_log_suppress = 1;
+        tffs_panic_log_open();
+        do_posix_clock_monotonic_gettime(&uptime);
+        monotonic_to_bootbased(&uptime);
+        time_stamp_buf_len = snprintf(time_stamp_buf, sizeof(time_stamp_buf), "UPTIME: %lu\n(%s - panic on %s)\nPANIC LOG VERSION 2.0\n",  
+																			(unsigned long)uptime.tv_sec, 
+																			human_readable_time(huptime, sizeof(huptime), (unsigned long)uptime.tv_sec),
+																			time_to_ascii((unsigned long)get_act_time(), htime, sizeof(htime), "")
+																			);
+        tffs_panic_log_write(time_stamp_buf, time_stamp_buf_len);
+#if defined(CONFIG_AVM_WATCHDOG)
+        AVM_WATCHDOG_emergency_retrigger();
+#endif
+        if(anzahl < len) {  /*--- alles im Buffer ---*/
+            tffs_panic_log_write(buf, anzahl);
+        } else {
+            tffs_panic_log_write(buf + end, len - end);
+#if defined(CONFIG_AVM_WATCHDOG)
+            AVM_WATCHDOG_emergency_retrigger();
+#endif
+            tffs_panic_log_write(buf, end);
+        }
+        tffs_panic_log_close();
+    }
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
 void tffs_panic_log_register_spi(void) {
     tffs_spi_mode = 1;
 }
@@ -115,8 +194,12 @@
 static unsigned int calc_sum_and_correct(unsigned char *buf, int buf_len, int correct) {
     unsigned int i, sum = 0;
     for(i = 0; i < buf_len; i++) {
-        if(correct && (buf[i] == 0)) buf[i] = ' ';   /*--- correct buffer (support null-teminated string) ---*/
-        sum += buf[i];
+		unsigned int val = buf[i];
+		if(val == 0) {
+			val = ' ';
+			if(correct) buf[i] = val;   /*--- correct buffer (support null-teminated string) ---*/
+    }
+        sum += val; 
     }
     return sum ^ (buf_len << 16);
 }
@@ -140,7 +223,7 @@
 
     ret = tffs_open(&tffs_inode, &tffs_file);
     if(ret) {
-        printk(KERN_ERR"%s tffs_open failed ret=%d\n", __func__, ret);
+        /*--- printk(KERN_ERR"%s tffs_open failed ret=%d\n", __func__, ret); ---*/
         return;
     }
     open_data = (struct _tffs_open *)tffs_file.private_data;
@@ -181,7 +264,7 @@
 #endif
             cs = calc_sum_and_correct(logbufuncached, event.loglen, 0);
             if(cs != event.checksum) {
-                printk(KERN_ERR"%s: obscure checksum %x != %x -> ignore\n", __func__, event.checksum, cs);
+                printk(KERN_ERR"%s: type=%d obscure checksum %x != %x -> ignore\n", __func__, event.logtype, event.checksum, cs);
                 iounmap(logbufuncached);
                 return;
             }
@@ -204,12 +287,18 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static void remote_log_register_sink(void *private __attribute__((unused)), unsigned int param1 __attribute__((unused)), unsigned int param2 __attribute__((unused))){ 
+#if AVM_DIST_EVENT_VERSION > 0x10000
+	struct _avm_event_id_mask id_mask;
+#endif
     if(remote_log_event_sink_handle) {
         return;
     }
     remote_log_event_sink_handle = avm_event_sink_register("log_remote_sink",
-                                                          (1ULL << avm_event_id_log) |
-                                                           0,
+#if AVM_DIST_EVENT_VERSION > 0x10000
+   													       avm_event_build_id_mask(&id_mask, 1, avm_event_id_log),
+#else
+						                                   1ULL << avm_event_id_log,
+#endif
                                                            remote_log_sink,
                                                            NULL
                                                           );
@@ -239,6 +328,7 @@
     }
     return MAX_LOG_IDS;
 }
+static unsigned int log_read_multiple[MAX_LOG_IDS];
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static int tffs_panic_log_read(unsigned char *buf, int buf_len, unsigned int id) {
@@ -267,24 +357,6 @@
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
-static char *time_to_ascii(char *buf, int len, char *prefix) {
-    static char *month[] = { "Jan",  "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-    static char *day[]   = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-    struct rtc_time tm;
-    struct timeval now;
-    unsigned int local_time;
-    do_gettimeofday(&now);
-    /*--- local_time = (u32)(now.tv_sec - (sys_tz.tz_minuteswest * 60)); ---*//*---  tz_minuteswest == 0 ?  ---*/
-    local_time = (u32)(now.tv_sec);
-    rtc_time_to_tm(local_time, &tm);
-    snprintf(buf, len, "%s %s %02d %02d:%02d:%02d %d UTC %s", day[tm.tm_wday],  month[tm.tm_mon], tm.tm_mday, 
-                                                  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900,
-                                                  prefix
-                                                  );
-    return buf;
-}
-/*--------------------------------------------------------------------------------*\
-\*--------------------------------------------------------------------------------*/
 static int paniclog_show(struct seq_file *seq, void *data __attribute__((unused))) {
 
     /*--- printk(KERN_INFO"%s %p %p\n", __func__, seq->private, data); ---*/
@@ -294,54 +366,65 @@
     return 0;
 }
 /*--------------------------------------------------------------------------------*\
- * return: Pointer auf Zeitstempel, gefuelltes checksum, read_once
- *
- * 2 Formate werden unterstuezt:
- * alt: panic_cs, panic_sram_cs, read_once_cr, time
- * neu: [id]cs,[id2]cs,.., read_once_cr; time
 \*--------------------------------------------------------------------------------*/
-const char *parse_crash_env(const char *crashp, unsigned int checksum[], unsigned int *read_once) {
-    memset(checksum, 0, MAX_LOG_IDS * sizeof(unsigned int));
-    *read_once =  0;
-    if(*crashp == 0) {
-        return crashp;
+struct _time_checksum {
+	unsigned int cs;
+	unsigned int ts;		/* timestamp on read */
+#define READ_BY_CR			0x1
+#define READ_BY_SD			0x2
+#define FIRST_READ_BY_SD	0x4		/* first read by SD */
+	unsigned int readmask;
+};
+#define SKIP_UNTIL_CHAR(p, sign) while(*p && (*p != sign)) p++
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline unsigned COUNT_UNTIL_CHAR(const char *p, unsigned char sign, unsigned char count_sign) {
+	unsigned int count = 0;
+	while(*p && (*p != sign)) {
+		if(*p == count_sign) {
+			count++;
     }
-    if(*crashp != '[') {
-        /*--- altes Format: ---*/
-        sscanf(crashp, "0x%x,0x%x,0x%x;", &checksum[0], &checksum[1], read_once);
-        while(*crashp && (*crashp != ';')) crashp++;        
-        if(*crashp == ';') crashp++;
-        return crashp;
+		p++;
     }
+	return count;
+}
+/*--------------------------------------------------------------------------------*\
+ * return: gefuelltes checksum
+ * [id]cs,ts,readmask,[id2]cs,ts,readmask
+\*--------------------------------------------------------------------------------*/
+void parse_crash_env(const char *crashp, struct _time_checksum checksum[]) {
+    memset(checksum, 0, MAX_LOG_IDS * sizeof(struct _time_checksum));
     while(*crashp) {
-        unsigned int id, val;
+        unsigned int id, val, val1, val2;
         if(*crashp == '[') {
-            sscanf(++crashp,"%x]%x,", &id,&val);
+            sscanf(++crashp,"%x]%x,%x,%x", &id, &val, &val1, &val2);
             if(id < MAX_LOG_IDS) {
-                checksum[id] = val;
+				unsigned int count = COUNT_UNTIL_CHAR(crashp, '[', ',');
+                checksum[id].cs		  = val;
+				checksum[id].ts	      = val1;
+				if(count >= 1) {
+					checksum[id].ts	      = val1;
             }
-            while(*crashp && (*crashp != ',')) crashp++;        
-            if(*crashp == ',') crashp++;
+				if(count >= 2) {
+					checksum[id].readmask = val2;
+				}
+            }
+			SKIP_UNTIL_CHAR(crashp, '[');
         } else {
-            sscanf(crashp,"%x,", read_once);
-            while(*crashp && (*crashp != ';')) crashp++;        
-            if(*crashp == ';') crashp++;
-            return crashp;
+            return;
         }
     }
-    return crashp;
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
-static void set_crash_env(char *crashp, int len, unsigned int checksum[], unsigned int read_once, const char *timestart) {
+static void set_crash_env(char *crashp, int len, struct _time_checksum checksum[]) {
     unsigned int written, i;
     for(i = 0; i < MAX_LOG_IDS; i++) {
         if(len > 0) {
-            written = snprintf(crashp, len, "[%x]%x,", i, checksum[i]);
+            written = snprintf(crashp, len, "[%x]%x,%x,%x", i, checksum[i].cs, checksum[i].ts, checksum[i].readmask);
             len -= written, crashp += written;
         }
     }
-    if(len > 0) snprintf(crashp, len, "%x;%s\n", read_once, timestart);
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
@@ -351,17 +434,25 @@
     const char *timestart = "";
     int buf_len = (0x1 << 17) - 64; /*--- ReserveTimestamp ---*/
     int len = buf_len;
-    unsigned int tffs_once_cr = 0;
-    unsigned int saved_checksum[MAX_LOG_IDS];
+    struct _time_checksum saved_checksum[MAX_LOG_IDS];
+	unsigned int new_read_mask = 0;
     unsigned int map_idx = map_log_id_to_index(id);
     char *buf;
 
-    memset(saved_checksum, 0, MAX_LOG_IDS);
     /*--- printk(KERN_ERR"%s: id=%d map_idx=%x %s\n", __func__, id, map_idx, crashreport ? "cr" : "sd"); ---*/
     if(map_idx >= MAX_LOG_IDS) {
         /*--- printk("%s: error: id=%d too big\n", __func__, map_idx); ---*/
         return -ENODATA;
     }
+    /*--- printk(KERN_ERR"%s: id=%d map_idx=%x %s f:_flags=%x\n", __func__, id, map_idx, crashreport ? "cr" : "sd", file->f_flags); ---*/
+    if(file->f_flags & O_WRONLY) {
+		unsigned int mapvalue;
+	    mapvalue  = crashreport ? READ_BY_CR : READ_BY_SD;
+		mapvalue |= map_idx << 8;
+		file->private_data = (void *)mapvalue;
+		return 0;
+	}
+    memset(saved_checksum, 0, sizeof(saved_checksum));
 	buf = kmalloc(len, GFP_KERNEL);
     if(buf == NULL) {
 		return -ENOMEM;
@@ -369,53 +460,60 @@
     len = sizeof(crashenv);
     crashenv[0] = 0;
     if(TFFS_Read(NULL, FLASH_FS_CRASH, crashenv, &len) == 0) {
-        timestart = parse_crash_env(crashenv, &saved_checksum[0], &tffs_once_cr);
-        strncpy(timebuf, timestart, sizeof(timebuf) - 1);
-        timestart = timebuf;
-        /*--- printk(KERN_ERR"%s: cs[]=%x %x %x %x readonce=%x\n(%s)", __func__, saved_checksum[0], saved_checksum[1], saved_checksum[2], saved_checksum[3], tffs_once_cr, crashenv); ---*/
+        parse_crash_env(crashenv, &saved_checksum[0]);
     }
     buf[0] = 0;
     if((len = tffs_panic_log_read(buf, buf_len, id)) > 0) {
         unsigned int new_sum = calc_sum_and_correct(buf, len, 1);
         /*--- printk(KERN_INFO"%s: sum=%x len=%d\n", __func__, new_sum, len); ---*/
-        if(new_sum != saved_checksum[map_idx]) {
-            /*--- new panic-log: clear counter ---*/
-            tffs_once_cr &= ~(1 << map_idx);
-            timestart = time_to_ascii(timebuf, sizeof(timebuf), crashreport ? "by crash report" : "by support data");
-            saved_checksum[map_idx] = new_sum;
+        if(new_sum != saved_checksum[map_idx].cs) {
+            /*--- new panic-log: set struct ---*/
+			new_read_mask					 = crashreport ? READ_BY_CR : (READ_BY_SD | FIRST_READ_BY_SD);
+			saved_checksum[map_idx].readmask = 0;
+			saved_checksum[map_idx].ts		 = get_act_time();
+            saved_checksum[map_idx].cs		 = new_sum;
+        } else {
+			new_read_mask					 = crashreport ? READ_BY_CR : READ_BY_SD;
         }
     } else {
         len = 0;
     }
-#if defined(CONFIG_MACH_AR934x)
+#if defined(CONFIG_MACH_AR934x) || defined(CONFIG_MACH_QCA953x)
     if(id == FLASH_FS_ID_PANIC_LOG) {
         unsigned int sram_len = ath_restore_log_from_ram(buf, buf_len);
         if(sram_len) {
             unsigned int new_sram_sum;
-            if(crashreport) tffs_once_cr |= (1 << map_idx); /*--- mark flashfile as readed ... ---*/
             map_idx = 1;
             /*--- ... and prefer sram-log---*/
             len = sram_len;
             new_sram_sum = calc_sum_and_correct(buf, len, 1);
             /*--- printk(KERN_INFO"%s: prefer sram-trace len=%d", __func__, sram_len); ---*/
-            if(new_sram_sum != saved_checksum[map_idx]) {
+            if(new_sram_sum != saved_checksum[map_idx].cs) {
                 struct timeval now;
                 /*--- new sram-panic-log: clear counter ---*/
-                tffs_once_cr &= ~(1 << map_idx);
-                timestart = time_to_ascii(timebuf, sizeof(timebuf), crashreport ? "by crash report" : "by support data");
-                saved_checksum[map_idx] = new_sram_sum;
+				new_read_mask					 = crashreport ? READ_BY_CR : (READ_BY_SD | FIRST_READ_BY_SD);
+				saved_checksum[map_idx].readmask = 0;
+				saved_checksum[map_idx].ts		 = get_act_time();
+                saved_checksum[map_idx].cs		 = new_sram_sum;
+            } else {
+				new_read_mask					 = crashreport ? READ_BY_CR : READ_BY_SD;
             }
         }
     }
 #endif/*--- #if defined(CONFIG_MACH_AR934x) ---*/
-    if((len == 0) || (crashreport && (tffs_once_cr & (1 << map_idx)))) {
+    if((len == 0) || (((saved_checksum[map_idx].readmask & new_read_mask) == new_read_mask) &&
+					  !((log_read_multiple[map_idx] & new_read_mask) == new_read_mask)
+				)) {
         /*--- check if sent ---*/
         kfree(buf);
         return -ENODATA;
     }
-    if(crashreport) tffs_once_cr |= (1 << map_idx);
+	saved_checksum[map_idx].readmask |= new_read_mask;
+	if(saved_checksum[map_idx].ts){
+		timestart = time_to_ascii(saved_checksum[map_idx].ts, timebuf, sizeof(timebuf), (saved_checksum[map_idx].readmask & FIRST_READ_BY_SD) ? "by support data" : "by crash report");
+	}
     sprintf(&buf[len], "-----\n(first) sent on: %s\n", timestart);
-    set_crash_env(crashenv, sizeof(crashenv), saved_checksum, tffs_once_cr, timestart);
+    set_crash_env(crashenv, sizeof(crashenv), saved_checksum);
     TFFS_Write(NULL, FLASH_FS_CRASH, crashenv, strlen(crashenv) + 1, 0);
 
     return single_open(file, paniclog_show, buf);
@@ -440,27 +538,70 @@
 
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
+static ssize_t log_proc_write(struct file *file, const char *buffer, size_t count, loff_t *offset __maybe_unused) {
+    unsigned char procfs_buffer[64];
+    size_t procfs_buffer_size;
+	unsigned int id, report;
+
+	/*--- von wo kommen wir: ---*/
+	id	   = ((unsigned int) file->private_data) >> 8;
+	report = ((unsigned int)file->private_data)  & 0xFF;
+	if(id >= MAX_LOG_IDS) {
+		return count;
+	}
+    if (count >= sizeof(procfs_buffer)) {
+       procfs_buffer_size = sizeof(procfs_buffer) - 1;
+    } else {
+       procfs_buffer_size = count;
+    }
+    /* write data to the buffer */
+    if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size - 1) ) {
+        return -EFAULT;
+    }
+    procfs_buffer[procfs_buffer_size] = 0;
+	if(strstr(procfs_buffer, "readmultiple")) {
+		log_read_multiple[id] |= report;
+	} else if(strstr(procfs_buffer, "readonce")) {
+		log_read_multiple[id] &= ~report;
+	} else {
+		printk(KERN_INFO"unknown option: use readmultiple or readonce\n");
+	}
+	/*--- 	printk(KERN_INFO"%s: '%s' %p log_read_multiple[%d]=%x (report=%x)\n", __func__, procfs_buffer, file->private_data, id, log_read_multiple[id], report); ---*/
+    return count;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static int log_proc_release(struct inode *inode, struct file *file) {
+    if(!(file->f_flags & O_WRONLY)) {
+		/*--- printk(KERN_INFO"%s: free after read\n", __func__); ---*/
+		return seq_release_private(inode, file); /*---  gibt txtbuf frei ----*/
+	}
+	/*--- 	printk(KERN_INFO"%s no free\n", __func__); ---*/
+	return 0;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
 static struct _logproc {
     const char *dir;
     const char *name;
     struct file_operations fops;
     struct proc_dir_entry *dir_entry;
 } logproc[] = {
-    { dir: "avm/log_cr", name: "panic",  fops: {open: paniclog_open_cr,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
-    { dir: "avm/log_cr", name: "crash",  fops: {open: crashlog_open_cr,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
+    { dir: "avm/log_cr", name: "panic",  fops: {open: paniclog_open_cr, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
+    { dir: "avm/log_cr", name: "crash",  fops: {open: crashlog_open_cr, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
 #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SINK)
-    { dir: "avm/log_cr", name: "panic2", fops: {open: panic2log_open_cr, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}},
-    { dir: "avm/log_cr", name: "crash2", fops: {open: crash2log_open_cr, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
+    { dir: "avm/log_cr", name: "panic2", fops: {open: panic2log_open_cr,write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }},
+    { dir: "avm/log_cr", name: "crash2", fops: {open: crash2log_open_cr,write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
 #endif/*--- #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SINK) ---*/
-    { dir: "avm/log_sd", name: "panic",  fops: {open: paniclog_open_sd,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
-    { dir: "avm/log_sd", name: "crash",  fops: {open: crashlog_open_sd,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
+    { dir: "avm/log_sd", name: "panic",  fops: {open: paniclog_open_sd, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
+    { dir: "avm/log_sd", name: "crash",  fops: {open: crashlog_open_sd, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
 #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SINK)
-    { dir: "avm/log_sd", name: "panic2", fops: {open: panic2log_open_sd, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
-    { dir: "avm/log_sd", name: "crash2", fops: {open: crash2log_open_sd, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}},
+    { dir: "avm/log_sd", name: "panic2", fops: {open: panic2log_open_sd, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }}, 
+    { dir: "avm/log_sd", name: "crash2", fops: {open: crash2log_open_sd, write: log_proc_write, read: seq_read, llseek: seq_lseek, release: log_proc_release }},
 #endif/*--- #if defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SINK) ---*/
     /*--- compatible to the "old" solution: ---*/
-    { dir: NULL, name: "avm_panic_cr",  fops: {open: paniclog_open_cr,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
-    { dir: NULL, name: "avm_panic_sd",  fops: {open: paniclog_open_sd,  read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
+    { dir: NULL, name: "avm_panic_cr",  fops: {open: paniclog_open_cr,  write: log_proc_write, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
+    { dir: NULL, name: "avm_panic_sd",  fops: {open: paniclog_open_sd,  write: log_proc_write, read: seq_read, llseek: seq_lseek, release: seq_release_private /*--- gibt txtbuf frei ---*/}}, 
 };
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
@@ -480,12 +621,12 @@
         }
 #if !defined(CRASHPANIC_LOG_PER_REMOTE_EVENT_SOURCE)
         if(logproc[i].dir == NULL) {
-            if(!proc_create(logproc[i].name, 0444, NULL, &logproc[i].fops)) {
+            if(!proc_create(logproc[i].name, 0666, NULL, &logproc[i].fops)) {
                 printk(KERN_ERR"%s can't proc_create(%s)\n", __func__, logproc[i].name);
             }
         } else if(dir_entry) {
             logproc[i].dir_entry = dir_entry;
-            if(!proc_create(logproc[i].name, 0444, dir_entry, &logproc[i].fops)) {
+            if(!proc_create(logproc[i].name, 0666, dir_entry, &logproc[i].fops)) {
                 printk(KERN_ERR"%s can't proc_create(%s)\n", __func__, logproc[i].name);
             }
         }
--- linux-2.6.32/drivers/net/avm_cpmac/common/supportdata.avmnet
+++ linux-2.6.32/drivers/net/avm_cpmac/common/supportdata.avmnet
@@ -19,6 +19,11 @@
 
 if [ -e /proc/eth/mib ] ; then  cat /proc/eth/mib ; fi
 
+if [ -e /proc/eth/htu ] ; then  
+    echo "IFX HTU DUMP:"
+    cat /proc/eth/htu ; 
+fi
+
 if [ -e /proc/driver/avmnet/swi_*/ppe_sessions ] ; then  
     echo "IFX PPA HW Sessions:"
     cat /proc/driver/avmnet/swi_*/ppe_sessions
--- linux-2.6.32/drivers/net/avm_cpmac/phy/phy_wasp.c
+++ linux-2.6.32/drivers/net/avm_cpmac/phy/phy_wasp.c
@@ -334,6 +334,10 @@
 }
 EXPORT_SYMBOL(cpmac_magpie_mdio_read);
 
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+void (*cpmac_magpie_reset_cb_hook)(void);
+EXPORT_SYMBOL(cpmac_magpie_reset_cb_hook);
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 void cpmac_magpie_reset(enum avm_cpmac_magpie_reset value)
@@ -394,8 +398,12 @@
         }else{
             ifx_gpio_output_clear(reset_pin, IFX_GPIO_MODULE_WLAN_OFFLOAD_WASP_RESET);
         }
-
-        msleep(500);
+		if(cpmac_magpie_reset_cb_hook) {
+			msleep(10);
+			cpmac_magpie_reset_cb_hook();
+		} else {
+			msleep(500);
+		}
         wasp_in_reset = 0;
     }
 
--- linux-2.6.32/drivers/net/avm_cpmac/phy/phy_wasp.h
+++ linux-2.6.32/drivers/net/avm_cpmac/phy/phy_wasp.h
@@ -33,6 +33,7 @@
 void cpmac_magpie_reset(enum avm_cpmac_magpie_reset value);
 unsigned int cpmac_magpie_mdio_read(unsigned short regadr, unsigned short phyadr);
 void cpmac_magpie_mdio_write(unsigned short regadr, unsigned short phyadr, unsigned short data);
+extern void (*cpmac_magpie_reset_cb_hook)(void); /*--- wird aufgerufen, 10 ms nachdem die WLan-CPU aus dem Reset geholt wurde ---*/
 
 typedef struct _phy_wasp_heartbeat_work
 {
--- linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/7port/swi_7port.c
+++ linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/7port/swi_7port.c
@@ -1804,6 +1804,15 @@
             }
 
             mac_nr = egress_hw->mac_nr;
+	    
+	    if (ingress_hw->flags & AVMNET_DEVICE_IFXPPA_VIRT_RX ){
+		    if ( speed_on_mac_nr( mac_nr ) == 2 ){
+			    AVMNET_INFO( "[%s] do acc VIRT_RX -> 1000mbit lan/ata (dstmac =%d) \n", __FUNCTION__ , mac_nr );
+		    } else {
+			    AVMNET_INFO( "[%s] no acc for VIRT_RX -> 100/10mbit lan/ata (dstmac =%d) \n", __FUNCTION__ , mac_nr );
+			    continue;
+		    }
+	    }
 
             AVMNET_INFO("[%s] Egress MAC: %d\n", __func__, mac_nr);
             AVMNET_INFO("[%s] Adding new egress device for pid handle %d on port %d\n",
--- linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/ifx_ppa_mini_sessions.c
+++ linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/ifx_ppa_mini_sessions.c
@@ -913,6 +913,17 @@
 		}
 		p_item->dslwan_qid = ifx_ppa_drv_avm_get_eth_qid( egress_hw->mac_nr, priority );
 
+		// we need to disable acceleration for (PCIE-WLAN -> ETHERNET), if
+		// port is not running in GE Mode, otherwise we might drop burtsy wlan traffic
+		// in our switch
+		if ( ingress_hw->flags & AVMNET_DEVICE_IFXPPA_VIRT_RX ){
+			if ( speed_on_mac_nr( egress_hw->mac_nr ) == 2 ){
+				session_debug(DBG_ENABLE_MASK_ADD_SESSION, "[%s] do acc VIRT_RX -> 1000mbit lan/ata (dstmac =%d) \n", __FUNCTION__ , egress_hw->mac_nr );
+			} else {
+				session_debug(DBG_ENABLE_MASK_ADD_SESSION, "[%s] no acc for VIRT_RX -> 100/10mbit lan/ata (dstmac =%d) \n", __FUNCTION__ , egress_hw->mac_nr );
+				goto ERR_FREE_PITEM;
+			}
+		}
 		session_debug(DBG_ENABLE_MASK_ADD_SESSION, "[%s] xxx -> lan/ata (dstmac =%d) qid=%d \n", __FUNCTION__ , egress_hw->mac_nr, p_item->dslwan_qid );
 	}
 
--- linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/swi_ifx_common.c
+++ linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/swi_ifx_common.c
@@ -363,6 +363,24 @@
 \*------------------------------------------------------------------------------------------*/
 
 /*
+ * returns: 
+ *	0-10MBit 
+ *	1-100MBit 
+ *	2-1GBit 
+ *	3-undefined ---
+ */
+unsigned int speed_on_mac_nr( int mac_nr ){
+	avmnet_device_t *avm_dev = mac_nr_to_avm_dev(mac_nr);
+	if (! avm_dev )
+		return 3;
+	return avm_dev->status.Details.speed;
+}
+EXPORT_SYMBOL(speed_on_mac_nr);
+
+/*------------------------------------------------------------------------------------------*\
+\*------------------------------------------------------------------------------------------*/
+
+/*
  * setup wan dev by name in AVM_PA flags, and remove wan_port from multicast returns mac_wan_mask
  */
 int avmnet_swi_ifx_common_set_ethwan_dev_by_name( const char *devname ) {
--- linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/swi_ifx_common.h
+++ linux-2.6.32/drivers/net/avm_cpmac/switch/ifx/common/swi_ifx_common.h
@@ -269,6 +269,7 @@
 
 int avm_dev_to_mac_nr(avmnet_device_t *avm_dev);
 avmnet_device_t *mac_nr_to_avm_dev(int mac_nr);
+unsigned int speed_on_mac_nr( int mac_nr );
 
 /*------------------------------------------------------------------------------------------*\
  * some static functions for all datapath drivers...
--- linux-2.6.32/drivers/serial/serial_avm_asc.c
+++ linux-2.6.32/drivers/serial/serial_avm_asc.c
@@ -15,6 +15,7 @@
 #define WORKAROUND_ACK_TIR_ON_ENTRY
 #define WORKAROUND_ACK_RIR_ON_ENTRY
 #define WORKAROUND_GEN_MISSING_ENABLE_TX_IRQ
+#define WORKAROUND_GEN_MISSING_TX_IRQ
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/addrspace.h>
@@ -45,18 +46,12 @@
 	struct ifx_asc_port_priv *priv = (struct ifx_asc_port_priv *)port_priv_data->port_specificdata;
     ifx_asc_reg_t *asc_reg = priv->base;
 
-	unsigned int fifocnt;
-	fifocnt = (asc_reg->asc_fstat & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
-	if (( fifocnt == 0 ) && !(asc_reg->asc_irnicr & IFX_ASC_IRQ_LINE_TIR) ){
-#if defined(WORKAROUND_GEN_MISSING_ENABLE_TX_IRQ)
-        asc_reg->asc_irnicr |= IFX_ASC_IRQ_LINE_TIR;
-#endif
-        tx_bugfix_count_enable ++;
-	}
+	unsigned int fifofree;
+	fifofree = (asc_reg->asc_fstat & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
 
     asc_reg->asc_irnen |= IFX_ASC_IRQ_LINE_TIR;
 
-	if (( fifocnt == 0 ) && !(asc_reg->asc_irnicr & IFX_ASC_IRQ_LINE_TIR) ){
+	if ( fifofree && !(asc_reg->asc_irnicr & IFX_ASC_IRQ_LINE_TIR) ){
 #if defined(WORKAROUND_GEN_MISSING_ENABLE_TX_IRQ)
         asc_reg->asc_irnicr |= IFX_ASC_IRQ_LINE_TIR;
 #endif
@@ -257,7 +252,7 @@
 
 	if (uart_circ_empty(xmit)) {
 		uart_avm_stop_tx(port);
-    } else if ((( asc_reg->asc_fstat & ASCFSTAT_TXFREEMASK ) >> ASCFSTAT_TXFREEOFF ) == 0 ) {
+    } else if ((( asc_reg->asc_fstat & ASCFSTAT_TXFREEMASK ) >> ASCFSTAT_TXFREEOFF )) {
 
         mb();
 
--- linux-2.6.32/drivers/usb/core/hcd.c
+++ linux-2.6.32/drivers/usb/core/hcd.c
@@ -45,7 +45,11 @@
 #include "hcd.h"
 #include "hub.h"
 
-
+extern struct usb_host_interface *usb_find_alt_setting(
+		struct usb_host_config *config,
+		unsigned int iface_num,
+		unsigned int alt_num);
+		
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1602,19 +1606,35 @@
 	}
 }
 
-/* Check whether a new configuration or alt setting for an interface
- * will exceed the bandwidth for the bus (or the host controller resources).
- * Only pass in a non-NULL config or interface, not both!
- * Passing NULL for both new_config and new_intf means the device will be
- * de-configured by issuing a set configuration 0 command.
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+/**
+ * usb_hcd_alloc_bandwidth - check whether a new bandwidth setting exceeds
+ *				the bus bandwidth
+ * @udev: target &usb_device
+ * @new_config: new configuration to install
+ * @cur_alt: the current alternate interface setting
+ * @new_alt: alternate interface setting that is being installed
+ *
+ * To change configurations, pass in the new configuration in new_config,
+ * and pass NULL for cur_alt and new_alt.
+ *
+ * To reset a device's configuration (put the device in the ADDRESSED state),
+ * pass in NULL for new_config, cur_alt, and new_alt.
+ *
+ * To change alternate interface settings, pass in NULL for new_config,
+ * pass in the current alternate interface setting in cur_alt,
+ * and pass in the new alternate interface setting in new_alt.
+ *
+ * Returns an error if the requested bandwidth change exceeds the
+ * bus bandwidth or host controller internal resources.
  */
-int usb_hcd_check_bandwidth(struct usb_device *udev,
+int usb_hcd_alloc_bandwidth(struct usb_device *udev,
 		struct usb_host_config *new_config,
-		struct usb_interface *new_intf)
+		struct usb_host_interface *cur_alt,
+		struct usb_host_interface *new_alt)
 {
 	int num_intfs, i, j;
-	struct usb_interface_cache *intf_cache;
-	struct usb_host_interface *alt = 0;
+	struct usb_host_interface *alt = NULL;
 	int ret = 0;
 	struct usb_hcd *hcd;
 	struct usb_host_endpoint *ep;
@@ -1624,7 +1644,7 @@
 		return 0;
 
 	/* Configuration is being removed - set configuration 0 */
-	if (!new_config && !new_intf) {
+	if (!new_config && !cur_alt) {
 		for (i = 1; i < 16; ++i) {
 			ep = udev->ep_out[i];
 			if (ep)
@@ -1661,19 +1681,17 @@
 			}
 		}
 		for (i = 0; i < num_intfs; ++i) {
+			struct usb_host_interface *first_alt;
+			int iface_num;
+
+			first_alt = &new_config->intf_cache[i]->altsetting[0];
+			iface_num = first_alt->desc.bInterfaceNumber;
+			/* Set up endpoints for alternate interface setting 0 */
+			alt = usb_find_alt_setting(new_config, iface_num, 0);
+			if (!alt)
+				/* No alt setting 0? Pick the first setting. */
+				alt = first_alt;
 
-			/* Dig the endpoints for alt setting 0 out of the
-			 * interface cache for this interface
-			 */
-			intf_cache = new_config->intf_cache[i];
-			for (j = 0; j < intf_cache->num_altsetting; j++) {
-				if (intf_cache->altsetting[j].desc.bAlternateSetting == 0)
-					alt = &intf_cache->altsetting[j];
-			}
-			if (!alt) {
-				printk(KERN_DEBUG "Did not find alt setting 0 for intf %d\n", i);
-				continue;
-			}
 			for (j = 0; j < alt->desc.bNumEndpoints; j++) {
 				ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]);
 				if (ret < 0)
@@ -1681,6 +1699,44 @@
 			}
 		}
 	}
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	if (cur_alt && new_alt) {
+		struct usb_interface *iface = usb_ifnum_to_if(udev,
+				cur_alt->desc.bInterfaceNumber);
+				
+		if (!iface)
+			return -EINVAL;
+			
+		if (iface->resetting_device) {
+			/*
+			 * The USB core just reset the device, so the xHCI host
+			 * and the device will think alt setting 0 is installed.
+			 * However, the USB core will pass in the alternate
+			 * setting installed before the reset as cur_alt.  Dig
+			 * out the alternate setting 0 structure, or the first
+			 * alternate setting if a broken device doesn't have alt
+			 * setting 0.
+			 */
+			cur_alt = usb_altnum_to_altsetting(iface, 0);
+			if (!cur_alt)
+				cur_alt = &iface->altsetting[0];
+		}
+
+		/* Drop all the endpoints in the current alt setting */
+		for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) {
+			ret = hcd->driver->drop_endpoint(hcd, udev,
+					&cur_alt->endpoint[i]);
+			if (ret < 0)
+				goto reset;
+		}
+		/* Add all the endpoints in the new alt setting */
+		for (i = 0; i < new_alt->desc.bNumEndpoints; i++) {
+			ret = hcd->driver->add_endpoint(hcd, udev,
+					&new_alt->endpoint[i]);
+			if (ret < 0)
+				goto reset;
+		}
+	}
 	ret = hcd->driver->check_bandwidth(hcd, udev);
 reset:
 	if (ret < 0)
@@ -1997,6 +2053,8 @@
 #ifdef CONFIG_PM
 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	mutex_init(&hcd->bandwidth_mutex);
 
 	hcd->driver = driver;
 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
--- linux-2.6.32/drivers/usb/core/hcd.h
+++ linux-2.6.32/drivers/usb/core/hcd.h
@@ -115,6 +115,21 @@
 	u64			rsrc_len;	/* memory/io resource length */
 	unsigned		power_budget;	/* in mA, 0 = no limit */
 
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	/* bandwidth_mutex should be taken before adding or removing
+	 * any new bus bandwidth constraints:
+	 *   1. Before adding a configuration for a new device.
+	 *   2. Before removing the configuration to put the device into
+	 *      the addressed state.
+	 *   3. Before selecting a different configuration.
+	 *   4. Before selecting an alternate interface setting.
+	 *
+	 * bandwidth_mutex should be dropped after a successful control message
+	 * to the device, or resetting the bandwidth after a failed attempt.
+	 */
+	struct mutex		bandwidth_mutex;
+
+
 #define HCD_BUFFER_POOLS	4
 	struct dma_pool		*pool [HCD_BUFFER_POOLS];
 
@@ -280,6 +295,7 @@
 		 */
 	int	(*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,
 			struct usb_tt *tt, gfp_t mem_flags);
+	int	(*reset_device)(struct usb_hcd *, struct usb_device *);
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -298,9 +314,10 @@
 extern void usb_hcd_reset_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
-extern int usb_hcd_check_bandwidth(struct usb_device *udev,
+extern int usb_hcd_alloc_bandwidth(struct usb_device *udev,
 		struct usb_host_config *new_config,
-		struct usb_interface *new_intf);
+		struct usb_host_interface *old_alt,
+		struct usb_host_interface *new_alt);
 extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
--- linux-2.6.32/drivers/usb/core/hub.c
+++ linux-2.6.32/drivers/usb/core/hub.c
@@ -2334,7 +2334,9 @@
 				struct usb_device *udev, unsigned int delay)
 {
 	int i, status;
+	struct usb_hcd *hcd;
 
+	hcd = bus_to_hcd(udev->bus);
 	/* Block EHCI CF initialization during the port reset.
 	 * Some companion controllers don't like it when they mix.
 	 */
@@ -2362,6 +2364,15 @@
 			/* TRSTRCY = 10 ms; plus some extra */
 			msleep(10 + 40);
 			update_address(udev, 0);
+			/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+			if (hcd->driver->reset_device) {
+				status = hcd->driver->reset_device(hcd, udev);
+				if (status < 0) {
+					dev_err(&udev->dev, "Cannot reset "
+							"HCD device state\n");
+					break;
+				}
+			}
 			/* FALL THROUGH */
 		case -ENOTCONN:
 		case -ENODEV:
@@ -2973,24 +2984,13 @@
 
 	mutex_lock(&usb_address0_mutex);
 
-	if ((hcd->driver->flags & HCD_USB3) && udev->config) {
-		/* FIXME this will need special handling by the xHCI driver. */
-		dev_dbg(&udev->dev,
-				"xHCI reset of configured device "
-				"not supported yet.\n");
-		retval = -EINVAL;
+	/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	/* Reset the device; full speed may morph to high speed */
+	/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
+	retval = hub_port_reset(hub, port1, udev, delay);
+	if (retval < 0)		/* error or disconnect */
 		goto fail;
-//	} else if (!udev->config && oldspeed == USB_SPEED_SUPER) {
-//		/* Don't reset USB 3.0 devices during an initial setup */
-//		usb_set_device_state(udev, USB_STATE_DEFAULT);
-	} else {
-		/* Reset the device; full speed may morph to high speed */
-		/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
-		retval = hub_port_reset(hub, port1, udev, delay);
-		if (retval < 0)		/* error or disconnect */
-			goto fail;
-		/* success, speed is known */
-	}
+	/* success, speed is known */
 	retval = -ENODEV;
 
 	if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) {
@@ -3068,7 +3068,9 @@
 
 #endif /* CONFIG_MACH_QCA955x */
 
-	if (udev->speed != USB_SPEED_SUPER)
+/* --20140828 AVM/WKR don't exclude USB 3.0 --*/
+//	if (udev->speed != USB_SPEED_SUPER)
+
 		dev_info(&udev->dev,
 				"%s %s speed %sUSB device using %s and address %d\n",
 				(udev->config) ? "reset" : "new", speed, type,
@@ -3210,7 +3212,9 @@
 			msleep(10);
 			if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
 				break;
-  		}
+		}
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+		msleep (50);
 
 		retval = usb_get_device_descriptor(udev, 8);
 		if (retval < 8) {
@@ -3947,7 +3951,8 @@
 			changed = 1;
 			break;
 		}
-		if (memcmp (buf, udev->rawdescriptors[index], old_length)
+	
+	if (memcmp (buf, udev->rawdescriptors[index], old_length)
 				!= 0) {
 			dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
 				index,
@@ -4009,6 +4014,7 @@
 {
 	struct usb_device		*parent_hdev = udev->parent;
 	struct usb_hub			*parent_hub;
+	struct usb_hcd			*hcd = bus_to_hcd(udev->bus);
 	struct usb_device_descriptor	descriptor = udev->descriptor;
 	int 				i, ret = 0;
 	int				port1 = udev->portnum;
@@ -4029,7 +4035,7 @@
 
 	set_bit(port1, parent_hub->busy_bits);
 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
-
+		
 		/* ep0 maxpacket size may change; let the HCD know about it.
 		 * Other endpoints will be handled by re-enumeration. */
 		usb_ep0_reinit(udev);
@@ -4052,6 +4058,17 @@
 	/* Restore the device's previous configuration */
 	if (!udev->actconfig)
 		goto done;
+
+	/* -- 20140828 AVM/WK use mutex for XHCI --*/
+	mutex_lock(&hcd->bandwidth_mutex);
+	ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL);
+	if (ret < 0) {
+		dev_warn(&udev->dev,
+				"Busted HC?  Not enough HCD resources for "
+				"old configuration.\n");
+		mutex_unlock(&hcd->bandwidth_mutex);
+		goto re_enumerate;
+	}
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			USB_REQ_SET_CONFIGURATION, 0,
 			udev->actconfig->desc.bConfigurationValue, 0,
@@ -4060,8 +4077,10 @@
 		dev_err(&udev->dev,
 			"can't restore configuration #%d (error=%d)\n",
 			udev->actconfig->desc.bConfigurationValue, ret);
+		mutex_unlock(&hcd->bandwidth_mutex);
 		goto re_enumerate;
-  	}
+	}
+	mutex_unlock(&hcd->bandwidth_mutex);
 	usb_set_device_state(udev, USB_STATE_CONFIGURED);
 
 	/* Put interfaces back into the same altsettings as before.
@@ -4071,7 +4090,8 @@
 	 * endpoint state.
 	 */
 	for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-		struct usb_interface *intf = udev->actconfig->interface[i];
+		struct usb_host_config *config = udev->actconfig;
+		struct usb_interface *intf = config->interface[i];
 		struct usb_interface_descriptor *desc;
 
 		desc = &intf->cur_altsetting->desc;
@@ -4080,8 +4100,15 @@
 			usb_enable_interface(udev, intf, true);
 			ret = 0;
 		} else {
+			/* Let the bandwidth allocation function know that this
+			 * device has been reset, and it will have to use
+			 * alternate setting 0 as the current alternate setting.
+			 */
+			intf->resetting_device = 1;
+
 			ret = usb_set_interface(udev, desc->bInterfaceNumber,
 					desc->bAlternateSetting);
+			intf->resetting_device = 0;
 		}
 		if (ret < 0) {
 			dev_err(&udev->dev, "failed to restore interface %d "
--- linux-2.6.32/drivers/usb/core/message.c
+++ linux-2.6.32/drivers/usb/core/message.c
@@ -1306,6 +1306,8 @@
 {
 	struct usb_interface *iface;
 	struct usb_host_interface *alt;
+	struct usb_hcd *hcd = bus_to_hcd(dev->bus);
+
 	int ret;
 	int manual = 0;
 	unsigned int epaddr;
@@ -1323,11 +1325,24 @@
 
 	alt = usb_altnum_to_altsetting(iface, alternate);
 	if (!alt) {
-		dev_warn(&dev->dev, "selecting invalid altsetting %d",
+		dev_warn(&dev->dev, "selecting invalid altsetting %d\n",
 			 alternate);
 		return -EINVAL;
 	}
 
+	/* -- 20140828 AVM/WK use mutex patch from newer kernels --*/
+	/* Make sure we have enough bandwidth for this alternate interface.
+	 * Remove the current alt setting and add the new alt setting.
+	 */
+	mutex_lock(&hcd->bandwidth_mutex);
+	ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
+	if (ret < 0) {
+		dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
+				alternate);
+		mutex_unlock(&hcd->bandwidth_mutex);
+		return ret;
+	}
+
 	if (dev->quirks & USB_QUIRK_NO_SET_INTF)
 		ret = -EPIPE;
 	else
@@ -1343,8 +1358,13 @@
 			"manual set_interface for iface %d, alt %d\n",
 			interface, alternate);
 		manual = 1;
-	} else if (ret < 0)
+	} else if (ret < 0) {
+		/* Re-instate the old alt setting */
+		usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
+		mutex_unlock(&hcd->bandwidth_mutex);
 		return ret;
+	}
+	mutex_unlock(&hcd->bandwidth_mutex);
 
 	/* FIXME drivers shouldn't need to replicate/bugfix the logic here
 	 * when they implement async or easily-killable versions of this or
@@ -1426,6 +1446,7 @@
 {
 	int			i, retval;
 	struct usb_host_config	*config;
+	struct usb_hcd *hcd = bus_to_hcd(dev->bus);
 
 	if (dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
@@ -1440,13 +1461,48 @@
 		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
 	}
 
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
 	config = dev->actconfig;
+	retval = 0;
+	mutex_lock(&hcd->bandwidth_mutex);
+	/* Make sure we have enough bandwidth for each alternate setting 0 */
+	for (i = 0; i < config->desc.bNumInterfaces; i++) {
+		struct usb_interface *intf = config->interface[i];
+		struct usb_host_interface *alt;
+
+		alt = usb_altnum_to_altsetting(intf, 0);
+		if (!alt)
+			alt = &intf->altsetting[0];
+		if (alt != intf->cur_altsetting)
+			retval = usb_hcd_alloc_bandwidth(dev, NULL,
+					intf->cur_altsetting, alt);
+		if (retval < 0)
+			break;
+	}
+	/* If not, reinstate the old alternate settings */
+	if (retval < 0) {
+reset_old_alts:
+		for (i--; i >= 0; i--) {
+			struct usb_interface *intf = config->interface[i];
+			struct usb_host_interface *alt;
+
+			alt = usb_altnum_to_altsetting(intf, 0);
+			if (!alt)
+				alt = &intf->altsetting[0];
+			if (alt != intf->cur_altsetting)
+				usb_hcd_alloc_bandwidth(dev, NULL,
+						alt, intf->cur_altsetting);
+		}
+		mutex_unlock(&hcd->bandwidth_mutex);
+		return retval;
+	}
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0,
 			config->desc.bConfigurationValue, 0,
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval < 0)
-		return retval;
+		goto reset_old_alts;
+	mutex_unlock(&hcd->bandwidth_mutex);
 
 	/* re-init hc/hcd interface/endpoint state */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
@@ -1655,6 +1711,7 @@
 	int i, ret;
 	struct usb_host_config *cp = NULL;
 	struct usb_interface **new_interfaces = NULL;
+	struct usb_hcd *hcd = bus_to_hcd(dev->bus);
 	int n, nintf;
 
 	if (dev->authorized == 0 || configuration == -1)
@@ -1724,12 +1781,12 @@
 	 * host controller will not allow submissions to dropped endpoints.  If
 	 * this call fails, the device state is unchanged.
 	 */
-	if (cp)
-		ret = usb_hcd_check_bandwidth(dev, cp, NULL);
-	else
-		ret = usb_hcd_check_bandwidth(dev, NULL, NULL);
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	mutex_lock(&hcd->bandwidth_mutex);
+	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
 	if (ret < 0) {
 		usb_autosuspend_device(dev);
+		mutex_unlock(&hcd->bandwidth_mutex);
 		goto free_interfaces;
 	}
 
@@ -1755,10 +1812,12 @@
 	dev->actconfig = cp;
 	if (!cp) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
-		usb_hcd_check_bandwidth(dev, NULL, NULL);
+		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
 		usb_autosuspend_device(dev);
+		mutex_unlock(&hcd->bandwidth_mutex);
 		goto free_interfaces;
 	}
+	mutex_unlock(&hcd->bandwidth_mutex);
 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
 	/* Initialize the new interface structures and the
--- linux-2.6.32/drivers/usb/core/usb.c
+++ linux-2.6.32/drivers/usb/core/usb.c
@@ -62,6 +62,43 @@
 #define usb_autosuspend_delay		0
 #endif
 
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+/**
+ * usb_find_alt_setting() - Given a configuration, find the alternate setting
+ * for the given interface.
+ * @config: the configuration to search (not necessarily the current config).
+ * @iface_num: interface number to search in
+ * @alt_num: alternate interface setting number to search for.
+ *
+ * Search the configuration's interface cache for the given alt setting.
+ */
+struct usb_host_interface *usb_find_alt_setting(
+		struct usb_host_config *config,
+		unsigned int iface_num,
+		unsigned int alt_num)
+{
+	struct usb_interface_cache *intf_cache = NULL;
+	int i;
+
+	for (i = 0; i < config->desc.bNumInterfaces; i++) {
+		if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber
+				== iface_num) {
+			intf_cache = config->intf_cache[i];
+			break;
+		}
+	}
+	if (!intf_cache)
+		return NULL;
+	for (i = 0; i < intf_cache->num_altsetting; i++)
+		if (intf_cache->altsetting[i].desc.bAlternateSetting == alt_num)
+			return &intf_cache->altsetting[i];
+
+	printk(KERN_DEBUG "Did not find alt setting %u for intf %u, "
+			"config %u\n", alt_num, iface_num,
+			config->desc.bConfigurationValue);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(usb_find_alt_setting);
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
--- linux-2.6.32/drivers/usb/host/xhci.h
+++ linux-2.6.32/drivers/usb/host/xhci.h
@@ -20,6 +20,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* -- 20140828 AVM/WK some XHCI reset patches from newer kernel --*/
 #ifndef __LINUX_XHCI_HCD_H
 #define __LINUX_XHCI_HCD_H
 
@@ -1234,6 +1235,7 @@
 void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
 int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);
 int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
+void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, struct usb_device *udev);
 unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
 unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
 unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
@@ -1280,6 +1282,7 @@
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
+int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
@@ -1306,6 +1309,7 @@
 		u32 slot_id);
 int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
 		unsigned int ep_index);
+int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
 void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_td *cur_td, struct xhci_dequeue_state *state);
--- linux-2.6.32/drivers/usb/host/xhci-hcd.c
+++ linux-2.6.32/drivers/usb/host/xhci-hcd.c
@@ -1157,6 +1157,7 @@
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
 	ctrl_ctx->drop_flags = 0;
 	ctrl_ctx->add_flags = 0;
+
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
 	slot_ctx->dev_info &= SWAP32(~LAST_CTX_MASK);
 	/* Endpoint 0 is always valid */
@@ -1265,6 +1266,16 @@
 		cmd_completion = command->completion;
 		cmd_status = &command->status;
 		command->command_trb = xhci->cmd_ring->enqueue;
+
+/* -- 20140828 AVM/WK XHCI patch from new kernel --*/
+		/* Enqueue pointer can be left pointing to the link TRB,
+		 * we must handle that
+		 */
+		if ((SWAP32(command->command_trb->link.control) & TRB_TYPE_BITMASK)
+				== TRB_TYPE(TRB_LINK))
+			command->command_trb =
+				xhci->cmd_ring->enq_seg->next->trbs;
+
 		list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
 	} else {
 		in_ctx = virt_dev->in_ctx;
@@ -1360,6 +1371,16 @@
 	xhci_dbg_ctx(xhci, virt_dev->out_ctx,
 			LAST_CTX_TO_EP_NUM(SWAP32(slot_ctx->dev_info)));
 
+	/* -- 20140828 AVM/WK XHCI patch from new kernel --*/
+	for (i = 1; i < 31; ++i) {
+		if (virt_dev->eps[i].ring) {
+			if (xhci_get_endpoint_flag_from_index(i) & SWAP32(ctrl_ctx->drop_flags)) {
+				xhci_ring_free(xhci, virt_dev->eps[i].ring);
+				virt_dev->eps[i].ring = NULL;
+			}
+		}
+	}
+	
 	xhci_zero_in_ctx(xhci, virt_dev);
 	/* Free any old rings */
 	for (i = 1; i < 31; ++i) {
@@ -1536,8 +1557,173 @@
 		xhci_warn(xhci, "FIXME allocate a new ring segment\n");
 }
 
+/* -- 20140828 AVM/WK XHCI patch from newer kernel --*/
+
+static inline char *xhci_get_slot_state(struct xhci_hcd *xhci,
+		struct xhci_container_ctx *ctx)
+{
+	struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+
+	switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
+	case 0:
+		return "enabled/disabled";
+	case 1:
+		return "default";
+	case 2:
+		return "addressed";
+	case 3:
+		return "configured";
+	default:
+		return "reserved";
+	}
+} 
+
+/* -- 20140828 AVM/WK XHCI patch from newer kernel --*/
+
 /*
- * At this point, the struct usb_device is about to go away, the device has
+ * This submits a Reset Device Command, which will set the device state to 0,
+ * set the device address to 0, and disable all the endpoints except the default
+ * control endpoint.  The USB core should come back and call
+ * xhci_address_device(), and then re-set up the configuration.  If this is
+ * called because of a usb_reset_and_verify_device(), then the old alternate
+ * settings will be re-installed through the normal bandwidth allocation
+ * functions.
+ *
+ * Wait for the Reset Device command to finish.  Remove all structures
+ * associated with the endpoints that were disabled.  Clear the input device
+ * structure?  Cache the rings?  Reset the control endpoint 0 max packet size?
+ */
+int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	int ret, i;
+	unsigned long flags;
+	struct xhci_hcd *xhci;
+	unsigned int slot_id;
+	struct xhci_virt_device *virt_dev;
+	struct xhci_command *reset_device_cmd;
+	struct xhci_slot_ctx *slot_ctx;
+	
+	int timeleft;
+	int last_freed_endpoint;
+
+	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	if (ret <= 0)
+		return ret;
+	xhci = hcd_to_xhci(hcd);
+	slot_id = udev->slot_id;
+	virt_dev = xhci->devs[slot_id];
+	if (!virt_dev) {
+		xhci_dbg(xhci, "%s called with invalid slot ID %u\n",
+				__func__, slot_id);
+		return -EINVAL;
+	}
+
+	/* If device is not setup, there is no point in resetting it */
+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+	if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
+						0 /*SLOT_STATE_DISABLED*/)
+		return 0;
+
+	xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
+	/* Allocate the command structure that holds the struct completion.
+	 * Assume we're in process context, since the normal device reset
+	 * process has to wait for the device anyway.  Storage devices are
+	 * reset as part of error handling, so use GFP_NOIO instead of
+	 * GFP_KERNEL.
+	 */
+	reset_device_cmd = xhci_alloc_command(xhci, true, GFP_NOIO);
+	if (!reset_device_cmd) {
+		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+		return -ENOMEM;
+	}
+
+	/* Attempt to submit the Reset Device command to the command ring */
+	spin_lock_irqsave(&xhci->lock, flags);
+	reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
+	/* Enqueue pointer can be left pointing to the link TRB,
+	 * we must handle that
+	 */
+	if ((SWAP32(reset_device_cmd->command_trb->link.control) & TRB_TYPE_BITMASK)
+			== TRB_TYPE(TRB_LINK))
+		reset_device_cmd->command_trb =
+			xhci->cmd_ring->enq_seg->next->trbs;
+
+	list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
+	ret = xhci_queue_reset_device(xhci, slot_id);
+	if (ret) {
+		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
+		list_del(&reset_device_cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		goto command_cleanup;
+	}
+	xhci_ring_cmd_db(xhci);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+
+	/* Wait for the Reset Device command to finish */
+	timeleft = wait_for_completion_interruptible_timeout(
+			reset_device_cmd->completion,
+			USB_CTRL_SET_TIMEOUT);
+	if (timeleft <= 0) {
+		xhci_warn(xhci, "%s while waiting for reset device command\n",
+				timeleft == 0 ? "Timeout" : "Signal");
+		spin_lock_irqsave(&xhci->lock, flags);
+		/* The timeout might have raced with the event ring handler, so
+		 * only delete from the list if the item isn't poisoned.
+		 */
+		if (reset_device_cmd->cmd_list.next != LIST_POISON1)
+			list_del(&reset_device_cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		ret = -ETIME;
+		goto command_cleanup;
+	}
+
+	/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
+	 * unless we tried to reset a slot ID that wasn't enabled,
+	 * or the device wasn't in the addressed or configured state.
+	 */
+	ret = reset_device_cmd->status;
+	switch (ret) {
+	case COMP_EBADSLT: /* 0.95 completion code for bad slot ID */
+	case COMP_CTX_STATE: /* 0.96 completion code for same thing */
+		xhci_warn(xhci, "Can't reset device (slot ID %u) in %s state\n",
+				slot_id,
+				xhci_get_slot_state(xhci, virt_dev->out_ctx));
+		xhci_info(xhci, "Not freeing device rings.\n");
+		/* Don't treat this as an error.  May change my mind later. */
+		ret = 0;
+		goto command_cleanup;
+	case COMP_SUCCESS:
+		xhci_warn(xhci, "Successful reset device command.\n");
+		break;
+	default:
+		//if (xhci_is_vendor_info_code(xhci, ret))
+		//	break;
+		xhci_warn(xhci, "Unknown completion code %u for "
+				"reset device command.\n", ret);
+		ret = -EINVAL;
+		goto command_cleanup;
+	}
+
+	/* Everything but endpoint 0 is disabled, so free or cache the rings. */
+	last_freed_endpoint = 1;
+	for (i = 1; i < 31; ++i) {
+		if (!virt_dev->eps[i].ring)
+			continue;
+			xhci_warn(xhci, "reset_dev:free ring#%u=%p\n",i,virt_dev->eps[i].ring);
+		xhci_ring_free(xhci, virt_dev->eps[i].ring);
+		virt_dev->eps[i].ring = NULL;
+		last_freed_endpoint = i;
+	}
+	xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
+	xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
+	ret = 0;
+
+command_cleanup:
+	xhci_free_command(xhci, reset_device_cmd);
+	return ret;
+}
+
+/* At this point, the struct usb_device is about to go away, the device has
  * disconnected, and all traffic has been stopped and the endpoints have been
  * disabled.  Free any HC data structures associated with that device.
  */
@@ -1648,12 +1834,23 @@
 		return -EINVAL;
 	}
 
+/* -- 20140828 AVM/WK XHCI patches from newer kernel --*/
 	virt_dev = xhci->devs[udev->slot_id];
+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+
 
 	/* If this is a Set Address to an unconfigured device, setup ep 0 */
-	if (!udev->config)
+	if (!slot_ctx->dev_info)
 		xhci_setup_addressable_virt_dev(xhci, udev);
-	/* Otherwise, assume the core has the device configured how it wants */
+	/* Otherwise, update the control endpoint ring enqueue pointer. */
+	else
+		xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
+		
+	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+	ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
+	ctrl_ctx->drop_flags = 0;
+	
+		
 	xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
--- linux-2.6.32/drivers/usb/host/xhci-mem.c
+++ linux-2.6.32/drivers/usb/host/xhci-mem.c
@@ -336,6 +336,35 @@
 	return 0;
 }
 
+/* -- 20140828 AVM/WK XHCI patch from newer kernel --*/
+void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
+		struct usb_device *udev)
+{
+	struct xhci_virt_device *virt_dev;
+	struct xhci_ep_ctx	*ep0_ctx;
+	struct xhci_ring	*ep_ring;
+	dma_addr_t addr;
+	
+
+	virt_dev = xhci->devs[udev->slot_id];
+
+	ep0_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, 0);
+	ep_ring = virt_dev->eps[0].ring;
+	/*
+	 * FIXME we don't keep track of the dequeue pointer very well after a
+	 * Set TR dequeue pointer, so we're setting the dequeue pointer of the
+	 * host to our enqueue pointer.  This should only be called after a
+	 * configured device has reset, so all control transfers should have
+	 * been completed or cancelled before the reset.
+	 */
+	 
+	addr = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
+	ep0_ctx->deq = SWAP64(addr|ep_ring->cycle_state);
+
+	ep_ring->dequeue = ep_ring->enqueue;
+
+}
+
 /* Setup an xHCI virtual device for a Set Address command */
 int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev)
 {
--- linux-2.6.32/drivers/usb/host/xhci-pci.c
+++ linux-2.6.32/drivers/usb/host/xhci-pci.c
@@ -144,6 +144,8 @@
 	.reset_bandwidth =	xhci_reset_bandwidth,
 	.address_device =	xhci_address_device,
 	.update_hub_device =	xhci_update_hub_device,
+/* -- 20140828 AVM/WK XHCI patch from newer kernel --*/
+	.reset_device =		xhci_reset_device,
 
 	/*
 	 * scheduling support
--- linux-2.6.32/drivers/usb/host/xhci-ring.c
+++ linux-2.6.32/drivers/usb/host/xhci-ring.c
@@ -185,7 +185,7 @@
 
 	chain = SWAP32(ring->enqueue->generic.field[3]) & TRB_CHAIN;
 	next = ++(ring->enqueue);
-
+	
 	ring->enq_updates++;
 	/* Update the dequeue pointer further if that was a link TRB or we're at
 	 * the end of an event ring segment (which doesn't have link TRBS)
@@ -850,6 +850,18 @@
 	case TRB_TYPE(TRB_RESET_EP):
 		handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
 		break;
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+	case TRB_TYPE(TRB_RESET_DEV):
+		xhci_dbg(xhci, "Completed reset device command.\n");
+		slot_id = TRB_TO_SLOT_ID(SWAP32(
+				xhci->cmd_ring->dequeue->generic.field[3]));
+		virt_dev = xhci->devs[slot_id];
+		if (virt_dev)
+			handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
+		else
+			xhci_warn(xhci, "Reset device command completion "
+					"for disabled slot %u\n", slot_id);
+		break;
 	default:
 		/* Skip over unknown commands on the event ring */
 		xhci->error_bitmask |= 1 << 6;
@@ -1490,7 +1502,7 @@
 	list_add_tail(&(*td)->td_list, &xdev->eps[ep_index].ring->td_list);
 	(*td)->start_seg = xdev->eps[ep_index].ring->enq_seg;
 	(*td)->first_trb = xdev->eps[ep_index].ring->enqueue;
-
+	
 	return 0;
 }
 
@@ -2014,6 +2026,15 @@
 			false);
 }
 
+/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/
+/* Queue a reset device command TRB */
+int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
+{
+	return queue_command(xhci, 0, 0, 0,
+			TRB_TYPE(TRB_RESET_DEV) | SLOT_ID_FOR_TRB(slot_id),
+			false);
+}
+
 /* Queue a configure endpoint command TRB */
 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id, bool command_must_succeed)
--- linux-2.6.32/drivers/usb/musb/ifxhcd.c
+++ linux-2.6.32/drivers/usb/musb/ifxhcd.c
@@ -154,19 +154,28 @@
 	/* AVM/BC 20131115 Fix: from old ifxhcd_complete_urb */
 	if (!_urbd->epqh) {
 		IFX_ERROR("%s: invalid epqd\n",__func__);
-	}
+	} else if(_urbd->is_active) {
+		if (_urbd->epqh->urbd != _urbd) {
+			IFX_ERROR("%s: mismatching ephq->urbd:%p->%p, urbd %p\n",__func__, _urbd->epqh, _urbd->epqh->urbd, _urbd);
+		}
+		
+		/* AVM/WKR 20141010 Fix: set urbd inactive */
+		_urbd->is_active = 0;
+		_urbd->epqh->urbd = NULL;
+		
 #if defined(__UNALIGNED_BUFFER_ADJ__)
-	else if(_urbd->is_active) {
 		if( _urbd->epqh->aligned_checked   &&
-		    _urbd->epqh->using_aligned_buf &&
-		    _urbd->xfer_buff &&
-		    _urbd->is_in )
+			_urbd->epqh->using_aligned_buf &&
+			_urbd->xfer_buff &&
+			_urbd->is_in ) 
+		{
 			memcpy(_urbd->xfer_buff,_urbd->epqh->aligned_buf,_urbd->xfer_len);
+		}
 		_urbd->epqh->using_aligned_buf=0;
 		_urbd->epqh->using_aligned_setup=0;
 		_urbd->epqh->aligned_checked=0;
-	}
 #endif
+	}
 
 	local_ifxhcd_complete_urb(_ifxhcd, _urbd, _status);
 }
@@ -184,13 +193,20 @@
 
 	_urbd->status = _status;
 
+	IFX_WARN_ON(!_urbd->is_active);
 	/* AVM/BC 20131115 Fix: from old ifxhcd_complete_urb */
 	if (!_urbd->epqh) {
 		IFX_ERROR("%s: invalid epqd\n",__func__);
-	}
-#if defined(__UNALIGNED_BUFFER_ADJ__)
-	else if(_urbd->is_active) {
+	} else if(_urbd->is_active) {
+		if (_urbd->epqh->urbd != _urbd) {
+			IFX_ERROR("%s: mismatching ephq->urbd:%p->%p, urbd %p\n",__func__, _urbd->epqh, _urbd->epqh->urbd, _urbd);
+		}
+		
+		/* AVM/WKR 20141010 Fix: set urbd inactive */
+		_urbd->is_active = 0;
+		_urbd->epqh->urbd = NULL;
 
+#if defined(__UNALIGNED_BUFFER_ADJ__)
 		if( _urbd->epqh->aligned_checked   &&
 		    _urbd->epqh->using_aligned_buf &&
 		    _urbd->xfer_buff &&
@@ -200,8 +216,9 @@
 		_urbd->epqh->using_aligned_buf=0;
 		_urbd->epqh->using_aligned_setup=0;
 		_urbd->epqh->aligned_checked=0;
-	}
 #endif
+	}
+	
 	if (	(_status != 0) 
 		||  ((_urbd->urb) && !(_urbd->urb->transfer_flags & URB_NO_INTERRUPT)))
 	{
@@ -239,6 +256,27 @@
 	}
 }
 
+/* 20140917 AVM/WK giveback all urbs in complete list
+	call in SPIN_LOCK before ephq_free
+*/
+static void complete_all_deferred_urbs(ifxhcd_hcd_t *_ifxhcd)
+{
+	while (!list_empty(&_ifxhcd->urbd_complete_list))
+	{
+		struct list_head *urbd_ptr;
+		ifxhcd_urbd_t    *urbd;
+
+		urbd_ptr = _ifxhcd->urbd_complete_list.next;
+		list_del_init(urbd_ptr);
+
+		urbd = list_entry(urbd_ptr, ifxhcd_urbd_t, urbd_list_entry);
+		IFX_PRINT ("%s: complete deferred urbs epqh %p urbd %p ->urb %p\n",__func__, urbd->epqh, urbd, urbd->urb);
+
+		local_ifxhcd_complete_urb(_ifxhcd, urbd, urbd->status);
+
+	}
+
+}
 
 /*!
  \brief Free all EPS in one Processes all the URBs in a single list of EPQHs. Completes them with
@@ -269,6 +307,9 @@
 //static
 void epqh_list_free_all(ifxhcd_hcd_t *_ifxhcd)
 {
+	/* 20140917 AVM/WK giveback all urbs in complete list first*/
+	complete_all_deferred_urbs(_ifxhcd);
+
 	epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_active   );
 	epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_ready    );
 	epqh_list_free(_ifxhcd, &_ifxhcd->epqh_intr_active );
@@ -516,7 +557,7 @@
 	 */
 //	retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, SA_INTERRUPT|SA_SHIRQ);
 #if defined (CONFIG_USB_HOST_IFX_AVM_YIELD)
-	retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, IRQF_DISABLED | IRQF_SHARED |IRQF_TRIGGER_RISING);
+	retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, IRQF_DISABLED | IRQF_TRIGGER_RISING);
 #else
 	retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, IRQF_DISABLED | IRQF_SHARED );
 #endif /*--- defined (CONFIG_USB_HOST_IFX_AVM_YIELD) ---*/
@@ -879,6 +920,7 @@
 			epqh->is_active=0;
 	else if (epqh->is_active && urbd->is_active)
 	{
+		IFX_BUG_ON(epqh->urbd != urbd);
 		/*== AVM/WK 20100709 - halt channel only if really started ==*/
 		//if (epqh->hc->xfer_started && !epqh->hc->wait_for_sof) {
 		/*== AVM/WK 20101112 - halt channel if started ==*/
@@ -987,6 +1029,8 @@
 			}
 #endif
 
+			/* 20140917 AVM/WK giveback all urbs in complete list */
+			complete_all_deferred_urbs(ifxhcd);
 			ifxhcd_epqh_free(epqh);
 			_sysep->hcpriv = NULL;
 		}
@@ -1471,6 +1515,8 @@
 	urbd = list_entry(_epqh->urbd_list.next, ifxhcd_urbd_t, urbd_list_entry);
 	urb  = urbd->urb;
 
+	IFX_BUG_ON(_epqh->urbd);
+
 	_epqh->hc   = ifxhc;
 	_epqh->urbd = urbd;
 	ifxhc->epqh = _epqh;
@@ -1892,25 +1938,26 @@
 
 	if(xfer_len > 0 && ((unsigned long)_urbd->xfer_buff) & 3)
 	{
-		IFX_WARN("WARN:adjusting unaligned xfer_buff %p, len %u\n",_urbd->xfer_buff, xfer_len);
+		IFX_PRINT("adjusting unaligned xfer_buff %p, len %u, EP %02X\n",_urbd->xfer_buff, xfer_len, usb_pipeendpoint(_urbd->urb->pipe));
+		if(_epqh->old_aligned_buf)
+		{
+			ifxusb_free_buf(_epqh->old_aligned_buf);
+			_epqh->old_aligned_buf = NULL;
+		}
+		
 		if(_epqh->aligned_buf_len < xfer_len)
 		{
+			IFX_WARN("enhancing aligned_buf from %u to %u\n", _epqh->aligned_buf_len, xfer_len);
 			if(_epqh->new_aligned_buf) 
 			{
 				ifxusb_free_buf(_epqh->new_aligned_buf);
 				_epqh->new_aligned_buf = NULL;
 			}
-			if(_epqh->old_aligned_buf)
-			{
-				ifxusb_free_buf(_epqh->old_aligned_buf);
-				_epqh->old_aligned_buf = NULL;
-			}
 
 			_epqh->new_aligned_buf = ifxusb_alloc_buf(xfer_len, _urbd->is_in);
-			if(_epqh->new_aligned_buf)
-				_epqh->aligned_buf_len = xfer_len;
-			else
-				IFX_WARN("%s():%d\n",__func__,__LINE__);
+			_epqh->aligned_buf_len = xfer_len;
+			IFX_BUG_ON(!_epqh->new_aligned_buf);
+
 		}
 	}
 
@@ -1918,11 +1965,13 @@
 	{
 		if(((unsigned long)_urbd->setup_buff) & 3)
 		{
-			IFX_WARN("WARN:adjusting unaligned setup_buff %p\n",_urbd->setup_buff);
-			if(! _epqh->aligned_setup) {
+			IFX_PRINT("adjusting unaligned setup_buff %p\n",_urbd->setup_buff);
+			if(! _epqh->aligned_setup)
+			{
+				IFX_WARN("alloc aligned_setup\n");
 				_epqh->aligned_setup = ifxusb_alloc_buf(8,0);
-				IFX_WARN_ON(!_epqh->aligned_setup);
 			}
+			IFX_BUG_ON(!_epqh->aligned_setup);
 		}
 	}
 }
--- linux-2.6.32/drivers/usb/musb/ifxhcd_intr.c
+++ linux-2.6.32/drivers/usb/musb/ifxhcd_intr.c
@@ -3148,8 +3148,12 @@
 	IFX_DEBUGPL(DBG_HCDV, "  0x%08x & 0x%08x = 0x%08x\n",
 		    hcintval, hcintmsk, hcint.d32);
 
-	if (list_empty(&ifxhc->epqh->urbd_list)) {
-		IFX_WARN("handle_hc_n_intr: No urbd in hch#%d,flags=%X\n", _num, hcint.d32);
+	/* == 20140908 AVM/WK Fix: orphaned interrupt must be acked and will not be handled ==*/
+	if ((!ifxhc->epqh) || (list_empty(&ifxhc->epqh->urbd_list))) {
+		IFX_WARN_ON(!ifxhc->epqh);
+		IFX_WARN_ON(ifxhc->epqh && list_empty(&ifxhc->epqh->urbd_list));
+		IFX_WARN("WARN:handle_hc_n_intr: No urbd in hch#%d,flags=%X\n", _num, hcint.d32);
+		ifxusb_wreg(&hc_regs->hcint,hcintval);
 		return 0;
 	}
 	
@@ -3727,8 +3731,6 @@
 {
 	int retval = 0;
 
-	unsigned long     flags;
-
 	ifxusb_core_if_t *core_if = &_ifxhcd->core_if;
 	/* AVM/BC 20101111 Unnecesary variable removed*/
 	//gint_data_t gintsts,gintsts2;
@@ -3741,16 +3743,12 @@
 	}
 	#endif
 
-	SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
-
 	/* Check if HOST Mode */
 	if (ifxusb_is_device_mode(core_if))
 	{
-		SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
 		IFX_ERROR("%s() CRITICAL!  IN DEVICE MODE\n", __func__);
 		return 0;
 	}
-
 	gintsts.d32 = ifxusb_read_core_intr(core_if);
 
 #if defined (CONFIG_USB_HOST_IFX_AVM_YIELD)
@@ -3758,79 +3756,86 @@
 	gintsts.b.hcintr = 0;
 #endif
 
-	//Common INT
-	if (gintsts.b.modemismatch)
-	{
-		retval |= handle_mode_mismatch_intr(_ifxhcd);
-		gintsts.b.modemismatch=0;
-	}
-	if (gintsts.b.otgintr)
-	{
-		retval |= handle_otg_intr(_ifxhcd);
-		gintsts.b.otgintr=0;
-	}
-	if (gintsts.b.conidstschng)
-	{
-		retval |= handle_conn_id_status_change_intr(_ifxhcd);
-		gintsts.b.conidstschng=0;
-	}
-	if (gintsts.b.disconnect)
-	{
-		retval |= handle_disconnect_intr(_ifxhcd);
-		gintsts.b.disconnect=0;
-	}
-	if (gintsts.b.sessreqintr)
-	{
-		retval |= handle_session_req_intr(_ifxhcd);
-		gintsts.b.sessreqintr=0;
-	}
-	if (gintsts.b.wkupintr)
-	{
-		retval |= handle_wakeup_detected_intr(_ifxhcd);
-		gintsts.b.wkupintr=0;
-	}
-	if (gintsts.b.usbsuspend)
+	if (gintsts.d32) 
 	{
-		retval |= handle_usb_suspend_intr(_ifxhcd);
-		gintsts.b.usbsuspend=0;
-	}
+		unsigned long     flags;
+
+		SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
+
+		//Common INT
+		if (gintsts.b.modemismatch)
+		{
+			retval |= handle_mode_mismatch_intr(_ifxhcd);
+			gintsts.b.modemismatch=0;
+		}
+		if (gintsts.b.otgintr)
+		{
+			retval |= handle_otg_intr(_ifxhcd);
+			gintsts.b.otgintr=0;
+		}
+		if (gintsts.b.conidstschng)
+		{
+			retval |= handle_conn_id_status_change_intr(_ifxhcd);
+			gintsts.b.conidstschng=0;
+		}
+		if (gintsts.b.disconnect)
+		{
+			retval |= handle_disconnect_intr(_ifxhcd);
+			gintsts.b.disconnect=0;
+		}
+		if (gintsts.b.sessreqintr)
+		{
+			retval |= handle_session_req_intr(_ifxhcd);
+			gintsts.b.sessreqintr=0;
+		}
+		if (gintsts.b.wkupintr)
+		{
+			retval |= handle_wakeup_detected_intr(_ifxhcd);
+			gintsts.b.wkupintr=0;
+		}
+		if (gintsts.b.usbsuspend)
+		{
+			retval |= handle_usb_suspend_intr(_ifxhcd);
+			gintsts.b.usbsuspend=0;
+		}
 
 #if !defined (CONFIG_USB_HOST_IFX_AVM_YIELD)
-	//Host Int
-	if (gintsts.b.sofintr)
-	{
-		retval |= handle_sof_intr (_ifxhcd);
-		gintsts.b.sofintr=0;
-	}
+		//Host Int
+		if (gintsts.b.sofintr)
+		{
+			retval |= handle_sof_intr (_ifxhcd);
+			gintsts.b.sofintr=0;
+		}
 #endif
 
-	if (gintsts.b.portintr)
-	{
-		retval |= handle_port_intr (_ifxhcd);
-		gintsts.b.portintr=0;
-	}
+		if (gintsts.b.portintr)
+		{
+			retval |= handle_port_intr (_ifxhcd);
+			gintsts.b.portintr=0;
+		}
 
 #if !defined (CONFIG_USB_HOST_IFX_AVM_YIELD)
-	if (gintsts.b.hcintr)
-	{
-		int i;
-		haint_data_t haint;
-		haint.d32 = ifxusb_read_host_all_channels_intr(core_if);
-		for (i=0; i< core_if->params.host_channels; i++)
-			if (haint.b2.chint & (1 << i))
-				retval |= handle_hc_n_intr (_ifxhcd, i);
-		gintsts.b.hcintr=0;
-	}
-	
+		if (gintsts.b.hcintr)
+		{
+			int i;
+			haint_data_t haint;
+			haint.d32 = ifxusb_read_host_all_channels_intr(core_if);
+			for (i=0; i< core_if->params.host_channels; i++)
+				if (haint.b2.chint & (1 << i))
+					retval |= handle_hc_n_intr (_ifxhcd, i);
+			gintsts.b.hcintr=0;
+		}
 #endif
 
 #if !defined (CONFIG_USB_HOST_IFX_AVM_YIELD)
-	if (atomic_read( &_ifxhcd->need_eps)) {
-		tasklet_schedule(&_ifxhcd->comp_task);
-	}
+		if (atomic_read( &_ifxhcd->need_eps)) 
+		{
+			tasklet_schedule(&_ifxhcd->comp_task);
+		}
 #endif
 
-	SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
+		SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
+	}
 
 	return retval;
 }
--- linux-2.6.32/drivers/usb/musb/ifxhcd_queue.c
+++ linux-2.6.32/drivers/usb/musb/ifxhcd_queue.c
@@ -194,6 +194,9 @@
 		IFX_WARN("%s() invalid epqh state\n",__func__);
 
 	#if defined(__UNALIGNED_BUFFER_ADJ__)
+		WARN_ON(_epqh->using_aligned_buf);
+		WARN_ON(_epqh->using_aligned_setup);
+
 		if(_epqh->aligned_buf)
 			ifxusb_free_buf(_epqh->aligned_buf);
 		if(_epqh->new_aligned_buf)
@@ -314,6 +317,7 @@
 		else
 			list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_np_ready);
 	}
+	IFX_BUG_ON(_epqh->urbd);
 	_epqh->is_active=0;
 //	local_irq_restore(flags);
 }
@@ -332,6 +336,7 @@
 	if (!list_empty(&_epqh->urbd_list))
 		IFX_WARN("%s() invalid epqh state(not empty)\n",__func__);
 
+	IFX_BUG_ON(_epqh->urbd);
 	_epqh->is_active=0;
 	list_del_init(&_epqh->epqh_list_entry);
 	#ifdef __EPQD_DESTROY_TIMEOUT__
--- linux-2.6.32/drivers/usb/musb/ifxusb_plat.h
+++ linux-2.6.32/drivers/usb/musb/ifxusb_plat.h
@@ -1189,8 +1189,8 @@
 /*  Basic message printing. */
 #define IFX_PRINT(x...) avm_DebugPrintf(KERN_INFO IFXUSB x )
 
-#define IFX_WARN_ON(x...) if(x){IFX_WARN("WARN:%s in %s:line %u\n",##x,__func__,__LINE__);}
-#define IFX_BUG_ON(x...) if(x){IFX_ERROR("BUG:%s in %s:line %u\n",##x,__func__,__LINE__);}
+#define IFX_WARN_ON(x) if(x){IFX_WARN("WARN:%s in %s:line %u\n",#x,__func__,__LINE__);}
+#define IFX_BUG_ON(x) if(x){IFX_ERROR("BUG:%s in %s:line %u\n",#x,__func__,__LINE__);}
 
 #endif
 
--- linux-2.6.32/include/linux/avm_pa.h
+++ linux-2.6.32/include/linux/avm_pa.h
@@ -1,7 +1,7 @@
 /*
  *     Definitions for AVM packet acceleration
  *
- * Copyright (c) 2011-2013 AVM GmbH <info@avm.de>
+ * Copyright (c) 2011-2014 AVM GmbH <info@avm.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -137,7 +137,7 @@
    struct packet_type    *ptype; /* avm_pa_framing_ptype */
 };
 
-#define AVM_PA_PID_ECFG_VERSION 2
+#define AVM_PA_PID_ECFG_VERSION 3
 struct avm_pa_pid_ecfg {
     int           version;
 	/* version 0 */
@@ -152,6 +152,9 @@
 	/* version 2 */
 	void  (*rx_slow)(void *arg, PKT *pkt);
     void  *rx_slow_arg;
+	/* version 3 */
+#define AVM_PA_PID_GROUP_WLAN_STA             1
+	int   pid_group;
 };
 
 struct avm_pa_vpid_cfg {
--- linux-2.6.32/include/linux/netdevice.h
+++ linux-2.6.32/include/linux/netdevice.h
@@ -1531,6 +1531,9 @@
 
 extern int		netdev_budget;
 
+extern int acquire_offload_lock(struct net *net, const char *name);
+extern void release_offload_lock(int in_offload_lock);
+
 /* Called by rtnetlink.c:rtnl_unlock() */
 extern void netdev_run_todo(void);
 
--- linux-2.6.32/include/linux/tffs.h
+++ linux-2.6.32/include/linux/tffs.h
@@ -637,10 +637,8 @@
 extern unsigned int TFFS_Info(void *, unsigned int *);
 extern unsigned char *TFFS_Read_Buffer(void *, unsigned int **);
 extern unsigned char *TFFS_Write_Buffer(void *, unsigned int **);
-void tffs_panic_log_open(void);
-void tffs_panic_log_close(void);
-extern void tffs_panic_log_write(char *buffer, unsigned int len);
 extern unsigned int tffs_panic_log_suppress;
+void tffs_panic_log_printkbuf(void);
 void tffs_panic_log_register_spi(void);
 #endif /*--- #if defined(CONFIG_TFFS) ---*/
 
--- linux-2.6.32/include/linux/usb.h
+++ linux-2.6.32/include/linux/usb.h
@@ -192,6 +192,8 @@
 	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
 	unsigned reset_running:1;
+	/* -- 20140828 AVM/WK Patch from 2.6.34 for XHCI--*/
+	unsigned resetting_device:1;	/* true: bandwidth alloc after reset */
 
 	struct device dev;		/* interface specific device info */
 	struct device *usb_dev;
--- linux-2.6.32/kernel/panic.c
+++ linux-2.6.32/kernel/panic.c
@@ -31,8 +31,6 @@
 
 #ifdef CONFIG_TFFS_PANIC_LOG
 #include <linux/tffs.h>
-unsigned int tffs_panic_log_suppress = 0;
-EXPORT_SYMBOL(tffs_panic_log_suppress);
 #endif /*--- #ifdef CONFIG_TFFS_PANIC_LOG ---*/
 int panic_on_oops = 1;
 static unsigned long tainted_mask;
@@ -109,36 +107,7 @@
 	smp_send_stop();
 
 #ifdef CONFIG_TFFS_PANIC_LOG
-    if(tffs_panic_log_suppress == 0) {
-        unsigned long printk_get_buffer(char **p_log_buf, unsigned long *p_log_end, unsigned long *p_anzahl);
-        char *buf;
-        unsigned long end;
-        unsigned long anzahl;
-        unsigned long len = printk_get_buffer(&buf, &end, &anzahl);
-        struct timespec uptime;
-        static char time_stamp_buf[sizeof("UPTIME: \n") + 10 + sizeof("PANIC LOG VERSION 2.0\n")];
-        unsigned long time_stamp_buf_len;
-
-        tffs_panic_log_suppress = 1;
-        tffs_panic_log_open();
-        do_posix_clock_monotonic_gettime(&uptime);
-        monotonic_to_bootbased(&uptime);
-        time_stamp_buf_len = snprintf(time_stamp_buf, sizeof(time_stamp_buf), "UPTIME: %lu\nPANIC LOG VERSION 2.0\n", (unsigned long) uptime.tv_sec);
-        tffs_panic_log_write(time_stamp_buf, time_stamp_buf_len + 1);
-#if defined(CONFIG_AVM_WATCHDOG)
-        AVM_WATCHDOG_emergency_retrigger();
-#endif
-        if(anzahl < len) {  /*--- alles im Buffer ---*/
-            tffs_panic_log_write(buf, anzahl);
-        } else {
-            tffs_panic_log_write(buf + end, len - end);
-#if defined(CONFIG_AVM_WATCHDOG)
-            AVM_WATCHDOG_emergency_retrigger();
-#endif
-            tffs_panic_log_write(buf, end);
-        }
-        tffs_panic_log_close();
-    }
+	tffs_panic_log_printkbuf();
 #endif /*--- #ifdef CONFIG_TFFS_PANIC_LOG ---*/
 	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
 
--- linux-2.6.32/net/avm_pa/avm_pa.c
+++ linux-2.6.32/net/avm_pa/avm_pa.c
@@ -1,10 +1,10 @@
-#define AVM_PA_VERSION "4.3.8 2014-07-08"
+#define AVM_PA_VERSION "4.3.10 2014-09-21"
 /*
  * Packet Accelerator Interface
  *
  * vim:set expandtab shiftwidth=3 softtabstop=3:
  * 
- * Copyright (c) 2011-2013 AVM GmbH <info@avm.de>
+ * Copyright (c) 2011-2014 AVM GmbH <info@avm.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -83,6 +83,18 @@
  *   ACTIVE -> pa_kill_session()     -> DEAD
  *   DEAD   -> pa_session_gc()       -> FREE
  *
+ * Changes for 4.3.10:
+ * - pa_session_get lieferte sessions mit session_id 0
+ *   => alte Sessions in /proc/net/avm_pa/bessions
+ * - FUSIV: Session vom WLAN expireten immer sofort, da in
+ *          avm_pa_hardware_session_report() die Counter immer 0 sind.
+ * - FUSIV: Guard gegen Crashes in handle_fp_bridge_pkt() und
+ *          handle_fp_route_pkt() weil die Session in den Wald zeigt.
+ *
+ * Changes for 4.3.9:
+ * - Pid groups eingefuehrt (WLAN-Repeater 1750)
+ * - Ingress Pid change check only for unicast
+ *
  * Changes for 4.3.8:
  * - Bugfix: bridge packets were cut, when third position of
  *           mac address was 0x00, because ethernet header
@@ -370,8 +382,6 @@
 
 #define AVM_PA_PRIOACK_THRESH_PKTS   40   /* wait for X packets to do the TCP-ACK check */
 #define AVM_PA_PRIOACK_RATIO         70   /* % of packets have to be TCP-ACKs for positive check */
-#define AVM_PA_PRIOACK_PACKET_SIZE   120  /* packet-size to recognize a packet as TCP-ACK */
-#define AVM_PA_PRIOACK_PRIORITY      4    /* priority for TCP-ACK packets */
 
 /* ------------------------------------------------------------------------ */
 
@@ -390,10 +400,14 @@
                               tx_channel_activated:1,
                               rx_channel_stopped:1,
    /* prioack handling */
-                              prioack_enabled:1;
+                              prioack_enabled:1,
+                              tget_enabled:1; /* tget = turbo HTTP-GET */
    unsigned int               prioack_priority;
    unsigned                   prioack_acks;
    unsigned                   prioack_accl_acks;
+   unsigned int               tget_priority;
+   unsigned                   tgets;
+   unsigned                   tget_accl;
    
    /* stats */
    u32                        tx_pkts;
@@ -511,7 +525,6 @@
    unsigned                  tok_rate[TOK_SAMLES];
    unsigned                  tok_pps[TOK_SAMLES];
    unsigned long             tok_overlimit[TOK_SAMLES];
-   unsigned                  prioack_packet_size;
    unsigned                  prioack_thresh_packets;
    unsigned                  prioack_ratio;
    struct avm_hardware_pa    hardware_pa;
@@ -551,7 +564,6 @@
    .ewma_log = AVM_PA_EST_DEFAULT_EWMA_LOG,
    .cputime_est_idx = AVM_PA_CPUTIME_EST_DEFAULT_IDX,
    .cputime_ewma_log = AVM_PA_CPUTIME_EST_DEFAULT_EWMA_LOG,
-   .prioack_packet_size = AVM_PA_PRIOACK_PACKET_SIZE,
    .prioack_thresh_packets = AVM_PA_PRIOACK_THRESH_PKTS,
    .prioack_ratio = AVM_PA_PRIOACK_RATIO,
 };
@@ -1919,9 +1931,25 @@
    struct avm_pa_pkt_info *info = AVM_PKT_INFO(pkt);
 
    if (egress->not_local) {
-      if (pid->prioack_enabled && info->match.ack_only) {
-         egress->tcpack_pkts++;
-         pkt->priority =  pid->prioack_priority;
+      if (pid->prioack_enabled) {
+         if (info->match.ack_only) {
+            egress->tcpack_pkts++;
+            pkt->priority =  pid->prioack_priority;
+#if AVM_PA_TRACE
+            if (ctx->dbgprioacktrace)
+                pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s), reset tcpack prio to 0x%X\n",
+                          pkt->uniq_id & 0xffffff, pid->cfg.name, pkt->priority);
+#endif
+         } else if (pid->tget_enabled && (info->match.pkttype & AVM_PA_PKTTYPE_PROTO_MASK) == IPPROTO_TCP && egress->tx_pkts < ctx->prioack_thresh_packets) {
+            pkt->priority =  pid->tget_priority;
+#if AVM_PA_TRACE
+            if (ctx->dbgprioack)
+                pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s), reset tget prio to 0x%X\n",
+                          pkt->uniq_id & 0xffffff, pid->cfg.name, pkt->priority);
+#endif
+         } else {
+            pkt->priority = egress->output.priority;
+         }
       } else  {
          pkt->priority = egress->output.priority;
       }
@@ -1966,8 +1994,8 @@
       skb_set_network_header(pkt, egress->push_l2_len);
 #if AVM_PA_TRACE
       if (ctx->dbgtrace)
-         pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s)\n",
-                               pkt->uniq_id & 0xffffff, pid->cfg.name);
+         pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s), prio=0x%X, info->match.ack_only=%d\n",
+                               pkt->uniq_id & 0xffffff, pid->cfg.name, pkt->priority, info->match.ack_only);
 #endif
       (*pid->cfg.tx_func)(pid->cfg.tx_arg, pkt);
    } else {
@@ -2387,6 +2415,7 @@
    struct avm_pa_global *ctx = &pa_glob;
    u32 hash = macaddr_hash(mac);
    struct avm_pa_macaddr *p;
+   int pid_group = PA_PID(ctx, pid_handle)->ecfg.pid_group;
    int pid_changed = 0;
    AVM_PA_LOCK_DECLARE;
 
@@ -2394,9 +2423,13 @@
    
    for (p = ctx->macaddr_hash[hash%CONFIG_AVM_PA_MAX_SESSION]; p; p = p->link) {
       if (memcmp(mac, &p->mac, ETH_ALEN) == 0) {
-         if (   p->pid_handle != pid_handle
-             && PA_PID(ctx, p->pid_handle)->ingress_pid_handle != pid_handle)
-            pid_changed = 1;
+         if (p->pid_handle != pid_handle) {
+            struct avm_pa_pid *pid = PA_PID(ctx, p->pid_handle);
+            if (pid->ingress_pid_handle != pid_handle) {
+               if (pid_group == 0 || pid_group != pid->ecfg.pid_group)
+                  pid_changed = 1;
+            }
+         }
          break;
       }
    }
@@ -2591,7 +2624,7 @@
    struct avm_pa_session *session;
 
    session = PA_SESSION(ctx, session_handle);
-   if (!pa_session_valid(session))
+   if (!pa_session_valid(session) || session->session_handle == 0)
       session = 0;
    return session;
 }
@@ -2917,6 +2950,12 @@
          if (pid->prioack_enabled) {
             /*--- prompt = "ack prio pkts"; ---*/
             snprintf(buf, sizeof(buf), "%u (accl acks %u)", pid->prioack_acks, pid->prioack_accl_acks);
+            (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+         }
+         if (pid->tget_enabled) {
+            /*--- prompt = "ack prio pkts"; ---*/
+            snprintf(buf, sizeof(buf), "%u (accl %u)", pid->tgets, pid->tget_accl);
+            (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
          }
       } else {
          prompt = "Dest";
@@ -3609,8 +3648,10 @@
    if ((ethh = pa_get_ethhdr(pid->ingress_framing, pkt)) != 0) {
       if ((session = pa_bsession_search(pid, ethh_hash(ethh), ethh)) != 0)
          goto accelerate;
-      if ((pid->ecfg.flags & AVM_PA_PID_FLAG_NO_PID_CHANGED_CHECK) == 0)
-         pa_check_and_handle_ingress_pid_change(ethh->h_source, pid_handle);
+      if ((ethh->h_dest[0] & 1) == 0) {
+         if ((pid->ecfg.flags & AVM_PA_PID_FLAG_NO_PID_CHANGED_CHECK) == 0)
+            pa_check_and_handle_ingress_pid_change(ethh->h_source, pid_handle);
+      }
    }
 
    info->ingress_pid_handle = pid_handle;
@@ -3918,10 +3959,12 @@
    struct avm_pa_vpid *evpid;
    struct ethhdr *ethh;
    unsigned int orig_packet_prio;
+   unsigned int set_tget_prio;
    unsigned negress;
    int headroom;
    char buf[64];
    u32 hash; /* not used uninitialized */
+   int do_tget = 0;
 
 #if AVM_PA_TRACE
    if (ctx->dbgtrace) {
@@ -3940,25 +3983,33 @@
    
    if (!sk) {
       if (epid->prioack_enabled) {
+         int is_tcp = ((info->match.pkttype & AVM_PA_PKTTYPE_PROTO_MASK) == IPPROTO_TCP) ? 1 : 0;
          if (ctx->dbgprioacktrace) {
-            printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: info->match.syn=%d, info->match.ack_only=%d, PKT_LEN(pkt)=%d, pkt->priority=%x\n", 
-                   info->match.syn, info->match.ack_only, PKT_LEN(pkt), pkt->priority);
+            printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: info->match.syn=%d, info->match.ack_only=%d, is_tcp=%d, pid->tget_enabled=%d, epid->tget_priority=0x%X, PKT_LEN(pkt)=%d, pkt->priority=%x\n", 
+                   info->match.syn, info->match.ack_only, is_tcp, epid->tget_enabled, epid->tget_priority, PKT_LEN(pkt), pkt->priority);
          }
          if (info->match.syn || info->match.fin || info->match.ack_only) {
-            epid->prioack_acks++;
             /* change TCP-Ack priority */
+            epid->prioack_acks++;
             if (pkt->priority > epid->prioack_priority) {
                pkt->priority = epid->prioack_priority;
                epid->prioack_accl_acks++;
                if (ctx->dbgprioacktrace) {
-                  printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: reset priority to=%x\n", pkt->priority);
+                  printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: reset tcpack priority to=%x\n", pkt->priority);
                }
             } 
+         } else if (is_tcp && epid->tget_enabled) {
+            /* change TCP-GET priority */
+            //epid->tgets ++;
+            if (info->can_be_accelerated && pkt->priority > epid->tget_priority) {
+               set_tget_prio = epid->tget_priority;
+               do_tget = 1;
+            } 
          }
       }
    }
    if (ctx->dbgprioacktrace && epid->prioack_enabled) 
-        printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: priority=%x\n", pkt->priority);
+        printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: priority=%x, epid->tget_enabled=%d, info->can_be_accelerated=%d\n", pkt->priority, epid->tget_enabled, info->can_be_accelerated);
 
    if (!info->can_be_accelerated) {
       ctx->stats.tx_bypass++;
@@ -4025,6 +4076,23 @@
             return AVM_PA_TX_ERROR_SESSION;
          }
       }
+
+      if (do_tget) {
+         if (ctx->dbgprioack) {
+            printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: info->match.syn=%d, info->match.ack_only=%d, pid->tget_enabled=%d, PKT_LEN(pkt)=%d, pkt->priority=%x\n", 
+                   info->match.syn, info->match.ack_only, epid->tget_enabled, PKT_LEN(pkt), pkt->priority);
+         }
+         /* change TCP-GET priority */
+         epid->tgets ++;
+         if (pkt->priority > set_tget_prio) {
+            pkt->priority = set_tget_prio;
+            //epid->tget_accl++;
+            if (ctx->dbgprioack) {
+               printk(KERN_DEBUG "avm_pa_pid_snoop_transmit: reset tget priority to=%x\n", pkt->priority);
+            }
+         } 
+      }
+      
       /* Session State: CREATE */
       session->ingress_pid_handle = info->ingress_pid_handle;
       session->ingress_vpid_handle = info->ingress_vpid_handle;
@@ -4334,6 +4402,8 @@
       return -1;
    memset(&pid->ecfg, 0, sizeof(struct avm_pa_pid_ecfg));
    switch (ecfg->version) {
+      case 3:
+        pid->ecfg.pid_group = ecfg->pid_group;
       case 2:
         pid->ecfg.rx_slow = ecfg->rx_slow;
         pid->ecfg.rx_slow_arg = ecfg->rx_slow_arg;
@@ -4415,7 +4485,7 @@
                              pid->cfg.name,
                              pidflags2str(pid->ecfg.flags, buf, sizeof(buf)));
          if (pid->prioack_enabled)
-            (*fprintffunc)(arg, " ack prio 0x%x\n", pid->prioack_priority);
+            (*fprintffunc)(arg, " ack prio 0x%x (tget=%d, tget prio 0x%x)\n", pid->prioack_priority, pid->tget_enabled, pid->tget_priority);
          else
             (*fprintffunc)(arg, "\n");
       } else {
@@ -4430,7 +4500,7 @@
                              PA_PID(ctx, pid->ingress_pid_handle)->cfg.name,
                              pidflags2str(pid->ecfg.flags, buf, sizeof(buf)));
          if (pid->prioack_enabled)
-            (*fprintffunc)(arg, " ack prio 0x%x\n", pid->prioack_priority);
+            (*fprintffunc)(arg, " ack prio 0x%x (tget=%d, tget prio 0x%x)\n", pid->prioack_priority, pid->tget_enabled, pid->tget_priority);
          else
             (*fprintffunc)(arg, "\n");
       }
@@ -4608,6 +4678,8 @@
    }
    pid->prioack_enabled = enable ? 1 : 0;
    pid->prioack_priority = prio;
+   pid->tget_enabled = pid->prioack_enabled;
+   pid->tget_priority = prio-1;
    return 0;
 }
 EXPORT_SYMBOL(avm_pa_pid_activate_tcpackprio);
@@ -6099,7 +6171,6 @@
   
    seq_printf(seq, "Packet Threshold : %u\n",ctx->prioack_thresh_packets);
    seq_printf(seq, "Ratio            : %u\n",ctx->prioack_ratio);
-   seq_printf(seq, "ACK Size         : %u\n",ctx->prioack_packet_size);
    
    for (n=1; n < CONFIG_AVM_PA_MAX_PID; n++) {
       struct avm_pa_pid *pid = PA_PID(ctx, n);
@@ -6107,6 +6178,10 @@
       seq_printf(seq, "PID%d: ACK Priority     : %x\n",pid->pid_handle, pid->prioack_priority);
       seq_printf(seq, "PID%d: Detected ACKs    : %u\n",pid->pid_handle, pid->prioack_acks);
       seq_printf(seq, "PID%d: Accelerated ACKs : %u\n",pid->pid_handle, pid->prioack_accl_acks);
+      if (!pid->tget_enabled) continue;
+      seq_printf(seq, "PID%d: TGET Priority    : %x\n",pid->pid_handle, pid->tget_priority);
+      seq_printf(seq, "PID%d: Detected GETs    : %u\n",pid->pid_handle, pid->tgets);
+      seq_printf(seq, "PID%d: Accelerated GETs : %u\n",pid->pid_handle, pid->tget_accl);
    }
 
    return 0;
@@ -6551,6 +6626,8 @@
                   struct avm_pa_pid *pid = PA_PID(ctx, AVM_PA_DEVINFO(dev)->pid_handle);
                   pid->prioack_enabled = 1;
                   pid->prioack_priority = simple_strtoul(argv[3], 0, 10);
+                  pid->tget_enabled = 1;
+                  pid->tget_priority = pid->prioack_priority-1;
                   dev_put(dev);
                }
             }
@@ -6561,12 +6638,47 @@
                   struct avm_pa_pid *pid = PA_PID(ctx, AVM_PA_DEVINFO(dev)->pid_handle);
                   pid->prioack_enabled = 0;
                   pid->prioack_priority = 0;
+                  pid->tget_enabled = 0;
+                  pid->tget_priority = 0;
                   dev_put(dev);
                }
+            } else {
+               int n;
+               for (n=1; n < CONFIG_AVM_PA_MAX_PID; n++) {
+                  struct avm_pa_pid *pid = PA_PID(ctx, n);
+                  pid->prioack_enabled = 0;
+                  pid->prioack_priority = 0;
+                  pid->tget_enabled = 0;
+                  pid->tget_priority = 0;
+               }
+            }
+         } else if (strcmp(argv[1], "tgetenable") == 0) {
+            if (argv[2] && argv[3]) {
+               struct net_device *dev = dev_get_by_name(&init_net, argv[2]);
+               if (dev) {
+                  struct avm_pa_pid *pid = PA_PID(ctx, AVM_PA_DEVINFO(dev)->pid_handle);
+                  pid->tget_enabled = 1;
+                  pid->tget_priority = simple_strtoul(argv[3], 0, 10);
+                  dev_put(dev);
+               }
+            }
+         } else if (strcmp(argv[1], "tgetdisable") == 0) {
+            if (argv[2]) {
+               struct net_device *dev = dev_get_by_name(&init_net, argv[2]);
+               if (dev) {
+                  struct avm_pa_pid *pid = PA_PID(ctx, AVM_PA_DEVINFO(dev)->pid_handle);
+                  pid->tget_enabled = 0;
+                  pid->tget_priority = 0;
+                  dev_put(dev);
+               }
+            } else {
+               int n;
+               for (n=1; n < CONFIG_AVM_PA_MAX_PID; n++) {
+                  struct avm_pa_pid *pid = PA_PID(ctx, n);
+                  pid->tget_enabled = 0;
+                  pid->tget_priority = 0;
+               }
             }
-         } else if (strcmp(argv[1], "psize") == 0) {
-            if (argv[2]) val = simple_strtoul(argv[2], 0, 10);
-            if (val) ctx->prioack_packet_size = val;
          } else if (strcmp(argv[1], "pthresh") == 0) {
             if (argv[2]) val = simple_strtoul(argv[2], 0, 10);
             if (val) ctx->prioack_thresh_packets = val;
--- linux-2.6.32/net/avm_pa/avm_pa_fusiv.c
+++ linux-2.6.32/net/avm_pa/avm_pa_fusiv.c
@@ -1,8 +1,10 @@
-#ifdef CONFIG_FUSIV_VX180
+#if defined(CONFIG_FUSIV_VX180) || defined(CONFIG_FUSIV_VX185)
 /*
- * Copyright (c) 2011-2013 AVM GmbH <info@avm.de>
+ * Copyright (c) 2011-2014 AVM GmbH <info@avm.de>
  * All rights reserved.
  *
+ * vim:set expandtab shiftwidth=3 softtabstop=3:
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -49,6 +51,10 @@
 #include <netpro/apdefs.h>
 #include <netpro/userapi.h>
 #include <netpro/hostapif.h>
+#ifdef CONFIG_FUSIV_VX185
+#include <netpro/vx185/ftindex.h>
+#include <netpro/vx185/descriptorsdefs.h>
+#endif
 
 #include <netpro/apstatistics.h>
 
@@ -56,15 +62,19 @@
 #undef AVM_PA_FUSIV_TRACE
 
 #if defined(AVM_PA_FUSIV_DEBUG)
-#  define AVM_PA_FUSIV_DBG(a...) printk(KERN_ERR "[avm_pa_fusiv] " a);
+#define AVM_PA_FUSIV_DBG(a...) printk(KERN_ERR "[avm_pa_fusiv] " a);
 #else
-#  define AVM_PA_FUSIV_DBG(a...)
+#define AVM_PA_FUSIV_DBG(a...)
 #endif
 
 #if defined(AVM_PA_FUSIV_TRACE)
-#  define AVM_PA_FUSIV_TRC(a...) printk(KERN_ERR "[avm_pa_fusiv] " a);
+#define AVM_PA_FUSIV_TRC(a...) printk(KERN_ERR "[avm_pa_fusiv] " a);
 #else
-#  define AVM_PA_FUSIV_TRC(a...)
+#define AVM_PA_FUSIV_TRC(a...)
+#endif
+
+#ifdef CONFIG_FUSIV_VX185
+extern descInfo_t descinfo[];
 #endif
 
 extern newapIfStruct_t apArray[];
@@ -79,45 +89,51 @@
  * AVM PA fusiv
 \*------------------------------------------------------------------------------------------*/
 struct avm_pa_fusiv_session {
-    struct avm_pa_session *avm_session;
-    unsigned char valid_session;
-	unsigned char rxApId;
-	unsigned char txApId;
-	unsigned short flowhash;
-	enum fusivflowtype flowtype;
-	union 
-	{
-	   apFlowEntry_t     *v4;
-	   apIpv6FlowEntry_t *v6;
-	} flow;
-	apNewBridgeEntry_t *bridgeFlow;
-#ifdef CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-	apStatistics_t prevStat;
+   struct avm_pa_session *avm_session;
+   unsigned char valid_session;
+   unsigned char rxApId;
+   unsigned char txApId;
+   unsigned short flowhash;
+   enum fusivflowtype flowtype;
+   union {
+      apFlowEntry_t *v4;
+      apIpv6FlowEntry_t *v6;
+   } flow;
+   apNewBridgeEntry_t *bridgeFlow;
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   apStatistics_t prevStat;
 #endif
 };
 
 static int avm_pa_fusiv_add_session(struct avm_pa_session *avm_session);
 static int avm_pa_fusiv_remove_session(struct avm_pa_session *avm_session);
-int avm_pa_fusiv_try_to_accelerate(avm_pid_handle pid_handle, struct sk_buff *skb);
+int avm_pa_fusiv_try_to_accelerate(avm_pid_handle pid_handle,
+                                   struct sk_buff *skb);
 int avm_pa_fusiv_alloc_rx_channel(avm_pid_handle pid_handle);
 int avm_pa_fusiv_alloc_tx_channel(avm_pid_handle pid_handle);
 
-static DEFINE_SPINLOCK( session_list_lock );
+static DEFINE_SPINLOCK(session_list_lock);
 
 static struct avm_hardware_pa avm_pa_fusiv = {
-   .add_session               = avm_pa_fusiv_add_session,
-   .remove_session            = avm_pa_fusiv_remove_session,
-   .try_to_accelerate         = avm_pa_fusiv_try_to_accelerate,
-   .alloc_rx_channel          = avm_pa_fusiv_alloc_rx_channel,
-   .alloc_tx_channel          = avm_pa_fusiv_alloc_tx_channel,
-   .free_rx_channel           = NULL/*avm_pa_fusiv_free_rx_channel*/,
-   .free_tx_channel           = NULL/*avm_pa_fusiv_free_tx_channel*/,
+   .add_session = avm_pa_fusiv_add_session,
+   .remove_session = avm_pa_fusiv_remove_session,
+   .try_to_accelerate = avm_pa_fusiv_try_to_accelerate,
+   .alloc_rx_channel = avm_pa_fusiv_alloc_rx_channel,
+   .alloc_tx_channel = avm_pa_fusiv_alloc_tx_channel,
+   .free_rx_channel = NULL /* avm_pa_fusiv_free_rx_channel */ ,
+   .free_tx_channel = NULL /* avm_pa_fusiv_free_tx_channel */ ,
 };
 
+static struct avm_pa_fusiv_session
+   fusiv_session_array[CONFIG_AVM_PA_MAX_SESSION];
 
-static struct avm_pa_fusiv_session fusiv_session_array[CONFIG_AVM_PA_MAX_SESSION];
+static int inline avm_pa_fusiv_session_valid(struct avm_pa_fusiv_session *sess)
+{
+   return    sess >= &fusiv_session_array[0]
+          && sess < &fusiv_session_array[CONFIG_AVM_PA_MAX_SESSION];
+}
 
-#ifdef CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
 #define AVM_PA_FUSIV_STAT_POLLING_TIME 1
 static struct timer_list statistics_timer;
 #endif
@@ -127,693 +143,1025 @@
 
 static const char *mac2str(const void *cp, char *buf, size_t size)
 {
-    const unsigned char *mac = (const unsigned char *)cp;
-    snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X",
-                        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-    return buf;
+   const unsigned char *mac = (const unsigned char *) cp;
+
+   snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2],
+            mac[3], mac[4], mac[5]);
+   return buf;
 }
 
-/*------------------------------------------------------------------------------------------*\
-\*------------------------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------*/
 
-void handle_fp_bridge_pkt(apPreHeader_t *apBuf, struct net_device *dev) {
+void handle_fp_bridge_pkt(apPreHeader_t * apBuf, struct net_device *dev)
+{
 
-	struct sk_buff *skb;
-    apNewBridgeEntry_t *ap_bridge_entry;
-	
-	AVM_PA_FUSIV_TRC("call handle_fp_bridge_pkt\n");
+   struct sk_buff *skb;
+   apNewBridgeEntry_t *ap_bridge_entry;
 
-	ap_bridge_entry = (apNewBridgeEntry_t *)(PHYS_TO_K1(apBuf->matchedEntryAddr));
+   AVM_PA_FUSIV_TRC("call handle_fp_bridge_pkt\n");
 
-	if (ap_bridge_entry && ap_bridge_entry->userHandle) {
-	   struct avm_pa_fusiv_session *fusiv_session = 
-		  (struct avm_pa_fusiv_session *) (ap_bridge_entry->userHandle);
+   ap_bridge_entry = (apNewBridgeEntry_t *)(apBuf->matchedEntryAddr);
 
-	   if (fusiv_session->avm_session) {
-		   skb = (struct sk_buff *)translateApbuf2Mbuf(apBuf);
-		   avm_pa_tx_channel_accelerated_packet(fusiv_session->avm_session->egress[0].pid_handle, 
-				                                fusiv_session->avm_session->session_handle, 
-												skb);
-	       AVM_PA_FUSIV_TRC("handle_fp_bridge_pkt: packet accelerated (pid %u session %u) \n",
-				 fusiv_session->avm_session->egress[0].pid_handle, 
-				 fusiv_session->avm_session->session_handle);
-		   
-	   }
-	}
+   if (ap_bridge_entry) {
+#ifdef CONFIG_FUSIV_VX185
+      if ((unsigned int)ap_bridge_entry & (1 << FT_ENTRY_IN_LMEM_CHKFRMHOST_BIT))
+         ap_bridge_entry = (apNewBridgeEntry_t *)LMEM_PIO2CBUS(ap_bridge_entry);
+#endif
+      ap_bridge_entry = (apNewBridgeEntry_t *)PHYS_TO_K1(ap_bridge_entry);
+   }
+
+   if (ap_bridge_entry && ap_bridge_entry->userHandle) {
+      struct avm_pa_fusiv_session *fusiv_session =
+         (struct avm_pa_fusiv_session *) (ap_bridge_entry->userHandle);
+
+      if (unlikely(!avm_pa_fusiv_session_valid(fusiv_session))) {
+         if (net_ratelimit())
+            printk(KERN_ERR "handle_fp_bridge_pkt: avm session invalid %p\n",
+                            fusiv_session);
+         putCluster(apBuf);
+         return;
+      }
+
+      if (fusiv_session->avm_session) {
+         if ((skb = (struct sk_buff *) translateApbuf2Mbuf(apBuf)) != 0) {
+            avm_pa_tx_channel_accelerated_packet(fusiv_session->avm_session->
+                                                 egress[0].pid_handle,
+                                                 fusiv_session->
+                                                 avm_session->session_handle,
+                                                 skb);
+            AVM_PA_FUSIV_TRC
+               ("handle_fp_bridge_pkt: packet accelerated (pid %u session %u) \n",
+                fusiv_session->avm_session->egress[0].pid_handle,
+                fusiv_session->avm_session->session_handle);
+         }
+         return;
+      }
+   }
+   putCluster(apBuf);
 }
 
-void handle_fp_route_pkt(apPreHeader_t *apBuf, struct net_device *dev) {
+void handle_fp_route_pkt(apPreHeader_t * apBuf, struct net_device *dev)
+{
 
-	struct sk_buff *skb;
-    apFlowEntry_t *flow;
-	
-	AVM_PA_FUSIV_TRC("call handle_fp_route_pkt\n");
+   struct sk_buff *skb;
+   apFlowEntry_t *flow;
 
-	flow = (apFlowEntry_t *)(PHYS_TO_K1(apBuf->matchedEntryAddr));
+   AVM_PA_FUSIV_TRC("call handle_fp_route_pkt\n");
 
-	if (flow && flow->userHandle) {
-	   struct avm_pa_fusiv_session *fusiv_session = 
-		  (struct avm_pa_fusiv_session *) (flow->userHandle);
+   flow = (apFlowEntry_t *)(apBuf->matchedEntryAddr);
 
-	   if (fusiv_session->avm_session) {
-		   skb = (struct sk_buff *)translateApbuf2Mbuf(apBuf);
-		   avm_pa_tx_channel_accelerated_packet(fusiv_session->avm_session->egress[0].pid_handle, 
-				                                fusiv_session->avm_session->session_handle, 
-												skb);
-	       AVM_PA_FUSIV_TRC("handle_fp_route_pkt: packet accelerated (pid %u session %u) \n",
-				 fusiv_session->avm_session->egress[0].pid_handle, 
-				 fusiv_session->avm_session->session_handle);
-		   
-	   }
-	}
+   if (flow) {
+#ifdef CONFIG_FUSIV_VX185
+      if ((unsigned int)flow & (1 << FT_ENTRY_IN_LMEM_CHKFRMHOST_BIT))
+         flow = (apFlowEntry_t *)LMEM_PIO2CBUS(flow);
+#endif
+      flow = (apFlowEntry_t *)PHYS_TO_K1(flow);
+   }
+
+   if (flow && flow->userHandle) {
+      struct avm_pa_fusiv_session *fusiv_session =
+         (struct avm_pa_fusiv_session *) (flow->userHandle);
+
+      if (unlikely(!avm_pa_fusiv_session_valid(fusiv_session))) {
+         if (net_ratelimit())
+            printk(KERN_ERR "handle_fp_route_pkt: avm session invalid %p\n",
+                            fusiv_session);
+         putCluster(apBuf);
+         return;
+      }
+
+      if (fusiv_session->avm_session) {
+         if ((skb = (struct sk_buff *) translateApbuf2Mbuf(apBuf)) != 0) {
+            avm_pa_tx_channel_accelerated_packet(fusiv_session->avm_session->
+                                                 egress[0].pid_handle,
+                                                 fusiv_session->
+                                                 avm_session->session_handle,
+                                                 skb);
+            AVM_PA_FUSIV_TRC
+               ("handle_fp_route_pkt: packet accelerated (pid %u session %u) \n",
+                fusiv_session->avm_session->egress[0].pid_handle,
+                fusiv_session->avm_session->session_handle);
+         }
+         return;
+      }
+   }
+   putCluster(apBuf);
 }
 
-typedef void (*wlan_tx_cb)(void *,void *);
 #define MAX_SSID_LEN 6
+
 struct txInfo {
-	struct net_device *netdev;
-	wlan_tx_cb                 *fp;
-	unsigned char bssid[MAX_SSID_LEN];
+   struct net_device *netdev;
+   void (*fp) (apPreHeader_t *, struct net_device *);
+   unsigned char bssid[MAX_SSID_LEN];
 };
 
 struct txInfo tx_info_bridge = {
-	.fp = handle_fp_bridge_pkt,
+   .fp = handle_fp_bridge_pkt,
 };
 
 struct txInfo tx_info_route = {
-	.fp = handle_fp_route_pkt,
+   .fp = handle_fp_route_pkt,
 };
 
+static int avm_pa_fusiv_add_bridge_session(struct avm_pa_session *avm_session)
+{
+   apNewBridgeEntry_t bridgeEntry, *newBridgeEntry;
+   struct avm_pa_fusiv_session new_session;
+   struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
+   unsigned short hash;
+   unsigned long slock_flags;
+   int res = AVM_PA_TX_ERROR_SESSION;
+   int rc;
 
-static int avm_pa_fusiv_add_bridge_session(struct avm_pa_session *avm_session) {
-	apNewBridgeEntry_t bridgeEntry, *newBridgeEntry;
-    struct avm_pa_fusiv_session new_session;
-	struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
-	unsigned short hash;
-    unsigned long slock_flags;
-    int res = AVM_PA_TX_ERROR_SESSION;
-	int rc;
+   ingress_hw = avm_pa_pid_get_hwinfo(avm_session->ingress_pid_handle);
+   egress_hw = avm_pa_pid_get_hwinfo(avm_session->egress[0].pid_handle);
 
-	ingress_hw = avm_pa_pid_get_hwinfo( avm_session->ingress_pid_handle );
-	egress_hw  = avm_pa_pid_get_hwinfo( avm_session->egress[0].pid_handle );
+   if ((ingress_hw == NULL) || (egress_hw == NULL))
+      return res;
 
-	memset(&bridgeEntry, 0, sizeof (bridgeEntry));
+   /* == AVM/UGA 20140707 AP2AP/Bridging accallertion for WLAN/PERI AP ==
+    * reenabled since we most probably fixed the buffer leak in apClassify
+    */
+#if 0
+   /*
+    * == AVM/SKI 20140515 == AP2AP/Bridging accallertion for WLAN/PERI AP
+    * disabled because of currently unknown AP buffer leak. 
+    */
+   if (egress_hw->apId == PERI_ID)
+      return res;
+#endif
 
-	if (egress_hw->apId == PERI_ID) {
-	   bridgeEntry.egressList[0].pEgress = (void *)0xFFFFFFFF;
-	   bridgeEntry.egressList[1].pEgress = &tx_info_bridge;
-	   bridgeEntry.rxPort = (unsigned short)((K1_TO_PHYS (PERI_BASE_ADDR)) >> 16);
-	} else if (ingress_hw->apId == PERI_ID) {
-	   bridgeEntry.egressList[0].pEgress = (void *)(K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
-	   if (egress_hw->apId == MAC1_ID)
-		  bridgeEntry.rxPort = (unsigned short)((K1_TO_PHYS (MAC1_BASE_ADDR)) >> 16);
-	   else if (egress_hw->apId == MAC2_ID)
-		  bridgeEntry.rxPort = (unsigned short)((K1_TO_PHYS (MAC2_BASE_ADDR)) >> 16);
-	} else {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_bridge_session: unsupported bridging AP%u -> AP%u\n",
-			            ingress_hw->apId, egress_hw->apId);
-	   return res;
-	}
-	bridgeEntry.egressList[0].pFlowID = (void *)0;
-	bridgeEntry.used = 1;
-	bridgeEntry.vlanAddr = 1;
-	bridgeEntry.bridgeState = AP_BRIDGE_OPERATIONAL;
-    bridgeEntry.operations = (0x1 << AP_BRIDGE_VALID_BIT);
-	memcpy(bridgeEntry.macAddr, avm_session->bsession->ethh.h_dest, ETH_ALEN);
-	bridgeEntry.userHandle =  (unsigned int)&fusiv_session_array[ avm_session->session_handle ];
-	hash = apBridgeCalculateHash(ingress_hw->apId, &bridgeEntry);
+   memset(&bridgeEntry, 0, sizeof(bridgeEntry));
 
-	rc = apAddBridgeEntry(1, hash, &bridgeEntry, &newBridgeEntry);
+   if (egress_hw->apId == PERI_ID) {
+      bridgeEntry.egressList[0].pEgress = (void *) 0xFFFFFFFF;
+      bridgeEntry.egressList[1].pEgress = &tx_info_bridge;
+      bridgeEntry.rxPort =
+         (unsigned short) ((K1_TO_PHYS(PERI_BASE_ADDR)) >> 16);
+   } else if (ingress_hw->apId == PERI_ID) {
+      bridgeEntry.egressList[0].pEgress =
+         (void *) (K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
+      if (egress_hw->apId == MAC1_ID)
+         bridgeEntry.rxPort =
+            (unsigned short) ((K1_TO_PHYS(MAC1_BASE_ADDR)) >> 16);
+      else if (egress_hw->apId == MAC2_ID)
+         bridgeEntry.rxPort =
+            (unsigned short) ((K1_TO_PHYS(MAC2_BASE_ADDR)) >> 16);
+   } else {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_bridge_session: unsupported bridging AP%u -> AP%u\n",
+          ingress_hw->apId, egress_hw->apId);
+      return res;
+   }
+   bridgeEntry.egressList[0].pFlowID = (void *) 0;
+   bridgeEntry.used = 1;
+   bridgeEntry.vlanAddr = 1;
+   bridgeEntry.bridgeState = AP_BRIDGE_OPERATIONAL;
+   bridgeEntry.operations = (0x1 << AP_BRIDGE_VALID_BIT);
+   memcpy(bridgeEntry.macAddr, avm_session->bsession->ethh.h_dest, ETH_ALEN);
+   bridgeEntry.userHandle =
+      (unsigned int) &fusiv_session_array[avm_session->session_handle];
+   hash = apBridgeCalculateHash(ingress_hw->apId, &bridgeEntry);
 
-	if (rc != 0) {
-	   AVM_PA_FUSIV_DBG("apAddBridgeEntry returned %d\n", rc);
-	   return res;
-	}
+   rc = apAddBridgeEntry(1, hash, &bridgeEntry, &newBridgeEntry);
 
-	AVM_PA_FUSIV_DBG("apAddBridgeEntry successful hash %u\n", hash);
+   if (rc != 0) {
+      AVM_PA_FUSIV_DBG("apAddBridgeEntry returned %d\n", rc);
+      return res;
+   }
 
-	new_session.avm_session = avm_session;
-	new_session.valid_session = 1;
-	new_session.rxApId = ingress_hw->apId;
-	new_session.txApId = egress_hw->apId;
-	new_session.flowhash = hash;
-	new_session.bridgeFlow = newBridgeEntry;
-	new_session.flowtype = fusiv_bridge_flow;
+   AVM_PA_FUSIV_DBG("apAddBridgeEntry successful hash %u\n", hash);
 
-	// take_session_lock
-	spin_lock_irqsave( &session_list_lock, slock_flags);
-	if ( !fusiv_session_array[ avm_session->session_handle ].valid_session ){
-		fusiv_session_array[ avm_session->session_handle ] = new_session;
-		res = AVM_PA_TX_SESSION_ADDED;
-	} else {
-        AVM_PA_FUSIV_DBG("session add failed - double call for add by avm_pa?!");
-        dump_stack();
-	}
-	// release_session_lock
-	spin_unlock_irqrestore( &session_list_lock, slock_flags);
-	return res;
+   new_session.avm_session = avm_session;
+   new_session.valid_session = 1;
+   new_session.rxApId = ingress_hw->apId;
+   new_session.txApId = egress_hw->apId;
+   new_session.flowhash = hash;
+   new_session.bridgeFlow = newBridgeEntry;
+   new_session.flowtype = fusiv_bridge_flow;
+
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   memset(&new_session.prevStat, 0, sizeof(apStatistics_t));
+#endif
+
+   // take_session_lock
+   spin_lock_irqsave(&session_list_lock, slock_flags);
+   if (!fusiv_session_array[avm_session->session_handle].valid_session) {
+      fusiv_session_array[avm_session->session_handle] = new_session;
+      res = AVM_PA_TX_SESSION_ADDED;
+   } else {
+      UINT32 moved;
+      apDeleteBridgeEntry(1, hash, newBridgeEntry, &moved);
+      printk(KERN_CRIT "session add failed - double call for add by avm_pa?!");
+      dump_stack();
+   }
+   // release_session_lock
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
+   return res;
 }
 
+/*--------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------*/
 
-/*------------------------------------------------------------------------------------------*\
-\*------------------------------------------------------------------------------------------*/
+/* 
+ * TODO: fuer Vx185 muss die DESC ADDR richtig gesetzt werden, z.B.:
+ * COPY_DESC(DESC_SELECT_ROUTE_SNAT_PPPOE_PLAIN, flow.descAddr);
+ */
 
-static int avm_pa_fusiv_add_session_v4(struct avm_pa_session *avm_session) {
-    unsigned long slock_flags;
-    int i, rc;
-    struct avm_pa_fusiv_session new_session;
-    int res = AVM_PA_TX_ERROR_SESSION;
-	apFlowEntry_t flow;
-	apFlowEntry_t *newflow;
-	unsigned int proto, priority, mtu;
-	struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
-	unsigned short flowhash;
-	char srcmac[32], dstmac[32], insrc[32];
+static int avm_pa_fusiv_add_session_v4(struct avm_pa_session *avm_session)
+{
+   unsigned long slock_flags;
+   int i, rc;
+   struct avm_pa_fusiv_session new_session;
+   int res = AVM_PA_TX_ERROR_SESSION;
+   apFlowEntry_t flow;
+   apFlowEntry_t *newflow;
+   unsigned int proto, priority, mtu;
+   struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
+   unsigned short flowhash;
+   char srcmac[32], dstmac[32], insrc[32];
 
-	AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: start\n");
-	
-	ingress_hw = avm_pa_pid_get_hwinfo( avm_session->ingress_pid_handle );
-	egress_hw  = avm_pa_pid_get_hwinfo( avm_session->egress[0].pid_handle );
+   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: start\n");
 
-	proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
+   ingress_hw = avm_pa_pid_get_hwinfo(avm_session->ingress_pid_handle);
+   egress_hw = avm_pa_pid_get_hwinfo(avm_session->egress[0].pid_handle);
 
-	memset(&flow, 0, sizeof(flow));
-	flow.entryType = AP_TCP_UDP_ENTRY;
+   if (ingress_hw == 0 || egress_hw == 0)
+      return res;
 
-	for (i = 0; i < avm_session->ingress.nmatch; i++) {
-	   struct avm_pa_match_info *p = &avm_session->ingress.match[i];
-	   hdrunion_t *hdr = (hdrunion_t *)&avm_session->ingress.hdrcopy[p->offset + avm_session->ingress.hdroff];
-	   
-	   switch (p->type) {
-	   case AVM_PA_VLAN:
-		  break;
-	   case AVM_PA_ETH:
-		  memcpy(flow.inSrcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
-		  break;
-	   case AVM_PA_PPP:
-		  break;
-	   case AVM_PA_PPPOE:
-		  {
-			 flow.inSessionId = hdr->pppoeh.sid;
-		     flow.operations |= (1 << AP_CHECK_PPPOE_BIT);
-		  }
-		  break;
-	   case AVM_PA_IPV4:
-		  flow.srcIPAddr = hdr->iph.saddr;
-		  flow.dstIPAddr = hdr->iph.daddr;
-		  flow.pktInfo.l3Proto.proto = proto;
-		  break;
-	   case AVM_PA_IPV6:
-		  break;
-	   case AVM_PA_PORTS:
-		  flow.otherInfo.tcpUdpInfo.srcPort = ntohs(hdr->ports[0]);
-		  flow.otherInfo.tcpUdpInfo.dstPort = ntohs(hdr->ports[1]);
-		  break;
-	   default:
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: can not accelerate, unsupported ingress match type %d \n", p->type);
-		  return res;
-	   }
-	}
+   proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
 
-	for (i = 0; i < avm_session->egress[0].match.nmatch; i++) {
-	   struct avm_pa_match_info *p = avm_session->egress[0].match.match+i;
-	   hdrunion_t *hdr = (hdrunion_t *)&avm_session->egress[0].match.hdrcopy[p->offset + avm_session->egress[0].match.hdroff ];
-		
-	   switch (p->type) {
-	   case AVM_PA_VLAN:
-		  if (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT))
-			 return AVM_PA_TX_ERROR_SESSION;
-	      flow.vlanId = hdr->vlanh.vlan_tci;
-	      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
-		  break;
-	   case AVM_PA_ETH:
-		  memcpy(flow.srcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
-		  memcpy(flow.dstMacAddr, &hdr->ethh.h_dest, ETH_ALEN);
-		  flow.operations |= (1 << AP_DO_ETH_HDR_BIT);
-		  break;
-	   case AVM_PA_PPP:
-		  break;
-	   case AVM_PA_PPPOE:
-		  {
-			 struct pppoehdr *pppoe_hdr = (struct pppoehdr *)(avm_session->egress[0].match.hdrcopy 
-									   + avm_session->egress[0].match.hdroff + avm_session->egress[0].pppoe_offset);
-			 flow.outSessionId = pppoe_hdr->sid;
-			 flow.operations |= (1 << AP_ADD_PPPOE_HDR_BIT);
-			 break;
-		  }
-	   case AVM_PA_IPV4:
-		  break;
-	   case AVM_PA_IPV6:
-		  memcpy(flow.srcIpv6Addr, hdr->ipv6h.saddr.s6_addr32, 16);
-		  memcpy(flow.dstIpv6Addr, hdr->ipv6h.daddr.s6_addr32, 16);
-		  flow.operations |= (1 << AP_IPV4_TO_IPV6_TUNNEL_BIT);
-		  break;
-	   case AVM_PA_PORTS:
-		  break;
-	   default:
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: can not accelerate, unsupported egress match type %d \n", p->type);
-		  break;
-	   }
-	}
+   memset(&flow, 0, sizeof(flow));
+#ifdef CONFIG_FUSIV_VX180
+   flow.entryType = AP_TCP_UDP_ENTRY;
+#endif
 
-	/* ATA -> LAN: add port VLAN for WAN Port */
-	if (   (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT)) == 0
-		&& (egress_hw->apId == MAC1_ID) && (ingress_hw->apId == MAC1_ID)
-		&& (avm_session->egress[0].pid_handle != avm_session->ingress_pid_handle)) {
-	   flow.vlanId = avm_cpmac_get_wan_port_vlan();
-	   flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
-	}
+   for (i = 0; i < avm_session->ingress.nmatch; i++) {
+      struct avm_pa_match_info *p = &avm_session->ingress.match[i];
+      hdrunion_t *hdr =
+         (hdrunion_t *) & avm_session->ingress.hdrcopy[p->offset +
+                                                       avm_session->ingress.
+                                                       hdroff];
 
-#if CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-	memset(&flow.apStatistics, 0, sizeof(apStatistics_t));
-    memset(&new_session.prevStat, 0, sizeof(apStatistics_t));
+      switch (p->type) {
+         case AVM_PA_VLAN:
+            break;
+         case AVM_PA_ETH:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(flow.inSrcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
+#else
+            memcpy(flow.apCompare.fields.inMAC, &hdr->ethh.h_source, ETH_ALEN);
 #endif
+            break;
+         case AVM_PA_PPP:
+            break;
+         case AVM_PA_PPPOE:
+            {
+#ifdef CONFIG_FUSIV_VX180
+               flow.inSessionId = hdr->pppoeh.sid;
+#else
+               flow.apCompare.inSessionID = hdr->pppoeh.sid;
+#endif
+               flow.operations |= (1 << AP_CHECK_PPPOE_BIT);
+            }
+            break;
+         case AVM_PA_IPV4:
+#ifdef CONFIG_FUSIV_VX180
+            flow.srcIPAddr = hdr->iph.saddr;
+            flow.dstIPAddr = hdr->iph.daddr;
+            flow.pktInfo.l3Proto.proto = proto;
+#else
+            flow.apCompare.srcIP = hdr->iph.saddr;
+            flow.apCompare.dstIP = hdr->iph.daddr;
+            flow.apCompare.protocol = proto;
+#endif
+            break;
+         case AVM_PA_IPV6:
+            break;
+         case AVM_PA_PORTS:
+#ifdef CONFIG_FUSIV_VX180
+            flow.otherInfo.tcpUdpInfo.srcPort = ntohs(hdr->ports[0]);
+            flow.otherInfo.tcpUdpInfo.dstPort = ntohs(hdr->ports[1]);
+#else
+            flow.apCompare.fields.ports.srcPort = ntohs(hdr->ports[0]);
+            flow.apCompare.fields.ports.dstPort = ntohs(hdr->ports[1]);
+#endif
+            break;
+         default:
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_add_session_v4: can not accelerate, unsupported ingress match type %d\n",
+                p->type);
+            return res;
+      }
+   }
 
-	if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_DADDR) {
-	   flow.natDstIPAddr = avm_session->mod.v4_mod.daddr;
-	   flow.natDstPort = flow.otherInfo.tcpUdpInfo.dstPort;
-	   flow.operations |= (1 << AP_DO_DST_NAT_BIT);
-	}
-	if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_DPORT) {
-	   flow.natDstPort = avm_session->mod.v4_mod.dport;
-	   flow.operations |= (1 << AP_DO_DST_NAT_BIT);
-	}
-	if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_SADDR) {
-	   flow.natIPAddr = avm_session->mod.v4_mod.saddr;
-	   flow.natPort = flow.otherInfo.tcpUdpInfo.srcPort;
-	   flow.operations |= (1 << AP_DO_SRC_NAT_BIT);
-	}
-	if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_SPORT) {
-	   flow.natPort = avm_session->mod.v4_mod.sport;
-	   flow.operations |= (1 << AP_DO_SRC_NAT_BIT);
-	}
+   for (i = 0; i < avm_session->egress[0].match.nmatch; i++) {
+      struct avm_pa_match_info *p = avm_session->egress[0].match.match + i;
+      hdrunion_t *hdr =
+         (hdrunion_t *) & avm_session->egress[0].match.hdrcopy[p->offset +
+                                                               avm_session->
+                                                               egress[0].match.
+                                                               hdroff];
 
-	priority = avm_session->egress[0].output.priority;
-	priority = (priority & TC_H_MIN_MASK);
-	if (priority > 7) priority = 7;
-	flow.egressList[0].pFlowID = (void *) priority;
+      switch (p->type) {
+         case AVM_PA_VLAN:
+            if (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT))
+               return AVM_PA_TX_ERROR_SESSION;
+#ifdef CONFIG_FUSIV_VX180
+            flow.vlanId = hdr->vlanh.vlan_tci;
+#else
+            flow.apModify.vlanID = hdr->vlanh.vlan_tci;
+            flow.apModify.etherType = 0x8100;
+#endif
+            flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+            break;
+         case AVM_PA_ETH:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(flow.srcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
+            memcpy(flow.dstMacAddr, &hdr->ethh.h_dest, ETH_ALEN);
+#else
+            memcpy(flow.apModify.srcMAC, &hdr->ethh.h_source, ETH_ALEN);
+            memcpy(flow.apModify.dstMAC, &hdr->ethh.h_dest, ETH_ALEN);
+#endif
+            flow.operations |= (1 << AP_DO_ETH_HDR_BIT);
+            break;
+         case AVM_PA_PPP:
+            break;
+         case AVM_PA_PPPOE:
+            {
+               struct pppoehdr *pppoe_hdr =
+                  (struct pppoehdr *) (avm_session->egress[0].match.hdrcopy +
+                                       avm_session->egress[0].match.hdroff +
+                                       avm_session->egress[0].pppoe_offset);
+#ifdef CONFIG_FUSIV_VX180
+               flow.outSessionId = pppoe_hdr->sid;
+#else
+               flow.apModify.sessionID = pppoe_hdr->sid;
+               flow.apModify.etherType = 0x8864;
+#endif
+               flow.operations |= (1 << AP_ADD_PPPOE_HDR_BIT);
+               break;
+            }
+         case AVM_PA_IPV4:
+            break;
+         case AVM_PA_IPV6:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(flow.srcIpv6Addr, hdr->ipv6h.saddr.s6_addr32, 16);
+            memcpy(flow.dstIpv6Addr, hdr->ipv6h.daddr.s6_addr32, 16);
+            flow.operations |= (1 << AP_IPV4_TO_IPV6_TUNNEL_BIT);
+#endif
+            break;
+         case AVM_PA_PORTS:
+            break;
+         default:
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_add_session_v4: can not accelerate, unsupported egress match type %d\n",
+                p->type);
+            break;
+      }
+   }
 
-	mtu = avm_session->egress[0].mtu;
-	flow.egressList[0].pFlowID = (void *)((UINT32)flow.egressList[0].pFlowID |
-		              (UINT32)(mtu) << MTU_SIZE_OFFSET_INSIDE_FLOW_ID);
+   /*
+    * ATA -> LAN: add port VLAN for WAN Port 
+    */
+   if ((flow.operations & (1 << AP_ADD_VLAN_HDR_BIT)) == 0
+       && (egress_hw->apId == MAC1_ID) && (ingress_hw->apId == MAC1_ID)
+       && (avm_session->egress[0].pid_handle !=
+           avm_session->ingress_pid_handle)) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.vlanId = avm_cpmac_get_wan_port_vlan();
+      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+#else
+      flow.apModify.vlanID = avm_cpmac_get_wan_port_vlan();
+      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+#endif
+   }
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   memset(&flow.apStatistics, 0, sizeof(apStatistics_t));
+   memset(&new_session.prevStat, 0, sizeof(apStatistics_t));
+#endif
+
+   if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_DADDR) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.natDstIPAddr = avm_session->mod.v4_mod.daddr;
+      flow.natDstPort = flow.otherInfo.tcpUdpInfo.dstPort;
+#else
+      flow.apModify.natIP = avm_session->mod.v4_mod.daddr;
+      flow.apModify.natPort = flow.apCompare.fields.ports.dstPort;
+#endif
+      flow.operations |= (1 << AP_DO_DST_NAT_BIT);
+   }
+   if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_DPORT) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.natDstPort = avm_session->mod.v4_mod.dport;
+#else
+      flow.apModify.natPort = avm_session->mod.v4_mod.dport;
+#endif
+      flow.operations |= (1 << AP_DO_DST_NAT_BIT);
+   }
+   if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_SADDR) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.natIPAddr = avm_session->mod.v4_mod.saddr;
+      flow.natPort = flow.otherInfo.tcpUdpInfo.srcPort;
+#else
+      flow.apModify.natIP = avm_session->mod.v4_mod.saddr;
+      flow.apModify.natPort = flow.apCompare.fields.ports.srcPort;
+#endif
+      flow.operations |= (1 << AP_DO_SRC_NAT_BIT);
+   }
+   if (avm_session->mod.v4_mod.flags & AVM_PA_V4_MOD_SPORT) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.natPort = avm_session->mod.v4_mod.sport;
+#else
+      flow.apModify.natPort = avm_session->mod.v4_mod.sport;
+#endif
+      flow.operations |= (1 << AP_DO_SRC_NAT_BIT);
+   }
+
+   priority = avm_session->egress[0].output.priority;
+   priority = (priority & TC_H_MIN_MASK);
+   if (priority > 7)
+      priority = 7;
+   flow.egressList[0].pFlowID = (void *) priority;
+
+   mtu = avm_session->egress[0].mtu;
+   flow.egressList[0].pFlowID = (void *) ((UINT32) flow.egressList[0].pFlowID |
+                                          (UINT32) (mtu) <<
+                                          MTU_SIZE_OFFSET_INSIDE_FLOW_ID);
 
    if (egress_hw->apId == PERI_ID) {
-	   flow.egressList[0].pEgress = (void *)0xFFFFFFFF;
-	   flow.egressList[1].pEgress = &tx_info_route;
-	} else {
-	   flow.egressList[0].pEgress = (void *)(K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
-	}
+      flow.egressList[0].pEgress = (void *) 0xFFFFFFFF;
+      flow.egressList[1].pEgress = &tx_info_route;
+   } else {
+      flow.egressList[0].pEgress =
+         (void *) (K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
+   }
 
-	flow.userHandle = (unsigned int)&fusiv_session_array[ avm_session->session_handle ];
-	flow.operations |= (0x1 << AP_ROUTE_VALID_BIT);
+   flow.userHandle =
+      (unsigned int) &fusiv_session_array[avm_session->session_handle];
+   flow.operations |= (0x1 << AP_ROUTE_VALID_BIT);
 
-	flowhash = apCalculateHash(ingress_hw->apId, &flow);
+   flowhash = apCalculateHash(ingress_hw->apId, &flow);
 
-	rc = apAddFlowEntry(ingress_hw->apId, flowhash, &flow, &newflow);
+   rc = apAddFlowEntry(ingress_hw->apId, flowhash, &flow, &newflow);
 
-	if (rc != 0) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: can not accelerate, apAddFlowEntry returned %d \n", rc);
-	   return res;
-	}
+   if (rc != 0) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session_v4: can not accelerate, apAddFlowEntry returned %d\n",
+          rc);
+      return res;
+   }
 
-	new_session.avm_session = avm_session;
-	new_session.valid_session = 1;
-	new_session.rxApId = ingress_hw->apId;
-	new_session.txApId = egress_hw->apId;
-	new_session.flowhash = flowhash;
-	new_session.flow.v4 = newflow;
-	new_session.flowtype = fusiv_flow_v4;
+   new_session.avm_session = avm_session;
+   new_session.valid_session = 1;
+   new_session.rxApId = ingress_hw->apId;
+   new_session.txApId = egress_hw->apId;
+   new_session.flowhash = flowhash;
+   new_session.flow.v4 = newflow;
+   new_session.flowtype = fusiv_flow_v4;
+   new_session.bridgeFlow = 0;
 
-    mac2str(flow.srcMacAddr, srcmac, sizeof(srcmac));
-    mac2str(flow.dstMacAddr, dstmac, sizeof(dstmac));
-    mac2str(flow.inSrcMacAddr, insrc, sizeof(insrc));
-	AVM_PA_FUSIV_DBG("apAddFlowEntry: AP#%d->AP#%d srcmac %s dstmac %s insrc %s\n",
-		   ingress_hw->apId, egress_hw->apId, srcmac, dstmac, insrc);
-	
-	// take_session_lock
-	spin_lock_irqsave( &session_list_lock, slock_flags);
-	if ( !fusiv_session_array[ avm_session->session_handle ].valid_session ){
-		fusiv_session_array[ avm_session->session_handle ] = new_session;
-		res = AVM_PA_TX_SESSION_ADDED;
-	} else {
-        AVM_PA_FUSIV_DBG("session add failed - double call for add by avm_pa?!");
-        dump_stack();
-	}
-	// release_session_lock
-	spin_unlock_irqrestore( &session_list_lock, slock_flags);
+#ifdef CONFIG_FUSIV_VX180
+   mac2str(flow.srcMacAddr, srcmac, sizeof(srcmac));
+   mac2str(flow.dstMacAddr, dstmac, sizeof(dstmac));
+   mac2str(flow.inSrcMacAddr, insrc, sizeof(insrc));
+#else
+   mac2str(flow.apModify.srcMAC, srcmac, sizeof(srcmac));
+   mac2str(flow.apModify.dstMAC, dstmac, sizeof(dstmac));
+   mac2str(flow.apCompare.fields.inMAC, insrc, sizeof(insrc));
+#endif
+   AVM_PA_FUSIV_DBG
+      ("apAddFlowEntry: AP#%d->AP#%d srcmac %s dstmac %s insrc %s\n",
+       ingress_hw->apId, egress_hw->apId, srcmac, dstmac, insrc);
 
-	AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: done\n");
+   // take_session_lock
+   spin_lock_irqsave(&session_list_lock, slock_flags);
+   if (!fusiv_session_array[avm_session->session_handle].valid_session) {
+      fusiv_session_array[avm_session->session_handle] = new_session;
+      res = AVM_PA_TX_SESSION_ADDED;
+   } else {
+      UINT32 moved;
+      if (apDeleteFlowEntry(ingress_hw->apId, flowhash, newflow, &moved) == 0) {
+         if (moved) {
+            struct avm_pa_fusiv_session *fusiv_session = (struct avm_pa_fusiv_session *) (newflow->userHandle);
+            fusiv_session->flow.v4 = newflow;
+         }
+      }
+      printk(KERN_CRIT "session add failed - double call for add by avm_pa?!");
+      dump_stack();
+   }
+   // release_session_lock
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
 
-    return res;
+   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v4: done\n");
+
+   return res;
 }
 
-static int avm_pa_fusiv_add_session_v6(struct avm_pa_session *avm_session) {
-    unsigned long slock_flags;
-    int i, rc;
-    struct avm_pa_fusiv_session new_session;
-    int res = AVM_PA_TX_ERROR_SESSION;
-	apIpv6FlowEntry_t flow;
-	apIpv6FlowEntry_t *newflow;
-	unsigned int proto, priority;
-	struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
-	unsigned short flowhash;
-	char srcmac[32], dstmac[32], insrc[32];
+static int avm_pa_fusiv_add_session_v6(struct avm_pa_session *avm_session)
+{
+   unsigned long slock_flags;
+   int i, rc;
+   struct avm_pa_fusiv_session new_session;
+   int res = AVM_PA_TX_ERROR_SESSION;
+   apIpv6FlowEntry_t flow;
+   apIpv6FlowEntry_t *newflow;
+   unsigned int proto, priority;
+   struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
+   unsigned short flowhash;
+   char srcmac[32], dstmac[32], insrc[32];
 
-	AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: start\n");
-	
-	ingress_hw = avm_pa_pid_get_hwinfo( avm_session->ingress_pid_handle );
-	egress_hw  = avm_pa_pid_get_hwinfo( avm_session->egress[0].pid_handle );
+   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: start\n");
 
-	proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
+   ingress_hw = avm_pa_pid_get_hwinfo(avm_session->ingress_pid_handle);
+   egress_hw = avm_pa_pid_get_hwinfo(avm_session->egress[0].pid_handle);
 
-	memset(&flow, 0, sizeof(flow));
+   if (ingress_hw == 0 || egress_hw == 0)
+      return res;
 
-	if (proto == IPPROTO_UDP)
-	   flow.entryType = AP_UDP_ENTRY;
-	else if (proto == IPPROTO_TCP)
-	   flow.entryType = AP_TCP_ENTRY;
-	else {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: unsupported protocol %u\n", proto);
-	   return res;
-	}
+   if (ingress_hw->apId == PERI_ID || egress_hw->apId == PERI_ID)
+      return res;
 
-	for (i = 0; i < avm_session->ingress.nmatch; i++) {
-	   struct avm_pa_match_info *p = &avm_session->ingress.match[i];
-	   hdrunion_t *hdr = (hdrunion_t *)&avm_session->ingress.hdrcopy[p->offset + avm_session->ingress.hdroff];
-	   
-	   switch (p->type) {
-	   case AVM_PA_VLAN:
-		  break;
-	   case AVM_PA_ETH:
-		  memcpy(&flow.inSrcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
-		  break;
-	   case AVM_PA_PPP:
-		  break;
-	   case AVM_PA_PPPOE:
-		  {
-			 flow.inSessionId = hdr->pppoeh.sid;
-		     flow.operations |= (1 << AP_CHECK_PPPOE_BIT);
-		  }
-		  break;
-	   case AVM_PA_IPV4:
-		  break;
-	   case AVM_PA_IPV6:
-		  memcpy(flow.srcIpv6Addr, hdr->ipv6h.saddr.s6_addr32, 16);
-		  memcpy(flow.dstIpv6Addr, hdr->ipv6h.daddr.s6_addr32, 16);
-		  break;
-	   case AVM_PA_PORTS:
-		  flow.otherInfo.tcpUdpInfo.srcPort = ntohs(hdr->ports[0]);
-		  flow.otherInfo.tcpUdpInfo.dstPort = ntohs(hdr->ports[1]);
-		  break;
-	   default:
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: can not accelerate, unsupported ingress match type %d \n", p->type);
-		  return res;
-	   }
-	}
+   proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
 
-	for (i = 0; i < avm_session->egress[0].match.nmatch; i++) {
-	   struct avm_pa_match_info *p = avm_session->egress[0].match.match+i;
-	   hdrunion_t *hdr = (hdrunion_t *)&avm_session->egress[0].match.hdrcopy[p->offset + avm_session->egress[0].match.hdroff ];
-		
-	   switch (p->type) {
-	   case AVM_PA_VLAN:
-	      if (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT))
-		     return AVM_PA_TX_ERROR_SESSION;
-	      flow.vlanId = hdr->vlanh.vlan_tci;
-	      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
-		  break;
-	   case AVM_PA_ETH:
-		  memcpy(flow.srcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
-		  memcpy(flow.dstMacAddr, &hdr->ethh.h_dest, ETH_ALEN);
-		  flow.operations |= (1 << AP_DO_ETH_HDR_BIT);
-		  break;
-	   case AVM_PA_PPP:
-		  break;
-	   case AVM_PA_PPPOE:
-		  {
-			 struct pppoehdr *pppoe_hdr = (struct pppoehdr *)(avm_session->egress[0].match.hdrcopy 
-									   + avm_session->egress[0].match.hdroff + avm_session->egress[0].pppoe_offset);
-			 flow.outSessionId = pppoe_hdr->sid;
-			 flow.operations |= (1 << AP_ADD_PPPOE_HDR_BIT);
-			 break;
-		  }
-	   case AVM_PA_IPV4:
-		  flow.srcIPAddr = hdr->iph.saddr;
-		  flow.dstIPAddr = hdr->iph.daddr;
-		  flow.operations |= (0x1 << AP_IPV6_TO_IPV4_TUNNEL_BIT);
-		  break;
-	   case AVM_PA_IPV6:
-		  break;
-	   case AVM_PA_PORTS:
-		  break;
-	   default:
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: can not accelerate, unsupported egress match type %d \n", p->type);
-		  break;
-	   }
-	}
+   memset(&flow, 0, sizeof(flow));
 
-	/* ATA -> LAN: add port VLAN for WAN Port */
-	if (   (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT)) == 0
-	    && (egress_hw->apId == MAC1_ID) && (ingress_hw->apId == MAC1_ID)
-		&& (avm_session->egress[0].pid_handle != avm_session->ingress_pid_handle)) {
-	   flow.vlanId = avm_cpmac_get_wan_port_vlan();
-	   flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
-	}
+#ifdef CONFIG_FUSIV_VX180
+   if (proto == IPPROTO_UDP) {
+      flow.entryType = AP_UDP_ENTRY;
+   } else if (proto == IPPROTO_TCP) {
+      flow.entryType = AP_TCP_ENTRY;
+   } else {
+      AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: unsupported protocol %u\n",
+                       proto);
+      return res;
+   }
+#endif
 
-#if CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-	memset(&flow.apStatistics, 0, sizeof(apStatistics_t));
-    memset(&new_session.prevStat, 0, sizeof(apStatistics_t));
+   for (i = 0; i < avm_session->ingress.nmatch; i++) {
+      struct avm_pa_match_info *p = &avm_session->ingress.match[i];
+      hdrunion_t *hdr =
+         (hdrunion_t *) & avm_session->ingress.hdrcopy[p->offset +
+                                                       avm_session->ingress.
+                                                       hdroff];
+
+      switch (p->type) {
+         case AVM_PA_VLAN:
+            break;
+         case AVM_PA_ETH:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(&flow.inSrcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
+#else
+            memcpy(&flow.apCompare.inMAC, &hdr->ethh.h_source, ETH_ALEN);
 #endif
+            break;
+         case AVM_PA_PPP:
+            break;
+         case AVM_PA_PPPOE:
+            {
+#ifdef CONFIG_FUSIV_VX180
+               flow.inSessionId = hdr->pppoeh.sid;
+#else
+               flow.apCompare.inSessionID = hdr->pppoeh.sid;
+#endif
+               flow.operations |= (1 << AP_CHECK_PPPOE_BIT);
+            }
+            break;
+         case AVM_PA_IPV4:
+            break;
+         case AVM_PA_IPV6:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(flow.srcIpv6Addr, hdr->ipv6h.saddr.s6_addr32, 16);
+            memcpy(flow.dstIpv6Addr, hdr->ipv6h.daddr.s6_addr32, 16);
+#else
+            memcpy(flow.apCompare.srcIpv6Addr, hdr->ipv6h.saddr.s6_addr32, 16);
+            memcpy(flow.apCompare.dstIpv6Addr, hdr->ipv6h.daddr.s6_addr32, 16);
+#endif
+            break;
+         case AVM_PA_PORTS:
+#ifdef CONFIG_FUSIV_VX180
+            flow.otherInfo.tcpUdpInfo.srcPort = ntohs(hdr->ports[0]);
+            flow.otherInfo.tcpUdpInfo.dstPort = ntohs(hdr->ports[1]);
+#else
+            flow.apCompare.fields.ports.srcPort = ntohs(hdr->ports[0]);
+            flow.apCompare.fields.ports.dstPort = ntohs(hdr->ports[1]);
+#endif
+            break;
+         default:
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_add_session_v6: can not accelerate, unsupported ingress match type %d\n",
+                p->type);
+            return res;
+      }
+   }
 
-	priority = avm_session->egress[0].output.priority;
-	priority = (priority & TC_H_MIN_MASK);
-	if (priority > 7) priority = 7;
+   for (i = 0; i < avm_session->egress[0].match.nmatch; i++) {
+      struct avm_pa_match_info *p = avm_session->egress[0].match.match + i;
+      hdrunion_t *hdr =
+         (hdrunion_t *) & avm_session->egress[0].match.hdrcopy[p->offset +
+                                                               avm_session->
+                                                               egress[0].match.
+                                                               hdroff];
 
-	flow.userHandle = (unsigned int)&fusiv_session_array[ avm_session->session_handle ];
-	flow.egressList[0].pEgress = (void *)(K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
-	flow.egressList[0].pFlowID = (void *) priority;
-	flow.operations |= (0x1 << AP_ROUTE_VALID_BIT);
+      switch (p->type) {
+         case AVM_PA_VLAN:
+            if (flow.operations & (1 << AP_ADD_VLAN_HDR_BIT))
+               return AVM_PA_TX_ERROR_SESSION;
 
-	flowhash = apIpv6CalculateHash(ingress_hw->apId, &flow);
+#ifdef CONFIG_FUSIV_VX180
+            flow.vlanId = hdr->vlanh.vlan_tci;
+#else
+            flow.apModify.vlanID = hdr->vlanh.vlan_tci;
+#endif
+            flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+            break;
+         case AVM_PA_ETH:
+#ifdef CONFIG_FUSIV_VX180
+            memcpy(flow.srcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
+            memcpy(flow.dstMacAddr, &hdr->ethh.h_dest, ETH_ALEN);
+#else
+            memcpy(flow.apModify.srcMacAddr, &hdr->ethh.h_source, ETH_ALEN);
+            memcpy(flow.apModify.dstMacAddr, &hdr->ethh.h_dest, ETH_ALEN);
+#endif
+            flow.operations |= (1 << AP_DO_ETH_HDR_BIT);
+            break;
+         case AVM_PA_PPP:
+            break;
+         case AVM_PA_PPPOE:
+            {
+               struct pppoehdr *pppoe_hdr =
+                  (struct pppoehdr *) (avm_session->egress[0].match.hdrcopy +
+                                       avm_session->egress[0].match.hdroff +
+                                       avm_session->egress[0].pppoe_offset);
+#ifdef CONFIG_FUSIV_VX180
+               flow.outSessionId = pppoe_hdr->sid;
+#else
+               flow.apModify.sessionID = pppoe_hdr->sid;
+#endif
+               flow.operations |= (1 << AP_ADD_PPPOE_HDR_BIT);
+               break;
+            }
+         case AVM_PA_IPV4:
+#ifdef CONFIG_FUSIV_VX180
+            flow.srcIPAddr = hdr->iph.saddr;
+            flow.dstIPAddr = hdr->iph.daddr;
+            flow.operations |= (0x1 << AP_IPV6_TO_IPV4_TUNNEL_BIT);
+#endif
+            break;
+         case AVM_PA_IPV6:
+            break;
+         case AVM_PA_PORTS:
+            break;
+         default:
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_add_session_v6: can not accelerate, unsupported egress match type %d\n",
+                p->type);
+            break;
+      }
+   }
 
-	rc = apIpv6AddFlowEntry(ingress_hw->apId, flowhash, &flow, &newflow);
+   /*
+    * ATA -> LAN: add port VLAN for WAN Port 
+    */
+   if ((flow.operations & (1 << AP_ADD_VLAN_HDR_BIT)) == 0
+       && (egress_hw->apId == MAC1_ID) && (ingress_hw->apId == MAC1_ID)
+       && (avm_session->egress[0].pid_handle !=
+           avm_session->ingress_pid_handle)) {
+#ifdef CONFIG_FUSIV_VX180
+      flow.vlanId = avm_cpmac_get_wan_port_vlan();
+      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+#else
+      flow.apModify.vlanID = avm_cpmac_get_wan_port_vlan();
+      flow.operations |= (1 << AP_ADD_VLAN_HDR_BIT);
+#endif
+   }
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   memset(&flow.apStatistics, 0, sizeof(apStatistics_t));
+   memset(&new_session.prevStat, 0, sizeof(apStatistics_t));
+#endif
 
-	if (rc != 0) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: can not accelerate, apAddFlowEntry returned %d \n", rc);
-	   return res;
-	}
+   priority = avm_session->egress[0].output.priority;
+   priority = (priority & TC_H_MIN_MASK);
+   if (priority > 7)
+      priority = 7;
 
-	new_session.avm_session = avm_session;
-	new_session.valid_session = 1;
-	new_session.rxApId = ingress_hw->apId;
-	new_session.txApId = egress_hw->apId;
-	new_session.flowhash = flowhash;
-	new_session.flow.v6 = newflow;
-	new_session.flowtype = fusiv_flow_v6;
+   flow.userHandle =
+      (unsigned int) &fusiv_session_array[avm_session->session_handle];
+   flow.egressList[0].pEgress =
+      (void *) (K1_TO_PHYS(apArray[egress_hw->apId].apTxFifo));
+   flow.egressList[0].pFlowID = (void *) priority;
+   flow.operations |= (0x1 << AP_ROUTE_VALID_BIT);
 
-    mac2str(flow.srcMacAddr, srcmac, sizeof(srcmac));
-    mac2str(flow.dstMacAddr, dstmac, sizeof(dstmac));
-    mac2str(flow.inSrcMacAddr, insrc, sizeof(insrc));
-	AVM_PA_FUSIV_DBG("apAddFlowEntry: AP#%d->AP#%d srcmac %s dstmac %s insrc %s\n",
-		   ingress_hw->apId, egress_hw->apId, srcmac, dstmac, insrc);
-	
-	// take_session_lock
-	spin_lock_irqsave( &session_list_lock, slock_flags);
-	if ( !fusiv_session_array[ avm_session->session_handle ].valid_session ){
-		fusiv_session_array[ avm_session->session_handle ] = new_session;
-		res = AVM_PA_TX_SESSION_ADDED;
-	} else {
-        AVM_PA_FUSIV_DBG("session add failed - double call for add by avm_pa?!");
-        dump_stack();
-	}
-	// release_session_lock
-	spin_unlock_irqrestore( &session_list_lock, slock_flags);
+   flowhash = apIpv6CalculateHash(ingress_hw->apId, &flow);
 
-	AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: done\n");
+   rc = apIpv6AddFlowEntry(ingress_hw->apId, flowhash, &flow, &newflow);
 
-    return res;
+   if (rc != 0) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session_v6: can not accelerate, apAddFlowEntry returned %d\n",
+          rc);
+      return res;
+   }
+
+   new_session.avm_session = avm_session;
+   new_session.valid_session = 1;
+   new_session.rxApId = ingress_hw->apId;
+   new_session.txApId = egress_hw->apId;
+   new_session.flowhash = flowhash;
+   new_session.flow.v6 = newflow;
+   new_session.flowtype = fusiv_flow_v6;
+   new_session.bridgeFlow = 0;
+
+#ifdef CONFIG_FUSIV_VX180
+   mac2str(flow.srcMacAddr, srcmac, sizeof(srcmac));
+   mac2str(flow.dstMacAddr, dstmac, sizeof(dstmac));
+   mac2str(flow.inSrcMacAddr, insrc, sizeof(insrc));
+#else
+   mac2str(flow.apModify.srcMacAddr, srcmac, sizeof(srcmac));
+   mac2str(flow.apModify.dstMacAddr, dstmac, sizeof(dstmac));
+   mac2str(flow.apCompare.inMAC, insrc, sizeof(insrc));
+#endif
+
+   AVM_PA_FUSIV_DBG
+      ("apAddFlowEntry: AP#%d->AP#%d srcmac %s dstmac %s insrc %s\n",
+       ingress_hw->apId, egress_hw->apId, srcmac, dstmac, insrc);
+
+   // take_session_lock
+   spin_lock_irqsave(&session_list_lock, slock_flags);
+   if (!fusiv_session_array[avm_session->session_handle].valid_session) {
+      fusiv_session_array[avm_session->session_handle] = new_session;
+      res = AVM_PA_TX_SESSION_ADDED;
+   } else {
+      UINT32 moved;
+      if (apIpv6DeleteFlowEntry(ingress_hw->apId, flowhash, newflow, &moved) == 0) {
+         if (moved) {
+            struct avm_pa_fusiv_session *fusiv_session = (struct avm_pa_fusiv_session *) (newflow->userHandle);
+            fusiv_session->flow.v6 = newflow;
+         }
+      }
+      printk(KERN_CRIT "session add failed - double call for add by avm_pa?!");
+      dump_stack();
+   }
+   // release_session_lock
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
+
+   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session_v6: done\n");
+
+   return res;
 }
 
-static int avm_pa_fusiv_add_session(struct avm_pa_session *avm_session) {
-	struct avm_pa_pkt_match *ingress;
-	struct avm_pa_egress *egress;
-	struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
-	unsigned int proto;
-	static int called = 0;
-	unsigned short hash;
+static int avm_pa_fusiv_add_session(struct avm_pa_session *avm_session)
+{
+   struct avm_pa_pkt_match *ingress;
+   struct avm_pa_egress *egress;
+   struct avm_pa_pid_hwinfo *ingress_hw, *egress_hw;
+   unsigned int proto;
 
-    BUG_ON( avm_session->session_handle >= CONFIG_AVM_PA_MAX_SESSION);
+   BUG_ON(avm_session->session_handle >= CONFIG_AVM_PA_MAX_SESSION);
 
-	if (avm_session->negress != 1) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, egress = %d\n", avm_session->negress);
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
+   if (avm_session->negress != 1) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate, egress = %d\n",
+          avm_session->negress);
+      return AVM_PA_TX_ERROR_SESSION;
+   }
 
-	ingress = &avm_session->ingress;
-	egress = &avm_session->egress[0];
-	ingress_hw = avm_pa_pid_get_hwinfo( avm_session->ingress_pid_handle );
-	egress_hw  = avm_pa_pid_get_hwinfo( avm_session->egress[0].pid_handle );
+   ingress = &avm_session->ingress;
+   egress = &avm_session->egress[0];
+   ingress_hw = avm_pa_pid_get_hwinfo(avm_session->ingress_pid_handle);
+   egress_hw = avm_pa_pid_get_hwinfo(avm_session->egress[0].pid_handle);
 
-	if (!ingress_hw || !egress_hw) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, hw pointer not valid\n");
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
+   if (!ingress_hw || !egress_hw) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate, hw pointer not valid\n");
+      return AVM_PA_TX_ERROR_SESSION;
+   }
 
-	if ((egress_hw->apId == 0) || (ingress_hw->apId == 0)) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, %s AP-ID is 0\n",
-			 egress_hw->apId ? "ingress" : "egress");
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
-	if (egress_hw->apId == BMU_ID) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, AP-ID %d not supported\n",
-			 egress_hw->apId);
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
+   if ((egress_hw->apId == 0) || (ingress_hw->apId == 0)) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate, %s AP-ID is 0\n",
+          egress_hw->apId ? "ingress" : "egress");
+      return AVM_PA_TX_ERROR_SESSION;
+   }
+   if (egress_hw->apId == BMU_ID) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate, AP-ID %d not supported\n",
+          egress_hw->apId);
+      return AVM_PA_TX_ERROR_SESSION;
+   }
 
-	if (avm_session->bsession)
-	   return avm_pa_fusiv_add_bridge_session(avm_session);
+   if (avm_session->bsession)
+      return avm_pa_fusiv_add_bridge_session(avm_session);
 
-	proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
-	if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, protocol %u not supported \n", proto);
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
-	if ((ingress->pkttype & AVM_PA_PKTTYPE_LISP) || (egress->match.pkttype & AVM_PA_PKTTYPE_LISP)) {
-	   AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate LISP tunnel packets \n");
-	   return AVM_PA_TX_ERROR_SESSION;
-	}
+   proto = avm_session->ingress.pkttype & AVM_PA_PKTTYPE_PROTO_MASK;
+   if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate, protocol %u not supported \n",
+          proto);
+      return AVM_PA_TX_ERROR_SESSION;
+   }
+   if ((ingress->pkttype & AVM_PA_PKTTYPE_LISP)
+       || (egress->match.pkttype & AVM_PA_PKTTYPE_LISP)) {
+      AVM_PA_FUSIV_DBG
+         ("avm_pa_fusiv_add_session: can not accelerate LISP tunnel packets \n");
+      return AVM_PA_TX_ERROR_SESSION;
+   }
 
-	if (((ingress->pkttype & AVM_PA_PKTTYPE_IP_MASK) == AVM_PA_PKTTYPE_IPV4)) {
-	   /* IPV4 -> IPV4 */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-	      return avm_pa_fusiv_add_session_v4(avm_session);
-	   /* IPV4 -> IPV4 in IPV6 (DsLite) */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_IPV6ENCAP)
-	      return avm_pa_fusiv_add_session_v4(avm_session); /* currently buggy */
-	      //return AVM_PA_TX_ERROR_SESSION;
-	   /* IPV4 in IPV6 -> IPV4 (DsLite) */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_IPV6ENCAP)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-	      return avm_pa_fusiv_add_session_v4(avm_session);
-	} else if ((ingress->pkttype & AVM_PA_PKTTYPE_IP_MASK) == AVM_PA_PKTTYPE_IPV6) {
-	   /* IPV6 -> IPV6 */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-	      return avm_pa_fusiv_add_session_v6(avm_session);
-	   /* IPV6 -> IPV6 in IPV4 (6to4) */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_IPV4ENCAP)
-	      return avm_pa_fusiv_add_session_v6(avm_session);
-	   /* IPV6 in IPV4 -> IPV6 (6to4) */
-	   if (((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_IPV4ENCAP)
-		   && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) == AVM_PA_PKTTYPE_NONE)
-	      return avm_pa_fusiv_add_session_v6(avm_session);
-	}
-	AVM_PA_FUSIV_DBG("avm_pa_fusiv_add_session: can not accelerate, unsupported protocol\n");
-	return AVM_PA_TX_ERROR_SESSION;
+   if ((ingress->pkttype & AVM_PA_PKTTYPE_IP_MASK) == AVM_PA_PKTTYPE_IPV4) {
+      /*
+       * IPV4 -> IPV4 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE)
+         return avm_pa_fusiv_add_session_v4(avm_session);
+#ifdef CONFIG_FUSIV_VX180
+      /*
+       * IPV4 -> IPV4 in IPV6 (DsLite) 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_IPV6ENCAP)
+         return avm_pa_fusiv_add_session_v4(avm_session); /* currently buggy */
+      /*
+       * IPV4 in IPV6 -> IPV4 (DsLite) 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_IPV6ENCAP
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE)
+         return avm_pa_fusiv_add_session_v4(avm_session);
+#endif
+   } else if ((ingress->pkttype & AVM_PA_PKTTYPE_IP_MASK) ==
+              AVM_PA_PKTTYPE_IPV6) {
+      /*
+       * IPV6 -> IPV6 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE)
+         return avm_pa_fusiv_add_session_v6(avm_session);
+#ifdef CONFIG_FUSIV_VX180
+      /*
+       * IPV6 -> IPV6 in IPV4 (6to4) 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_IPV4ENCAP)
+         return avm_pa_fusiv_add_session_v6(avm_session);
+      /*
+       * IPV6 in IPV4 -> IPV6 (6to4) 
+       */
+      if ((ingress->pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_IPV4ENCAP
+          && (egress->match.pkttype & AVM_PA_PKTTYPE_IPENCAP_MASK) ==
+          AVM_PA_PKTTYPE_NONE)
+         return avm_pa_fusiv_add_session_v6(avm_session);
+#endif
+   }
+   AVM_PA_FUSIV_DBG
+      ("avm_pa_fusiv_add_session: can not accelerate, unsupported protocol\n");
+   return AVM_PA_TX_ERROR_SESSION;
 }
 
-
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static int avm_pa_fusiv_remove_session( struct avm_pa_session *avm_session ){
-	int status = AVM_PA_TX_ERROR_SESSION;
-    unsigned long slock_flags;
-    struct avm_pa_fusiv_session session_to_remove;
-	void *moved;
-	int rc = 0;
-	
-    BUG_ON( avm_session->session_handle >= CONFIG_AVM_PA_MAX_SESSION);
+static int avm_pa_fusiv_remove_session(struct avm_pa_session *avm_session)
+{
+   int status = AVM_PA_TX_ERROR_SESSION;
+   unsigned long slock_flags;
+   struct avm_pa_fusiv_session session_to_remove;
+   void *moved;
+   int rc = 0;
 
-    // take_session_lock
-	spin_lock_irqsave( &session_list_lock, slock_flags);
-    if ( ( avm_session == fusiv_session_array[ avm_session->session_handle ].avm_session)
-            && fusiv_session_array[ avm_session->session_handle ].valid_session ){
-        session_to_remove = fusiv_session_array[ avm_session->session_handle ];
-    } else {
-        // no valid session found
-        // release_session_lock and return
-	    spin_unlock_irqrestore( &session_list_lock, slock_flags);
-	    return status;
-    }
-    // release_session_lock
-	spin_unlock_irqrestore( &session_list_lock, slock_flags);
+   BUG_ON(avm_session->session_handle >= CONFIG_AVM_PA_MAX_SESSION);
 
-	if (session_to_remove.flowtype == fusiv_flow_v4 && session_to_remove.flow.v4) {
-	   if ((rc = apDeleteFlowEntry(session_to_remove.rxApId, session_to_remove.flowhash, 
-				                   session_to_remove.flow.v4, (void *)&moved)) == 0) {
-		  apFlowEntry_t *flowp = session_to_remove.flow.v4;
+   // take_session_lock
+   spin_lock_irqsave(&session_list_lock, slock_flags);
+   if ((avm_session ==
+        fusiv_session_array[avm_session->session_handle].avm_session)
+       && fusiv_session_array[avm_session->session_handle].valid_session) {
+      session_to_remove = fusiv_session_array[avm_session->session_handle];
+   } else {
+      // no valid session found
+      // release_session_lock and return
+      spin_unlock_irqrestore(&session_list_lock, slock_flags);
+      return status;
+   }
+   // release_session_lock
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
+
+   if (session_to_remove.flowtype == fusiv_flow_v4 && session_to_remove.flow.v4) {
+      if ((rc = apDeleteFlowEntry(session_to_remove.rxApId,
+                                  session_to_remove.flowhash,
+                                  session_to_remove.flow.v4,
+                                  (void *) &moved)) == 0) {
+         apFlowEntry_t *flowp = session_to_remove.flow.v4;
 
 #if defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE) && defined(AVM_PA_FUSIV_DEBUG)
-		  AVM_PA_FUSIV_DBG("ap2apFlowDelete Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte \n",
-				flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte, flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
+         AVM_PA_FUSIV_DBG
+            ("ap2apFlowDelete Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte\n",
+             flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte,
+             flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
 #endif
-		  if (moved) {
-		     struct avm_pa_fusiv_session *fusiv_session = (struct avm_pa_fusiv_session *) (flowp->userHandle);
-			 fusiv_session->flow.v4 = flowp;
-			 AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: v4 flow entry moved \n");
-		  }
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apDeleteFlowEntry successful \n");
-	   } else {
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apDeleteFlowEntry failed (rc=%u) APID %d\n", rc, session_to_remove.rxApId);
-	   }
-	} else if (session_to_remove.flowtype == fusiv_flow_v6 && session_to_remove.flow.v6) {
-	   if ((rc = apIpv6DeleteFlowEntry(session_to_remove.rxApId, session_to_remove.flowhash, 
-				                   session_to_remove.flow.v6, (void *)&moved)) == 0) {
-		  apIpv6FlowEntry_t *flowp = session_to_remove.flow.v6;
+         if (moved) {
+            struct avm_pa_fusiv_session *fusiv_session =
+               (struct avm_pa_fusiv_session *) (flowp->userHandle);
+
+            fusiv_session->flow.v4 = flowp;
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_remove_session: v4 flow entry moved\n");
+         }
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apDeleteFlowEntry successful\n");
+      } else {
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apDeleteFlowEntry failed (rc=%u) APID %d\n",
+             rc, session_to_remove.rxApId);
+      }
+   } else if (session_to_remove.flowtype == fusiv_flow_v6
+              && session_to_remove.flow.v6) {
+      if ((rc =
+           apIpv6DeleteFlowEntry(session_to_remove.rxApId,
+                                 session_to_remove.flowhash,
+                                 session_to_remove.flow.v6,
+                                 (void *) &moved)) == 0) {
+         apIpv6FlowEntry_t *flowp = session_to_remove.flow.v6;
 
 #if defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE) && defined(AVM_PA_FUSIV_DEBUG)
-		  AVM_PA_FUSIV_DBG("ap2apFlowDelete Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte \n",
-				flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte, flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
+         AVM_PA_FUSIV_DBG
+            ("ap2apFlowDelete Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte \n",
+             flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte,
+             flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
 #endif
-		  if (moved) {
-		     struct avm_pa_fusiv_session *fusiv_session = (struct avm_pa_fusiv_session *) (flowp->userHandle);
-			 fusiv_session->flow.v6 = flowp;
-			 AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: v6 flow entry moved \n");
-		  }
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apIpv6DeleteFlowEntry successful \n");
-	   } else {
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apIpv6DeleteFlowEntry failed (rc=%d) \n", rc);
-	   }
-	} else if (session_to_remove.flowtype == fusiv_bridge_flow && session_to_remove.bridgeFlow) {
-	   if ((rc = apDeleteBridgeEntry(1, session_to_remove.flowhash,
-				   session_to_remove.bridgeFlow, (void *)&moved)) == 0) {
-		  apNewBridgeEntry_t *flowp = session_to_remove.bridgeFlow;
+         if (moved) {
+            struct avm_pa_fusiv_session *fusiv_session =
+               (struct avm_pa_fusiv_session *) (flowp->userHandle);
+
+            fusiv_session->flow.v6 = flowp;
+            AVM_PA_FUSIV_DBG
+               ("avm_pa_fusiv_remove_session: v6 flow entry moved\n");
+         }
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apIpv6DeleteFlowEntry successful\n");
+      } else {
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apIpv6DeleteFlowEntry failed (rc=%d)\n",
+             rc);
+      }
+   } else if (session_to_remove.flowtype == fusiv_bridge_flow
+              && session_to_remove.bridgeFlow) {
+      if ((rc =
+           apDeleteBridgeEntry(1, session_to_remove.flowhash,
+                               session_to_remove.bridgeFlow,
+                               (void *) &moved)) == 0) {
 #if defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE) && defined(AVM_PA_FUSIV_DEBUG)
-		  AVM_PA_FUSIV_DBG("apDeleteBridgeEntry Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte \n",
-				flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte, flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
-#endif
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apDeleteBridgeEntry successful \n");
-	   } else {
-		  AVM_PA_FUSIV_DBG("avm_pa_fusiv_remove_session: apDeleteBridgeEntry failed (rc=%d) \n", rc);
-	   }
-	}
+         apNewBridgeEntry_t *flowp = session_to_remove.bridgeFlow;
 
-    // take_session_lock
-	spin_lock_irqsave( &session_list_lock, slock_flags);
-    if ( ( avm_session == fusiv_session_array[ avm_session->session_handle ].avm_session)
-            && fusiv_session_array[ avm_session->session_handle ].valid_session ){
-        memset(&fusiv_session_array[ avm_session->session_handle ],0 , sizeof(struct avm_pa_fusiv_session) );
-    	status = AVM_PA_TX_OK;
-    } else {
-        AVM_PA_FUSIV_DBG("session has been removed already - double call for remove by avm_pa?!");
-        dump_stack();
-    }
-    // release_session_lock
-	spin_unlock_irqrestore( &session_list_lock, slock_flags);
+         AVM_PA_FUSIV_DBG
+            ("apDeleteBridgeEntry Stats %lu rxPkt %lu rxByte %lu txPkt %lu txByte\n",
+             flowp->apStatistics.rxPkt, flowp->apStatistics.rxByte,
+             flowp->apStatistics.txPkt, flowp->apStatistics.txByte);
+#endif
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apDeleteBridgeEntry successful\n");
+      } else {
+         AVM_PA_FUSIV_DBG
+            ("avm_pa_fusiv_remove_session: apDeleteBridgeEntry failed (rc=%d)\n",
+             rc);
+      }
+   }
+   // take_session_lock
+   spin_lock_irqsave(&session_list_lock, slock_flags);
+   if ((avm_session ==
+        fusiv_session_array[avm_session->session_handle].avm_session)
+       && fusiv_session_array[avm_session->session_handle].valid_session) {
+      memset(&fusiv_session_array[avm_session->session_handle], 0,
+             sizeof(struct avm_pa_fusiv_session));
+      status = AVM_PA_TX_OK;
+   } else {
+      printk(KERN_CRIT
+             "session has been removed already - double call for remove by avm_pa?!");
+      dump_stack();
+   }
+   // release_session_lock
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
 
-    return status;
+   return status;
 }
 
-
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 
-
-#ifdef CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-static void avm_pa_check_stat(unsigned long dummy) {
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+static void avm_pa_check_stat(unsigned long dummy)
+{
    unsigned int i;
    struct avm_pa_fusiv_session *session;
    unsigned long bytes_since_last_report;
@@ -823,168 +1171,227 @@
    apNewBridgeEntry_t *bridgeflow;
    unsigned long slock_flags;
 
-   spin_lock_irqsave( &session_list_lock, slock_flags);
+   spin_lock_irqsave(&session_list_lock, slock_flags);
 
    for (i = 0; i < CONFIG_AVM_PA_MAX_SESSION; i++) {
-      session =  &fusiv_session_array[i];
-	  if (!session->valid_session) continue;
+      session = &fusiv_session_array[i];
+      if (!session->valid_session)
+         continue;
+      if (session->rxApId == PERI_ID) /* not used on rx */
+         continue;
 
-	  if (session->flowtype == fusiv_flow_v4) {
-	     flowpv4 = session->flow.v4;
-		 if (flowpv4->apStatistics.txByte >= session->prevStat.txByte) {
-			bytes_since_last_report = flowpv4->apStatistics.txByte - session->prevStat.txByte;
-		 } else {
-			bytes_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txByte + flowpv4->apStatistics.txByte;
-		 }
-		 if (flowpv4->apStatistics.txPkt >= session->prevStat.txPkt) {
-			packets_since_last_report = flowpv4->apStatistics.txPkt - session->prevStat.txPkt;
-		 } else {
-			packets_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txPkt + flowpv4->apStatistics.txPkt;
-		 }
-		 session->prevStat.txByte = flowpv4->apStatistics.txByte;
-		 session->prevStat.rxByte = flowpv4->apStatistics.rxByte;
-		 session->prevStat.txPkt = flowpv4->apStatistics.txPkt;
-		 session->prevStat.rxPkt = flowpv4->apStatistics.rxPkt;
-	  } else if (session->flowtype == fusiv_flow_v6) {
-	     flowpv6 = session->flow.v6;
-		 if (flowpv6->apStatistics.txByte >= session->prevStat.txByte) {
-			bytes_since_last_report = flowpv6->apStatistics.txByte - session->prevStat.txByte;
-		 } else {
-			bytes_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txByte + flowpv6->apStatistics.txByte;
-		 }
-		 if (flowpv6->apStatistics.txPkt >= session->prevStat.txPkt) {
-			packets_since_last_report = flowpv6->apStatistics.txPkt - session->prevStat.txPkt;
-		 } else {
-			packets_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txPkt + flowpv6->apStatistics.txPkt;
-		 }
-		 session->prevStat.txByte = flowpv6->apStatistics.txByte;
-		 session->prevStat.rxByte = flowpv6->apStatistics.rxByte;
-		 session->prevStat.txPkt = flowpv6->apStatistics.txPkt;
-		 session->prevStat.rxPkt = flowpv6->apStatistics.rxPkt;
-	  } else if (session->flowtype == fusiv_bridge_flow) {
-	     bridgeflow = session->bridgeFlow;
-		 if (bridgeflow->apStatistics.txByte >= session->prevStat.txByte) {
-			bytes_since_last_report = bridgeflow->apStatistics.txByte - session->prevStat.txByte;
-		 } else {
-			bytes_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txByte + bridgeflow->apStatistics.txByte;
-		 }
-		 if (bridgeflow->apStatistics.txPkt >= session->prevStat.txPkt) {
-			packets_since_last_report = bridgeflow->apStatistics.txPkt - session->prevStat.txPkt;
-		 } else {
-			packets_since_last_report = 
-			   ((unsigned long) -1) - session->prevStat.txPkt + bridgeflow->apStatistics.txPkt;
-		 }
-		 session->prevStat.txByte = bridgeflow->apStatistics.txByte;
-		 session->prevStat.rxByte = bridgeflow->apStatistics.rxByte;
-		 session->prevStat.txPkt = bridgeflow->apStatistics.txPkt;
-		 session->prevStat.rxPkt = bridgeflow->apStatistics.rxPkt;
-		 AVM_PA_FUSIV_DBG("bridge flow stats %lu bytse \n", bytes_since_last_report);
-	  }
+      if (session->flowtype == fusiv_flow_v4) {
+         flowpv4 = session->flow.v4;
+         if (flowpv4->apStatistics.txByte >= session->prevStat.txByte) {
+            bytes_since_last_report =
+               flowpv4->apStatistics.txByte - session->prevStat.txByte;
+         } else {
+            bytes_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txByte +
+               flowpv4->apStatistics.txByte;
+         }
+         if (flowpv4->apStatistics.txPkt >= session->prevStat.txPkt) {
+            packets_since_last_report =
+               flowpv4->apStatistics.txPkt - session->prevStat.txPkt;
+         } else {
+            packets_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txPkt +
+               flowpv4->apStatistics.txPkt;
+         }
+         session->prevStat.txByte = flowpv4->apStatistics.txByte;
+         session->prevStat.rxByte = flowpv4->apStatistics.rxByte;
+         session->prevStat.txPkt = flowpv4->apStatistics.txPkt;
+         session->prevStat.rxPkt = flowpv4->apStatistics.rxPkt;
+      } else if (session->flowtype == fusiv_flow_v6) {
+         flowpv6 = session->flow.v6;
+         if (flowpv6->apStatistics.txByte >= session->prevStat.txByte) {
+            bytes_since_last_report =
+               flowpv6->apStatistics.txByte - session->prevStat.txByte;
+         } else {
+            bytes_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txByte +
+               flowpv6->apStatistics.txByte;
+         }
+         if (flowpv6->apStatistics.txPkt >= session->prevStat.txPkt) {
+            packets_since_last_report =
+               flowpv6->apStatistics.txPkt - session->prevStat.txPkt;
+         } else {
+            packets_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txPkt +
+               flowpv6->apStatistics.txPkt;
+         }
+         session->prevStat.txByte = flowpv6->apStatistics.txByte;
+         session->prevStat.rxByte = flowpv6->apStatistics.rxByte;
+         session->prevStat.txPkt = flowpv6->apStatistics.txPkt;
+         session->prevStat.rxPkt = flowpv6->apStatistics.rxPkt;
+      } else if (session->flowtype == fusiv_bridge_flow) {
+         bridgeflow = session->bridgeFlow;
+         if (bridgeflow->apStatistics.txByte >= session->prevStat.txByte) {
+            bytes_since_last_report =
+               bridgeflow->apStatistics.txByte - session->prevStat.txByte;
+         } else {
+            bytes_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txByte +
+               bridgeflow->apStatistics.txByte;
+         }
+         if (bridgeflow->apStatistics.txPkt >= session->prevStat.txPkt) {
+            packets_since_last_report =
+               bridgeflow->apStatistics.txPkt - session->prevStat.txPkt;
+         } else {
+            packets_since_last_report =
+               ((unsigned long) -1) - session->prevStat.txPkt +
+               bridgeflow->apStatistics.txPkt;
+         }
+         session->prevStat.txByte = bridgeflow->apStatistics.txByte;
+         session->prevStat.rxByte = bridgeflow->apStatistics.rxByte;
+         session->prevStat.txPkt = bridgeflow->apStatistics.txPkt;
+         session->prevStat.rxPkt = bridgeflow->apStatistics.rxPkt;
+         AVM_PA_FUSIV_DBG("bridge flow stats %lu bytes\n",
+                          bytes_since_last_report);
+      } else {
+         packets_since_last_report = 0;
+         bytes_since_last_report = 0;
+      }
 
-	  if (session->avm_session && session->avm_session->session_handle)
-	     avm_pa_hardware_session_report(session->avm_session->session_handle,
-			                            packets_since_last_report, bytes_since_last_report);
-	  else 
-	     AVM_PA_FUSIV_DBG("avm_pa_check_stat: no session handle\n");
+      if (session->avm_session && session->avm_session->session_handle) {
+#if 0
+
+         printk(KERN_ERR "avm_pa_hardware_session_report(%u): rxId %u txId %u pkts %lu bytes %llu\n",
+                         session->avm_session->session_handle,
+                         (unsigned)session->rxApId,
+                         (unsigned)session->txApId,
+                         packets_since_last_report,
+                         bytes_since_last_report);
+#endif
+         avm_pa_hardware_session_report(session->avm_session->session_handle,
+                                        packets_since_last_report,
+                                        bytes_since_last_report);
+      } else {
+         AVM_PA_FUSIV_DBG("avm_pa_check_stat: no session handle\n");
+      }
    }
-   spin_unlock_irqrestore( &session_list_lock, slock_flags);
+   spin_unlock_irqrestore(&session_list_lock, slock_flags);
 
-   mod_timer(&statistics_timer,  jiffies + HZ * AVM_PA_FUSIV_STAT_POLLING_TIME - 1);
+   mod_timer(&statistics_timer,
+             jiffies + HZ * AVM_PA_FUSIV_STAT_POLLING_TIME - 1);
 
-   //TODO: statistics bei loeschen
+   // TODO: statistics bei loeschen
 }
 #endif
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-void pkt_from_ap(apPreHeader_t *ap_buf) {
-	struct sk_buff *skb;
-	avm_pid_handle pid_handle;
+void pkt_from_ap(apPreHeader_t * ap_buf)
+{
+   struct sk_buff *skb;
+   avm_pid_handle pid_handle;
 
-	pid_handle = ap_buf->specInfoElement;
-	ap_buf->specInfoElement = 1;
+   pid_handle = ap_buf->specInfoElement;
+   ap_buf->specInfoElement = 1;
 
-	AVM_PA_FUSIV_TRC("%s called pid_handle %u\n", __func__, pid_handle);
+   AVM_PA_FUSIV_TRC("%s called pid_handle %u\n", __func__, pid_handle);
 
-	skb = (struct sk_buff *)translateApbuf2Mbuf(ap_buf);
-    avm_pa_rx_channel_packet_not_accelerated(pid_handle, skb);
+   if ((skb = (struct sk_buff *) translateApbuf2Mbuf(ap_buf)) != 0)
+      avm_pa_rx_channel_packet_not_accelerated(pid_handle, skb);
 }
 
-extern int  apClassify(unsigned char apId, apPreHeader_t *pFrame, void *handle);
+extern int apClassify(unsigned char apId, apPreHeader_t * pFrame, void *handle);
 extern void (*wlan_pkt_from_ap_ptr) (apPreHeader_t *);
 
-int avm_pa_fusiv_try_to_accelerate(avm_pid_handle pid_handle, struct sk_buff *skb) {
+int avm_pa_fusiv_try_to_accelerate(avm_pid_handle pid_handle,
+                                   struct sk_buff *skb)
+{
 
-	struct avm_pa_pid_hwinfo *hwinfo;
-	apPreHeader_t *ap_buf;
+   struct avm_pa_pid_hwinfo *hwinfo;
+   apPreHeader_t *ap_buf;
 
-	hwinfo = avm_pa_pid_get_hwinfo(pid_handle);
-	if (!hwinfo) {
-	   AVM_PA_FUSIV_TRC(KERN_ERR "avm_pa_fusiv_try_to_accelerate: no hw info for pid %u\n", pid_handle);
-	   return AVM_PA_RX_BYPASS;
-	}
+   hwinfo = avm_pa_pid_get_hwinfo(pid_handle);
+   if (!hwinfo) {
+      AVM_PA_FUSIV_TRC(KERN_ERR
+                       "avm_pa_fusiv_try_to_accelerate: no hw info for pid %u\n",
+                       pid_handle);
+      return AVM_PA_RX_BYPASS;
+   }
 
-	ap_buf = (apPreHeader_t *)(translateMbuf2Apbuf(skb, 0));
-	ap_buf->flags1 = 1 << AP_FLAG1_IS_ETH_BIT;
-	ap_buf->specInfoElement = pid_handle;
-	ap_buf->flags2 = 0;
-	dev_kfree_skb_any(skb);
+   /* == AVM/UGA 20140707 no HW acceleration for ingress WLAN/PERI AP pkts ==
+    * Workaround for trouble-free telephony.
+    * AVM PA rate throttling is not working for ingres WLAN pkts because they
+    * are not seen/counted by it atm.
+    * Thus, we fallback to SW acceleration which sees/counts pkts
+    * appropriately so throttling works.
+    */
+#if 1
+   if (hwinfo->apId == PERI_ID)
+      return AVM_PA_RX_BYPASS;
+#endif
 
-	AVM_PA_FUSIV_TRC("avm_pa_fusiv_try_to_accelerate: apClassify apId %u\n", hwinfo->apId);
-	apClassify(hwinfo->apId, ap_buf, (void *)pkt_from_ap);
-	return AVM_PA_RX_STOLEN;
+   ap_buf = (apPreHeader_t *) (translateMbuf2Apbuf(skb, 0));
+   if (!ap_buf) {
+      return AVM_PA_RX_BYPASS;
+   }
+   ap_buf->flags1 = 1 << AP_FLAG1_IS_ETH_BIT;
+   ap_buf->specInfoElement = pid_handle;
+   ap_buf->flags2 = 0;
+   dev_kfree_skb_any(skb);
+
+   AVM_PA_FUSIV_TRC("avm_pa_fusiv_try_to_accelerate: apClassify apId %u\n",
+                    hwinfo->apId);
+   if (apClassify(hwinfo->apId, ap_buf, (void *) pkt_from_ap) != SIM_OK) {
+      putCluster(ap_buf);
+   }
+   return AVM_PA_RX_STOLEN;
 }
 
-int avm_pa_fusiv_alloc_rx_channel(avm_pid_handle pid_handle) {
+int avm_pa_fusiv_alloc_rx_channel(avm_pid_handle pid_handle)
+{
 
-	wlan_pkt_from_ap_ptr = pkt_from_ap;
+   wlan_pkt_from_ap_ptr = pkt_from_ap;
 
-	return 0;
+   return 0;
 }
 
-int avm_pa_fusiv_alloc_tx_channel(avm_pid_handle pid_handle) {
+int avm_pa_fusiv_alloc_tx_channel(avm_pid_handle pid_handle)
+{
 
-	apBridgeTable(1, 0xCC, 0xff);
+   apBridgeTable(1, 0xCC, 0xff);
 
-	return 0;
+   return 0;
 }
 
-
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 
-static int __init avm_pa_fusiv_init(void) {
-	AVM_PA_FUSIV_DBG("[%s] start \n", __func__);
+static int __init avm_pa_fusiv_init(void)
+{
+   AVM_PA_FUSIV_DBG("[%s] start \n", __func__);
 
-    memset( &fusiv_session_array[0], 0 , sizeof( struct avm_pa_fusiv_session ) * CONFIG_AVM_PA_MAX_SESSION );
+   memset(&fusiv_session_array[0], 0,
+          sizeof(struct avm_pa_fusiv_session) * CONFIG_AVM_PA_MAX_SESSION);
 
-    avm_pa_register_hardware_pa( &avm_pa_fusiv );
+   avm_pa_register_hardware_pa(&avm_pa_fusiv);
 
-#ifdef CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-	setup_timer(&statistics_timer, avm_pa_check_stat, 0 );
-    mod_timer(&statistics_timer, jiffies + HZ * AVM_PA_FUSIV_STAT_POLLING_TIME - 1);
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   setup_timer(&statistics_timer, avm_pa_check_stat, 0);
+   mod_timer(&statistics_timer,
+             jiffies + HZ * AVM_PA_FUSIV_STAT_POLLING_TIME - 1);
 #endif
 
-	AVM_PA_FUSIV_DBG("[%s] init complete \n", __func__);
+   AVM_PA_FUSIV_DBG("[%s] init complete \n", __func__);
 
-	return 0;
+   return 0;
 }
 
-static void __exit avm_pa_fusiv_exit(void) {
-	AVM_PA_FUSIV_DBG("[%s] start \n", __func__);
+static void __exit avm_pa_fusiv_exit(void)
+{
+   AVM_PA_FUSIV_DBG("[%s] start \n", __func__);
 
-#ifdef CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE
-    del_timer(&statistics_timer);
+#if defined(CONFIG_FUSIV_VX180) && defined(CONFIG_FUSIV_KERNEL_APSTATISTICS_PER_INTERFACE)
+   del_timer(&statistics_timer);
 #endif
 
-    avm_pa_register_hardware_pa( 0 );
+   avm_pa_register_hardware_pa(0);
 
-	AVM_PA_FUSIV_DBG("[%s] exit complete \n", __func__);
+   AVM_PA_FUSIV_DBG("[%s] exit complete \n", __func__);
 }
 
 module_init(avm_pa_fusiv_init);
@@ -1002,11 +1409,10 @@
 
 #undef unix
 struct module __this_module
-__attribute__((section(".gnu.linkonce.this_module"))) = {
-    .name = "avm_pa_fusiv",
-	.init = init_module,
+   __attribute__ ((section(".gnu.linkonce.this_module"))) = {
+   .name = "avm_pa_fusiv",.init = init_module,
 #ifdef CONFIG_MODULE_UNLOAD
-	.exit = cleanup_module,
+      .exit = cleanup_module,
 #endif
 };
 
--- linux-2.6.32/net/core/dev.c
+++ linux-2.6.32/net/core/dev.c
@@ -4549,12 +4549,12 @@
  *	This function handles all "interface"-type I/O control requests. The actual
  *	'doing' part of this is dev_ifsioc above.
  */
-static void release_offload_lock(int in_offload_lock){
+void release_offload_lock(int in_offload_lock){
     if (in_offload_lock)
         rtnl_offload_read_unlock();
 }
 
-static int acquire_offload_lock(struct net *net, const char *name){
+int acquire_offload_lock(struct net *net, const char *name){
 	struct net_device *dev;
 	int need_lock;
 
--- linux-2.6.32/net/ipv4/devinet.c
+++ linux-2.6.32/net/ipv4/devinet.c
@@ -592,6 +592,7 @@
 	char *colon;
 	int ret = -EFAULT;
 	int tryaddrmatch = 0;
+	int in_offload_lock = 0;
 
 	/*
 	 *	Fetch the caller's info block into kernel space
@@ -645,6 +646,7 @@
 		goto out;
 	}
 
+	in_offload_lock = acquire_offload_lock(net, ifr.ifr_name);
 	rtnl_lock();
 
 	ret = -ENODEV;
@@ -809,10 +811,12 @@
 	}
 done:
 	rtnl_unlock();
+	release_offload_lock(in_offload_lock);
 out:
 	return ret;
 rarok:
 	rtnl_unlock();
+	release_offload_lock(in_offload_lock);
 	ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
 	goto out;
 }
