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

    diff -durN --no-dereference 7390.06.30 7390.06.51 > this.patch

--- linux-2.6.28/arch/arm/include/asm/socket.h
+++ linux-2.6.28/arch/arm/include/asm/socket.h
@@ -55,4 +55,7 @@
 #define SO_MARK			36
 #define SO_MARKTASK     37  /* AVM calle */
 
+#define SO_PROTOCOL		38  /* Backport 2.6.32 */
+#define SO_DOMAIN		39  /* Backport 2.6.32 */
+
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.28/arch/mips/fusiv/fusiv_mips32/fusiv_mtd.c
+++ linux-2.6.28/arch/mips/fusiv/fusiv_mips32/fusiv_mtd.c
@@ -35,7 +35,6 @@
 #include <asm/setup.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 #define DO_MTD
 
 #include <linux/mtd/mtd.h>
@@ -60,114 +59,110 @@
 /*--- #define FUSIV_MTD_DEBUG ---*/
 
 #if defined(FUSIV_MTD_DEBUG)
-    #define DEBUG_MTD(fmt, arg...) printk(KERN_ERR "[%d:%s/%d] " fmt "\n", smp_processor_id(), __func__, __LINE__, ##arg);
+#define DEBUG_MTD(fmt, arg...) pr_err("[%d:%s/%d] " fmt "\n", smp_processor_id(), __func__, __LINE__, ##arg);
 #else
-    #define DEBUG_MTD(fmt, arg...)
+#define DEBUG_MTD(fmt, arg...)
 #endif
 
 #if defined(CONFIG_FUSIV_VX185)
-#define FUSIV_MTD_NAND_PARTS        6
-#define FUSIV_MTD_SPI_PARTS   3
-#else
-#define FUSIV_MTD_NAND_PARTS        1
-#define FUSIV_MTD_SPI_PARTS   0
+#elif defined(CONFIG_FUSIV_VX180)
 #endif
 
-#define FUSIV_MTD_NOR_PARTS         6
-#define FUSIV_MTD_JFFS2_MIN_SIZE  6
-#define FUSIV_MTD_JFFS2_MAX_SIZE  16
-
 /*-------------------------------------------------------------------------------------*\
  * Zuerst wird das JFFS2 gesucht, dann das Squash-FS!
-\*-------------------------------------------------------------------------------------*/
-static const char *probes[] = { "find_jffs2", "find_squashfs", NULL };
+ \*-------------------------------------------------------------------------------------*/
+static const char *probes[] = { "find_squashfs", NULL };
 
 void fusiv_ram_mtd_set_rw(struct device *pdev, int);
 extern int __init root_dev_setup(char *line);
 static unsigned int flash_erase_block_size = (1U << 16);
+
+#if defined(CONFIG_FUSIV_VX180)
 static unsigned int fusiv_nor_flashsize;
 extern unsigned long g_fusiv_nor_flash_start;
 extern unsigned long g_fusiv_nor_flash_size;
 
-
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-struct _nmi_vector_location {
+struct _nmi_vector_location
+{
     unsigned int firmware_length;
     unsigned int vector_gap;
     char vector_id[32];
 };
 
-
-struct _nmi_vector_location *nmi_vector_location = (struct _nmi_vector_location *)0xbfc00040;
-extern void set_nmi_vetor_gap(unsigned int start, unsigned int firmware_size, unsigned int gap_size);
+struct _nmi_vector_location *nmi_vector_location = (struct _nmi_vector_location *) 0xbfc00040;
+extern void set_nmi_vetor_gap(unsigned int start, unsigned int firmware_size,
+        unsigned int gap_size);
+#endif
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-enum _flash_map_enum {
-    MAP_UNKNOWN,
-    MAP_RAM,
-    MAP_NOR_FLASH,
-    MAP_NAND_FLASH,
-    MAP_SPI_FLASH
+enum _flash_map_enum
+{
+    MAP_UNKNOWN, MAP_RAM, MAP_NOR_FLASH, MAP_NAND_FLASH, MAP_SPI_FLASH
 };
 
+#if defined(CONFIG_FUSIV_VX180)
+#define FUSIV_MTD_NAND_PARTS        1
+#define FUSIV_MTD_NOR_PARTS         6
+#define FUSIV_MTD_JFFS2_MIN_SIZE    6
+#define FUSIV_MTD_JFFS2_MAX_SIZE    16
 
 /*------------------------------------------------------------------------------------------*\
  * NOR
-\*------------------------------------------------------------------------------------------*/
+ \*------------------------------------------------------------------------------------------*/
 struct mtd_partition fusiv_nor_partitions[FUSIV_MTD_NOR_PARTS];
 
-static struct resource fusiv_nor_resource[] = {
+static struct resource fusiv_nor_resource[] ={
     {
-        .start		= 0,
-        .end		= 0 + (128),    /* 128 MB */
-        .flags		= IORESOURCE_MEM,
-        .parent     = &iomem_resource
+        .start = 0,
+        .end = 0 + (128), /* 128 MB */
+        .flags = IORESOURCE_MEM,
+        .parent = &iomem_resource
     },
 };
 
-static struct physmap_flash_data fusiv_nor_data = {
-	.width		= 2,
-	.parts		= fusiv_nor_partitions,
-	.nr_parts	= ARRAY_SIZE(fusiv_nor_partitions),
-    .probes     = probes
+static struct physmap_flash_data fusiv_nor_data ={
+    .width = 2,
+    .parts = fusiv_nor_partitions,
+    .nr_parts = ARRAY_SIZE(fusiv_nor_partitions),
+    .probes = probes
 };
 
-struct platform_device fusiv_nor_device[] = {
+struct platform_device fusiv_nor_device[] ={
     {
-        .name		= "physmap-flash",
-        .id		    = -1,
-        .dev		= {
-            .platform_data	= &fusiv_nor_data,
+        .name = "physmap-flash",
+        .id = -1,
+        .dev ={
+            .platform_data = &fusiv_nor_data,
         },
-        .num_resources	= 1,
-        .resource	= &fusiv_nor_resource[0],
+        .num_resources = 1,
+        .resource = &fusiv_nor_resource[0],
     }
 };
 
-#if defined(CONFIG_FUSIV_VX180)
 /*------------------------------------------------------------------------------------------*\
  * NAND
-\*------------------------------------------------------------------------------------------*/
+ \*------------------------------------------------------------------------------------------*/
 struct mtd_partition fusiv_nand_partitions[FUSIV_MTD_NAND_PARTS];
 
-static struct resource fusiv_nand_resource[] = {
-    [0] = {
-            .start  = CONFIG_MTD_NAND_DIRECT_AVM_DATA,
-            .end    = CONFIG_MTD_NAND_DIRECT_AVM_DATA + (16<<20)-1,
-            .flags  = IORESOURCE_MEM,
-        },
+static struct resource fusiv_nand_resource[] ={
+    [0] ={
+        .start = CONFIG_MTD_NAND_DIRECT_AVM_DATA,
+        .end = CONFIG_MTD_NAND_DIRECT_AVM_DATA + (16<<20)-1,
+        .flags = IORESOURCE_MEM,
+    },
 #if defined(CONFIG_MTD_NAND_DIRECT_AVM_ADDR)
-    [1] = {
-            .start = CONFIG_MTD_NAND_DIRECT_AVM_CONTROL,
-            .end = CONFIG_MTD_NAND_DIRECT_AVM_CONTROL + (16 << 20) - 1,
-            .flags = IORESOURCE_MEM,
-        },
+    [1] ={
+        .start = CONFIG_MTD_NAND_DIRECT_AVM_CONTROL,
+        .end = CONFIG_MTD_NAND_DIRECT_AVM_CONTROL + (16 << 20) - 1,
+        .flags = IORESOURCE_MEM,
+    },
 #endif /*--- #if defined(CONFIG_MTD_NAND_DIRECT_AVM_ADDR) ---*/
 };
 
-static struct direct_avm_nand_platdata direct_avm_nand_platform_data = {
+static struct direct_avm_nand_platdata direct_avm_nand_platform_data ={
 #if defined(CONFIG_MTD_NAND_DIRECT_AVM_ADDR)
     .addr_nce = (1 << 16),
     .addr_nwp = (1 << 18),
@@ -177,438 +172,354 @@
 #if defined(CONFIG_MTD_NAND_DIRECT_AVM_GPIO) || defined(CONFIG_MTD_NAND_COMPLETE_AVM)
     .gpio_rdy0 = CONFIG_MTD_NAND_DIRECT_AVM_READY0,
     .gpio_rdy1 = CONFIG_MTD_NAND_DIRECT_AVM_READY1,
-    .gpio_nwp  = CONFIG_MTD_NAND_DIRECT_AVM_NWP,
+    .gpio_nwp = CONFIG_MTD_NAND_DIRECT_AVM_NWP,
     .gpio_nce0 = CONFIG_MTD_NAND_DIRECT_AVM_NCE0,
     .gpio_nce1 = CONFIG_MTD_NAND_DIRECT_AVM_NCE1,
-    .gpio_cle  = CONFIG_MTD_NAND_DIRECT_AVM_CLE,
-    .gpio_ale  = CONFIG_MTD_NAND_DIRECT_AVM_ALE,
+    .gpio_cle = CONFIG_MTD_NAND_DIRECT_AVM_CLE,
+    .gpio_ale = CONFIG_MTD_NAND_DIRECT_AVM_ALE,
 #endif /*--- #if defined(CONFIG_MTD_NAND_DIRECT_AVM_GPIO) || defined(CONFIG_MTD_NAND_COMPLETE_AVM) ---*/
-    /*--- .adjust_parts = direct_avm_nand_adjust_partitions, ---*/ /*--- => NOP aus platform.c ---*/
-    .parts      = fusiv_nand_partitions,
-    .num_parts  = ARRAY_SIZE(fusiv_nand_partitions),
-    .options    = 0, /*--- NAND_USE_FLASH_BBT | NAND_BBT_SCANALLPAGES | NAND_BBT_SCANEMPTY, ---*/
+    /*--- .adjust_parts = direct_avm_nand_adjust_partitions, ---*//*--- => NOP aus platform.c ---*/
+    .parts = fusiv_nand_partitions,
+    .num_parts = ARRAY_SIZE(fusiv_nand_partitions),
+    .options = 0, /*--- NAND_USE_FLASH_BBT | NAND_BBT_SCANALLPAGES | NAND_BBT_SCANEMPTY, ---*/
     .chip_delay = 0
 };
 
-struct platform_device fusiv_nand_device[] = {
+struct platform_device fusiv_nand_device[] ={
     {
         .name = "direct-avm-nand",
-        .id   = -1,
-        .dev  = {
-                .platform_data  = &direct_avm_nand_platform_data
-            },
+        .id = -1,
+        .dev ={
+            .platform_data = &direct_avm_nand_platform_data
+        },
         .num_resources = ARRAY_SIZE(fusiv_nand_resource),
         .resource = &fusiv_nand_resource[0],
     }
 };
 
-#if defined (FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 )
-/*------------------------------------------------------------------------------------------*\
- * SPI
-\*------------------------------------------------------------------------------------------*/
-struct mtd_partition fusiv_spi_partitions[FUSIV_MTD_SPI_PARTS];
-
-/* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
- * limits addresses to 16M, so using addresses past 16M will wrap */
-static struct resource fusiv_spi_resource[] = {
-    {
-        .start		= 0,
-        .end		= 0 + (256 << 10),    /* 256 KB */
-        .flags		= IORESOURCE_MEM,
-        .parent     = &sflash_resource
-    },
-};
-
-static struct physmap_flash_data fusiv_spi_data = {
-	.width		= 2,
-	.parts		= fusiv_spi_partitions,
-	.nr_parts	= ARRAY_SIZE(fusiv_spi_partitions),
-    .probes     = NULL
-};
-
-struct platform_device fusiv_spi_device[] = {
-    {
-        .name		= "macronix",
-        .id		    = 0,
-        .dev		= {
-            .platform_data	= &fusiv_spi_data,
-        },
-        .num_resources	= 1,
-        .resource	= &fusiv_spi_resource[0],
-    }
-};
-#endif /*--- #if defined (FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 ) ---*/
 #elif defined(CONFIG_FUSIV_VX185)
 
-#if defined(CONFIG_MTD_NAND)
+#define FUSIV_MTD_NAND_PARTS        6
+#define FUSIV_MTD_SPI_PARTS         3
+
 struct mtd_partition fusiv_nand_partitions[FUSIV_MTD_NAND_PARTS];
 
 static struct resource fusiv_nand_resources[] = {
-    [0] = {
-           .start = NFC_BASEADDR+NFC_DATA,
-           .end = NFC_BASEADDR+NFC_SECT7_SYNDROME78,
-           .flags = IORESOURCE_MEM,
-           },
-    [1] = {
-           .start = NAND_FLASH_INT,
-           .end = NAND_FLASH_INT,
-           .flags = IORESOURCE_IRQ,
-           },
+        [0] = {
+                .start = NFC_BASEADDR + NFC_DATA,
+                .end = NFC_BASEADDR + NFC_SECT7_SYNDROME78,
+                .flags = IORESOURCE_MEM,
+              },
+        [1] = {
+                .start = NAND_FLASH_INT,
+                .end = NAND_FLASH_INT,
+                .flags = IORESOURCE_IRQ,
+              },
 };
 
 static struct fusiv_nand_platform nand_platform_data = {
-    .partitions = fusiv_nand_partitions,
-    .nr_partitions = ARRAY_SIZE(fusiv_nand_partitions),
+        .partitions = fusiv_nand_partitions,
+        .nr_partitions = ARRAY_SIZE(fusiv_nand_partitions),
 };
 
 static struct platform_device fusiv_nand_device[] = {
-    {
-        .name = "fusiv-nand",
-        .id = 0,
-        .dev = {
-            .platform_data = &nand_platform_data,
-            },
-        .num_resources = ARRAY_SIZE(fusiv_nand_resources),
-        .resource = fusiv_nand_resources,
-    }
+        {
+                .name = "fusiv-nand",
+                .id = 0,
+                .dev = { .platform_data = &nand_platform_data, },
+                .num_resources = ARRAY_SIZE(fusiv_nand_resources),
+                .resource = fusiv_nand_resources,
+        }
 };
-#endif // #if defined(CONFIG_MTD_NAND)
 
-#if defined(FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 )
 /*------------------------------------------------------------------------------------------*\
  * SPI
-\*------------------------------------------------------------------------------------------*/
+ \*------------------------------------------------------------------------------------------*/
 struct mtd_partition fusiv_spi_partitions[FUSIV_MTD_SPI_PARTS];
 
-/* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
- * limits addresses to 16M, so using addresses past 16M will wrap */
-static struct resource fusiv_spi_resource[] = {
-    {
-        .name       = "vx185_snor_fifos",
-        .start      = VX185_SPI0_RX_FIFO,
-        .end        = VX185_SPI0_TX_FIFO + 128 - 1, /* Datasheet says 256 bytes per FIFO,
-                                                     * RX/TX base addresses are
-                                                     * 128 bytes apart, example code
-                                                     * says 64 bytes... :-\
-                                                     */
-        .flags      = IORESOURCE_MEM,
-        .parent     = &sflash_resource
-    },
-};
-
 static struct vx185_snor_platform vx185_snor_data = {
-    .partitions      = fusiv_spi_partitions,
-    .nr_partitions   = ARRAY_SIZE(fusiv_spi_partitions),
+        .partitions = fusiv_spi_partitions,
+        .nr_partitions = ARRAY_SIZE(fusiv_spi_partitions),
 };
 
 struct platform_device fusiv_spi_device[] = {
         {
-            .name       = "vx185_snor",
-            .id         = -1,
-            .dev        = {
-                .platform_data  = &vx185_snor_data,
-            },
+                .name = "vx185_snor",
+                .id = -1,
+                .dev = { .platform_data = &vx185_snor_data, },
         }
 };
-#endif /*--- #if defined (FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 ) ---*/
-#endif // #if defined(FUSIV_VX180) #elif defined(CONFIG_FUSIV_VX185)
 
+#if defined(CONFIG_TFFS_PANIC_LOG)
+struct mtd_info *fusiv_tffs_mtd[2];
+EXPORT_SYMBOL(fusiv_tffs_mtd);
+#endif
+
+#endif // #if defined(FUSIV_VX180) #elif defined(CONFIG_FUSIV_VX185)
 /*------------------------------------------------------------------------------------------*\
  * RAM
-\*------------------------------------------------------------------------------------------*/
-#ifdef CONFIG_FUSIV_VX185
+ \*------------------------------------------------------------------------------------------*/
 static struct mtd_partition fusiv_ram_partitions[2];
-#else
-static struct mtd_partition fusiv_ram_partitions[1];
-#endif
 
 static struct resource fusiv_ram_resource[] = {
-    {   /* für ins RAM geladenes Filesystem */
-        .start		= 0,
-        .end		= 0 + (32 << 20),
-        .flags		= IORESOURCE_MEM,
-    }
+        { /* für ins RAM geladenes Filesystem */
+                .start = 0,
+                .end = 0 + (32 << 20),
+                .flags = IORESOURCE_MEM,
+        }
 };
 
 static struct platdata_mtd_ram fusiv_ram_data = {
-	.mapname       = "ram-filesystem",
-	.bankwidth	   = 4,
-	.partitions    = fusiv_ram_partitions,
-#ifdef CONFIG_FUSIV_VX185
-	.nr_partitions = 0,
-#else
-	.nr_partitions = ARRAY_SIZE(fusiv_ram_partitions),
-#endif
-    .set_rw        = fusiv_ram_mtd_set_rw,
-    .probes        = probes
+        .mapname = "ram-filesystem",
+        .bankwidth = 4,
+        .partitions = fusiv_ram_partitions,
+        .nr_partitions = 0, // wird im setup richtig gesetzt
+        .set_rw = fusiv_ram_mtd_set_rw,
+        .probes = probes
 };
 
 struct platform_device fusiv_ram_device = {
-	.name		= "mtd-ram",
-	.id		    = -1,
-	.dev		= {
-		.platform_data	= &fusiv_ram_data,
-	},
-	.num_resources	= 1,
-	.resource	= &fusiv_ram_resource[0],
+        .name = "mtd-ram",
+        .id = -1,
+        .dev = { .platform_data = &fusiv_ram_data, },
+        .num_resources = 1,
+        .resource = &fusiv_ram_resource[0],
 };
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static int fusiv_squashfs_parser_function(struct mtd_info *mtd, struct mtd_partition **p_mtd_pat, unsigned long param) {
-    enum _flash_map_enum maptype = MAP_UNKNOWN;
-    unsigned count = 1, maxcount = 0;
-    
+static int fusiv_squashfs_parser_function(struct mtd_info *mtd,
+        struct mtd_partition **p_mtd_pat, unsigned long param)
+{
+    enum _flash_map_enum maptype;
+    struct mtd_partition *kernel_part, *fs_part;
+    size_t readlen;
+    loff_t curr_offset;
+    int count;
+    uint32_t magic;
+
 #if defined(FUSIV_MTD_DEBUG)
-    printk(KERN_ERR "[fusiv_squashfs_parser_function] mtd_info->name %s mtd_info->index %u param=%lu p_mtd_pat=0x%p\n", mtd->name, mtd->index, param, p_mtd_pat);
-#endif
-    
-#ifdef CONFIG_FUSIV_VX185
-    if (!strcmp(mtd->name, "ram-filesystem")) {
-#else
-    if (!strcmp(mtd->name, "mtd-ram")) {
+    pr_err("[%s] mtd_info->name %s mtd_info->index %u param=%lu p_mtd_pat=0x%p\n",
+            __func__, mtd->name, mtd->index, param, p_mtd_pat);
 #endif
+
+    count = 0;
+    maptype = MAP_UNKNOWN;
+    kernel_part = NULL;
+    fs_part = NULL;
+
+    if(!strcmp(mtd->name, "ram-filesystem") || !strcmp(mtd->name, "mtd-ram")){
         maptype = MAP_RAM;
-    } else if (!strcmp(mtd->name, "physmap-flash")) {
+    }else if(!strcmp(mtd->name, "physmap-flash")){
         maptype = MAP_NOR_FLASH;
         flash_erase_block_size = mtd->erasesize;
-#ifdef CONFIG_FUSIV_VX185
-    } else if (!strcmp(mtd->name, "mtd-spi_nor")) {
+    }else if(!strcmp(mtd->name, "mtd-spi_nor")){
         maptype = MAP_SPI_FLASH;
         flash_erase_block_size = mtd->erasesize;
-#endif
-    } else {
-        printk(KERN_WARNING "[fusiv_squashfs_parser_function] with unknown mtd type %s\n", mtd->name);
-        return 0;
+    }else{
+        pr_warning("[fusiv_squashfs_parser_function] with unknown mtd type %s\n", mtd->name);
+        goto done;
     }
 
-    if(p_mtd_pat) {
-        unsigned int magic = 0, readlen = 0;
-        loff_t pos, start_offset;
+    if(p_mtd_pat == NULL){
+        pr_err("[%s] Invalid partition table pointer.\n", __func__);
+        goto done;
+    }
 
-        if(*p_mtd_pat) 
-            printk("[fusiv_squashfs_parser_function] *p_mtd_pat->name %s\n", (*p_mtd_pat)->name);
+    if(*p_mtd_pat){
+        printk("[fusiv_squashfs_parser_function] (*p_mtd_pat)[0].name %s\n",
+               (*p_mtd_pat)[0].name);
+    }
 
-        switch (maptype) {
-            case MAP_NOR_FLASH:
-                if(*p_mtd_pat == NULL) {
-                    *p_mtd_pat = fusiv_nor_partitions;
-                }
-                maxcount = ARRAY_SIZE(fusiv_nor_partitions);
-                break;
-            case MAP_RAM:
-                if(*p_mtd_pat == NULL) {
-                    *p_mtd_pat = fusiv_ram_partitions;
-                }
-                maxcount = ARRAY_SIZE(fusiv_ram_partitions);
-                break;
-#ifdef CONFIG_FUSIV_VX185
-            case MAP_SPI_FLASH:
-                if(*p_mtd_pat == NULL) {
-                    *p_mtd_pat = fusiv_spi_partitions;
-                }
-                maxcount = ARRAY_SIZE(fusiv_spi_partitions);
-                break;
-#endif
-            default:
-                break;
+    switch(maptype){
+#if defined(CONFIG_FUSIV_VX180)
+    case MAP_NOR_FLASH:
+        if(*p_mtd_pat == NULL){
+            *p_mtd_pat = fusiv_nor_partitions;
         }
-
-#if defined(FUSIV_MTD_DEBUG)
-        printk("[fusiv_squashfs_parser_function] try partition %s (offset 0x%x len %u blocksize=%x)\n", 
-                (*p_mtd_pat)[count].name,
-                (*p_mtd_pat)[count].offset,
-                (*p_mtd_pat)[count].size,
-                mtd->erasesize);
+        count = ARRAY_SIZE(fusiv_nor_partitions);
+        break;
 #endif
-
-        start_offset = pos = (*p_mtd_pat)[count].offset;
-        while(pos < (*p_mtd_pat)[1].offset + (*p_mtd_pat)[count].size) {
-            mtd->read(mtd, (loff_t)pos, sizeof(unsigned int), &readlen, (u_char*)&magic);
-            /*--- printk("[fusiv_squashfs_parser_function] read %u bytes, magic = 0x%08x index %u pos 0x%x\n", readlen, magic, mtd->index, (unsigned int)pos); ---*/
-            if(magic == 0x73717368) {
-                /*-------------------------------------------------------------------------------------*\
-                 *
-                 *    +---+---------------------+-----------------------+--------------------+
-                 *    |   |     Kernel          |     SquashFS          |      JFFS2         |
-                 *    +---+---------------------+-----------------------+--------------------+
-                 *        A                     ^_pos                                        E
-                 *
-                 *    Zu Beginn ist das Layout obiges:
-                 *    start_offset = A
-                 *    MTD1 mit Kernel reicht von A bis E
-                 *    MTD5 für JFFS2 kann gesetzt sein, wenn JFFS2 Parser vorher schon was gefunden hat
-                 *
-                 *    Wenn SquashFS gefunden wird, wird MTD1 auf den Kernel verkleinert,
-                 *    MTD0 für das FS wird von pos bis E angelegt
-                 *    Wenn noch kein MTD5 mit JFFS2 existiert wird dieses innerhalb von MTD0 angelegt
-                 *
-                \*-------------------------------------------------------------------------------------*/
-                (*p_mtd_pat)[0].offset = pos;
-                (*p_mtd_pat)[0].size	 = (u_int32_t)start_offset + (u_int32_t)(*p_mtd_pat)[1].size - (u_int32_t)pos;
-#ifdef CONFIG_FUSIV_VX180
-                (*p_mtd_pat)[0].name	 = "rootfs";
+    case MAP_RAM:
+        if(*p_mtd_pat == NULL ){
+            *p_mtd_pat = fusiv_ram_partitions;
+        }
+        // we can only be sure to have the filesystem.
+        count = 1;
+        break;
+#if defined(CONFIG_FUSIV_VX185)
+    case MAP_SPI_FLASH:
+        if(*p_mtd_pat == NULL ){
+            *p_mtd_pat = fusiv_spi_partitions;
+        }
+        count = ARRAY_SIZE(fusiv_spi_partitions);
+        goto done;
 #endif
-                (*p_mtd_pat)[1].size	 = (u_int32_t)pos - (u_int32_t)start_offset;
+    default:
+        pr_err("[%s] unknown map type for mtd %s\n", __func__, mtd->name);
+        goto done;
+    }
 
-#ifdef CONFIG_FUSIV_VX185
-                /*
-                 * nur umbenennen, wenn es keine RAM-MTDs sind
-                 *
-                 */
-                if(maptype != MAP_RAM) {
-                    (*p_mtd_pat)[0].name     = "rootfs";
-                    (*p_mtd_pat)[1].name     = "kernel";
-                }
+#if defined(FUSIV_MTD_DEBUG)
+    printk("[fusiv_squashfs_parser_function] try partition %s (offset 0x%x len %u blocksize=%x)\n",
+           (*p_mtd_pat)[0].name,
+           (*p_mtd_pat)[0].offset,
+           (*p_mtd_pat)[0].size,
+           mtd->erasesize);
 #endif
 
-                printk("[fusiv_squashfs_parser_function] magic found @pos 0x%x\n", (unsigned int)pos);
-                if ((maptype == MAP_NOR_FLASH) && (memcmp(fusiv_nor_partitions[5].name, "jffs2", 4) != 0)) {
-                    /* JFFS2 nicht gefunden: Wenn jffs2_size gesetzt ist, ggf. verkleinern */
-                    /* sonst anlegen mit der verbleibenden Flash Grösse nach Filesystem % 64k */
-                    u_int32_t   jffs2_size, jffs2_start, jffs2_earliest_start;
-                    struct squashfs_super_block squashfs_sb;
+    /*
+     * we can get here only for RAM and NOR MTDs. In the former case the MTD
+     * might contain a combined Kernel+FS image and has to be split up.
+     * This is always the case for a NOR MTD, which might also contain a jffs2
+     */
+    kernel_part = &((*p_mtd_pat)[1]);
+    fs_part = &((*p_mtd_pat)[0]);
+    curr_offset = 0;
+    while(curr_offset < kernel_part->size){
+        mtd->read(mtd, kernel_part->offset + curr_offset,
+                  sizeof(magic), &readlen, (u_char*) &magic);
 
-                    mtd->read(mtd, (loff_t)pos, sizeof(struct squashfs_super_block), &readlen, (u_char*)&squashfs_sb);
-                    jffs2_earliest_start = (u_int32_t)pos + (u_int32_t)squashfs_sb.bytes_used;
-                    /*--- printk("squashfs pos: %x\n", (u_int32_t)pos); ---*/
-                    /*--- printk("squashfs size: %x\n", (u_int32_t)squashfs_sb.bytes_used); ---*/
-                    /*--- printk("jffs2_start (squashfs pos + len) = %x\n", (u_int32_t)jffs2_earliest_start); ---*/
-                    if (jffs2_earliest_start & (mtd->erasesize-1)) {
-                        /*--- printk("align jffs: start: %x\n", jffs2_earliest_start); ---*/
-                        jffs2_earliest_start = (jffs2_earliest_start & ~(mtd->erasesize-1)) + mtd->erasesize;
-                    }
-                    /*--- printk("jffs2_earliest_start (aligned) = %x\n", jffs2_earliest_start); ---*/
-                    jffs2_size = ((*p_mtd_pat)[0].offset + (*p_mtd_pat)[0].size - jffs2_earliest_start) >> 16;
-                    /* jffs2_size in 64k Blöcken. Muss ggf. um 1 veringert werden für 128k Block Flash */
-                    /*--- printk("jffs2_size = %x\n", jffs2_size); ---*/
-                    jffs2_size = jffs2_size & ~((mtd->erasesize / 0x10000)-1);
-                    /*--- printk("jffs2_size = %x\n", jffs2_size); ---*/
-                    if (jffs2_size < (FUSIV_MTD_JFFS2_MIN_SIZE * (mtd->erasesize/0x10000))) {
-                        printk(KERN_WARNING "[fusiv_squashfs_parser_function]: not enough space for JFFS2!\n");
-                    } else {
-                        printk("[fusiv_squashfs_parser_function] flashsize=%x\n", fusiv_nor_flashsize);
-                        if ((fusiv_nor_flashsize <= 0x800000) && (jffs2_size > (FUSIV_MTD_JFFS2_MIN_SIZE * (mtd->erasesize/0x10000)))) {
-                            /* Für 7270 und W920V mit nur 8MB Flash das JFFS2 auf Minimalgröße halten/verringern */
-                            jffs2_start = jffs2_earliest_start + ((jffs2_size - FUSIV_MTD_JFFS2_MIN_SIZE) * mtd->erasesize);
-                            jffs2_size = FUSIV_MTD_JFFS2_MIN_SIZE * (mtd->erasesize/0x10000);
-                        } else {
-                            /* Für 7270v3 mit vergeigter Produktion (ohne JFFS_SIZE im Urlader-Env.) die Größe
-                             * auf 50 begrenzen und nach hinten schieben, damit nicht bei jedem FW Update das
-                             * JFFS überschrieben wird */
-                            if (jffs2_size > FUSIV_MTD_JFFS2_MAX_SIZE) {
-                                jffs2_start = jffs2_earliest_start + (jffs2_size - FUSIV_MTD_JFFS2_MAX_SIZE) * 0x10000;
-                                jffs2_size = FUSIV_MTD_JFFS2_MAX_SIZE;
-                            } else {
-                                jffs2_start = jffs2_earliest_start;
-                            }
-                        }
-                        fusiv_nor_partitions[5].offset = jffs2_start;
-                        fusiv_nor_partitions[5].size   = jffs2_size * 0x10000;
-                        fusiv_nor_partitions[5].name   = "jffs2";
-                        printk(KERN_ERR "[fusiv_squashfs_parser_function] jffs2_start@%x size: %d\n", jffs2_start, jffs2_size); 
-                        {
-                            struct erase_info instr;
-                            int ret;
+        /*--- printk("[fusiv_squashfs_parser_function] read %u bytes, magic = 0x%08x index %u pos 0x%x\n", readlen, magic, mtd->index, (unsigned int)pos); ---*/
+        if(magic == 0x73717368){
+            /*-------------------------------------------------------------------------------------*\
+             *
+             *    +---+---------------------+-----------------------+--------------------+
+             *    |   |     Kernel          |     SquashFS          |      JFFS2         |
+             *    +---+---------------------+-----------------------+--------------------+
+             *        A                     ^_pos                                        E
+             *
+             *    Zu Beginn ist das Layout obiges:
+             *    start_offset = A
+             *    MTD1 mit Kernel reicht von A bis E
+             *    MTD5 für JFFS2 kann gesetzt sein, wenn JFFS2 Parser vorher schon was gefunden hat
+             *
+             *    Wenn SquashFS gefunden wird, wird MTD1 auf den Kernel verkleinert,
+             *    MTD0 für das FS wird von pos bis E angelegt
+             *    Wenn noch kein MTD5 mit JFFS2 existiert wird dieses innerhalb von MTD0 angelegt
+             *
+             \*-------------------------------------------------------------------------------------*/
+            fs_part->offset += curr_offset;
+            fs_part->size -= curr_offset;
+            kernel_part->size = curr_offset;
 
-                            memset(&instr, 0, sizeof(instr));
-                            instr.mtd = mtd;
-                            instr.addr = jffs2_start;
-                            instr.len = jffs2_size * 0x10000;
-                            instr.callback = NULL;
-                            instr.fail_addr = 0xffffffff;
+            printk("[%s] magic found @offset 0x%llx\n", __func__, curr_offset);
 
-                            ret = mtd->erase(mtd, &instr);
-                            if (ret) {
-                                printk(KERN_ERR "jffs mtd erase failed %d\n", ret);
-                            }
-                        }
-                    }
-                }
-                return maxcount;
+            if(maptype == MAP_NOR_FLASH){
+                // FIXME: why not name them right at setup?!
+                kernel_part->name = "kernel";
+                fs_part->name = "rootfs";
+            } else if(maptype == MAP_RAM && curr_offset > 0){
+                ++count;
             }
-            pos += 256;
+
+            break;
         }
-        
+
+        curr_offset += 256;
     }
-    return 0;
-}
 
+    // TODO: jffs stuff
+done:
+    return count;
+}
+#if 0
 #define JFFS_NODES ( JFFS2_NODETYPE_DIRENT | JFFS2_NODETYPE_INODE | JFFS2_NODETYPE_CLEANMARKER | JFFS2_NODETYPE_PADDING | JFFS2_NODETYPE_SUMMARY | JFFS2_NODETYPE_XATTR | JFFS2_NODETYPE_XREF) 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static int fusiv_jffs2_parser_function(struct mtd_info *mtd, struct mtd_partition **p_mtd_pat, unsigned long param) {
+static int fusiv_jffs2_parser_function(struct mtd_info *mtd, struct mtd_partition **p_mtd_pat,
+        unsigned long param)
+{
     enum _flash_map_enum maptype = MAP_UNKNOWN;
     unsigned int count = 1;
-    
-    DEBUG_MTD("mtd_info->name %s mtd_info->index %u param=%lu p_mtd_pat=0x%p\n", mtd->name, mtd->index, param, p_mtd_pat);
 
-    if (!strcmp(mtd->name, "ram-filesystem")) {
+    DEBUG_MTD("mtd_info->name %s mtd_info->index %u param=%lu p_mtd_pat=0x%p\n",
+              mtd->name,
+              mtd->index,
+              param,
+              p_mtd_pat);
+
+    if(!strcmp(mtd->name, "ram-filesystem")){
         maptype = MAP_RAM;
-    } else if (!strcmp(mtd->name, "physmap-flash")) {
+    }else if(!strcmp(mtd->name, "physmap-flash")){
         maptype = MAP_NOR_FLASH;
-    } else {
-        printk(KERN_WARNING "[%s] with unknown mtd type %s\n", __func__, mtd->name);
+    }else{
+        pr_warning("[%s] with unknown mtd type %s\n", __func__, mtd->name);
         return 0;
     }
 
-    if(p_mtd_pat) {
+    if(p_mtd_pat){
         unsigned int magic = 0, readlen = 0;
         loff_t pos;
-        if(*p_mtd_pat) 
+        if(*p_mtd_pat)
             printk("[%s] *p_mtd_pat->name %s\n", __func__, (*p_mtd_pat)->name);
 
-        switch (maptype) {
-            case MAP_NOR_FLASH:
-                if(*p_mtd_pat == NULL) {
-                    *p_mtd_pat = fusiv_nor_partitions;
-                }
-                break;
-            case MAP_RAM:
-                count = 2;
-                if(*p_mtd_pat == NULL) {
-                    *p_mtd_pat = fusiv_ram_partitions;
-                }
-                /*--- return 0; ---*/   /* nicht im RAM suchen */
-                break;
-            default:
-                break;
+        switch(maptype){
+        case MAP_NOR_FLASH:
+            if(*p_mtd_pat == NULL ){
+                *p_mtd_pat = fusiv_nor_partitions;
+            }
+            break;
+        case MAP_RAM:
+            count = 2;
+            if(*p_mtd_pat == NULL ){
+                *p_mtd_pat = fusiv_ram_partitions;
+            }
+            //return 0;   /* nicht im RAM suchen */
+            break;
+        default:
+            break;
         }
 
 #if defined(FUSIV_MTD_DEBUG)
-        printk("[%s] try partition %s (offset 0x%x len %u)\n", 
-                __func__,
-                (*p_mtd_pat)[count].name,
-                (*p_mtd_pat)[count].offset,
-                (*p_mtd_pat)[count].size);
+        printk("[%s] try partition %s (offset 0x%x len %u)\n",
+               __func__,
+               (*p_mtd_pat)[count].name,
+               (*p_mtd_pat)[count].offset,
+               (*p_mtd_pat)[count].size);
 #endif
 
         pos = (*p_mtd_pat)[count].offset;
-        while(pos < (*p_mtd_pat)[count].offset + (*p_mtd_pat)[count].size) {
-            mtd->read(mtd, (loff_t)pos, sizeof(unsigned int), &readlen, (u_char*)&magic);
-            /*--- printk("[%s] read %u bytes, magic = 0x%08x index %u pos 0x%x\n", __func__, readlen, magic, mtd->index, pos); ---*/
+        while(pos < (*p_mtd_pat)[count].offset + (*p_mtd_pat)[count].size){
+            mtd->read(mtd, (loff_t) pos, sizeof(unsigned int), &readlen, (u_char*) &magic);
+            printk("[%s] read %u bytes, magic = 0x%08x index %u pos 0x%llx\n",
+                   __func__,
+                   readlen,
+                   magic,
+                   mtd->index,
+                   pos);
 #ifdef __LITTLE_ENDIAN
-            if ((((magic >> 16) & ~JFFS_NODES) == 0) && ((magic & 0xFFFF) == JFFS2_MAGIC_BITMASK)) {
+            if ((((magic >> 16) & ~JFFS_NODES) == 0) && ((magic & 0xFFFF) == JFFS2_MAGIC_BITMASK)){
 #else
-            if (((magic >> 16) == JFFS2_MAGIC_BITMASK) && (((magic & 0xFFFF) & ~JFFS_NODES) == 0)) {
+            if(((magic >> 16) == JFFS2_MAGIC_BITMASK)
+                    && (((magic & 0xFFFF) & ~JFFS_NODES)== 0)){
 #endif
-                switch (maptype) {
-                    case MAP_NOR_FLASH:
-                        (*p_mtd_pat)[5].size	 = (*p_mtd_pat)[1].offset + (*p_mtd_pat)[1].size - pos;
-                        (*p_mtd_pat)[5].offset   = pos;
-                        (*p_mtd_pat)[5].name	 = "jffs2";
-                        /*--- printk("mtd1: size %d\n", (*p_mtd_pat)[1].size); ---*/
-                        printk("[%s] magic %04x found @pos 0x%x, size %d\n", __func__, magic, (unsigned int)pos, (*p_mtd_pat)[5].size);
-                        break;
-                    case MAP_RAM:
-                        (*p_mtd_pat)[2].size	 = (*p_mtd_pat)[count].offset + (*p_mtd_pat)[count].size - pos;
-                        (*p_mtd_pat)[2].offset   = pos;
-                        (*p_mtd_pat)[2].name	 = "ram-jffs2";
-                        /*--- printk("mtd1: size %d\n", (*p_mtd_pat)[1].size); ---*/
-                        printk("[%s] magic %04x found @pos 0x%x, size %d\n", __func__, magic, (unsigned int)pos, (*p_mtd_pat)[2].size);
-                        break;
-                    default:
-                        break;
+                switch(maptype){
+                case MAP_NOR_FLASH:
+                    (*p_mtd_pat)[5].size = (*p_mtd_pat)[1].offset + (*p_mtd_pat)[1].size - pos;
+                    (*p_mtd_pat)[5].offset = pos;
+                    (*p_mtd_pat)[5].name = "jffs2";
+                    /*--- printk("mtd1: size %d\n", (*p_mtd_pat)[1].size); ---*/
+                    printk("[%s] magic %04x found @pos 0x%x, size %d\n",
+                           __func__,
+                           magic,
+                           (unsigned int) pos,
+                           (*p_mtd_pat)[5].size);
+                    break;
+                case MAP_RAM:
+                    (*p_mtd_pat)[2].size = (*p_mtd_pat)[count].offset
+                            + (*p_mtd_pat)[count].size - pos;
+                    (*p_mtd_pat)[2].offset = pos;
+                    (*p_mtd_pat)[2].name = "ram-jffs2";
+                    /*--- printk("mtd1: size %d\n", (*p_mtd_pat)[1].size); ---*/
+                    printk("[%s] magic %04x found @pos 0x%x, size %d\n",
+                           __func__,
+                           magic,
+                           (unsigned int) pos,
+                           (*p_mtd_pat)[2].size);
+                    break;
+                default:
+                    break;
                 }
                 return 0;
             }
@@ -620,16 +531,17 @@
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-struct mtd_part_parser fusiv_squashfs_parser = {
-	.name     = "find_squashfs",
-	.parse_fn = fusiv_squashfs_parser_function
+struct mtd_part_parser fusiv_jffs2_parser = {
+        .name = "find_jffs2",
+        .parse_fn = fusiv_jffs2_parser_function
 };
+#endif
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-struct mtd_part_parser fusiv_jffs2_parser = {
-	.name     = "find_jffs2",
-	.parse_fn = fusiv_jffs2_parser_function
+struct mtd_part_parser fusiv_squashfs_parser = {
+        .name = "find_squashfs",
+        .parse_fn = fusiv_squashfs_parser_function
 };
 
 /*------------------------------------------------------------------------------------------*\
@@ -637,60 +549,65 @@
 struct platform_device *fusiv_platform_devices[20];
 unsigned int fusiv_platform_devices_count = 0;
 
-void add_to_platform_device_list(struct platform_device *device){ 
-    printk(KERN_INFO "[FUSIV] add %s to the platform device list\n", device->name);
+void add_to_platform_device_list(struct platform_device *device)
+{
+    pr_info("[FUSIV] add %s to the platform device list\n", device->name);
     fusiv_platform_devices[fusiv_platform_devices_count++] = device;
 }
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-void fusiv_init_platform_devices(void) {
-    printk(KERN_INFO "[FUSIV] register %d platform device(s)\n", fusiv_platform_devices_count);
-	platform_add_devices(fusiv_platform_devices, fusiv_platform_devices_count);
+void fusiv_init_platform_devices(void)
+{
+    pr_info("[FUSIV] register %d platform device(s)\n", fusiv_platform_devices_count);
+    platform_add_devices(fusiv_platform_devices, fusiv_platform_devices_count);
 }
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static inline unsigned int get_flash_base(unsigned int flash_size) {
-    return 0x48000000; 
+static inline unsigned int get_flash_base(unsigned int flash_size)
+{
+    return 0x48000000;
 }
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-void fusiv_ram_mtd_set_rw(struct device *pdev, int mode) {
-    if(mode == PLATRAM_RO) {
+void fusiv_ram_mtd_set_rw(struct device *pdev, int mode)
+{
+    if(mode == PLATRAM_RO){
         DEBUG_MTD("PLATRAM_RO");
-    } else if(mode == PLATRAM_RW) {
+    }else if(mode == PLATRAM_RW){
         DEBUG_MTD("PLATRAM_RW");
     }
 }
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-unsigned int get_erase_block_size_on_ram_device(struct mtd_info *mtd) {
+unsigned int get_erase_block_size_on_ram_device(struct mtd_info *mtd)
+{
     unsigned int readlen = 0;
     loff_t pos = 0;
     unsigned int value1, value2;
 
-    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*)&value1);
+    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value1);
     if(readlen != sizeof(unsigned int))
         return 0;
     /*--- DEBUG_MTD("name=%s pos=0x%x value=0x%x" , mtd->name, pos, value1); ---*/
 
     pos += 0x10000ULL;
-    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*)&value2);
+    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2);
     if(readlen != sizeof(unsigned int))
         return 0;
     /*--- DEBUG_MTD("name=%s pos=0x%x value2=0x%x" , mtd->name, pos, value2); ---*/
 
-    if(value1 == value2) {
+    if(value1 == value2){
         pos += 0x10000ULL;
-        mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*)&value2);
+        mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2);
         if(readlen != sizeof(unsigned int))
             return 0;
         /*--- DEBUG_MTD("name=%s pos=0x%x value2=0x%x (check)" , mtd->name, pos, value2); ---*/
 
-        if(value1 == value2) {
+        if(value1 == value2){
             DEBUG_MTD("eraseblocksize=0x10000");
             return 0x10000;
         }
@@ -698,13 +615,13 @@
     }
 
     pos += 0x10000ULL;
-    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*)&value2);
+    mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2);
     if(readlen != sizeof(unsigned int))
         return 0;
     DEBUG_MTD("name=%s pos=0x%Lx value2=0x%x", mtd->name, pos, value2);
 
-    if(value1 == value2) {
-        DEBUG_MTD("eraseblocksize=0x20000" );
+    if(value1 == value2){
+        DEBUG_MTD("eraseblocksize=0x20000");
         return 0x20000;
     }
     return 0;
@@ -712,19 +629,20 @@
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static int get_partition_index(struct mtd_info *mtd) {
+static int get_partition_index(struct mtd_info *mtd)
+{
 
     extern struct mtd_info *mtd_table[MAX_MTD_DEVICES];
     unsigned int i;
 
-    for(i = 0 ; i < MAX_MTD_DEVICES ; i++) {
-        if(mtd_table[i] == mtd) {
+    for(i = 0; i < MAX_MTD_DEVICES; i++){
+        if(mtd_table[i] == mtd){
             return i;
         }
     }
-    return -1;
 
-} 
+    return -1;
+}
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
@@ -735,163 +653,150 @@
 char *str_rootfs[] = { "rootfs_ram", "rootfs", "filesystem" };
 struct mtd_info *fusiv_urlader_mtd;
 
-void fusiv_mtd_add_notifier(struct mtd_info *mtd) {
+void fusiv_mtd_add_notifier(struct mtd_info *mtd)
+{
 
     int i, index;
-#ifdef CONFIG_FUSIV_VX185
-    char buff[2048];
-    union _tffs_segment_entry *u;
-    size_t retlen;
-#endif
 
-    if(!mtd->name) {
+    if(!mtd->name){
         DEBUG_MTD("Leeres MTD übergeben!");
         return;
     }
-    DEBUG_MTD("name %s" , mtd->name);
-
+    DEBUG_MTD("name %s", mtd->name);
 
-    for (i = 0; i < sizeof(str_rootfs) / sizeof(char*) ; i++) {
-        if (!strcmp(mtd->name, str_rootfs[i])) {
+    for(i = 0; i < sizeof(str_rootfs) / sizeof(char*); i++){
+        if(!strcmp(mtd->name, str_rootfs[i])){
             DEBUG_MTD("found %s", mtd->name);
-            if (found_rootfs_ram)       /*--- we found a rootfs in RAM and use only this ---*/
+            if(found_rootfs_ram) /*--- we found a rootfs in RAM and use only this ---*/
                 return;
-            if (!strcmp(mtd->name, str_rootfs[0]))
-                found_rootfs_ram = 1;   /*--- signal that we found a rootfs in RAM ---*/
+            if(!strcmp(mtd->name, str_rootfs[0]))
+                found_rootfs_ram = 1; /*--- signal that we found a rootfs in RAM ---*/
 
             index = get_partition_index(mtd);
-            DEBUG_MTD("use %s" , mtd->name);
-            if (index >= 0) {
+            DEBUG_MTD("use %s", mtd->name);
+            if(index >= 0){
                 static char root_device[64];
                 sprintf(root_device, "/dev/mtdblock%d", index);
-                DEBUG_MTD("root device: %s (%s)" , root_device, mtd_table[index]->name);
+                DEBUG_MTD("root device: %s (%s)", root_device, mtd_table[index]->name);
                 root_dev_setup(root_device);
                 return;
-            } else {
-                DEBUG_MTD("error: could not find any root device for %s" , mtd->name);
+            }else{
+                DEBUG_MTD("error: could not find any root device for %s", mtd->name);
             }
         }
     }
 
-    if(!strcmp(mtd->name, "urlader")) {
+    if(!strcmp(mtd->name, "urlader")){
         DEBUG_MTD("set fusiv_urlader_mtd");
         fusiv_urlader_mtd = mtd;
 #if defined(CONFIG_TFFS)
-    } else if(!strcmp(mtd->name, "tffs (1)")) {
+    }else if(!strcmp(mtd->name, "tffs (1)")){
 
         index = get_partition_index(mtd);
 
-        if (index >= 0) {
-#ifdef CONFIG_FUSIV_VX185
-            mtd->read(mtd, 0, sizeof(union _tffs_segment_entry), &retlen, buff);
-            u = (union _tffs_segment_entry *) buff;
-            if(u->Entry.ID != FLASH_FS_ID_SEGMENT){
-                printk(KERN_ERR "[%s] No tffs segment header found on mtd%d, formatting it\n", __func__, index);
-                TFFS_Format(NULL, mtd);
-
-                u->Entry.ID = FLASH_FS_ID_SEGMENT;
-                u->Entry.Length = sizeof(unsigned int);
-                TFFS_SET_SEGMENT_VALUE(u, 1);
-
-                mtd->write(mtd, 0, sizeof(buff), &retlen, buff);
-            }
+        if(index >= 0){
+#if defined(CONFIG_FUSIV_VX185) && defined(CONFIG_TFFS_PANIC_LOG)
+            fusiv_tffs_mtd[0] = mtd;
 #endif
             DEBUG_MTD("tffs (1) on Index %d", index);
             tffs_mtd[0] = index;
         }
-    } else if(!strcmp(mtd->name, "tffs (2)")) {
+    }else if(!strcmp(mtd->name, "tffs (2)")){
 
         index = get_partition_index(mtd);
 
-        if (index >= 0) {
-#ifdef CONFIG_FUSIV_VX185
-            mtd->read(mtd, 0, sizeof(union _tffs_segment_entry), &retlen, buff);
-            u = (union _tffs_segment_entry *) buff;
-            if(u->Entry.ID != FLASH_FS_ID_SEGMENT){
-                printk(KERN_ERR "[%s] No tffs segment header found on mtd%d, formatting it\n", __func__, index);
-                TFFS_Format(NULL, mtd);
-
-                u->Entry.ID = FLASH_FS_ID_SEGMENT;
-                u->Entry.Length = sizeof(unsigned int);
-                TFFS_SET_SEGMENT_VALUE(u, 1);
-
-                mtd->write(mtd, 0, sizeof(buff), &retlen, buff);
-            }
+        if(index >= 0){
+#if defined(CONFIG_FUSIV_VX185) && defined(CONFIG_TFFS_PANIC_LOG)
+            fusiv_tffs_mtd[1] = mtd;
 #endif
             DEBUG_MTD("tffs (2) on Index %d", index);
             tffs_mtd[1] = index;
         }
 #endif /*--- #if defined(CONFIG_TFFS) ---*/
-    } else {
-        DEBUG_MTD("skip %s" , mtd->name);
+    }else{
+        DEBUG_MTD("skip %s", mtd->name);
     }
 }
 
-void fusiv_mtd_rm_notifier(struct mtd_info *mtd) {
+void fusiv_mtd_rm_notifier(struct mtd_info *mtd)
+{
     DEBUG_MTD("ignore %s", mtd->name);
 }
 
 struct mtd_notifier fusiv_mtd_notifier = {
-    add: fusiv_mtd_add_notifier,
-    remove: fusiv_mtd_rm_notifier
+        .add = fusiv_mtd_add_notifier,
+        .remove = fusiv_mtd_rm_notifier
 };
 
+#if defined(CONFIG_FUSIV_VX180)
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-void find_nmi_vector(void) {
+void find_nmi_vector(void)
+{
     unsigned int len;
-    if(strcmp(nmi_vector_location->vector_id, "NMI Boot Vector")) {
-        printk(KERN_ERR "[%s] no nmi vector found\n", __FUNCTION__);
+    if(strcmp(nmi_vector_location->vector_id, "NMI Boot Vector")){
+        pr_err("[%s] no nmi vector found\n", __FUNCTION__);
         return;
     }
-    len  = (nmi_vector_location->firmware_length + flash_erase_block_size) & ~(flash_erase_block_size  - 1);
-    printk(KERN_ERR "[%s] nmi vector found. Firmware length 0x%x bytes (erase block align 0x%x) vector gap size 0x%x bytes.\n", 
-            __FUNCTION__, nmi_vector_location->firmware_length, len, nmi_vector_location->vector_gap);
-    len += fusiv_nor_partitions[2].size;  /*--- urlader size ---*/
-    printk(KERN_ERR "[%s] add '%s' size 0x%x to length\n", __FUNCTION__, fusiv_nor_partitions[2].name, fusiv_nor_partitions[2].size);
-    
+    len = (nmi_vector_location->firmware_length + flash_erase_block_size)
+            & ~(flash_erase_block_size - 1);
+    pr_err("[%s] nmi vector found. Firmware length 0x%x bytes (erase block align 0x%x) vector gap size 0x%x bytes.\n",
+           __FUNCTION__,
+           nmi_vector_location->firmware_length,
+           len,
+           nmi_vector_location->vector_gap);
+    len += fusiv_nor_partitions[2].size; /*--- urlader size ---*/
+    pr_err("[%s] add '%s' size 0x%x to length\n",
+           __FUNCTION__,
+           fusiv_nor_partitions[2].name,
+           fusiv_nor_partitions[2].size);
+
     set_nmi_vetor_gap(0xbfc00000, len, nmi_vector_location->vector_gap);
 }
 
-
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-void find_nmi_vector_gap(unsigned int base, unsigned int end) {
+void find_nmi_vector_gap(unsigned int base, unsigned int end)
+{
     unsigned int len;
-    struct _nmi_vector_location *first_loc = (struct _nmi_vector_location *)(base + 0x40);
-    struct _nmi_vector_location *last_loc = (struct _nmi_vector_location *)(base + 0xbe0040);
-    while((unsigned long)first_loc <= (unsigned long)last_loc) {
+    struct _nmi_vector_location *first_loc = (struct _nmi_vector_location *) (base + 0x40);
+    struct _nmi_vector_location *last_loc = (struct _nmi_vector_location *) (base + 0xbe0040);
+    while((unsigned long) first_loc <= (unsigned long) last_loc){
         /*--- if(((unsigned long)first_loc > 0x87d95a00UL) && ((unsigned long)first_loc < 0x87d96000UL)) ---*/
-            /*--- printk(KERN_ERR "[NMI] %p => %10pB\n", first_loc, first_loc); ---*/
-        if(!strcmp(first_loc->vector_id, "NMI Boot Vector")) {
+        /*--- pr_err("[NMI] %p => %10pB\n", first_loc, first_loc); ---*/
+        if(!strcmp(first_loc->vector_id, "NMI Boot Vector")){
 
-            len = end - ((unsigned int)first_loc - 0x40) + first_loc->vector_gap;
+            len = end - ((unsigned int) first_loc - 0x40) + first_loc->vector_gap;
 
-            printk(KERN_ERR "[%s] nmi vector found. Firmware length 0x%x bytes (move length 0x%x) vector gap size 0x%x bytes.\n", 
-                __FUNCTION__, first_loc->firmware_length, len, first_loc->vector_gap);
+            pr_err("[%s] nmi vector found. Firmware length 0x%x bytes (move length 0x%x) vector gap size 0x%x bytes.\n",
+                   __FUNCTION__,
+                   first_loc->firmware_length,
+                   len,
+                   first_loc->vector_gap);
 
-            memmove((void *)((unsigned int)first_loc - 0x40), 
-                    (void *)((unsigned int)first_loc + first_loc->vector_gap - 0x40), 
+            memmove((void *) ((unsigned int) first_loc - 0x40),
+                    (void *) ((unsigned int) first_loc + first_loc->vector_gap - 0x40),
                     len);
             return;
         }
-        first_loc = (struct _nmi_vector_location *)((unsigned int)first_loc + 256);
+        first_loc = (struct _nmi_vector_location *) ((unsigned int) first_loc + 256);
     }
-    printk(KERN_ERR "[%s] no nmi vector found at base 0x%x\n", __FUNCTION__, base);
+    pr_err("[%s] no nmi vector found at base 0x%x\n", __FUNCTION__, base);
 }
-
-
+#endif
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-int __init fusiv_mtd_init(void) {
+int __init fusiv_mtd_init(void)
+{
 
     register_mtd_user(&fusiv_mtd_notifier);
-    register_mtd_parser(&fusiv_jffs2_parser);
     register_mtd_parser(&fusiv_squashfs_parser);
     fusiv_init_platform_devices();
 
+#if defined(CONFIG_FUSIV_VX180)
     find_nmi_vector();
+#endif
 
     return 0;
 }
@@ -900,107 +805,92 @@
 /*------------------------------------------------------------------------------------------*\
  * Parst die erste Größe in einem Größenangaben String vom Urlader
  * Format der Größenangaben: xxx_size=<nn>{,KB,MB}
-\*------------------------------------------------------------------------------------------*/
-unsigned long long parse_mtd_size(char *p) {
+ \*------------------------------------------------------------------------------------------*/
+unsigned long long parse_mtd_size(char *p)
+{
     unsigned long long size;
 
     DEBUG_MTD("'%s'", p);
 
-    if((p[0] == '0') && (p[1] == 'x')) {
+    if((p[0] == '0') && (p[1] == 'x')){
         size = simple_strtoul(p, NULL, 16);
-    } else {
+    }else{
         size = simple_strtoul(p, NULL, 10);
     }
-    
+
     p = strchr(p, 'B');
-    if(p) {
+    if(p){
         /*--- Die Größe enthält mindestens eine KB Angabe ---*/
         size *= 1024;
-        if(p[-1] == 'M')  {
+        if(p[-1] == 'M'){
             size *= 1024;
         }
     }
 
-    return size; 
+    return size;
 }
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-static int __init mtdram_setup(char *p) {
+static int __init mtdram_setup(char *p)
+{
     char *start;
-#ifdef CONFIG_FUSIV_VX185
-    resource_size_t mem_start, mem_end, space_left;
-    static unsigned int init_done = 0;
-
-    if(init_done)
-        return 0;
-#endif
+    resource_size_t mem_start, mem_end, size;
 
-    if(!p)
-        return 0;
+    if(!p){
+        pr_debug("[%s] Invalid parameter\n", __func__);
+        goto err_out;
+    }
 
     start = prom_getenv("linux_fs_start");
-    if(start && !strcmp(start, "nfs")) {
-        printk(KERN_ERR "dont use RAM filesystem, use NFS\n");
-        return 0;
+    if(start && !strcmp(start, "nfs")){
+        pr_info("dont use RAM filesystem, use NFS\n");
+        goto err_out;
     }
-    printk(KERN_ERR "mtdram1 %s\n" , p);
-    DEBUG_MTD("mtdram1 %s" , p);
 
-#if defined(CONFIG_FUSIV_VX180)
-    fusiv_ram_resource[0].start  = CPHYSADDR((unsigned int)simple_strtoul(p, NULL, 16));
-    fusiv_ram_resource[0].flags  = IORESOURCE_MEM;
-    p = strchr(p, ',');
-    if(p) {
-        p++;
-        fusiv_ram_resource[0].end  = CPHYSADDR((unsigned int)simple_strtoul(p, NULL, 16));
-        /*--- fusiv_ram_resource[0].end -= 1; ---*/
-    } else {
-        fusiv_ram_resource[0].start = 0;
-    }
-    DEBUG_MTD("mtdram1 0x%08x-0x%08x" , fusiv_ram_resource[0].start, fusiv_ram_resource[0].end );
-    fusiv_ram_partitions[0].name		 = "rootfs_ram";
-    fusiv_ram_partitions[0].offset	 = 0;
-    fusiv_ram_partitions[0].size		 = fusiv_ram_resource[0].end - fusiv_ram_resource[0].start;
-    fusiv_ram_partitions[0].mask_flags = MTD_ROM;
+    pr_debug("[%s] mtdram1 %s", __func__, p);
 
-    add_to_platform_device_list(&fusiv_ram_device);
-    find_nmi_vector_gap(fusiv_ram_resource[0].start | 0x80000000, fusiv_ram_resource[0].end | 0x80000000);
-#elif defined(CONFIG_FUSIV_VX185)
     mem_start = CPHYSADDR((unsigned int)simple_strtoul(p, NULL, 16));
+
     p = strchr(p, ',');
-    if(p) {
+    if(p){
         p++;
         mem_end = CPHYSADDR((unsigned int)simple_strtoul(p, NULL, 16));
-    } else {
+    }else{
         mem_start = 0;
     }
 
-    if(mem_start != 0 && mem_end != 0){
-        fusiv_ram_resource[0].start  = mem_start;
-        fusiv_ram_resource[0].end    = mem_end;
-        fusiv_ram_resource[0].flags  = IORESOURCE_MEM;
-        space_left = mem_end - mem_start + 1;
+    if(mem_start == 0 || mem_end == 0){
+        pr_err("[%s] Invalid memory addresses\n", __func__);
+        goto err_out;
+    }
 
-        DEBUG_MTD("mtdram1 0x%08x-0x%08x" , fusiv_ram_resource[0].start, fusiv_ram_resource[0].end );
+    fusiv_ram_resource[0].start = mem_start;
+    fusiv_ram_resource[0].end = mem_end;
+    fusiv_ram_resource[0].flags = IORESOURCE_MEM;
+    size = mem_end - mem_start + 1;
 
-        fusiv_ram_partitions[0].name       = "rootfs_ram";
-        fusiv_ram_partitions[0].offset     = 0;
-        fusiv_ram_partitions[0].size       = space_left;
-        fusiv_ram_partitions[0].mask_flags = MTD_ROM;
-//        space_left -= fusiv_ram_partitions[0].size;
+    pr_debug("mtdram1 0x%08x - 0x%08x",
+              fusiv_ram_resource[0].start,
+              fusiv_ram_resource[0].end);
 
-        fusiv_ram_partitions[1].name       = "kernel_ram";
-        fusiv_ram_partitions[1].offset     = 0;
-        fusiv_ram_partitions[1].size       = fusiv_ram_partitions[0].size;
-        fusiv_ram_partitions[1].mask_flags = MTD_ROM;
-//        space_left -= fusiv_ram_partitions[1].size;
+    fusiv_ram_partitions[0].name = "rootfs_ram";
+    fusiv_ram_partitions[0].offset = 0;
+    fusiv_ram_partitions[0].size = size;
+    fusiv_ram_partitions[0].mask_flags = MTD_ROM;
 
-        add_to_platform_device_list(&fusiv_ram_device);
-    }
-    init_done = 1;
+    fusiv_ram_partitions[1].name = "kernel_ram";
+    fusiv_ram_partitions[1].offset = 0;
+    fusiv_ram_partitions[1].size = size;
+    fusiv_ram_partitions[1].mask_flags = MTD_ROM;
+
+    add_to_platform_device_list(&fusiv_ram_device);
+
+#if defined(CONFIG_FUSIV_VX180)
+    find_nmi_vector_gap(fusiv_ram_resource[0].start | 0x80000000, fusiv_ram_resource[0].end | 0x80000000);
 #endif
 
+err_out:
     return 0;
 }
 __setup("mtdram1=", mtdram_setup);
@@ -1008,13 +898,12 @@
 #if defined(CONFIG_FUSIV_VX180)
 /*------------------------------------------------------------------------------------------*\
      * NAND Parameter parsen
-\*------------------------------------------------------------------------------------------*/
-static int __init mtdnand_setup(char *p) {
+ \*------------------------------------------------------------------------------------------*/
+static int __init mtdnand_setup(char *p){
     unsigned long long flashsize_nand = parse_mtd_size(p);
 
-
-    fusiv_nand_partitions[0].name   = (char *)"nand-filesystem";
-    fusiv_nand_partitions[0].size   = flashsize_nand;
+    fusiv_nand_partitions[0].name = (char *)"nand-filesystem";
+    fusiv_nand_partitions[0].size = flashsize_nand;
     fusiv_nand_partitions[0].offset = 0;
     DEBUG_MTD("nand_size = 0x%llx" , flashsize_nand);
 
@@ -1027,11 +916,12 @@
 
 /*------------------------------------------------------------------------------------------*\
      * NAND Parameter parsen
-\*------------------------------------------------------------------------------------------*/
-static int __init mtdnand_setup(char *p) {
+ \*------------------------------------------------------------------------------------------*/
+static int __init mtdnand_setup(char *p)
+{
     unsigned long mtd_start, mtd_end;
     unsigned long long fusiv_flashsize_nand;
-    char *_start = prom_getenv("linux_fs_start");
+    char *_start;
     unsigned int config_size = 0, kernel_size = 0, filesystem_size = 0, current_offset = 0;
     unsigned int skip_size = 0;
     int i;
@@ -1040,99 +930,86 @@
     if(init_done)
         return 0;
 
-
     if(!p)
         return 0;
 
-    if (!_start)
-        _start = "0";       /*--- default setzen ---*/
-
-    fusiv_nand_partitions[0].name = (char *)"kernel (1)";
-    fusiv_nand_partitions[1].name = (char *)"filesystem (1)";
-    fusiv_nand_partitions[2].name = (char *)"kernel (2)";
-    fusiv_nand_partitions[3].name = (char *)"filesystem (2)";
-    fusiv_nand_partitions[4].name = (char *)"config";
-    fusiv_nand_partitions[5].name = (char *)"nand-filesystem";
+    _start = prom_getenv("linux_fs_start");
+    if(!_start)
+        _start = "0"; /*--- default setzen ---*/
 
-    if(_start[0] == '0') {
-        fusiv_nand_partitions[0].name = (char *)"kernel";
-        fusiv_nand_partitions[1].name = (char *)"filesystem";
-        fusiv_nand_partitions[2].name = (char *)"reserved-kernel";
-        fusiv_nand_partitions[3].name = (char *)"reserved-filesystem";
-    }
-    if(_start[0] == '1') {
-        fusiv_nand_partitions[0].name = (char *)"reserved-kernel";
-        fusiv_nand_partitions[1].name = (char *)"reserved-filesystem";
-        fusiv_nand_partitions[2].name = (char *)"kernel";
-        fusiv_nand_partitions[3].name = (char *)"filesystem";
+    switch(_start[0]){
+    case '0':
+        fusiv_nand_partitions[0].name = (char *) "kernel";
+        fusiv_nand_partitions[1].name = (char *) "filesystem";
+        fusiv_nand_partitions[2].name = (char *) "reserved-kernel";
+        fusiv_nand_partitions[3].name = (char *) "reserved-filesystem";
+        break;
+    case '1':
+        fusiv_nand_partitions[0].name = (char *) "reserved-kernel";
+        fusiv_nand_partitions[1].name = (char *) "reserved-filesystem";
+        fusiv_nand_partitions[2].name = (char *) "kernel";
+        fusiv_nand_partitions[3].name = (char *) "filesystem";
+        break;
+    default:
+        fusiv_nand_partitions[0].name = (char *) "kernel (1)";
+        fusiv_nand_partitions[1].name = (char *) "filesystem (1)";
+        fusiv_nand_partitions[2].name = (char *) "kernel (2)";
+        fusiv_nand_partitions[3].name = (char *) "filesystem (2)";
+        break;
     }
 
+    fusiv_nand_partitions[4].name = (char *) "config";
+    fusiv_nand_partitions[5].name = (char *) "nand-filesystem";
+
     fusiv_flashsize_nand = parse_mtd_size(p);
-    DEBUG_MTD("nand_size = 0x%llx" , fusiv_flashsize_nand);
-    printk(KERN_ERR "[NAND] nand_size = 0x%llx\n" , fusiv_flashsize_nand);
+    DEBUG_MTD("nand_size = 0x%llx", fusiv_flashsize_nand);
+    pr_err("[NAND] nand_size = 0x%llx\n", fusiv_flashsize_nand);
 
-    if(fusiv_flashsize_nand == 0) {
+    if(fusiv_flashsize_nand == 0){
         return 0;
     }
 
     /*--------------------------------------------------------------------------------------*\
      * Größen ermitteln
-    \*--------------------------------------------------------------------------------------*/
-#if 0
-    p = prom_getenv("mtd0");
-    if(p) {
-        DEBUG_MTD("mtd0 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
-        p = strchr(p, ',');
-        if(p) {
-            p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            skip_size = mtd_end - mtd_start;
-        }
-    }
-#endif
-
-    /* U-Boot und FusivMTD */
-    skip_size = 0;
-
+     \*--------------------------------------------------------------------------------------*/
     p = prom_getenv("mtd1");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd1 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
             kernel_size = mtd_end - mtd_start;
         }
     }
     p = prom_getenv("mtd0");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd0 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
             filesystem_size = mtd_end - mtd_start;
         }
     }
     p = prom_getenv("mtd5");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd5 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
             config_size = mtd_end - mtd_start;
         }
     }
 
-/*--------------------------------------------------------------------------------------*\
+    /*--------------------------------------------------------------------------------------*\
      * prüfen ob die einzelnen Teile in das Flash passen
     \*--------------------------------------------------------------------------------------*/
-    if(filesystem_size  * 2 + kernel_size * 2 + config_size + skip_size > fusiv_flashsize_nand) {
+    if(filesystem_size * 2 + kernel_size * 2 + config_size + skip_size > fusiv_flashsize_nand){
         panic("Filesystem and Kernel dont fit in to NAND device\n");
     }
 
@@ -1140,40 +1017,43 @@
      * Groessen aufsetzen
     \*--------------------------------------------------------------------------------------*/
 
-    fusiv_nand_partitions[0].size       = kernel_size;
-    fusiv_nand_partitions[0].offset     = current_offset;
+    fusiv_nand_partitions[0].size = kernel_size;
+    fusiv_nand_partitions[0].offset = current_offset;
     fusiv_flashsize_nand -= kernel_size;
     current_offset += kernel_size;
 
-    fusiv_nand_partitions[1].size       = filesystem_size;
-    fusiv_nand_partitions[1].offset     = current_offset;
+    fusiv_nand_partitions[1].size = filesystem_size;
+    fusiv_nand_partitions[1].offset = current_offset;
     fusiv_flashsize_nand -= filesystem_size;
     current_offset += filesystem_size;
 
-    fusiv_nand_partitions[2].size       = kernel_size;
-    fusiv_nand_partitions[2].offset     = current_offset;
+    fusiv_nand_partitions[2].size = kernel_size;
+    fusiv_nand_partitions[2].offset = current_offset;
     fusiv_flashsize_nand -= kernel_size;
     current_offset += kernel_size;
 
-    fusiv_nand_partitions[3].size       = filesystem_size;
-    fusiv_nand_partitions[3].offset     = current_offset;
+    fusiv_nand_partitions[3].size = filesystem_size;
+    fusiv_nand_partitions[3].offset = current_offset;
     fusiv_flashsize_nand -= filesystem_size;
     current_offset += filesystem_size;
 
-    if(config_size) {
-        fusiv_nand_partitions[4].size   = config_size;
+    if(config_size){
+        fusiv_nand_partitions[4].size = config_size;
         fusiv_nand_partitions[4].offset = current_offset;
         fusiv_flashsize_nand -= config_size;
         current_offset += config_size;
     }
 
-    if(fusiv_flashsize_nand) {
-        fusiv_nand_partitions[5].size   = fusiv_flashsize_nand;
+    if(fusiv_flashsize_nand){
+        fusiv_nand_partitions[5].size = fusiv_flashsize_nand;
         fusiv_nand_partitions[5].offset = current_offset;
     }
 
     for(i = 0; i <= 5; ++i){
-        DEBUG_MTD("mtd%d: %08x - %08x", i, fusiv_nand_partitions[i].offset, fusiv_nand_partitions[i].offset + fusiv_nand_partitions[i].size - 1);
+        DEBUG_MTD("mtd%d: %08x - %08x",
+                  i,
+                  fusiv_nand_partitions[i].offset,
+                  fusiv_nand_partitions[i].offset + fusiv_nand_partitions[i].size - 1);
     }
 
     add_to_platform_device_list(&fusiv_nand_device[0]);
@@ -1182,268 +1062,212 @@
 
     return 0;
 }
-__setup("nand_size=", mtdnand_setup);
+__setup("nand_size=", mtdnand_setup)
+;
 
 #endif /* CONFIG_FUSIV_VX185 */
 
 #ifdef CONFIG_FUSIV_VX180
 extern void tffs_panic_log_register_nor(void);
-#endif
 
 /*------------------------------------------------------------------------------------------*\
      * NOR Parameter parsen
-\*------------------------------------------------------------------------------------------*/
-static int __init mtdnor_setup(char *p) {
+ \*------------------------------------------------------------------------------------------*/
+static int __init mtdnor_setup(char *p){
     unsigned long flashsize_nor;
     unsigned long mtd_start, mtd_end;
     unsigned long flashoffset_nor = 0;
-#ifdef CONFIG_FUSIV_VX185
-    static unsigned int init_done = 0;
 
-    if(init_done)
-        return 0;
-#endif
-
-    if(!p)
+    if(!p){
         return 0;
-
-#ifdef CONFIG_FUSIV_VX185
-    flashsize_nor = parse_mtd_size(p);
-    DEBUG_MTD("nor_size = 0x%lx" , flashsize_nor);
-#endif
+    }
 
     fusiv_nor_partitions[0].name = (char *)"filesystem";
     fusiv_nor_partitions[1].name = (char *)"kernel";
     fusiv_nor_partitions[2].name = (char *)"urlader";
     fusiv_nor_partitions[3].name = (char *)"tffs (1)";
     fusiv_nor_partitions[4].name = (char *)"tffs (2)";
-    fusiv_nor_partitions[5].name = (char *)"reserved";    /* Nie mit "jffs2" initialisieren! */
+    fusiv_nor_partitions[5].name = (char *)"reserved"; /* Nie mit "jffs2" initialisieren! */
     /* Die mtds werden vom Userland nach jffs2 gegrept und ggf. beschrieben, daher das
      * mtd nie jffs2 nennen, solange die Position/Größe noch nicht stimmt. */
 
     flashsize_nor = parse_mtd_size(p);
     DEBUG_MTD("nor_size = 0x%lx" , flashsize_nor);
-#ifdef CONFIG_FUSIV_VX185
-    printk(KERN_ERR "[NOR] nor_size = 0x%lx\n" , flashsize_nor);
-
-    if(flashsize_nor == 0) {
-        return 0;
-    }
-#endif
 
     /*--------------------------------------------------------------------------------------*\
      * Größen ermitteln
-    \*--------------------------------------------------------------------------------------*/
+     \*--------------------------------------------------------------------------------------*/
     p = prom_getenv("mtd2");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd2 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int)simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
+            mtd_end = (unsigned int)simple_strtoul(p, NULL, 16);
             flashoffset_nor = mtd_start;
             g_fusiv_nor_flash_start = mtd_start;
-            fusiv_nor_partitions[2].size   = mtd_end - mtd_start;
+            fusiv_nor_partitions[2].size = mtd_end - mtd_start;
             fusiv_nor_partitions[2].offset = mtd_start - flashoffset_nor;
-            fusiv_nor_resource[0].start    = mtd_start & ~0xE0000000;
-            fusiv_nor_resource[0].end      = fusiv_nor_resource[0].start + flashsize_nor;
-        }
-    }
-    p = prom_getenv("mtd0");
-    if(p) {
-        DEBUG_MTD("mtd0 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
-        p = strchr(p, ',');
-        if(p) {
-            p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            fusiv_nor_partitions[0].size   = mtd_end - mtd_start;
-            fusiv_nor_partitions[0].offset = mtd_start - flashoffset_nor;
+            fusiv_nor_resource[0].start = mtd_start & ~0xE0000000;
+            fusiv_nor_resource[0].end = fusiv_nor_resource[0].start + flashsize_nor;
         }
     }
+
     p = prom_getenv("mtd1");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd1 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int)simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            fusiv_nor_partitions[1].size   = mtd_end - mtd_start;
+            mtd_end = (unsigned int)simple_strtoul(p, NULL, 16);
+            fusiv_nor_partitions[1].size = mtd_end - mtd_start;
             fusiv_nor_partitions[1].offset = mtd_start - flashoffset_nor;
+
+            /*------------------------------------------------------------------------------------------*\
+             * mtd0 is an afterthought to enable splitting the firmware partition
+             * into kernel and root fs. If it does not exist, default to the same
+             * size and offset as mtd1 and let the partition parser adjust its values
+             * we don't need to parse for mtd0 !
+            \*------------------------------------------------------------------------------------------*/
+            fusiv_nor_partitions[0].size = fusiv_nor_partitions[1].size;
+            fusiv_nor_partitions[0].offset = fusiv_nor_partitions[1].offset;
         }
     }
+
     p = prom_getenv("mtd3");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd3 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int)simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            fusiv_nor_partitions[3].size   = mtd_end - mtd_start;
+            mtd_end = (unsigned int)simple_strtoul(p, NULL, 16);
+            fusiv_nor_partitions[3].size = mtd_end - mtd_start;
             fusiv_nor_partitions[3].offset = mtd_start - flashoffset_nor;
         }
     }
+
     p = prom_getenv("mtd4");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd4 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int)simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            fusiv_nor_partitions[4].size       = mtd_end - mtd_start;
-            fusiv_nor_partitions[4].offset     = mtd_start - flashoffset_nor;
+            mtd_end = (unsigned int)simple_strtoul(p, NULL, 16);
+            fusiv_nor_partitions[4].size = mtd_end - mtd_start;
+            fusiv_nor_partitions[4].offset = mtd_start - flashoffset_nor;
         }
     }
+
     p = prom_getenv("mtd5");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd5 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int)simple_strtoul(p, NULL, 16);
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            fusiv_nor_partitions[5].size       = mtd_end - mtd_start;
-            fusiv_nor_partitions[5].offset     = mtd_start - flashoffset_nor;
+            mtd_end = (unsigned int)simple_strtoul(p, NULL, 16);
+            fusiv_nor_partitions[5].size = mtd_end - mtd_start;
+            fusiv_nor_partitions[5].offset = mtd_start - flashoffset_nor;
         }
     }
+
     fusiv_nor_flashsize = flashsize_nor;
     g_fusiv_nor_flash_size = flashsize_nor;
     add_to_platform_device_list(&fusiv_nor_device[0]);
-    
-#ifdef CONFIG_FUSIV_VX180
+
     /*--- MTD-Offsets für Adressierung = MTD-Offset[3/4] - Urlader-Offset ---*/
     tffs_mtd_offset[0] = fusiv_nor_partitions[3].offset - fusiv_nor_partitions[2].offset;
     tffs_mtd_offset[1] = fusiv_nor_partitions[4].offset - fusiv_nor_partitions[2].offset;
-#endif
 
-#if defined(CONFIG_TFFS) && defined(CONFIG_TFFS_PANIC_LOG) && defined(CONFIG_FUSIV_VX180)
+#if defined(CONFIG_TFFS) && defined(CONFIG_TFFS_PANIC_LOG)
     tffs_panic_log_register_nor();
 #endif
 
-#ifdef CONFIG_FUSIV_VX185
-    init_done = 1;
-#endif
-
     return 0;
 }
 __setup("nor_size=", mtdnor_setup);
 
+#endif
+
+#if defined(CONFIG_FUSIV_VX185)
 /*------------------------------------------------------------------------------------------*\
  * SPI Flash Parameter parsen
 \*------------------------------------------------------------------------------------------*/
-#if defined (FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 )
 static int __init mtdspi_setup(char *p)
 {
     unsigned long flashsize_spi, mtd_start, mtd_end;
-#ifdef CONFIG_FUSIV_VX185
-    static unsigned int init_done = 0;
-
-    if(init_done)
-        return 0;
-#endif
-
 
     if(!p)
         return 0;
 
-    flashsize_spi = (unsigned long)parse_mtd_size(p);
-
-    DEBUG_MTD("sflash_size = 0x%lx" , flashsize_spi);
-
-#if defined(CONFIG_FUSIV_VX180)
-    p = prom_getenv("mtd2");
-    if(p) {
-        DEBUG_MTD("mtd2 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
-
-        p = strchr(p, ',');
-        if(p) {
-            p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)) {
-                fusiv_spi_partitions[0].name       = (char*)"urlader";
-                fusiv_spi_partitions[0].size       = mtd_end - mtd_start;
-                fusiv_spi_partitions[0].offset     = 0;
-                fusiv_spi_partitions[0].mask_flags = 0;
+    flashsize_spi = (unsigned long) parse_mtd_size(p);
 
-                fusiv_spi_partitions[1].name       = (char*)"tffs (1)";
-                fusiv_spi_partitions[1].size       = (flashsize_spi - fusiv_spi_partitions[0].size) / 2;
-                fusiv_spi_partitions[1].offset     = fusiv_spi_partitions[0].size; 
-                fusiv_spi_partitions[1].mask_flags = 0;
+    DEBUG_MTD("sflash_size = 0x%lx", flashsize_spi);
 
-                fusiv_spi_partitions[2].name       = (char*)"tffs (2)";
-                fusiv_spi_partitions[2].size       = (flashsize_spi - fusiv_spi_partitions[0].size) / 2;
-                fusiv_spi_partitions[2].offset     = fusiv_spi_partitions[0].size + fusiv_spi_partitions[1].size;
-                fusiv_spi_partitions[2].mask_flags = 0;
-            }
-        }
-    }
-#elif defined(CONFIG_FUSIV_VX185)
     p = prom_getenv("mtd2");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd2 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
 
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)) {
-                fusiv_spi_partitions[0].name       = (char*)"urlader";
-                fusiv_spi_partitions[0].offset     = mtd_start;
-                fusiv_spi_partitions[0].size       = mtd_end - mtd_start;
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
+            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)){
+                fusiv_spi_partitions[0].name = (char*) "urlader";
+                fusiv_spi_partitions[0].offset = mtd_start;
+                fusiv_spi_partitions[0].size = mtd_end - mtd_start;
                 fusiv_spi_partitions[0].mask_flags = 0;
             }
         }
     }
 
     p = prom_getenv("mtd3");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd3 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
 
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)) {
-                fusiv_spi_partitions[1].name       = (char*)"tffs (1)";
-                fusiv_spi_partitions[1].size       = mtd_end - mtd_start;
-                fusiv_spi_partitions[1].offset     = mtd_start;
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
+            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)){
+                fusiv_spi_partitions[1].name = (char*) "tffs (1)";
+                fusiv_spi_partitions[1].size = mtd_end - mtd_start;
+                fusiv_spi_partitions[1].offset = mtd_start;
                 fusiv_spi_partitions[1].mask_flags = 0;
             }
         }
     }
 
     p = prom_getenv("mtd4");
-    if(p) {
+    if(p){
         DEBUG_MTD("mtd4 = %s", p);
-        mtd_start  = (unsigned int)simple_strtoul(p, NULL, 16);
+        mtd_start = (unsigned int) simple_strtoul(p, NULL, 16);
 
         p = strchr(p, ',');
-        if(p) {
+        if(p){
             p++;
-            mtd_end  = (unsigned int)simple_strtoul(p, NULL, 16);
-            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)) {
-                fusiv_spi_partitions[2].name       = (char*)"tffs (2)";
-                fusiv_spi_partitions[2].size       = mtd_end - mtd_start;
-                fusiv_spi_partitions[2].offset     = mtd_start;
+            mtd_end = (unsigned int) simple_strtoul(p, NULL, 16);
+            if(mtd_end && (mtd_end - mtd_start <= flashsize_spi)){
+                fusiv_spi_partitions[2].name = (char*) "tffs (2)";
+                fusiv_spi_partitions[2].size = mtd_end - mtd_start;
+                fusiv_spi_partitions[2].offset = mtd_start;
                 fusiv_spi_partitions[2].mask_flags = 0;
             }
         }
     }
-#endif /* CONFIG_FUSIV_VX185 */
     add_to_platform_device_list(&fusiv_spi_device[0]);
-#ifdef CONFIG_FUSIV_VX185
-    init_done = 1;
+
+#if defined(CONFIG_TFFS) && defined(CONFIG_TFFS_PANIC_LOG)
+    tffs_panic_log_register_spi();
 #endif
     return 0;
 }
 __setup("sflash_size=", mtdspi_setup);
 
-#endif /*--- #if defined (FUSIV_MTD_SPI_PARTS) && (FUSIV_MTD_SPI_PARTS > 0 ) ---*/
 #endif
--- linux-2.6.28/arch/mips/fusiv/fusiv_mips32/setup.c
+++ linux-2.6.28/arch/mips/fusiv/fusiv_mips32/setup.c
@@ -29,6 +29,8 @@
 #include <asm/time.h>
 #include <asm/mipsregs.h>
 
+#include <asm/prom.h>
+
 #ifdef CONFIG_FUSIV_VX180
 #include <ikan6850.h>
 #endif
@@ -165,10 +167,10 @@
 unsigned int iks_reboot_status;
 
 int get_reboot_status(void) {
-    static char Buffer[512];
-    volatile unsigned char *mailbox = (volatile unsigned char *)(0xA1000000 - 512);
-    memcpy(Buffer, (void *)mailbox, 512);
-    Buffer[511] = '\0';
+    static char Buffer[AVM_REBOOT_STRING_SIZE];
+    volatile unsigned char *mailbox = (volatile unsigned char *)(AVM_REBOOT_STRING_LOCATION);
+    memcpy(Buffer, (void *)mailbox, AVM_REBOOT_STRING_SIZE);
+    Buffer[AVM_REBOOT_STRING_SIZE - 1] = '\0';
     /*--- printk("Reboot Status: %s\n", Buffer); ---*/
 
    if(!strcmp(Buffer, UPDATE_REBOOT_STATUS_TEXT)) {
@@ -207,7 +209,7 @@
 }
 
 static void set_reboot_status(char *text) {
-    volatile unsigned char *mailbox = (volatile unsigned char *)(0xA1000000 - 512);
+    volatile unsigned char *mailbox = (volatile unsigned char *)(AVM_REBOOT_STRING_LOCATION);
     int len;
     if((reboot_cause_written != NULL) && (reboot_cause_written != text)) {
         return;
--- linux-2.6.28/arch/mips/include/asm/mach-fusiv/vx185.h
+++ linux-2.6.28/arch/mips/include/asm/mach-fusiv/vx185.h
@@ -11,7 +11,6 @@
 #define IKS_REG_R32(_r)                   __raw_readl((u32 *)(_r))
 #define IKS_REG_W32(_v, _r)               __raw_writel((_v), (u32 *)(_r))
 
-
 /*------------------------------------------------------------------------------------------*\
  * System Configuration
 \*------------------------------------------------------------------------------------------*/
--- linux-2.6.28/arch/mips/include/asm/prom.h
+++ linux-2.6.28/arch/mips/include/asm/prom.h
@@ -70,4 +70,7 @@
 
 extern int prom_wlan_get_base_memory(unsigned int *base, unsigned int *len);
 
+#define AVM_REBOOT_STRING_LOCATION  (0xa1000000 - AVM_REBOOT_STRING_SIZE)
+#define AVM_REBOOT_STRING_SIZE      512
+
 #endif /* !(_MIPS_PROM_H) */
--- linux-2.6.28/arch/mips/include/asm/socket.h
+++ linux-2.6.28/arch/mips/include/asm/socket.h
@@ -76,6 +76,9 @@
 #define SO_MARK			36
 #define SO_MARKTASK     37  /* AVM calle */
 
+#define SO_PROTOCOL		38  /* Backport 2.6.32 */
+#define SO_DOMAIN		39  /* Backport 2.6.32 */
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
--- linux-2.6.28/arch/mips/kernel/setup.c
+++ linux-2.6.28/arch/mips/kernel/setup.c
@@ -595,6 +595,14 @@
                         }
                     }
                 }
+                {
+                    /*--- reserve memory for rebootstring ---*/
+                    if(reserve_bootmem(CPHYSADDR(AVM_REBOOT_STRING_LOCATION), AVM_REBOOT_STRING_SIZE, BOOTMEM_DEFAULT)) {
+                        printk(KERN_ERR "[%s] reserve memory for rebootstring failed (start 0x%x end 0x%x)\n", 
+                                __func__, CPHYSADDR(AVM_REBOOT_STRING_LOCATION), CPHYSADDR(AVM_REBOOT_STRING_LOCATION) + AVM_REBOOT_STRING_SIZE);
+                    }
+                }
+
                 run_once = 1;
             }
         }
--- linux-2.6.28/.config
+++ linux-2.6.28/.config
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.28.8
-# Wed Sep 11 10:29:44 2013
+# Mon Mar  9 21:50:40 2015
 #
 CONFIG_MIPS=y
 
@@ -185,9 +185,9 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_BSD_PROCESS_ACCT_V3=y
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
--- linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace.c
+++ linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace.c
@@ -11,11 +11,63 @@
 #include <linux/avm_net_trace.h>
 #include <linux/sched.h>
 #include <linux/poll.h>
+#include <linux/interrupt.h>
 #include <asm/mach_avm.h>
 
 struct avm_net_trace avm_net_trace[MAX_AVM_NET_TRACE_DEVICES];
 DEFINE_SPINLOCK(avm_net_trace_lock);
 
+#ifdef AVM_NET_TRACE_UDEV
+static struct class *avm_net_trace_class;
+
+static int avm_net_trace_major = 0;
+
+static void avm_net_trace_udev_work_func(struct work_struct *work);
+DECLARE_WORK(avm_net_trace_udev_work, avm_net_trace_udev_work_func);
+
+static void avm_net_trace_udev_work_func(struct work_struct *dummy) {
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave (&avm_net_trace_lock, flags);
+
+	for (i = 1; i < MAX_AVM_NET_TRACE_DEVICES; i++) {
+		struct device * udev_device = avm_net_trace[i].udev_device;
+		
+		if (avm_net_trace[i].ntd != NULL) {
+			if (udev_device == NULL) {
+				unsigned int minor = avm_net_trace[i].minor;
+				if (minor != 0) {
+					spin_unlock_irqrestore (&avm_net_trace_lock, flags);
+						udev_device = device_create(avm_net_trace_class, NULL, MKDEV(avm_net_trace_major, minor), NULL, "%s%d", "avm_net_trace", minor);
+					spin_lock_irqsave (&avm_net_trace_lock, flags);
+
+					if (!IS_ERR(udev_device)) {
+						printk (KERN_DEBUG "avm_net_trace: udev device %s created\n", dev_name(udev_device));
+						avm_net_trace[i].udev_device = udev_device;
+					} else {
+						printk (KERN_ERR "avm_net_trace: ERROR udev device %s%d not created, err=%p\n", "avm_net_trace", minor, udev_device);
+					}
+				}
+			}
+		} else {
+			if (udev_device != NULL) {
+				printk (KERN_DEBUG "avm_net_trace: destroy udev device %s\n", dev_name(udev_device));
+				if (avm_net_trace[i].minor) printk (KERN_ERR "avm_net_trace_work: ERROR must be reset to 0\n");
+
+				avm_net_trace[i].udev_device = NULL;
+				spin_unlock_irqrestore (&avm_net_trace_lock, flags);
+					device_destroy(avm_net_trace_class, udev_device->devt);
+				spin_lock_irqsave (&avm_net_trace_lock, flags);
+			}
+		}
+	}
+	spin_unlock_irqrestore (&avm_net_trace_lock, flags);
+}
+#else
+static const int avm_net_trace_major = AVM_NET_TRACE_MAJOR;
+#endif // AVM_NET_TRACE_UDEV
+
 int __avm_net_trace_func (
 		struct avm_net_trace *ant, struct sk_buff *skb, 
 		int skb_property, int direction) {
@@ -93,11 +145,69 @@
 	network: 0
 };
 
-static long avm_net_device_ioctl(struct file *file,
-                                           unsigned int cmd, unsigned long arg)
+
+static long _device_ioctl_buffer_size_set(
+		struct avm_net_trace * ant,
+		unsigned long          arg)
 {
-	unsigned long flags;
-	int ret = -EINVAL;
+	static const int BUFFER_SIZE_MIN = 20;
+	static const int BUFFER_SIZE_MAX = 5000;
+	int buffer_size = 0;
+
+	if (-1 == ant->rbuf_size) {
+		/* not a permanent trace point */
+		return -EPERM;
+	}
+
+	if (0 != copy_from_user(&buffer_size, (void *)arg, sizeof(buffer_size))) {
+		return -EFAULT;
+	}
+
+	if ((buffer_size < BUFFER_SIZE_MIN) || (buffer_size > BUFFER_SIZE_MAX)) {
+		return -ERANGE;
+	}
+
+	ant->rbuf_size = buffer_size;
+
+	while (skb_queue_len(&ant->recvqueue) > ant->rbuf_size) {
+		struct sk_buff * skb_del = skb_dequeue(&ant->recvqueue);
+		if (NULL == skb_del) {
+			break; /* preventive measure */
+		}
+		kfree_skb(skb_del);
+	}
+
+	return 0;
+} /* _device_ioctl_buffer_size_set */
+
+static long _device_ioctl_buffer_size_get(
+		struct avm_net_trace * ant,
+		unsigned long          arg)
+{
+	if (-1 == ant->rbuf_size) {
+		/* not a permanent trace point */
+		return -EPERM;
+	}
+
+	if (0 != copy_to_user((void *)arg, &ant->rbuf_size, sizeof(ant->rbuf_size))) {
+		return -EFAULT;
+	}
+
+	return 0;
+} /* _device_ioctl_buffer_size_get */
+
+static long avm_net_device_ioctl(
+		struct file  * file,
+		unsigned int   cmd ,
+		unsigned long  arg )
+{
+	unsigned int           minor = 0;
+	struct avm_net_trace * ant   = NULL;
+	unsigned long          flags = 0;
+	int                    ret   = -EINVAL;
+
+	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	ant   = (struct avm_net_trace *) file->private_data;
 
 	switch (cmd)
 	{
@@ -129,7 +239,7 @@
 						if (avm_net_trace[i].ntd) {
 							struct ioctl_ant_device dev;
 
-							strncpy(dev.name, avm_net_trace[i].ntd->name, AVM_NET_TRACE_IFNAMSIZ);
+							strncpy(dev.name, avm_net_trace[i].ntd->name, AVM_NET_TRACE_IFNAMSIZ-1);
 							dev.name[AVM_NET_TRACE_IFNAMSIZ-1] = '\0';
 							dev.minor = avm_net_trace[i].ntd->minor;
 							dev.iface = avm_net_trace[i].ntd->iface;
@@ -158,6 +268,12 @@
 				}
 			}
 			break;
+		case ANT_IOCTL_BUFFER_SIZE_SET:
+			ret = _device_ioctl_buffer_size_set(ant, arg);
+			break;
+		case ANT_IOCTL_BUFFER_SIZE_GET:
+			ret = _device_ioctl_buffer_size_get(ant, arg);
+			break;
 		default:
 			break;
 	}
@@ -414,6 +530,11 @@
 	ant->rbuf_size = rbuf_size;
 	ntd->ant = ant;
 
+#ifdef AVM_NET_TRACE_UDEV
+	ant->udev_device = NULL;
+	schedule_work(&avm_net_trace_udev_work);
+#endif
+
 	printk (KERN_INFO "avm_net_trace: New net trace device '%s' registered with minor %d.\n",
 			ntd->name, ant->minor);
 
@@ -446,6 +567,10 @@
 	avm_net_trace[ntd->minor].ntd = NULL;
 	ntd->ant = NULL;
 
+#ifdef AVM_NET_TRACE_UDEV
+	schedule_work(&avm_net_trace_udev_work);
+#endif
+
 	spin_unlock_irqrestore (&avm_net_trace_lock, flags);
 }
 EXPORT_SYMBOL(deregister_avm_net_trace_device);
@@ -498,12 +623,21 @@
 
 	int ret;
 
-	if ((ret = register_chrdev (AVM_NET_TRACE_MAJOR, "avm_net_trace", &avm_net_trace_fops)) < 0) {
+	if ((ret = register_chrdev (avm_net_trace_major, "avm_net_trace", &avm_net_trace_fops)) < 0) {
 		printk (KERN_ERR "avm_net_trace: register_chrdev failed\n");
 		return -EIO;
 	}
 
-	memset (&avm_net_trace, 0, sizeof (struct avm_net_trace));
+	memset (&avm_net_trace, 0, sizeof avm_net_trace);
+
+#ifdef AVM_NET_TRACE_UDEV
+	if (ret > 0) {
+		avm_net_trace_major = ret;
+	}
+	
+	avm_net_trace_class = class_create(THIS_MODULE, "avm_net_trace");
+	device_create(avm_net_trace_class, NULL, MKDEV(avm_net_trace_major, 0), NULL, "avm_net_trace0");
+#endif
 
 	printk (KERN_INFO "avm_net_trace: Up and running.\n");
 
@@ -517,7 +651,7 @@
 
 	spin_lock_irqsave (&avm_net_trace_lock, flags);
 
-	for (i = 0; i< MAX_AVM_NET_TRACE_DEVICES; i++) {
+	for (i = 0; i < MAX_AVM_NET_TRACE_DEVICES; i++) {
 		struct avm_net_trace *ant = avm_net_trace + i;
 
 		skb_queue_purge(&ant->recvqueue);
@@ -526,7 +660,14 @@
 
 	spin_unlock_irqrestore (&avm_net_trace_lock, flags);
 
-	unregister_chrdev(AVM_NET_TRACE_MAJOR, "avm_net_device");
+#ifdef AVM_NET_TRACE_UDEV
+	avm_net_trace_udev_work_func (NULL);
+	
+	device_destroy(avm_net_trace_class, MKDEV(avm_net_trace_major, 0));
+	class_destroy(avm_net_trace_class);
+#endif
+
+	unregister_chrdev(avm_net_trace_major, "avm_net_device");
 }
 
 module_init (avm_net_trace_init);
--- linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace.h
+++ linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace.h
@@ -4,8 +4,14 @@
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/avm_net_trace_ioctl.h>
+#include <linux/device.h>
+#include <linux/version.h>
 
-#define AVM_NET_TRACE_VERSION		3
+#define AVM_NET_TRACE_VERSION		4
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+#define AVM_NET_TRACE_UDEV
+#endif
 
 #define AVM_NET_TRACE_USE_SKB		0
 #define AVM_NET_TRACE_CLONE_SKB		1
@@ -28,6 +34,9 @@
 
 struct avm_net_trace {
 	struct avm_net_trace_device 	*ntd;
+#ifdef AVM_NET_TRACE_UDEV
+	struct device 			* udev_device;
+#endif
 	unsigned int			minor;
 	volatile int			is_open;
 	volatile int			do_trace;
--- linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace_ioctl.h
+++ linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace_ioctl.h
@@ -10,6 +10,7 @@
 #define AVM_NET_TRACE_TYPE_DSLIFACE 3 /* internet, voip, ... */
 #define AVM_NET_TRACE_TYPE_WLAN     4
 #define AVM_NET_TRACE_TYPE_USB      5
+#define AVM_NET_TRACE_TYPE_DSLFW    6
 
 #define AVM_NET_TRACE_IFNAMSIZ     32
 
@@ -33,7 +34,8 @@
 #define u_dev u.u_dev /* array of structures */
 };
 
-#define ANT_IOCTL_GET_DEVICES _IOR('C', 0x77, struct ioctl_ant_device_list)
+#define ANT_IOCTL_GET_DEVICES      _IOR('C', 0x77, struct ioctl_ant_device_list)
+#define ANT_IOCTL_BUFFER_SIZE_SET  _IOW('C', 0x01, int                         )
+#define ANT_IOCTL_BUFFER_SIZE_GET  _IOW('C', 0x02, int                         )
 
 #endif /* _AVM_NET_TRACE_IOCTL_H */
-
--- /dev/null
+++ linux-2.6.28/drivers/char/avm_net_trace/avm_net_trace_test.c
@@ -0,0 +1,341 @@
+/**
+ * \file    avm_net_trace_test.c
+ * \date    07/17/2015
+ * \author  AVM/RST
+ * \brief   Console test tool for AVM Net Trace interface.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/socket.h> 
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "avm_net_trace_ioctl.h"
+
+/* undef stupid and useless defines */
+#undef u_buf
+#undef u_dev
+
+static const size_t AVM_NET_TRACE_LEN_MAX  = 30;              /* max. trace device name */
+static const char * AVM_NET_TRACE_NAME     = "avm_net_trace"; /* Trace device name without id */
+static const size_t DEVICE_LIST_BUFFER_MAX = 2048;            /* Buffer size for device list */
+
+static struct ioctl_ant_device_list _device_list;             /* Globel device list. */
+
+
+/**************************************************************************//**
+ * \brief     Close device
+ * \param[inout] device_fd  Pointer to device handle. Will be set to NULL after
+ *                          completion.
+ */
+static void _ant_device_close(int * device_fd)
+{
+	if (*device_fd >= 0) {
+		close (*device_fd);
+		*device_fd = -1;
+	}
+} /* _ant_device_close */
+
+
+/**************************************************************************//**
+ * \brief      Open the given device.
+ * \param[in]  device_id  The device id.
+ * \param[out] device_fd  File descriptor on success. Otherwise NULL.
+ * \return      0: Open success.<br>
+ *             -1: Open failed.
+ */
+static int _ant_device_open(int device_id, int * device_fd)
+{
+	char device[AVM_NET_TRACE_LEN_MAX];
+
+	_ant_device_close(device_fd);
+
+	(void)snprintf(device, AVM_NET_TRACE_LEN_MAX, "/dev/%s%d", AVM_NET_TRACE_NAME, device_id);
+
+	*device_fd = open(device, O_RDONLY | O_NONBLOCK);
+	if (*device_fd < 0) {
+		printf ("ERR: Failed to open device '%s': %s\n", device, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+} /* _ant_device_open */
+
+
+/**************************************************************************//**
+ * \brief     Valide device id.
+ * \param[in] device_id  Device id to validate.
+ * \reutrn    0/1: Device id is not/is valid.
+ */
+static int _ant_device_id_valid(int device_id)
+{
+	struct ioctl_ant_device * device          = _device_list.u.u_dev;
+	size_t                    device_list_len = _device_list.buf_len;
+
+	while (device_list_len >= sizeof(*device)) {
+		if (device_id == device->minor) {
+			return 0;
+		}
+		device++;
+		device_list_len -= sizeof(*device);
+	}
+
+	return -1;
+} /* _ant_device_id_valid */
+
+
+/**************************************************************************//**
+ * \brief     Set buffer size for a permanent device interface.
+ * \param[in] device_id    The device id.
+ * \param[in] buffer_size  Buffer size in number of packets.
+ * \return     0: Set buffer succeeded.<br>
+ *            -1: Set buffer failed.
+ */
+static int _ant_device_perm_buffer_size_set(int device_id, int buffer_size)
+{
+	int ctrl_dev_fd = -1;
+	int ret         = 0;
+
+	ret = _ant_device_open(device_id, &ctrl_dev_fd);
+	if (ret < 0) {
+		return -1;
+	}
+
+	ret = ioctl(ctrl_dev_fd, ANT_IOCTL_BUFFER_SIZE_SET, &buffer_size);
+	if (ret < 0) {
+		printf("ERR: IOCTL 0x%08x failed: %s\n", ANT_IOCTL_GET_DEVICES, strerror(errno));
+	}
+
+	_ant_device_close(&ctrl_dev_fd);
+
+	return ret;
+} /* _ant_device_perm_buffer_size_set */
+
+
+/**************************************************************************//**
+ * \brief     Get buffer size for a permanent device interface.
+ * \param[in] device_id    The device id.
+ * \return     0: Get buffer succeeded.<br>
+ *            -1: Get buffer failed.
+ */
+static int _ant_device_perm_buffer_size_get(int device_id)
+{
+	int ctrl_dev_fd = -1;
+	int ret         = 0;
+	int buffer_size = -1;
+
+	ret = _ant_device_open(device_id, &ctrl_dev_fd);
+	if (ret < 0) {
+		return -1;
+	}
+
+	ret = ioctl(ctrl_dev_fd, ANT_IOCTL_BUFFER_SIZE_GET, &buffer_size);
+	if (ret < 0) {
+		printf("ERR: IOCTL 0x%08x failed: %s\n", ANT_IOCTL_GET_DEVICES, strerror(errno));
+	} else {
+		printf("Buffer size for trace interface %d is %d\n", device_id, buffer_size);
+	}
+
+	_ant_device_close(&ctrl_dev_fd);
+
+	return ret;
+} /* _ant_device_perm_buffer_size_get */
+
+
+/**************************************************************************//**
+ * \brief  Update device list informations.
+ * \return  0: Update successfully.<br>
+ *         -1: Update failed.
+ */
+static int _ant_device_update(void)
+{
+	int                       ctrl_dev_fd     = -1;
+	int                       ret             = 0;
+	struct ioctl_ant_device * device          = NULL;
+	size_t                    device_list_len = 0;
+
+	ret = _ant_device_open(0, &ctrl_dev_fd);
+	if (ret < 0) {
+		return -1;
+	}
+
+	_device_list.buf_len = DEVICE_LIST_BUFFER_MAX;
+	(void)memset(_device_list.u.u_buf, 0, DEVICE_LIST_BUFFER_MAX);
+
+	ret = ioctl(ctrl_dev_fd, ANT_IOCTL_GET_DEVICES, &_device_list);
+	if (ret < 0) {
+		printf("ERR: IOCTL 0x%08x failed: %s\n", ANT_IOCTL_GET_DEVICES, strerror(errno));
+		goto quit;
+	}
+
+quit:
+	_ant_device_close(&ctrl_dev_fd);
+
+	return 0;
+} /* _ant_device_update */
+
+
+/**************************************************************************//**
+ * \brief  Show a list of net trace devices.
+ * \return  0: Dump list succeeded.<br>
+ *         -1: Dump list failed.
+ */
+static int _ant_device_list(void)
+{
+	int                       ret             = 0;
+	struct ioctl_ant_device * device          = NULL;
+	size_t                    device_list_len = 0;
+
+	device = _device_list.u.u_dev;
+	device_list_len = _device_list.buf_len;
+	while (device_list_len >= sizeof(*device)) {
+		printf("Device :\n");
+		printf("  name    = '%s'\n", device->name   );
+		printf("  minor   = %d\n"  , device->minor  );
+		printf("  iface   = %d\n"  , device->iface  );
+		printf("  type    = %d\n"  , device->type   );
+		printf("  is_open = %d\n"  , device->is_open);
+		printf("\n");
+
+		device++;
+		device_list_len -= sizeof(*device);
+	}
+
+	return 0;
+} /* _ant_device_list */
+
+
+/**************************************************************************//**
+ * \brief  Do some global initializations.
+ * \return  0: Init succeeded.<br>
+ *         -1: Init failed.
+ */
+static int _ant_init(void)
+{
+
+	(void)memset(&_device_list, 0, sizeof(_device_list));
+
+	_device_list.buf_len = DEVICE_LIST_BUFFER_MAX;
+	_device_list.u.u_buf = (char *)malloc(DEVICE_LIST_BUFFER_MAX);
+	if (NULL == _device_list.u.u_buf) {
+		printf("ERR: Alloc device list buffer failed.\n");
+		return -1;
+	}
+	(void)memset(_device_list.u.u_buf, 0, DEVICE_LIST_BUFFER_MAX);
+
+	return 0;
+} /* _ant_init */
+
+
+/**************************************************************************//**
+ * \brief  Global deinit.
+ */
+static void _ant_deinit(void)
+{
+	_device_list.buf_len = DEVICE_LIST_BUFFER_MAX;
+	if (NULL != _device_list.u.u_buf) {
+		free(_device_list.u.u_buf);
+	}
+} /* _ant_deinit */
+
+
+/**************************************************************************//**
+ * \brief  Show program usage.
+ */
+static int _ant_test_usage(char option)
+{
+	if ('\0' != option) {
+		printf("ERR: Invalid option '%c'.\n\n", option);
+	}
+
+	printf("usage: avm_net_trace_test [-h] [-l] [-d device-id] [-g] [-b buffer-size]\n"
+	       "  -b  Set buffer size for permanent interface. The buffer size is"
+	            " defined in number of packets. Needs '-d'.\n"
+	       "  -g  Get buffer size for permanent interface. Needs '-d'.\n"
+	       "  -d  Set the device id. the device id is the minor number in the"
+	            " device list.\n"
+	       "  -h  Show this help.\n"
+	       "  -l  Dump interface list.\n"
+	       "\n");
+
+	return -1;
+} /* _ant_test_usage */
+
+
+/**************************************************************************//**
+ * \brief  Entry function.
+ */
+int main(int argc, char * argv[])
+{
+	int device_id = -1;
+	int ret       = 0;
+
+	if (1 == argc) {
+		ret = _ant_test_usage('\0');
+		return 0;
+	}
+
+	if (_ant_init() < 0) {
+		return -1;
+	}
+
+	if (_ant_device_update() < 0) {
+		return -1;
+	}
+
+	while (0 == ret) {
+		char option = getopt(argc, argv, "hlgb:d:");
+		if (option < 0) {
+			break;
+		}
+
+		switch (option) {
+			case 'h': {
+				ret = _ant_test_usage('\0');
+				break;
+			}
+			case 'l': {
+				ret = _ant_device_list();
+				break;
+			}
+			case 'b':
+			case 'g': {
+				if (device_id < 0) {
+					printf ("ERR: Device id is not set\n");
+					ret = -1;
+					break;
+				}
+				if (NULL == optarg) {
+					ret = _ant_device_perm_buffer_size_get(device_id);
+				} else {
+					int buffer_size = atoi(optarg);
+					ret = _ant_device_perm_buffer_size_set(device_id, buffer_size);
+				}
+				break;
+			}
+			case 'd': {
+				device_id = atoi(optarg);
+				ret = _ant_device_id_valid(device_id);
+				if (ret < 0) {
+					printf ("ERR: Invalid device id '%s'\n", optarg);
+					break;
+				}
+				break;
+			}
+			default: {
+				ret = _ant_test_usage(option);
+				break;
+			}
+		}
+	}
+
+quit:
+	_ant_deinit();
+
+	return 0;
+} /* main */
--- linux-2.6.28/drivers/char/avm_net_trace/init_net_trace
+++ linux-2.6.28/drivers/char/avm_net_trace/init_net_trace
@@ -2,6 +2,7 @@
 
 ln -fvs ../../drivers/char/avm_net_trace/avm_net_trace.h ../../../include/linux/avm_net_trace.h
 ln -fvs ../../drivers/char/avm_net_trace/avm_net_trace_ioctl.h ../../../include/linux/avm_net_trace_ioctl.h
+ln -fvs ../../../drivers/char/avm_net_trace/avm_net_trace_ioctl.h ../../../include/uapi/linux/avm_net_trace_ioctl.h
 
 exit 0
 
--- /dev/null
+++ linux-2.6.28/drivers/char/avm_net_trace/Kconfig
@@ -0,0 +1,11 @@
+#
+# AVM_NET_TRACE
+#
+#
+
+config AVM_NET_TRACE
+	bool "AVM net trace"
+	default y
+	help
+	  This driver provides tracing of network packets in pcap format.
+
--- /dev/null
+++ linux-2.6.28/drivers/char/avm_net_trace/Makefile-test
@@ -0,0 +1,15 @@
+#
+# The test program is for development purpose only, and it's not part of the normal build. 
+# Please call this make file manually in a build shell. And copy it to your box.
+# E.g.: 
+#   Open build box with './firmware build_menu xterm'
+#   Build with 'make -f Makefile-test'
+#
+export CC               := $(CROSS_COMPILE)gcc
+export GU_PATH_LIBS     := $(shell for i in $(FRITZ_BOX_LIB_PATH) ; do echo "-Wl,-rpath-link -Wl,$$i" ; done)
+export GU_PATH_LIBS     += $(shell for i in $(FRITZ_BOX_LIB_PATH) ; do echo "-L $$i" ; done)
+export GU_PATH_INCLUDES := $(shell for i in $(FRITZ_BOX_INCLUDE_PATH) ; do echo "-I$$i" ; done)
+
+
+all:
+	$(CC) avm_net_trace_test.c $(CLAGS) $(LDFLAGS) $(GU_PATH_LIBS) $(GU_PATH_INCLUDES) -o avm_net_trace_test
--- linux-2.6.28/drivers/char/avm_new/ar7wdt_file.c
+++ linux-2.6.28/drivers/char/avm_new/ar7wdt_file.c
@@ -215,8 +215,6 @@
 #endif/*--- #if defined(AVM_WDT_UDEV) ---*/
 
     AVM_WATCHDOG_init();
-    ar7wdt_hw_init();
-    ar7wdt_hw_trigger();
     return 0;
 }
 
--- linux-2.6.28/drivers/char/avm_new/ar7wdt_main.c
+++ linux-2.6.28/drivers/char/avm_new/ar7wdt_main.c
@@ -81,6 +81,7 @@
 static void AVM_WATCHDOG_timer_handler(unsigned long);
 static struct semaphore ar7wdt_sema;
 extern int ar7wdt_no_reboot;
+static unsigned int hw_wdt_is_running = 0;
 
 /*--- #define WATCHDOG_LIST_TASK_STATISTIC ---*/
 #if defined(WATCHDOG_LIST_TASK_STATISTIC)
@@ -162,6 +163,9 @@
     _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, -1);
 
 	add_simple_proc_file( "avm/wdt", lproc_wd_simulate, lproc_wdt, NULL);
+    ar7wdt_hw_init();
+    ar7wdt_hw_trigger();
+    hw_wdt_is_running = 1;
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
@@ -224,7 +228,6 @@
     if(Sekunden == 0) Sekunden = 120; /*--- 2 Minuten ---*/
 
     {
-        char hw_wdt_is_running = 1;
 
 #ifdef CONFIG_MIPS_UR8
         hw_wdt_is_running = ar7wdt_hw_is_wdt_running();
@@ -245,6 +248,7 @@
         if(!hw_wdt_is_running) {
             ar7wdt_hw_init();
             ar7wdt_hw_trigger();
+            hw_wdt_is_running = 1;
         }
     }
 
@@ -259,7 +263,7 @@
     strcpy(ar7wdt_data.appl[MAX_WDT_APPLS].Name, "init-ctrl");
 
 #ifdef CONFIG_PRINTK
-    printk("AVM_WATCHDOG: System Init UEberwachung %u Sekunden\n", Sekunden);
+    printk(KERN_CRIT"AVM_WATCHDOG: System Init UEberwachung %u Sekunden\n", Sekunden);
 #endif /*--- #ifdef CONFIG_PRINTK ---*/
     _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, MAX_WDT_APPLS);
     return MAX_WDT_APPLS + 1;
@@ -523,7 +527,7 @@
 int AVM_WATCHDOG_disable(int handle __attribute__((unused)), char *time __attribute__((unused)), int len __attribute__((unused))) {
     unsigned long flags;
     int i;
-    printk(KERN_INFO "%s()\n", __func__);
+    printk(KERN_CRIT "%s()\n", __func__);
     printk(KERN_INFO "registered appls:\n");
     for (i = 0; i < MAX_WDT_APPLS; i++) {
         spin_lock_irqsave(&ar7_wdt_lock, flags);
@@ -540,6 +544,7 @@
         }
     }
     _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, -1);
+    hw_wdt_is_running = 0;
     ar7wdt_hw_deinit();
     ar7wdt_no_reboot = 3;
     return 1; /*--- sonst Endlosschleife, weil private_data == 0 ---*/
@@ -871,7 +876,8 @@
 		mb();
 		_printk_save(&saved_printk);
 		if(sysctl_panic_on_oom) {
-			avm_debug_enable_avm_printk(); /* folgende Ausgaben sofort ausgeben */
+			bust_spinlocks(1);
+			avm_debug_disable_avm_printk(); /* folgende Ausgaben sofort raus */
 			console_verbose();
 			dump_stack();
 			show_mem();
@@ -1085,18 +1091,18 @@
 \*--------------------------------------------------------------------------------*/
 static struct task_struct *watchdog_task_list(int notrigger_handle) {
     char txtbuf[2][64];
-	struct task_struct *g, *p, *hungtask = NULL;
-	unsigned long flags, page_faults;
+    struct task_struct *g, *p, *hungtask = NULL;
+    unsigned long flags, page_faults;
     int handle, delayed = 0;
     unsigned int handle_mask = 0;
-	union saved_printk saved_printk;
-	struct timespec uptime;
+    union saved_printk saved_printk;
+    struct timespec uptime;
 
-	read_lock_irqsave(&tasklist_lock, flags);
-	_printk_save(&saved_printk);
-	avm_debug_enable_avm_printk(); /* folgende Ausgaben sofort ausgeben */
-	console_verbose();
-	do_posix_clock_monotonic_gettime(&uptime);
+    read_lock_irqsave(&tasklist_lock, flags);
+    _printk_save(&saved_printk);
+    avm_debug_disable_avm_printk(); /* folgende Ausgaben sofort ausgeben */
+    console_verbose();
+    do_posix_clock_monotonic_gettime(&uptime);
     /*--- printk("utime_sum: %lld unorm %d\n", utime_sum, unorm); ---*/
     printk(KERN_EMERG "[%lu][%x]AVM_WATCHDOG_reboot(hdl=%u, %s): reboot (current: %s pgfault %lu oom_score %lu)\n", 
                                     jiffies,
@@ -1108,7 +1114,7 @@
             );
     page_faults =  get_act_pagefaults();
     printk(KERN_EMERG "pagefaults absolut %lu since last %s-trigger %lu\n",  page_faults, ar7wdt_data.appl[notrigger_handle].Name, page_faults - ar7wdt_data.appl[notrigger_handle].pagefaults);
-	do_each_thread(g, p) {
+    do_each_thread(g, p) {
         if((handle = cmp_wdt_name(p->comm)) == 0) {
 			continue;
         }
@@ -1173,7 +1179,7 @@
 	}
 	_printk_restore(&saved_printk);
 
-    ar7wdt_hw_trigger();
+    if(hw_wdt_is_running) ar7wdt_hw_trigger();
     {
         extern void *current_rtnl_owner __attribute__ ((weak));
         if(&current_rtnl_owner) {
@@ -1191,10 +1197,10 @@
  * context  == 0: panic
 \*--------------------------------------------------------------------------------*/
 static void panic_function(unsigned long context) {
-	ar7wdt_hw_trigger();
-	avm_debug_disable_avm_printk();
+    if(hw_wdt_is_running) ar7wdt_hw_trigger();
+    avm_debug_disable_avm_printk();
 
-    ar7wdt_hw_trigger(); /*--- nochmal triggern - restore_printk() - dauert etwas ! ---*/
+    if(hw_wdt_is_running) ar7wdt_hw_trigger();
     if(context) {
         struct task_struct *hungtask = (struct task_struct *)context; 
         siginfo_t info;
@@ -1233,9 +1239,7 @@
     }
     if(ar7wdt_data.states & (1 << handle)) {
         struct task_struct *hungtask;
-        if(!ar7wdt_no_reboot) {
-            ar7wdt_hw_trigger();
-        }
+        if(hw_wdt_is_running) ar7wdt_hw_trigger();
         hungtask = watchdog_task_list(handle);
 #ifdef CONFIG_SCHEDSTATS
         if (ar7wdt_no_reboot == 1) {
@@ -1368,10 +1372,7 @@
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 void AVM_WATCHDOG_emergency_retrigger(void) {
-
-    if ( ! ar7wdt_no_reboot) {
-        ar7wdt_hw_trigger();
-    }
+    if(hw_wdt_is_running) ar7wdt_hw_trigger();
 }
 EXPORT_SYMBOL(AVM_WATCHDOG_emergency_retrigger);
 /*--------------------------------------------------------------------------------*\
@@ -1403,28 +1404,77 @@
 static void simulate_wdr(void) {
 	AVM_WATCHDOG_register(0, SIMULATE_WD, sizeof(SIMULATE_WD));
 }
+#if defined(CONFIG_SMP)
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static void knockout_cpu(void *dummy __attribute__((unused))) {
+    local_irq_disable();
+    for(;;) ;
+}
+#endif/*--- #if defined(CONFIG_SMP) ---*/
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static int lproc_wd_simulate(char *buffer, void *priv __attribute__((unused))) {
-    char parsbuf[256];
+    char parsbuf[256], *p;
 
 	strncpy(parsbuf, buffer, sizeof(parsbuf) - 1);
 	parsbuf[sizeof(parsbuf) -1] = '\0';
     /*--- printk(KERN_INFO"%s parsbuf='%s'\n", __func__, parsbuf); ---*/
-    if((strstr(parsbuf, "simulate_wdr"))) {
+    if(strstr(parsbuf, "simulate_wdr")) {
 		printk(KERN_ERR"\nSimulate Watchdog-Reboot with '%s'\n", SIMULATE_WD);
 		simulate_wdr();
-	} else if((strstr(parsbuf, "simulate_oomslab"))) {
+    } else if((p = strstr(parsbuf, "simulate_waddr"))) {
+        unsigned int addr = 0, val = 0;
+        p += sizeof("simulate_waddr") - 1;
+        while(*p == ' ' || *p == '\t') p++;
+        sscanf(p,"%x %x", &addr, &val);
+		printk(KERN_ERR"simulate_waddr: *(%x) = %x\n", addr, val);
+        *((unsigned int *)addr) = val;
+        wmb();
+    } else if((p = strstr(parsbuf, "simulate_raddr"))) {
+        unsigned int i, s = 3, addr = 0, count = 0, val;
+        p += sizeof("simulate_raddr") - 1;
+        while(*p == ' ' || *p == '\t') p++;
+        sscanf(p,"%x %u", &addr, &count);
+        if(count == 0) count = 1;
+		printk(KERN_ERR"simulate_raddr: addr=%x count=%x\n", addr, count);
+        for(i = 0; i < count; i++) {
+            val = *((unsigned int *)addr);
+            mb();
+            if(++s == 4) {
+                s = 0;
+                printk("\n%08x: %08x", addr, val);
+            } else {
+                printk(" %08x", val);
+            }
+            addr += 4;
+        }
+        printk("\n");
+	} else if(strstr(parsbuf, "simulate_oomslab")) {
 		printk(KERN_ERR"\nSimulate OOM per kmalloc\n");
 		simulate_oom(1);
-	} else if((strstr(parsbuf, "simulate_oom"))) {
+	} else if(strstr(parsbuf, "simulate_oom")) {
 		printk(KERN_ERR"\nSimulate OOM per vmalloc\n");
 		simulate_oom(0);
-	} else if((strstr(parsbuf, "simulate_kcrash"))) {
+	} else if(strstr(parsbuf, "simulate_kcrash")) {
 		printk(KERN_ERR"\nSimulate Kernel-Crash\n");
 		simulate_kernel_crash();
+	} else if(strstr(parsbuf, "simulate_hw_wdog")) {
+		local_irq_disable();
+#if defined(CONFIG_SMP)
+        on_each_cpu(knockout_cpu, NULL, 0);
+#endif/*--- #if defined(CONFIG_SMP) ---*/
+        for(;;) ;
+    } else if((p = strstr(parsbuf, "simulate_jump"))) {
+        unsigned int addr = 0;
+        p += sizeof("simulate_jump") - 1;
+        while(*p == ' ' || *p == '\t') p++;
+        sscanf(p,"%x", &addr);
+        if(addr) {
+            ((void (*)(void))addr)();
+        }
 	} else {
-		printk(KERN_INFO"unknown option use: simulate_wdr, simulate_oom, simulate_oomslab, simulate_kcrash\n");
+		printk(KERN_INFO"unknown option use: simulate_wdr, simulate_oom, simulate_oomslab, simulate_kcrash, simulate_hw_wdog, simulate_waddr <addr> <val>, simulate_raddr <addr> <count>, simulate_jump addr\n");
 	}
     return 0;
 }
--- linux-2.6.28/drivers/char/avm_new/ath_wdt.c
+++ linux-2.6.28/drivers/char/avm_new/ath_wdt.c
@@ -66,6 +66,7 @@
 #endif/*--- #if defined(CONFIG_NMI_ARBITER_WORKAROUND) ---*/
     {
         ath_reg_wr(ATH_WATCHDOG_TMR, (TIME_OUT_SECS * ahb_freq));
+        wmb();
 #if defined(CONFIG_MACH_AR724x) || defined(CONFIG_SOC_AR724X)
         ath_reg_wr(ATH_WATCHDOG_TMR_CONTROL, ATH_WD_ACT_RESET); 
 #else
--- linux-2.6.28/drivers/char/avm_new/avm_debug.c
+++ linux-2.6.28/drivers/char/avm_new/avm_debug.c
@@ -100,12 +100,12 @@
 \*------------------------------------------------------------------------------------------*/
 static struct _avm_debug {
     unsigned int init;
-    spinlock_t write_lock;
-    /*--- spinlock_t read_lock; ---*/
+    spinlock_t con_lock;
     spinlock_t client_lock;
     spinlock_t synclock;
     atomic_t   open_flag;
              unsigned char *buffer;
+             unsigned char  tmpbuf[PAGE_SIZE];
     volatile unsigned int read;
     volatile unsigned int write;
     volatile unsigned int wrap;
@@ -184,7 +184,7 @@
 };
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
-static inline int avmdebug_lock(spinlock_t *lock, unsigned long *flags) {
+static inline int avmdebug_lock(spinlock_t *lock, unsigned long *flags, unsigned int force) {
 #if defined(CONFIG_SMP)
     int try = 0;
 #if defined(CONFIG_MIPS) 
@@ -198,6 +198,10 @@
         return 1;
     }
 #endif/*--- #if defined(CONFIG_MIPS)  ---*/
+    if(force) {
+        spin_lock_irqsave(lock, *flags);
+        return 1;
+    }
     /*--- if interrupted with a fatal error on this vpe (and the other vpe is already disabled) ---*/
 	while(!spin_trylock_irqsave(lock, *flags)) {
         if(try++ > 20) {
@@ -305,8 +309,7 @@
         return -ERESTARTSYS;
     }
     spin_lock_init(&avm_debug.client_lock);
-    /*--- spin_lock_init(&avm_debug.read_lock); ---*/
-    spin_lock_init(&avm_debug.write_lock);
+    spin_lock_init(&avm_debug.con_lock);
     spin_lock_init(&avm_debug.synclock);
     init_waitqueue_head(&avm_debug.recvwait);
 
@@ -393,6 +396,7 @@
     if(avm_debug_open_minor[minor]) {
         return (*avm_debug_open_minor[minor])(inode, filp);
     }
+    /*--- printk_linux(KERN_ERR"[avm_debug]: avm_debug_open: %x %d\n", filp->f_mode, atomic_read(&avm_debug.open_flag)); ---*/
     if(filp->f_mode & FMODE_READ){
         if(atomic_add_return(1, &avm_debug.open_flag) > 1) {
             return -EBUSY;
@@ -410,7 +414,9 @@
     if(avm_debug_close_minor[minor]) {
         return (*avm_debug_close_minor[minor])(inode, filp);
     }
-    atomic_set(&avm_debug.open_flag, 0);
+    if(filp->f_mode & FMODE_READ){
+        atomic_set(&avm_debug.open_flag, 0);
+    }
     return 0;
 }
 /*------------------------------------------------------------------------------------------*\
@@ -600,19 +606,6 @@
         SKIP_SPACES(p);
         val = (*p == '1') ? 1 : 0;
         avm_debug.eof_sync = val;
-        if(avm_debug.eof_sync) {
-            /*--- unsigned long flags; ---*/
-            /*--- Debugbuffer nochmal reaktivieren ---*/
-            /*--- read_lock nutzen weil der 'read' Poiner manipuliert werden soll ---*/
-            /*--- avmdebug_lock(&avm_debug.read_lock, &flags); ---*/
-            if(avm_debug.written >= avm_debug.size) {
-                avm_debug.read = inc_idx(avm_debug.write, avm_debug.size);
-            } else {
-                avm_debug.read = 0;
-            }
-            /*--- avmdebug_unlock(&avm_debug.read_lock, flags); ---*/
-            printk(KERN_ERR"---> reanimated debugbuffer: read=%d write=%d, written=%d <---\n", avm_debug.read, avm_debug.write, avm_debug.written);
-        }
         /*--- printk(KERN_ERR"\n[avm_debug]eofsync %d\n", avm_debug.eof_sync); ---*/
     } else if(!strncmp(AVM_DBG_SIGNAL, p, sizeof(AVM_DBG_SIGNAL) - 1)) {
         int val = -1;
@@ -670,7 +663,7 @@
     struct _debug_client *pdbg;
     unsigned long flags;
 
-    avmdebug_lock(&avm_debug.client_lock, &flags);
+    avmdebug_lock(&avm_debug.client_lock, &flags, 1);
     pdbg = avm_debug.dbg_clientAnker;
     while(pdbg) {
         if(strncmp(prefix, pdbg->prefix, strlen(pdbg->prefix)) == 0) {
@@ -696,7 +689,7 @@
     pdbg->prefix        = (char *)pdbg + sizeof(struct _debug_client);
     strcpy(pdbg->prefix, prefix);
     pdbg->next = NULL;
-    avmdebug_lock(&avm_debug.client_lock, &flags);
+    avmdebug_lock(&avm_debug.client_lock, &flags, 1);
     pdbg->next                = avm_debug.dbg_clientAnker;
     avm_debug.dbg_clientAnker = pdbg;
     avmdebug_unlock(&avm_debug.client_lock, flags);
@@ -735,7 +728,7 @@
     struct _debug_client *pdbg, *prev = NULL;
     unsigned long flags;
     DEB_INFO("[avm_debug]avm_DebugCallUnRegister: %p done\n", handle);
-    avmdebug_lock(&avm_debug.client_lock, &flags);
+    avmdebug_lock(&avm_debug.client_lock, &flags, 1);
     pdbg = avm_debug.dbg_clientAnker;
     while(pdbg) {
         if(pdbg == handle) {
@@ -773,23 +766,59 @@
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 static ssize_t avm_debug_read(struct file *filp, char *read_buffer, size_t max_read_length, loff_t *read_pos) {
-    unsigned int copy_length = 0, wrap_length = 0;
+    char *dst;
+    unsigned int copy_length = 0;
     unsigned int local_read, local_write;
-    /*--- unsigned long flags, locked = 0; ---*/
+    unsigned long flags;
 
     if(filp) {
         unsigned int minor = (unsigned int)filp->private_data;
         if(avm_debug_read_minor[minor])
             return (*avm_debug_read_minor[minor])(filp, read_buffer, max_read_length, read_pos);
     }
+    if(filp) {
+        dst = avm_debug.tmpbuf;
+        if(max_read_length > sizeof(avm_debug.tmpbuf)) {
+            max_read_length = sizeof(avm_debug.tmpbuf);
+        }
+    } else {
+        dst = read_buffer;
+    }
     for( ;; ) {
-        if(avm_debug.read == avm_debug.write) {
+        if(avmdebug_lock(&avm_debug.con_lock, &flags, 0) == 0) {
+            /*--- printk_linux(KERN_ERR"%s: #no lock get\n\n", __func__); ---*/
             if(filp == NULL) {
-                return copy_length;
+                return 0;
+            }
+            if (filp->f_flags & O_NONBLOCK) {
+                return -EAGAIN;
+            }
+            interruptible_sleep_on_timeout(&avm_debug.recvwait, HZ / 10);
+            if (signal_pending(current)) {
+                return -ERESTARTNOHAND;
+            }
+            continue;
+        }
+        local_read  = avm_debug.read;
+        local_write = avm_debug.write;
+        if(local_read == local_write) {
+            if(filp == NULL) {
+                avmdebug_unlock(&avm_debug.con_lock, flags);
+                return 0;
+            }
+            if(avm_debug.eof_sync == 1) {
+                avm_debug.eof_sync = 3;
+                /*--- Debugbuffer nochmal reaktivieren ---*/
+                if(avm_debug.written >= avm_debug.size) {
+                    avm_debug.read = inc_idx(avm_debug.write, avm_debug.size);
+                } else {
+                    avm_debug.read = 0;
+                }
+                printk(KERN_ERR"---> reanimated debugbuffer: read=%d write=%d, written=%d <---\n", avm_debug.read, avm_debug.write, avm_debug.written);
             }
+            avmdebug_unlock(&avm_debug.con_lock, flags);
             if(avm_debug.eof_sync) {
                 /*--- erzwinge Beenden von cat etc. ---*/
-		/* printk_linux("avm_debug_read: end"); */
                 return -EPIPE;
             }
             if (filp->f_flags & O_NONBLOCK) {
@@ -801,55 +830,39 @@
             }
             continue;
         }
-        /*--- avmdebug_lock(&avm_debug.read_lock, &flags); ---*/
-        local_read = avm_debug.read;
-        local_write = avm_debug.write;
-
-        if(local_read < local_write) {
+        if(unlikely(avm_debug.wrap)) {
+            if(max_read_length >= sizeof(AVM_DBGWRAP_STR) - 1) {
+                avm_debug.wrap = 0;
+                copy_length = sizeof(AVM_DBGWRAP_STR) - 1;
+                if(dst) memcpy(dst, AVM_DBGWRAP_STR, copy_length);
+                goto wrap_continue;
+            }
+        }
+        if(local_read <= local_write) {
             copy_length = local_write - local_read;
         } else {
             copy_length = avm_debug.size - local_read;
         }
-        /*--- avmdebug_unlock(&avm_debug.read_lock, flags); ---*/
-
-        if(avm_debug.wrap) {
-            avm_debug.wrap = 0;
-            if(max_read_length >= sizeof(AVM_DBGWRAP_STR) - 1) {
-                wrap_length      = sizeof(AVM_DBGWRAP_STR) - 1;
-                if(filp == NULL) {
-                    if(read_buffer)memcpy(read_buffer, AVM_DBGWRAP_STR, wrap_length);
-                } else {
-                    if(copy_to_user(read_buffer, AVM_DBGWRAP_STR, wrap_length)) {
-                        return -EFAULT;
-                    }
-                }
-                max_read_length -= wrap_length;
-                if(read_buffer)read_buffer     += wrap_length;
-            }
-        }
         if(copy_length > max_read_length) {
             copy_length = max_read_length;
         }
-        if(filp == NULL) {
-            if (read_buffer) {
-                memcpy(read_buffer, avm_debug.buffer + local_read, copy_length);
-            }
-        } else {
-            if(copy_to_user(read_buffer, avm_debug.buffer + local_read, copy_length)) {
-                /*--- DEB_ERR("[avm_debug]: copy_to_user failed (read_pos %llu / copy length %u)\n", read_pos ? *read_pos : 0, copy_length); ---*/
-                return -EFAULT;
-            }
-        }
-        /*--- avmdebug_lock(&avm_debug.read_lock, &flags); ---*/
-        if(avm_debug.read + copy_length >= avm_debug.size)
+        if(dst) memcpy(dst, avm_debug.buffer + local_read, copy_length);
+        if(avm_debug.read + copy_length >= avm_debug.size) {
             avm_debug.read = 0;
-        else
+        } else {
             avm_debug.read += copy_length;
-        /*--- avmdebug_unlock(&avm_debug.read_lock, flags); ---*/
+        }
+wrap_continue:
+        avmdebug_unlock(&avm_debug.con_lock, flags);
+        /*--- copy_to_user() maybe sleep - tmpbuf needed ---*/
+        if(filp && copy_to_user(read_buffer, dst, copy_length)) {
+            /*--- DBG_ERR("[avm_debug]: copy_to_user failed (read_pos %llu / copy length %u)\n", read_pos ? *read_pos : 0, copy_length); ---*/
+            return -EFAULT;
+        }
         break;
     }
-    if(read_pos)*read_pos += copy_length + wrap_length;
-    return copy_length + wrap_length;
+    if(read_pos)*read_pos += copy_length;
+    return copy_length;
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
@@ -878,7 +891,7 @@
        *(DebugData+length-1) == '\n' ) {
         ret = 1;
     }
-    if(avmdebug_lock(&avm_debug.write_lock, &flags)) {
+    if(avmdebug_lock(&avm_debug.con_lock, &flags, 0)) {
         local_write = avm_debug.write;
         local_read  = avm_debug.read;
         avm_debug.written += length;
@@ -894,7 +907,7 @@
             avm_debug.wrap = wrap;
         }
         avm_debug.write = local_write;
-        avmdebug_unlock(&avm_debug.write_lock, flags);
+        avmdebug_unlock(&avm_debug.con_lock, flags);
 #if defined(CONFIG_SMP) && defined(CONFIG_MIPS)
         /*--- somit darf avmDebug_Printf auch im yield-context verwendet werden ---*/
         if(!is_yield_context())
@@ -1767,7 +1780,7 @@
     if(avm_debug.init == 0) {
         return;
     }
-    avmdebug_lock(&avm_debug.synclock, &flags);
+    avmdebug_lock(&avm_debug.synclock, &flags, 1);
     actlen = avm_debugfill();
     if(actlen > OUTPUT_LASTBUFFER) {
         waste = actlen - OUTPUT_LASTBUFFER;
@@ -1780,20 +1793,19 @@
     }
     for(;;) {
         int len;
-        len = avm_debug_read(NULL, syncbuf, sizeof(syncbuf) -1, NULL);
+        len = avm_debug_read(NULL, syncbuf, sizeof(syncbuf) - 1, NULL);
         if(len <= 0) {
             break;
         }
         if(start == 0) {
             start = 1;
-	    printk_linux("\n---- start avmdebug(suppress %ld bytes) ----\n",
-			 mw);
+            printk_linux("\n---- start avmdebug(suppress %ld bytes) ----\n", mw);
         }
         syncbuf[len] = 0;
-	printk_linux("%s", syncbuf);
+        printk_linux("%s", syncbuf);
     }
     if(start) {
-	printk_linux("\n---- eof avmdebug ----\n");
+        printk_linux("\n---- eof avmdebug ----\n");
     }
     avmdebug_unlock(&avm_debug.synclock, flags);
 }
@@ -1884,7 +1896,7 @@
         unsigned long flags;
         avm_DebugPrintf("%s: %x %s %d\n", __func__, signal & 0x1F, signal & 0x80000000 ? "user pid:" : "kernel info:", (signal & ~0x80000000) >> 8);
         signal &= 0x1F;
-        avmdebug_lock(&avm_debug.client_lock, &flags);
+        avmdebug_lock(&avm_debug.client_lock, &flags, 1);
         avm_debug.signal |= 0x1 << signal;
         avmdebug_unlock(&avm_debug.client_lock, flags);
         wake_up_interruptible(&avm_debug.wait_queue);
@@ -2015,7 +2027,7 @@
 			/* interrupted by signal -> exit */
 			return ret;
 
-		avmdebug_lock(&avm_debug.client_lock, &flags);
+		avmdebug_lock(&avm_debug.client_lock, &flags, 1);
 		sig = pdbg->signal | timeoutsignal;
 		pdbg->signal = 0;
 		avmdebug_unlock(&avm_debug.client_lock, flags);
--- linux-2.6.28/drivers/char/avm_new/avm_proc_profile.c
+++ linux-2.6.28/drivers/char/avm_new/avm_proc_profile.c
@@ -592,6 +592,7 @@
             if((ret = __get_userinfo(buf, maxbuflen, tsk->active_mm, addr))) {
                 ret = __get_userinfo(buf, maxbuflen, tsk->mm, addr);
             }
+            put_task_struct(tsk);
         }
         put_pid(ppid);
     }
@@ -651,6 +652,7 @@
                     tsk = get_pid_task(pid, PIDTYPE_PID);
                     if (tsk) {
                         strncpy(comm, tsk->comm, sizeof(act_pid_percpu[data->cpu_id].comm));
+                        put_task_struct(tsk);
                     }
                     put_pid(pid);
                 } else {
@@ -658,7 +660,11 @@
                 }
             }
             act_pid_percpu[data->cpu_id].pid = act_pid;
-            if(get_user_info(Symbols, sizeof(Symbols), act_pid, data->addr)){
+            if(get_user_info(Symbols, sizeof(Symbols), act_pid, data->addr 
+#if defined(CONFIG_MIPS) || defined(CONFIG_ARM)
+                        & ~0x3  /*--- falls mips16/tumb-code: keine Unaligneds provozieren ---*/
+#endif/*--- #if defined(CONFIG_MIPS) || defined(CONFIG_ARM) ---*/
+                        )){
                 sprint_symbol(Symbols, data->addr);
             }
             switch(mode) {
@@ -804,7 +810,7 @@
     unsigned long vpflags;
 
 #if 0
-    if (tc == smp_processor_id() ) {
+    if (tc == raw_smp_processor_id() ) {
 
        // printk(KERN_ERR "direct access for tc=%d\n", tc);
         switch(ctl_reg){
@@ -869,7 +875,7 @@
        // printk(KERN_ERR "store[%d][%d]=%#x\n", tc, count_reg, val);
     }
 #if 0
-    if (tc == smp_processor_id() ){
+    if (tc == raw_smp_processor_id() ){
        // printk(KERN_ERR "direct access for tc=%d\n", tc);
         switch(count_reg){
             case 0:
@@ -1067,7 +1073,7 @@
         int new_perf_ctl = 0;
 
 #if defined(CONFIG_CPU_MIPS_34K)
-        unsigned int current_tc_mask = (1 << smp_processor_id());
+        unsigned int current_tc_mask = (1 << raw_smp_processor_id());
         int counting_tc_mask = current_tc_mask;
         int set_perf_irq = 0;
         int preset_count = 0;
--- linux-2.6.28/drivers/char/avm_new/avm_profile_stat.c
+++ linux-2.6.28/drivers/char/avm_new/avm_profile_stat.c
@@ -1,3 +1,7 @@
+/*--------------------------------------------------------------------------------*\
+Originalsource im amv_new -Treiber (avm_profile_stat.c)
+gcc profile_new.c -O3 -m32 -Wall -g -ggdb -o profile_new
+\*--------------------------------------------------------------------------------*/
 #if defined(__KERNEL__)
 #include <linux/version.h>
 #include <linux/module.h>
@@ -27,6 +31,12 @@
 /*--------------------------------------------------------------------------------*\
  * SOF: Offline-testtool Offline-testtool Offline-testtool Offline-testtool Offline-testtool 
 \*--------------------------------------------------------------------------------*/
+#define CONFIG_PROC_FS
+#define CONFIG_KALLSYMS 
+#define NR_CPUS         4 
+#define PAGE_SHIFT      12 
+#define __GFP_NORETRY   0 
+#define unlikely(a)     a
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -327,15 +337,16 @@
         struct task_struct *tsk;
         struct pid *ppid;
         if(pid == AVM_PROFILE_IDLE_ID) {
-            snprintf(buf, KSYM_NAME_LEN, "IDLE");
+            snprintf(buf, TASK_COMM_LEN, "IDLE");
         } else if(pid && (ppid = find_get_pid(pid))) {
             tsk = get_pid_task(ppid, PIDTYPE_PID);
             if (tsk) {
-                snprintf(buf, KSYM_NAME_LEN, "%s", tsk->comm);
+                strncpy(buf, tsk->comm, TASK_COMM_LEN);
+                put_task_struct(tsk);
             }
             put_pid(ppid);
         } else {
-            snprintf(buf, KSYM_NAME_LEN, "PID_%d", pid);
+            snprintf(buf, TASK_COMM_LEN, "PID_%d", pid);
         }
         return buf;
     }
@@ -717,7 +728,7 @@
                                                                           __u32 total_activate,
 #endif/*--- #if defined(AVM_PROFILE_ACTIVITY_INCLUDED) ---*/
                                                                           enum _avm_profile_data_type type,
-                                                                          unsigned int addr, 
+                                                                          unsigned long addr, 
                                                                           pid_t pid,
                                                                           unsigned int id, 
                                                                           unsigned int mode) {
@@ -1011,7 +1022,7 @@
                                    pdata->total_activate - last[cpu_id].total_activate,
 #endif/*--- #if defined(AVM_PROFILE_ACTIVITY_INCLUDED) ---*/
                                    avm_profile_data_type_code_address_info,
-                                   (unsigned int)ple_code->addr,
+                                   (unsigned long)ple_code->addr,
                                    ple_code->id,
                                    ple_code->id, (timeline & 0xFF) | (CODE_ENTRY << 8));
                     diff_time = 0;
@@ -1028,7 +1039,7 @@
                 if(last[cpu_id].irq_flag != 0) {
                     /*--- error on csv or nested irq-call: ---*/
                     DBG_ERR("Warning:line %u Code-Entry with setting irq_flag=%d (missing End of IRQ - perhaps nested irq)- reset irq_flag\n", line, last[cpu_id].irq_flag);
-                    last[cpu_id].irq_flag = 0;
+                    /*--- last[cpu_id].irq_flag = 0; ---*/
                 }
                 if(last[cpu_id].ple_code) {
                     struct _profile_list_entry *ple_code= last[cpu_id].ple_code;
@@ -1085,6 +1096,12 @@
             } else {
                 DBG_TRC("\tsame %s %p %s pid=%u last_btime=%llu\n", pdata->id == AVM_PROFILE_IDLE_ID ? "idle" : "code", ple->addr, profile_find_symbol(0, pdata->id, txtbuf[0]), pdata->id, ple->last_btime);
             }
+			if(pdata->id == AVM_PROFILE_IDLE_ID) {
+				if(last[cpu_id].irq_flag) {
+					DBG_ERR("Warning:line %u IDLE-Entry with setting irq_flag (%d) -> reset\n", line, last[cpu_id].irq_flag = 0);
+					last[cpu_id].irq_flag = 0;
+				}
+            }
         /*--------------------------------------------------------------------------------*\
          * Handling for BEGIN_ENTRY 
         \*--------------------------------------------------------------------------------*/
@@ -1132,7 +1149,9 @@
             }
             if((dtm->operation & IRQ_ENTRY)) {
                 /*--- code interrupted ---*/
-                last[cpu_id].irq_flag++;
+                if(pdata->id != AVM_PROFILE_PAGE_FAULT_ID) {
+					last[cpu_id].irq_flag++;
+				}
                 ple->recursion++;
             }
         /*--------------------------------------------------------------------------------*\
@@ -1140,10 +1159,12 @@
         \*--------------------------------------------------------------------------------*/
         } else if(dtm->operation & END_ENTRY) {
             if((dtm->operation & IRQ_ENTRY)) {
-                if(last[cpu_id].irq_flag) {
-                    last[cpu_id].irq_flag--;
-                } else {
-                    DBG_ERR("Warning:line %u %s: End-Entry without setting irq_flag\n", line, avm_profile_data_short_names[pdata->type]);
+                if(pdata->id != AVM_PROFILE_PAGE_FAULT_ID) {
+					if(last[cpu_id].irq_flag) {
+						last[cpu_id].irq_flag--;
+					} else {
+						DBG_ERR("Warning:line %u %s: End-Entry without setting irq_flag\n", line, avm_profile_data_short_names[pdata->type]);
+					}
                 }
             }
             if(ple->recursion) {
@@ -1367,9 +1388,9 @@
             sym = profile_find_symbol(pce->addr, (pid_t)-1, txt[0]);
         while(*sym && (*sym != '+')) sym++;
         if(*sym == '+') *sym = 0;
-        rprint(txtbuf, txtbuf_len, "%-64s (%08x/%5d) %-16s %s %8u %6u\n", 
+        rprint(txtbuf, txtbuf_len, "%-64s (%08lx/%5d) %-16s %s %8u %6u\n", 
                       txt[0],               
-                      (unsigned int)pce->addr,
+                      (unsigned long)pce->addr,
                       pce->id, 
                       profile_find_symbol(0, pce->id, txt[1]),
                       percent(weight_val, weight_divider, txt[2]), 
@@ -1837,7 +1858,7 @@
         gCycle_per_usec = gFreq / 2;
     }
     avm_profile_data_entries = parse_profile_csv(fin, &data, &symbolname, &current_name, &maxcpus);
-    printf("entries=%u PROFILE_LIST_ENTRIES=%u size=%u maxcpus=%d\n", avm_profile_data_entries, PROFILE_LIST_ENTRIES, 
+    printf("entries=%u PROFILE_LIST_ENTRIES=%ld size=%lu maxcpus=%d\n", avm_profile_data_entries, PROFILE_LIST_ENTRIES, 
                     sizeof(struct _profile_list_entry), maxcpus);
     if(gCpu != -1) {
         startcpu = gCpu;
@@ -1871,7 +1892,7 @@
         fill_profilestat_lists(NULL, startcpu, maxcpus, formatflag );
         free_profilestat_lists();
     }
-    printf("pages_cnt=%d\n", pages_cnt);
+    /*--- printf("pages_cnt=%d\n", pages_cnt); ---*/
     return 0;
 }
 /*--------------------------------------------------------------------------------*\
--- linux-2.6.28/drivers/char/avm_new/linux_avm_event.h
+++ linux-2.6.28/drivers/char/avm_new/linux_avm_event.h
@@ -68,6 +68,16 @@
 #define AVM_EVENT_TYPE_WLAN_ERROR           1
 
 /*------------------------------------------------------------------------------------------*\
+ * 0x00002: 'avm_event_smarthome_switch_status': Umbenennung von 2 Feldern: 'name_length' -> 'ain_length', 'name' -> 'ain'
+ * 0x00003: 'avm_event_telefony': Erweiterung des Telefonie-Events
+\*------------------------------------------------------------------------------------------*/
+#define AVM_DIST_EVENT_VERSION                  0x00003
+#define AVM_DIST_EVENT_VERSION__GET_MAJOR(v)    ((v >> 16) & 0xffff)
+#define AVM_DIST_EVENT_VERSION__GET_MINOR(v)    (v & 0xffff)
+#define AVM_DIST_EVENT_VERSION__MAJOR           AVM_DIST_EVENT_VERSION__GET_MAJOR(AVM_DIST_EVENT_VERSION)
+#define AVM_DIST_EVENT_VERSION__MINOR           AVM_DIST_EVENT_VERSION__GET_MINOR(AVM_DIST_EVENT_VERSION)
+
+/*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
 enum _avm_event_id {
     avm_event_id_wlan_client_status      = 0,
@@ -98,11 +108,20 @@
     avm_event_id_cpu_idle                = 29,
     avm_event_id_powermanagment_status   = 30,
 
-    /*--- avm_event_id_ethernet_status         = 32, ---*/
+    avm_event_id_powerline_status        = 31,
     avm_event_id_ethernet_connect_status = 33,
     avm_event_id_powermanagment_remote   = 34,   /*--- for internal communication between powermanager on many-CPU-Devices ---*/
 
     avm_event_id_pm_ressourceinfo_status = 40,
+    avm_event_id_telephony_missed_call   = 41,
+    avm_event_id_telephony_tam_call      = 42,
+    avm_event_id_telephony_fax_received  = 43,
+    avm_event_id_internet_new_ip         = 44,
+    avm_event_id_firmware_update_available = 45,
+    avm_event_id_smarthome_switch_status = 46,
+    avm_event_id_telephony_incoming_call = 47,
+	avm_event_id_mass_storage_mount      = 48,
+	avm_event_id_mass_storage_unmount    = 49,
 
     avm_event_id_user_source_notify      = 63,
     avm_event_last                       = 64
@@ -629,4 +648,183 @@
 	unsigned char   rate_dvbccum;      /*--- kumulierter DVB-C-Leistungsverbrauch in Prozent ---*/
 };
 
+/*--------------------------------------------------------------------------------*\
+    avm_event_id_powerline_status        = 31
+\*--------------------------------------------------------------------------------*/
+enum ePLCState {
+	PLCStateRunningNotConnected = 0,		// powerline firmware is up and running, powerline is not connected
+	PLCStateRunningConnected    = 1,		// powerline firmware is up and running, powerline is connected
+	PLCStateNotRunning			= 2         // powerline firmware is not up and running (either chip is down or still in bootloader)
+};
+
+struct _avm_event_powerline_status {
+    struct _avm_event_header event_header; /* Header for the event structure */
+    enum ePLCState status; 
+};
+struct avm_event_powerline_status {
+    enum ePLCState status; 
+};
+
+
+/*-------------------------------------------------------------------------------------*\
+    avm_event_id_telephony_missed_call   = 41
+\*-------------------------------------------------------------------------------------*/
+enum avm_event_telephony_param_sel {
+	avm_event_telephony_params_name = 0,
+	avm_event_telephony_params_msn_name = 1,
+	avm_event_telephony_params_calling = 2,
+	avm_event_telephony_params_called = 3,
+	avm_event_telephony_params_duration = 4,
+	avm_event_telephony_params_port = 5,
+	avm_event_telephony_params_portname = 6,
+	avm_event_telephony_params_id = 7,
+	avm_event_telephony_params_tam_path = 8,
+};
+
+struct avm_event_telephony_string {
+	unsigned int length;
+	unsigned char string[0];
+} __attribute__((packed));
+
+union avm_event_telephony_call_params {
+	/*--- select by [select-variable] one of (avm_event_telephony_params_name avm_event_telephony_params_msn_name avm_event_telephony_params_portname avm_event_telephony_params_tam_path) ---*/
+	struct avm_event_telephony_string string;
+	/*--- select by [select-variable] one of (avm_event_telephony_params_calling avm_event_telephony_params_called) ---*/
+	unsigned char number[32];
+	/*--- select by [select-variable] one of (avm_event_telephony_params_duration) ---*/
+	unsigned int duration;
+	/*--- select by [select-variable] one of (avm_event_telephony_params_port) ---*/
+	unsigned char port;
+	/*--- select by [select-variable] one of (avm_event_telephony_params_id) ---*/
+	unsigned int id;
+} __attribute__((packed));
+
+struct _avm_event_telephony_missed_call_params {
+	enum avm_event_telephony_param_sel id;
+	union avm_event_telephony_call_params params;
+} __attribute__((packed));
+
+struct avm_event_telephony_missed_call {
+	unsigned int length;
+	struct _avm_event_telephony_missed_call_params p[0];
+} __attribute__((packed));
+
+struct _avm_event_telephony_missed_call {
+	struct _avm_event_header header;
+	unsigned int length;
+	struct _avm_event_telephony_missed_call_params p[0];
+} __attribute__((packed));
+
+
+/*-------------------------------------------------------------------------------------*\
+	avm_event_id_firmware_update_available = 45,
+\*-------------------------------------------------------------------------------------*/
+
+enum avm_event_firmware_type {
+	box_firmware = 0,
+	fritz_fon_firmware = 1,
+	fritz_dect_repeater = 2,
+	fritz_plug_switch = 3,
+	fritz_hkr = 4,
+};
+
+struct _avm_event_firmware_update_available {
+	struct _avm_event_header header;
+	enum avm_event_firmware_type type;
+	unsigned int version_length;
+	unsigned char version[0];
+} __attribute__((packed));
+
+struct avm_event_firmware_update_available {
+	enum avm_event_firmware_type type;
+	unsigned int version_length;
+	unsigned char version[0];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------------------*\
+	avm_event_id_internet_new_ip = 44,
+\*-------------------------------------------------------------------------------------*/
+
+enum avm_event_internet_new_ip_param_sel {
+	avm_event_internet_new_ip_v4 = 0,
+	avm_event_internet_new_ip_v6 = 1,
+};
+
+union avm_event_internet_new_ip_param {
+	/*--- select by [select-variable] one of (avm_event_internet_new_ip_v4) ---*/
+	unsigned char ipv4[4];
+	/*--- select by [select-variable] one of (avm_event_internet_new_ip_v6) ---*/
+	unsigned char ipv6[16];
+} __attribute__((packed));
+
+struct avm_event_internet_new_ip {
+	enum avm_event_internet_new_ip_param_sel sel;
+	union avm_event_internet_new_ip_param params;
+} __attribute__((packed));
+
+struct _avm_event_internet_new_ip {
+	struct _avm_event_header header;
+	enum avm_event_internet_new_ip_param_sel sel;
+	union avm_event_internet_new_ip_param params;
+} __attribute__((packed));
+
+
+/*-------------------------------------------------------------------------------------*\
+	avm_event_id_smarthome_switch_status = 46,
+\*-------------------------------------------------------------------------------------*/
+
+enum avm_event_switch_type {
+	binary = 0,
+	percent = 1,
+};
+
+struct avm_event_smarthome_switch_status {
+	enum avm_event_switch_type type;
+	unsigned int value;
+	unsigned int ain_length;
+	unsigned char ain[0];
+} __attribute__((packed));
+
+struct _avm_event_smarthome_switch_status {
+	struct _avm_event_header header;
+	enum avm_event_switch_type type;
+	unsigned int value;
+	unsigned int ain_length;
+	unsigned char ain[0];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------------------*\
+	avm_event_id_mass_storage_mount = 48,
+\*-------------------------------------------------------------------------------------*/
+
+struct avm_event_mass_storage_mount {
+	unsigned long long size;
+	unsigned long long free;
+	unsigned int name_length;
+	unsigned char name[0];
+} __attribute__((packed));
+
+struct _avm_event_mass_storage_mount {
+	struct _avm_event_header header;
+	unsigned long long size;
+	unsigned long long free;
+	unsigned int name_length;
+	unsigned char name[0];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------------------*\
+	avm_event_id_mass_storage_unmount = 49,
+\*-------------------------------------------------------------------------------------*/
+
+struct avm_event_mass_storage_unmount {
+	unsigned int name_length;
+	unsigned char name[0];
+} __attribute__((packed));
+
+struct _avm_event_mass_storage_unmount {
+	struct _avm_event_header header;
+	unsigned int name_length;
+	unsigned char name[0];
+} __attribute__((packed));
+
 #endif /*--- #ifndef _avm_linux_event_h_ ---*/
--- linux-2.6.28/drivers/char/avm_power/avm_cpu_process.c
+++ linux-2.6.28/drivers/char/avm_power/avm_cpu_process.c
@@ -16,6 +16,7 @@
 #if defined(CONFIG_AVM_SIMPLE_PROFILING)
 #include <linux/avm_profile.h>
 #endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/
+#include <asm/mach_avm.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
 /**
@@ -47,30 +48,14 @@
 unsigned int avm_page_faultlink_sum[NR_CPUS];
 unsigned int avm_page_faultlink_cnt[NR_CPUS];
 
-#if defined(CONFIG_AR9)
-#define CPU_TIMEOUT_10S (394 / 2)
-#elif defined(CONFIG_LANTIQ)
-#define CPU_TIMEOUT_10S (500 / 2)
-#elif defined(CONFIG_MACH_ATHEROS) || defined(CONFIG_ATH79)
-#define CPU_TIMEOUT_10S (560 / 2)
-#elif defined(CONFIG_X86)
-#define CPU_TIMEOUT_1S (cpu_khz / 1000)  /*--- because wraparround 1.2 GHz after 3.5 Seconds ! ---*/
-#elif defined(CONFIG_ARCH_PUMA5)
-#define CPU_TIMEOUT_10S (400 / 2)
-#elif defined(CONFIG_MAC_PUMA6)
-#define CPU_TIMEOUT_10S (450 / 2)
-#else
-#define CPU_TIMEOUT_10S (360 / 2)
-#endif /*--- #else ---*/ /*--- #if defined(CONFIG_MIPS_FUSIV) ---*/
+static unsigned long long gCycle_per_10sec = 250ULL * 1000ULL * 1000ULL * 10ULL;
 
 /*--------------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------------*/
 static struct _cpu_idlecount {
     unsigned int last_value;
     unsigned long last_value_done;
-#if defined(CPU_TIMEOUT_1S) 
     unsigned long long run_summary;
-#endif/*--- #if defined(CPU_TIMEOUT_1S)  ---*/
     unsigned int wait_count;
     unsigned int run_count;
     unsigned int sum_count;
@@ -81,20 +66,15 @@
 } cpu_idlecount[NR_CPUS];
 
 #define COUNT_DIFF(act, last)   ((act) - (last))
-
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static inline unsigned check_10second_without_idle(unsigned long act_cycle, struct _cpu_idlecount *pcpuidle) {
-#if defined(CPU_TIMEOUT_10S) 
-    return COUNT_DIFF(act_cycle, pcpuidle->last_value) > (1000 * 1000 /* usec */ * CPU_TIMEOUT_10S);
-#else/*--- #if defined(CPU_TIMEOUT_10S)  ---*/
     pcpuidle->run_summary += COUNT_DIFF(act_cycle, pcpuidle->last_value);
-    if(pcpuidle->run_summary > (unsigned long long)CPU_TIMEOUT_1S * 10ULL * 1000ULL * 1000ULL) {
+    if(pcpuidle->run_summary > gCycle_per_10sec) {
         pcpuidle->run_summary = 0;
         return 1;
     }
     return 0;
-#endif/*--- #else ---*//*--- #if defined(CPU_TIMEOUT_10S)  ---*/
 }
 
 /*--------------------------------------------------------------------------------*\
@@ -108,12 +88,12 @@
 \*--------------------------------------------------------------------------------*/
 void avm_cpu_wait_start(void) {
     unsigned int count, tmp;
-    struct _cpu_idlecount *pcpuidle = &cpu_idlecount[smp_processor_id()];
+    struct _cpu_idlecount *pcpuidle = &cpu_idlecount[raw_smp_processor_id()];
 
 #if defined(CONFIG_AVM_SIMPLE_PROFILING) 
     avm_simple_profiling_enter_idle((unsigned int)avm_cpu_wait_start);
 #endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING)  ---*/
-    count = get_cycles();
+    count = avm_get_cycles();
     if(pcpuidle->last_value) {
         tmp = COUNT_DIFF(count, pcpuidle->last_value) >> CPU_COUNT_SHIFT;
         pcpuidle->run_count += tmp;
@@ -121,9 +101,7 @@
     }
     pcpuidle->last_value      = count;
     pcpuidle->last_value_done = 0;
-#if defined(CPU_TIMEOUT_1S) 
     pcpuidle->run_summary     = 0;
-#endif/*--- #if defined(CPU_TIMEOUT_1S)  ---*/
     if(pcpuidle->fulldisp_jiffies == 0) {
         pcpuidle->fulldisp_jiffies = jiffies;
     }
@@ -233,13 +211,13 @@
  * call at the end of idle in wait_irq_off-function or direct in the irq-function
 \*--------------------------------------------------------------------------------------*/
 int avm_cpu_wait_end(void) {
-    unsigned int cpu =  smp_processor_id();
+    unsigned int cpu =  raw_smp_processor_id();
     unsigned int cpu_run = 0;
     struct _cpu_idlecount *pcpuidle = &cpu_idlecount[cpu];
 
     if(test_and_set_bit(0, &pcpuidle->last_value_done) == 0) {
         int count, tmp;
-        count = get_cycles();
+        count = avm_get_cycles();
         tmp = COUNT_DIFF(count, pcpuidle->last_value) >> CPU_COUNT_SHIFT;
         pcpuidle->wait_count += tmp;
         pcpuidle->sum_count  += tmp;
@@ -259,10 +237,10 @@
 #ifdef CONFIG_AVM_POWERMETER
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
-    if(check_10second_without_idle(get_cycles(), pcpuidle)) {
+    if(check_10second_without_idle(avm_get_cycles(), pcpuidle)) {
         register unsigned long j_diff;
         unsigned long curr_percent = 0, max_percent = 0, sum_percent = 0, pg_fault_cnt, pg_fault_avg, pg_fault_max; 
-        pcpuidle->last_value       = get_cycles();
+        pcpuidle->last_value       = avm_get_cycles();
         if(pcpuidle->fullrun == 0) {
             unsigned int i;
             pcpuidle->actrun = 100;
@@ -296,10 +274,9 @@
             } else {
                 pg_fault_avg = 0;
             }
-            printk(KERN_WARNING"[%u]system-load %d %s loadavg %lu.%lu %lu.%lu %lu.%lu - %d tasks:%lu %% curr:%s(%lu %%) max:%s(%lu %%, pid:%d), readytorun: %ld"
+            printk(KERN_WARNING"system-load %d %s loadavg %lu.%lu %lu.%lu %lu.%lu - %d tasks:%lu %% curr:%s(%lu %%) max:%s(%lu %%, pid:%d), readytorun: %ld"
                     ", pgfault %lu/s (max %lu avg %lu.%lu)"
                     "\n", 
-                    cpu,
                     pcpuidle->fullrun >= 10 ? 100 : pcpuidle->fullrun,
                     pcpuidle->fullrun >= 10 ? "%" : "",
                     LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
@@ -328,7 +305,7 @@
  * trigger powermanagment to inform about idle-rate
 \*--------------------------------------------------------------------------------*/
 void avm_cpu_wait_info(void) {
-    unsigned int cpu =  smp_processor_id();
+    unsigned int cpu =  raw_smp_processor_id();
     struct _cpu_idlecount *pcpuidle = &cpu_idlecount[cpu];
     register unsigned int sum_count =  pcpuidle->sum_count;
     unsigned int cpu_run = 0;
@@ -356,3 +333,10 @@
         pcpuidle->run_count  >>= 8;
     }
 }
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+int __init avm_cpu_process_init(void) {
+    gCycle_per_10sec = (unsigned long long)avm_get_cyclefreq() * 10ULL;
+    return 0;
+}
+__initcall(avm_cpu_process_init);
--- linux-2.6.28/drivers/char/avm_power/avm_power_cpuidle.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_cpuidle.c
@@ -73,8 +73,9 @@
 \*--------------------------------------------------------------------------------*/
 int avm_power_cpuidle_init(void){
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
-    cpu_idle_eventhandle =  avm_event_source_register( "cpu_idle", (
-                                                   (((unsigned long long) 1) << avm_event_id_cpu_idle)),
+	struct _avm_event_id_mask id_mask;
+    cpu_idle_eventhandle =  avm_event_source_register( "cpu_idle",
+												   avm_event_build_id_mask(&id_mask, 1, avm_event_id_cpu_idle),
                                                    avmevent_cpu_idle_notify,
                                                    &pm_ressourceinfo
                                                    );
--- linux-2.6.28/drivers/char/avm_power/avm_power_dsl.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_dsl.c
@@ -52,7 +52,7 @@
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
     avm_event_powermanagment_status_notify(&powermanagment_status_event, avm_event_id_powermanagment_status);
 #endif/*--- #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE)  ---*/
-    if(pm_ressourceinfo.thread_pid) {
+    if(pm_ressourceinfo.kthread) {
         /*--- triggere thread  ---*/
         pm_ressourceinfo.Changes++;
         wake_up_interruptible(&pm_ressourceinfo.wait_queue);
@@ -62,10 +62,11 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 int avm_power_dsl_init(void) {
+	struct _avm_event_id_mask id_mask;
     int ret = 0;
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
-    powermanagment_status_event.handle = avm_event_source_register( "powermanagment_status", (
-                                           (((unsigned long long) 1) << avm_event_id_powermanagment_status)),
+    powermanagment_status_event.handle = avm_event_source_register( "powermanagment_status",
+										   avm_event_build_id_mask(&id_mask, 1, avm_event_id_powermanagment_status),
                                            avm_event_powermanagment_status_notify,
                                            &powermanagment_status_event
                                            );
--- linux-2.6.28/drivers/char/avm_power/avm_power_file.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_file.c
@@ -82,7 +82,7 @@
 #define IDLE_MODE    "IDLE_MODE"
 #define LOAD_MODE    "LOAD_MODE"
 
-int avm_power_disp_loadrate = 0; 
+unsigned int avm_power_disp_loadrate = 0; 
 
 /*-----------------------------------------------------------------------------------------------*\
 \*-----------------------------------------------------------------------------------------------*/
@@ -194,7 +194,9 @@
 \*------------------------------------------------------------------------------------------*/
 static ssize_t avm_power_write(struct file *filp, const char *write_buffer, size_t write_length, loff_t *write_pos) {
     char Buffer[256], *p;
-    unsigned int org_write_length __attribute__((unused));
+#if defined(AVM_POWER_DEBUG)
+    unsigned int org_write_length;
+#endif
     struct _power_managment_dest_entry *powermodetab __attribute__((unused)) = NULL; 
 #if defined(CONFIG_FUSIV_VX180)
     int Mask;
@@ -203,7 +205,9 @@
     if(write_pos != NULL) {
         DEB_INFO("[%s]: %s write_length = %u *write_pos = 0x%LX\n", MODULE_NAME,  __func__, write_length, *write_pos);
     }
+#if defined(AVM_POWER_DEBUG)
     org_write_length = write_length;
+#endif
 
     if(write_length >= sizeof(Buffer)) {
         write_length = sizeof(Buffer) - 1;
@@ -395,7 +399,7 @@
     int bytesRead;
 
     fp = filp_open(filename, O_RDONLY, 00);
-    if(IS_ERR(fp)) {
+    if(IS_ERR(fp) || (fp->f_op == 0)) {
         str[0] = 0;
         /*--- printk(KERN_ERR " failed: open: %s\n", filename); ---*/
         return 0;
--- linux-2.6.28/drivers/char/avm_power/avm_power.h
+++ linux-2.6.28/drivers/char/avm_power/avm_power.h
@@ -110,6 +110,7 @@
     unsigned long rate_battcharge;
     unsigned long rate_usbhost;
     unsigned long rate_lte;
+    unsigned long rate_dvbc;
     long messure_count; /*--- Anzahl der Messungen ---*/
     signed long rate_temp;
     signed char min_temp;
@@ -122,7 +123,7 @@
 struct _power_managment_ressource_info {
     struct _power_managment_device_info deviceinfo[powerdevice_maxdevices];
     unsigned int NormP;             /*--- Norm-Leistungsverbrauch (entspricht 100 %) ---*/
-    struct task_struct *thread_pid;
+    volatile struct task_struct *kthread;
     struct completion on_exit;
     wait_queue_head_t wait_queue;
     void *event_handle;
@@ -198,7 +199,7 @@
 /*--------------------------------------------------------------------------------*\
  * avm_power_file.c
 \*--------------------------------------------------------------------------------*/
-extern int avm_power_disp_loadrate; 
+extern unsigned int avm_power_disp_loadrate; 
 extern int avm_power_file_init(void);
 extern void avm_power_file_exit(void);
 unsigned int avm_power_read_from_file(char *filename, char *str, int maxlen);
@@ -305,6 +306,7 @@
         case powerdevice_vdsp_loadrate: return "powerdevice_vdsp_loadrate";
         case powerdevice_lte:           return "powerdevice_lte";
         case powerdevice_loadrate2:     return "powerdevice_loadrate2";
+        case powerdevice_dvbc:          return "powerdevice_dvbc";
         case powerdevice_maxdevices:    return "powerdevice_maxdevices";
     }
     return "powerdevice_unknown";
--- linux-2.6.28/drivers/char/avm_power/avm_power_if.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_if.c
@@ -656,17 +656,53 @@
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 /*--------------------------------------------------------------------------------*\
+ * aktuell max. 4 CPU's
 \*--------------------------------------------------------------------------------*/
 static inline unsigned int cpusloadrate_to_powerrate(unsigned int cpuspowerrate) {
-    unsigned int i;
+    unsigned int cpu, norm = 0;
     unsigned int run = 0;
-    for(i = 0; i < NR_CPUS; i++) {
-        run += cpuspowerrate & 0xFF;
+
+    for(cpu = 0; cpu < NR_CPUS; cpu++) {
+        if (cpu_online(cpu)) {
+            norm++;
+            run += cpuspowerrate & 0xFF;
+        }
         cpuspowerrate >>= 8;
     }
-    return run / NR_CPUS;
+    if(norm == 0) {
+        return norm;
+    }
+    return run / norm;
 }
+/*--------------------------------------------------------------------------------*\
+ * aktuell max. 4 CPU's
+\*--------------------------------------------------------------------------------*/
+static char *display_per_cpurate(char *txt, int txt_len, unsigned int cpuspowerrate) {
+    unsigned int cpu, len, run;
+    char idle_txt[64], *pidle_txt = idle_txt;
+    char run_txt[64], *prun_txt   = run_txt;
+    unsigned int idle_txt_len = sizeof(idle_txt);
+    unsigned int run_txt_len  = sizeof(run_txt);
 
+    idle_txt[0] = 0;
+    run_txt[0]  = 0;
+    for(cpu = 0; cpu < NR_CPUS; cpu++) {
+        if(cpu_online(cpu)) {
+            run = cpuspowerrate & 0xFF;
+            if(idle_txt_len) {
+                len = snprintf(pidle_txt, idle_txt_len, "%s%u", idle_txt[0] ? "/" : "", 100 - run);
+                idle_txt_len -= len, pidle_txt += len;
+            }
+            if(run_txt_len) {
+                len = snprintf(prun_txt, run_txt_len, "%s%u", run_txt[0] ? "/" : "", run);
+                run_txt_len -= len, prun_txt += len;
+            }
+        }
+        cpuspowerrate >>= 8;
+    }
+    snprintf(txt, txt_len, "idle: %s %% (%s %%)", idle_txt, run_txt);
+    return txt;
+}
 /*--------------------------------------------------------------------------------*\
  * Funktion wird von Treibern aufgerufen um Infos ueber den aktuellen Power-Status zu liefern
 \*--------------------------------------------------------------------------------*/
@@ -678,7 +714,7 @@
         DEB_ERR("[avm_power]PowerManagmentRessourceInfo: unknown device: %d\n", device);
         return 0;
     }
-    ready =  pm_ressourceinfo.thread_pid ? 1 : 0;
+    ready =  pm_ressourceinfo.kthread ? 1 : 0;
 #if defined(DECTSYNC_PATCH)
     if(device == powerdevice_dectsync) {
         if(ready == 0) {
@@ -709,7 +745,7 @@
 #endif/*--- #if defined(DECTSYNC_PATCH) ---*/
     if(device == powerdevice_loadrate) {
         cpus_loadrate = power_rate;
-        power_rate = cpusloadrate_to_powerrate(cpus_loadrate);
+        power_rate    = cpusloadrate_to_powerrate(cpus_loadrate);
         pm_ressourceinfo.loadcntrl = avm_powermanager_load_control_handler(power_rate);
 #if defined(DECTSYNC_PATCH)
         {
@@ -731,26 +767,16 @@
 #if defined(DECTSYNC_PATCH)
             if(display_dectsync(pm_ressourceinfo.loadcntrl)) {
 #endif/*--- #else ---*//*--- #if defined(DECTSYNC_PATCH) ---*/
+                char txt[64];
                 unsigned long avnrun[3];
                 get_avenrun(avnrun, FIXED_1/200, 0);
-#if NR_CPUS == 2
-                printk(KERN_ERR"idle: %d/%d %%(%d/%d %%) loadavg %lu.%lu %lu.%lu %lu.%lu loadcntrl 0x%x\n", 
-                                       100 - ((cpus_loadrate >> 0) & 0xFF), 100 - ((cpus_loadrate >> 8) & 0xFF), 
-                                       (cpus_loadrate >> 0) & 0xFF, (cpus_loadrate >> 8) & 0xFF, 
+                printk(KERN_ERR"%s loadavg %lu.%lu %lu.%lu %lu.%lu loadcntrl 0x%x\n", 
+                                       display_per_cpurate(txt, sizeof(txt), cpus_loadrate),
                                        LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
                                        LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]),
                                        LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]),
                                        pm_ressourceinfo.loadcntrl
                                        );
-#else
-                printk(KERN_ERR"[%lu]idle: %d %%(%d %%) loadavg %lu.%lu %lu.%lu %lu.%lu loadcntrl 0x%x\n", jiffies, 
-                                    100 - power_rate, power_rate, 
-                                    LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
-                                    LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]),
-                                    LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]),
-                                    pm_ressourceinfo.loadcntrl);
-#endif
-
 #if defined(DECTSYNC_PATCH)
             }
 #endif/*--- #if defined(DECTSYNC_PATCH) ---*/
--- linux-2.6.28/drivers/char/avm_power/avm_power_pminfo.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_pminfo.c
@@ -136,6 +136,7 @@
     int rate_battcum = 0; 
     int rate_usbhostcum = 0; 
     int rate_ltecum = 0; 
+    int rate_dvbccum = 0;
     int rate_temp = 0;
     signed char min_temp, max_temp; 
 
@@ -163,6 +164,7 @@
             pcum->rate_battcharge   =  PM_CALC_SUM(pcum->rate_battcharge, pm_info->stat.rate_battchargeact, tail_messure);
             pcum->rate_usbhost      =  PM_CALC_SUM(pcum->rate_usbhost,    pm_info->stat.rate_usbhostact,   tail_messure);
             pcum->rate_lte          =  PM_CALC_SUM(pcum->rate_lte,    pm_info->stat.rate_lteact,   tail_messure);
+            pcum->rate_dvbc         =  PM_CALC_SUM(pcum->rate_dvbc,   pm_info->stat.rate_dvbcact,  tail_messure);
             pcum->rate_temp         =  PM_CALC_SUM(pcum->rate_temp, pm_info->stat.act_temperature,   tail_messure);
 
             if(pcum->min_temp > pm_info->stat.act_temperature){
@@ -202,6 +204,7 @@
             rate_battcum    += pcum->rate_battcharge;
             rate_usbhostcum += pcum->rate_usbhost;
             rate_ltecum     += pcum->rate_lte;
+            rate_dvbccum    += pcum->rate_dvbc;
             rate_temp       += pcum->rate_temp;
             if(min_temp > pcum->min_temp){
                 min_temp = pcum->min_temp;
@@ -224,6 +227,7 @@
         pm_info->stat.rate_battchargecum = (unsigned char)min(100, rate_battcum    / intervall);  /*--- kumulierter Verbrauch Battery-Charge in Prozent ---*/
         pm_info->stat.rate_usbhostcum    = (unsigned char)min(100, rate_usbhostcum / intervall);  /*--- kumulierter Verbrauch USB-Host in Prozent ---*/
         pm_info->stat.rate_ltecum        = (unsigned char)min(100, rate_ltecum     / intervall);  /*--- kumulierter Verbrauch LTE in Prozent ---*/
+        pm_info->stat.rate_dvbccum       = (unsigned char)min(100, rate_dvbccum    / intervall);  /*--- kumulierter Verbrauch DVB-C in Prozent ---*/
         pm_info->stat.avg_temperature    = rate_temp / intervall;
         pm_info->stat.min_temperature    = min_temp;
         pm_info->stat.max_temperature    = max_temp;
@@ -297,7 +301,6 @@
     int init = 1, activ_ethports, i;
 #endif/*--- #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE)  ---*/
     /*--- DEB_ERR("[avm_power]pm_ressourceinfo_thread: start\n"); ---*/
-    allow_signal(SIGTERM ); 
 	while (!kthread_should_stop()) {
         if(wait_event_interruptible( pm_info->wait_queue, pm_info->Changes)){
             break;
@@ -383,9 +386,10 @@
         pm_info->stat.rate_usbhostact    = (unsigned char) usbmwatt;
         pm_info->stat.usb_status         = PM_GET_RATE(pm_info->deviceinfo[powerdevice_usb_client].power_rate) ? 1 : 0;  /*--- USB-Client connected ---*/
         pm_info->stat.rate_lteact        = PM_GET_NORM_MWATT(&pm_info->deviceinfo[powerdevice_lte]);                 /*--- aktueller Verbrauch LTE Prozent ---*/
+        pm_info->stat.rate_dvbcact       = PM_GET_RATE(pm_info->deviceinfo[powerdevice_dvbc].power_rate);                 /*--- aktueller Verbrauch LTE Prozent ---*/
         avm_power_speedstep_mode();
-#if 0
-        printk(KERN_DEBUG"SUM:%d(%d) SYST:%d(%d)-%x DSP:%d(%d) WLAN:%d(%d)-%d-%x ETH:%d(%d)-%x ISDN:%x AB:%d(%d) DECT:%d(%d) USB:%d(%d)-%x TEMP(%d, %d min %d max %d) want:%d\n",
+        if(avm_power_disp_loadrate & 0x20) {
+            printk(KERN_DEBUG"SUM:%d(%d) SYST:%d(%d)-%x DSP:%d(%d) WLAN:%d(%d)-%d-%x ETH:%d(%d)-%x ISDN:%x AB:%d(%d) DECT:%d(%d) USB:%d(%d)-%x TEMP(%d, %d min %d max %d) want:%d\n",
                  pm_info->stat.rate_sumact,    pm_info->stat.rate_sumcum,
                  pm_info->stat.rate_systemact, pm_info->stat.rate_systemcum, pm_info->stat.system_status,
                  pm_info->stat.rate_dspact,    pm_info->stat.rate_dspcum,
@@ -398,15 +402,17 @@
                  pm_info->stat.act_temperature, pm_info->stat.avg_temperature, pm_info->stat.min_temperature, pm_info->stat.max_temperature,
                  avm_event_source_check_id(pm_info->event_handle, avm_event_id_pm_ressourceinfo_status)
               );
-#endif
+        }
 #endif/*--- #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE)  ---*/
     }
+    pm_ressourceinfo.kthread = NULL;
     DEB_ERR("[avm_power]pm_ressourceinfo_thread: exit\n");
 	return 0;
 }
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 int pm_ressourceinfo_init(void) {
+	struct _avm_event_id_mask id_mask;
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
     int i;
 #endif/*--- #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE)  ---*/
@@ -420,14 +426,14 @@
         pm_ressourceinfo.deviceinfo[powerdevice_systemclock].power_rate = FREQUENZ_TO_PERCENT(STD_SYSTEMCLK, MAX_SYSTEMCLK);
     }
     init_waitqueue_head(&pm_ressourceinfo.wait_queue);
-	pm_ressourceinfo.thread_pid = kthread_run(pm_ressourceinfo_thread, (void *) &pm_ressourceinfo, "pm_info");
-	BUG_ON((pm_ressourceinfo.thread_pid == NULL) || IS_ERR(pm_ressourceinfo.thread_pid));
+	pm_ressourceinfo.kthread = kthread_run(pm_ressourceinfo_thread, (void *) &pm_ressourceinfo, "pm_info");
+	BUG_ON((pm_ressourceinfo.kthread == NULL) || IS_ERR((void *)pm_ressourceinfo.kthread));
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
     for(i = 0; i < AVMPOWER_MAX_ETHERNETPORTS; i++) {
         pm_ressourceinfo.eth_status[i] = 2; /*--- auf normal vorinitialisieren ---*/
     }
-    pm_ressourceinfo.event_handle = avm_event_source_register( "pm_info_stat", (
-                                              (((unsigned long long) 1) << avm_event_id_pm_ressourceinfo_status)),
+    pm_ressourceinfo.event_handle = avm_event_source_register( "pm_info_stat", 
+											   avm_event_build_id_mask(&id_mask, 1, avm_event_id_pm_ressourceinfo_status),
                                                pm_ressourceinfo_notify,
 											  &pm_ressourceinfo
 											  );
@@ -442,9 +448,8 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 void pm_ressourceinfo_exit(void) {
-    if(pm_ressourceinfo.thread_pid) {
-        kthread_stop(pm_ressourceinfo.thread_pid);
-        pm_ressourceinfo.thread_pid = NULL;
+    if(pm_ressourceinfo.kthread) {
+        kthread_stop((struct task_struct *)pm_ressourceinfo.kthread);
     }
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
     if(pm_ressourceinfo.event_handle) { 
--- linux-2.6.28/drivers/char/avm_power/avm_power_remote_sink.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_remote_sink.c
@@ -71,14 +71,14 @@
 \*--------------------------------------------------------------------------------*/
 int avm_power_remote_sink_init(void) {
 #if defined(CONFIG_AVM_EVENT)
+	struct _avm_event_id_mask id_mask;
+
     if(powermanagment_remote_event_sink_handle) {
         printk(KERN_ERR"%s already registered\n", __func__);
         return 0;
     }
     powermanagment_remote_event_sink_handle = avm_event_sink_register("powermanagment_remote_sink",
-                                                                      (1ULL << avm_event_id_powermanagment_remote)|
-                                                                      /*--- (1ULL << avm_event_id_telefonprofile) | ---*/
-                                                                      0,
+																	   avm_event_build_id_mask(&id_mask, 1, avm_event_id_powermanagment_remote),
                                                                        avm_event_powermanagment_remote_sink,
                                                                       NULL
                                                                      );
--- linux-2.6.28/drivers/char/avm_power/avm_power_remote_source.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_remote_source.c
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/avm_power.h>
-#include <linux/avm_event.h>
+#include <linux/kthread.h>
 #include "avm_power.h"
 
 /*--- #define DEBUG_AVM_POWER ---*/
@@ -37,8 +37,7 @@
 \*--------------------------------------------------------------------------------*/
 struct _pw_remote_source  {
     unsigned int Changes;
-    struct task_struct *thread_pid;
-    struct completion on_exit;
+    volatile struct task_struct *kthread;
     wait_queue_head_t wait_queue;
     void *remote_event_handle;
 } pw_remote_source;
@@ -66,25 +65,22 @@
 static int remote_source_thread(void *data) {
     struct _pw_remote_source *pwrs  = (struct _pw_remote_source *)data;
     /*--- DEB_ERR("[%s]: start\n", __func__); ---*/
-    pwrs->thread_pid = current;
-    daemonize("pm_remote");
-    allow_signal(SIGTERM ); 
-    for(;;) {
+	while (!kthread_should_stop()) {
         if(wait_event_interruptible_timeout( pwrs->wait_queue, pwrs->Changes, 5 * HZ)){
             break;
         }
         pwrs->Changes = 0;
         PowerManagmentRessourceInfo(powerdevice_temperature, avm_power_temperature());
     }
-    pwrs->thread_pid = NULL;
+    pwrs->kthread = NULL;
     /*--- DEB_ERR("[%s]: exit\n", __func__); ---*/
-    complete_and_exit(&pwrs->on_exit, 0 );
+	return 0;
 }
 #if 0
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 static void remote_source_thread_trigger(void) {
-    if(pw_remote_source.thread_pid) {
+    if(pw_remote_source.kthread) {
         pw_remote_source.Changes++;
         wake_up_interruptible(&pw_remote_source.wait_queue);
     }
@@ -94,19 +90,20 @@
 \*--------------------------------------------------------------------------------*/
 int avm_power_remote_source_init(void) {
 #if defined(CONFIG_AVM_EVENT)
+	struct _avm_event_id_mask id_mask;
     int ret = 0;
     if(pw_remote_source.remote_event_handle) {
         return ret;
     }
     init_waitqueue_head(&pw_remote_source.wait_queue);
-    init_completion(&pw_remote_source.on_exit );
-	kernel_thread(remote_source_thread, (void *) &pw_remote_source, CLONE_SIGHAND);
+	pw_remote_source.kthread = kthread_run(remote_source_thread, (void *) &pw_remote_source, "pm_remote");
+	BUG_ON((pw_remote_source.kthread == NULL) || IS_ERR((void *)pw_remote_source.kthread));
 
-    pw_remote_source.remote_event_handle = avm_event_source_register( "powermanagment_remote", (
-                               (((unsigned long long) 1) << avm_event_id_powermanagment_remote)),
-                               avm_event_powermanagment_remote_notify,
-                               NULL
-                               );
+    pw_remote_source.remote_event_handle = avm_event_source_register( "powermanagment_remote", 
+																	avm_event_build_id_mask(&id_mask, 1, avm_event_id_powermanagment_remote),
+																	avm_event_powermanagment_remote_notify,
+																	NULL
+																    );
     if(pw_remote_source.remote_event_handle == NULL) {
         ret = -1;
         printk(KERN_ERR"[avm_power]%s not registered\n", __func__);
@@ -120,10 +117,8 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 void avm_power_remote_source_exit(void) {
-    if(pw_remote_source.thread_pid) {
-		send_sig(SIGTERM, pw_remote_source.thread_pid, 1);
-        pw_remote_source.thread_pid = NULL;
-        wait_for_completion(&pw_remote_source.on_exit);
+    if(pw_remote_source.kthread) {
+        kthread_stop((struct task_struct *)pw_remote_source.kthread);
     }
     if(pw_remote_source.remote_event_handle) {
         avm_event_source_release(pw_remote_source.remote_event_handle);
--- linux-2.6.28/drivers/char/avm_power/avm_power_speedstep.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_speedstep.c
@@ -26,7 +26,7 @@
     mm_segment_t oldfs;
 
     fp = filp_open(filename, O_WRONLY, 00);
-    if(IS_ERR(fp)) {
+    if(IS_ERR(fp) || (fp->f_op == 0)) {
         /*--- printk(KERN_ERR " failed: open : %s\n", filename); ---*/
         return;
     }
--- linux-2.6.28/drivers/char/avm_power/avm_power_telefon.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_telefon.c
@@ -95,6 +95,7 @@
 /*--------------------------------------------------------------------------------*\
 \*--------------------------------------------------------------------------------*/
 int avm_power_telefon_init(void){
+	struct _avm_event_id_mask id_mask;
     int ret = 0;
 #if defined(DECTSYNC_PATCH)
     if(request_resource(&gpio_resource, &dectsync_gpioressource)) {
@@ -102,8 +103,8 @@
     }
 #endif/*--- #if defined(DECTSYNC_PATCH) ---*/
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
-    telefonevent.handle =  avm_event_source_register( "telefonprofile", (
-                           (((unsigned long long) 1) << avm_event_id_telefonprofile)),
+    telefonevent.handle =  avm_event_source_register( "telefonprofile", 
+                           avm_event_build_id_mask(&id_mask, 1, avm_event_id_telefonprofile),
                            avmevent_telefonprofile_notify,
 						   &telefonevent
 						   );
--- linux-2.6.28/drivers/char/avm_power/avm_power_temperature.c
+++ linux-2.6.28/drivers/char/avm_power/avm_power_temperature.c
@@ -51,7 +51,7 @@
         /*--- unter Null Grad wird der Chip sowieso nicht arbeiten ... ---*/
         rest = 0;
     }
-    /*--- printk("[avm_power]temp %d\n", temperature + rest); ---*/
+    /*--- printk(KERN_INFO"[avm_power]temp %d\n", temperature + rest); ---*/
     return temperature + rest; 
 }
 #elif defined(CONFIG_X86)
@@ -66,6 +66,32 @@
     }
     return temperature;
 }
+#elif defined(CONFIG_SOC_GRX500) 
+#include <asm/mach_avm.h>
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline int arch_get_temperature(void) {
+    int rest, chan;
+    int max_temperature = -40;
+
+    for(chan = 0; chan < 2; chan++) {
+        int temperature = grx_get_chip_temperature(chan);
+        if(max_temperature < temperature) {
+            max_temperature = temperature;
+        }
+    }
+    rest = max_temperature % 3;
+    max_temperature /= 4;
+    if(rest >= 2)  {
+        /*--- aufrunden ---*/
+        rest = 1;
+    } else {
+        /*--- unter Null Grad wird der Chip sowieso nicht arbeiten ... ---*/
+        rest = 0;
+    }
+    /*--- printk(KERN_INFO"[avm_power]temp %d\n", max_temperature + rest); ---*/
+    return max_temperature + rest;
+}
 #else
 /*--------------------------------------------------------------------------------*\
  * Temperatursensor nicht unterstuetzt
@@ -113,8 +139,9 @@
 \*--------------------------------------------------------------------------------*/
 int avm_power_temperature_init(void){
 #if defined(CONFIG_AVM_EVENT) || defined(CONFIG_AVM_EVENT_MODULE) 
-    temperature_eventhandle =  avm_event_source_register( "temperature", (
-                                                   (((unsigned long long) 1) << avm_event_id_temperature)),
+	struct _avm_event_id_mask id_mask;
+    temperature_eventhandle =  avm_event_source_register( "temperature",
+												   avm_event_build_id_mask(&id_mask, 1, avm_event_id_temperature),
                                                    avmevent_temperature_notify,
                                                    NULL
                                                    );
--- linux-2.6.28/drivers/char/avm_power/dectsync.h
+++ linux-2.6.28/drivers/char/avm_power/dectsync.h
@@ -9,5 +9,5 @@
 int updaterun_dectsync(int run);
 int display_dectsync(int loadcontrol);
 
-extern int avm_power_disp_loadrate; 
+extern unsigned int avm_power_disp_loadrate; 
 #endif/*--- #ifndef __dectsync_h__ ---*/
--- /dev/null
+++ linux-2.6.28/drivers/char/avm_power/Kconfig
@@ -0,0 +1,44 @@
+#
+# AVM Powermanagment
+#
+#
+#
+menu "AVM Powermanagment"
+
+config AVM_POWER
+	bool "AVM power managment support"
+	default y
+	help
+	  This driver provides power managment functions for AVMs own drivers. Allow to set(and get) relevant power,bitfile,eth and other control-states.
+
+config AVM_POWERMETER
+	bool "AVM powermeter support"
+    depends on AVM_POWER
+	default y
+	help
+      This driver provides power managment ressource info function for AVMs own drivers. Collect dsl,temperature,power,idle,eth,usb,memory-state and send avm_events.
+
+config AVM_POWER_REMOTE_SOURCE
+	bool "Powermanagment Remote-Source"
+    depends on AVM_POWER && AVM_EVENTNODE_PUMA6
+	default y
+	help
+	  This powermanager service send messages to other cpu
+
+config AVM_POWER_REMOTE_SINK
+	bool "Powermanagment Remote-Sink"
+    depends on AVM_POWER && AVM_EVENTNODE_PUMA6
+	default y
+	help
+	  This powermanager service receive messages from other cpu
+
+
+config AVM_DECT_SYNC
+	int "AVM dect sync support"
+	depends on AVM_POWER && AVM_DECT_IO && MIPS_UR8
+	default -1
+	help
+      Zerberus - obsolet
+	  the number of gpio for sync-usage, -1: ignore sync
+
+endmenu
--- linux-2.6.28/drivers/char/avm_power/linux_avm_power.h
+++ linux-2.6.28/drivers/char/avm_power/linux_avm_power.h
@@ -186,7 +186,8 @@
     powerdevice_vdsp_loadrate = 20,       /*--- Voice-DSP power_rate in % (100 - % Idle-Wert) ---*/    
     powerdevice_lte           = 21,       /*--- power_rate in Milliwatt ---*/
     powerdevice_loadrate2     = 22,       /*--- remote-cpu power_rate in % (100 - % Idle-Wert) falls SMP: je 8 Bit eine CPU ---*/    
-    powerdevice_maxdevices    = 23
+    powerdevice_dvbc          = 23,       /*--- power_rate in % (100 - % Idle-Wert) ---*/
+    powerdevice_maxdevices    = 24
 };
 #endif /*--- #if !defined(CONFIG_AVM_EVENT_20) ---*/
 
@@ -261,19 +262,20 @@
  * call by start of mm-fault-handler
 \*--------------------------------------------------------------------------------*/
 static inline void avm_page_statistic_fault_get(void) {
-    atomic_inc(&avm_page_faultlink[smp_processor_id()]);
+    atomic_inc(&avm_page_faultlink[raw_smp_processor_id()]);
 }
 /*--------------------------------------------------------------------------------*\
  * call by end of mm-fault-handler
 \*--------------------------------------------------------------------------------*/
 static inline void avm_page_statistic_fault_put(void) {
-    unsigned int cpu=  smp_processor_id();
+    unsigned int cpu=  raw_smp_processor_id();
     int max = atomic_dec_return(&avm_page_faultlink[cpu]) + 1;
-
-    if(unlikely(max > avm_page_faultlink_max[cpu])) {
-        avm_page_faultlink_max[cpu] = max;
+    if(max > 0) {
+        if(unlikely(max > avm_page_faultlink_max[cpu])) {
+            avm_page_faultlink_max[cpu] = max;
+        }
+        avm_page_faultlink_sum[cpu] += max;
     }
-    avm_page_faultlink_sum[cpu] += max;
     avm_page_faultlink_cnt[cpu]++;
 }
 #endif /*--- #if defined(__KERNEL__) ---*/
--- linux-2.6.28/drivers/char/avm_power/temperature_policy.c
+++ linux-2.6.28/drivers/char/avm_power/temperature_policy.c
@@ -194,24 +194,26 @@
     local_irq_disable();
     dvpe();
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
-	vprintk_restore();
+    printk_avm_console_bend(0); /* force serial-output */
 #else
 	restore_printk();
 #endif
-    /*--- printk_sync(KERN_ERR"%s cpu=%x\n", __func__, smp_processor_id());  ---*/
+    /*--- printk_sync(KERN_ERR"%s cpu=%x\n", __func__, raw_smp_processor_id());  ---*/
     init_leds();
     AVM_WATCHDOG_disable(0, NULL, 0);
     for(;;) {
         if((read_c0_count() - last_cycle) > MSEC_TO_CLK(1000U)) {
             last_cycle = read_c0_count();
             jiffies   += HZ;
-            ifx_ts_get_temp(&temperature);
+            if(ifx_ts_get_temp(&temperature)){
+                temperature = 0;
+            } 
             temperature /= 10;
             if(temperature < CHILLED_TEMPERATURE) {
                 panic("chilled: t%d\n", temperature);
             }
             if(abs(temperature - old_temperature) > 3) {
-                printk(KERN_ERR"[%x]<machine stopped:t%d>\n", smp_processor_id(), temperature);
+                printk(KERN_ERR"[%x]<machine stopped:t%d>\n", raw_smp_processor_id(), temperature);
                 old_temperature = temperature;
             }
             toogle_leds();
--- linux-2.6.28/drivers/char/dect_io/init_dect_io
+++ linux-2.6.28/drivers/char/dect_io/init_dect_io
@@ -9,7 +9,7 @@
 
 for i in `find . -name Makefile.$KERNEL_CLASS` ; do
     dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
+    source="${i##*/}"
     rm -f $dest
     ln -fvs $source $dest
 done
--- linux-2.6.28/drivers/char/flash_update/init_flash_update
+++ linux-2.6.28/drivers/char/flash_update/init_flash_update
@@ -9,7 +9,7 @@
 
 for i in `find . -name Makefile.$KERNEL_CLASS` ; do
     dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
+    source="${i##*/}"
     rm -f $dest
     ln -fvs $source $dest
 done
--- linux-2.6.28/drivers/char/n_tty.c
+++ linux-2.6.28/drivers/char/n_tty.c
@@ -1495,6 +1495,7 @@
  *	This code must be sure never to sleep through a hangup.
  */
 
+unsigned int g_avm_console_open;
 static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
 			  const unsigned char *buf, size_t nr)
 {
@@ -1510,6 +1511,13 @@
 			return retval;
 	}
 
+    if (tty->driver->ops->is_avm_console) {
+        if (( ! g_avm_console_open) && tty->driver->ops->is_avm_console(tty)) {
+            b += nr;
+            goto skip_out;
+        }
+    }
+
 	add_wait_queue(&tty->write_wait, &wait);
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1565,6 +1573,7 @@
 break_out:
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&tty->write_wait, &wait);
+skip_out:
 	return (b - buf) ? b - buf : retval;
 }
 
@@ -1664,3 +1673,13 @@
 	.write_wakeup    = n_tty_write_wakeup
 };
 
+/*------------------------------------------------------------------------------------------*\
+ * keine Ausgaben auf der Console ohne g_avm_console_open=1
+ * n_tty_read schaltet die Ausgaben auf der Console wieder frei
+ * beim Kunden wird kein Read auf der Console erfolgen, also gibt es auch keine Ausgaben
+\*------------------------------------------------------------------------------------------*/
+static int setup_debug_console(char *p) {
+    g_avm_console_open = 1;
+    return 0;
+}
+__setup("debug_console", setup_debug_console);
--- linux-2.6.28/drivers/char/tffs-2.0/Makefile
+++ linux-2.6.28/drivers/char/tffs-2.0/Makefile
@@ -29,3 +29,21 @@
 ifdef CONFIG_FUSIV_VX180
 obj-$(CONFIG_TFFS_PANIC_LOG) += tffs_direct_nor.o
 endif
+ifdef CONFIG_FUSIV_VX185
+obj-$(CONFIG_TFFS_PANIC_LOG) += tffs_direct_spi_vx185.o
+endif
+
+extra-y         += supportdata
+
+quiet_cmd_install = INSTALL $< -> $@
+	cmd_install = ( test -d $(dir $@) || mkdir -p $(dir $@) ) && cp -p $< $@
+
+quiet_cmd_set_executable = CHMOD+x $@
+	cmd_set_executable = chmod +x $@
+      
+$(INSTALL_MOD_PATH)/bin/supportdata.tffs: $(src)/supportdata.tffs
+	$(call if_changed,install)
+	$(call if_changed,set_executable)
+
+PHONY+=$(obj)/supportdata
+$(obj)/supportdata: $(INSTALL_MOD_PATH)/bin/supportdata.tffs
--- /dev/null
+++ linux-2.6.28/drivers/char/tffs-2.0/supportdata.tffs
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+DUMP_DIR="/var/tmp/tffs-dump"
+ENC_CERT="/var/flash/test.cert"
+ENC_EXE="/bin/openssl_smime"
+
+if [ "`echo emailnotify.supportdata_enhanced | ar7cfgctl -s`" = yes ]
+then
+    for tffs in `sed -nr 'y/ /_/;s/^(mtd[0-9]+):.+"((nand-)*tffs(_\([12]\))*)"$/\2#\1/p' /proc/mtd`
+    do
+        mtd_dev="/dev/${tffs##*#}"
+        mtd_name="${tffs%%#*}"
+
+        mkdir -p "${DUMP_DIR}"
+        
+        case "${mtd_name}" in
+        nand-tffs*)
+            nanddump --bb=dumpbad --forcebinary --oob ${mtd_dev} | gzip -1 -c > "${DUMP_DIR}/${mtd_name}.dump.gz"
+            ;;
+        *)
+            cat ${mtd_dev} | gzip -1 -c  > "${DUMP_DIR}/${mtd_name}.dump.gz"
+            ;;
+        esac
+
+    done
+    
+    if [ -d "${DUMP_DIR}" ]
+    then
+        echo "##### BEGIN SECTION TFFS_DUMP TFFS Dump"
+        if [ -x "${ENC_EXE}" -a -e "${ENC_CERT}" ]
+        then
+            tar -c "${DUMP_DIR}" 2>/dev/null | \
+            ${ENC_EXE} -encrypt -binary -aes256 -subject tffs-dump.tar -outform SMIME "${ENC_CERT}"
+        else
+            tar -c "${DUMP_DIR}" 2>/dev/null | base64
+        fi
+        echo "##### END SECTION TFFS_DUMP"
+        rm -rf "${DUMP_DIR}"
+    fi
+fi
+
+if [ -e /proc/tffs -a -e /dev/debug ] ; then
+	echo index > /proc/tffs
+	
+	echo AVMDBG_EOF 1 >/dev/debug
+	
+	grep -E '\[TFFS\]' /dev/debug
+
+	echo AVMDBG_EOF 0 >/dev/debug
+
+fi
+
--- linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_nor.c
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_nor.c
@@ -218,7 +218,7 @@
     --pShort;
 
     /*------------------------------------------------------------------------------------------*\
-      toggle wurde eingeführt um einen sicheren Abbruch zu haben, wenn eine Zelle nicht 
+      toggle wurde eingeführt um einen sicheren Abbruch zu haben, wenn eine Zelle nicht
       programmiert werden kann - die MX-Mirrorbits antworten nicht mit Abort wenn in einer 
       Zelle 0x00 steht und mit 0x12 beschrieben wird
     \*------------------------------------------------------------------------------------------*/
@@ -361,7 +361,7 @@
 unsigned int tffs_direct_nor_init(void) {
 
     unsigned char *pchar;
-    unsigned int ret = FLASH_SUCCESS;
+    int ret = FLASH_SUCCESS;
     int i = 0;
     unsigned char addr;
     unsigned short bottom;
@@ -488,6 +488,7 @@
 
     } else  {
         __printk(KERN_ERR "<ERROR>: no valid Flash detected 0x%x\n", ret);
+        ret = -ENODEV;
     }
 
     return ret;
--- linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_spi_puma5.c
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_spi_puma5.c
@@ -335,7 +335,7 @@
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
-unsigned int tffs_spi_init(void) {
+int tffs_spi_init(void) {
 
 #if 0
     if(down_trylock(sfl_sema)) {
--- linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_spi_vr9.c
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_spi_vr9.c
@@ -463,7 +463,7 @@
 /*------------------------------------------------------------------------------------------*\
  * auf dem Demoboard nutzen wir SERIAL_CS1
 \*------------------------------------------------------------------------------------------*/
-unsigned int tffs_spi_init(void) {
+int tffs_spi_init(void) {
 
     unsigned int flash_data;
 
@@ -506,10 +506,10 @@
             break;
         default:
             DebugPrintf("[init_spi] <no valid flash detected>\n");
-            return FLASH_ID_FAILED;
+            return -ENODEV;
     }
 
-    return FLASH_SUCCESS;
+    return 0;
 
 }
 
--- /dev/null
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_direct_spi_vx185.c
@@ -0,0 +1,89 @@
+/*------------------------------------------------------------------------------------------*\
+ *   
+ *   Copyright (C) 2014 AVM GmbH <fritzbox_info@avm.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+\*------------------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------------------*\
+ * Quick'n'dirty hack to access SPI flash for TFFS in panic mode
+\*------------------------------------------------------------------------------------------*/
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <asm/fcntl.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+
+#define FLASH_SUCCESS           0
+#define FLASH_INVAL_ADDR        0x8002
+#define FLASH_ID_FAILED         0x8003
+#define FLASH_QUERY_FAILED      0x8004
+#define FLASH_ERASE_REGIONS     0x8005
+#define FLASH_MX_BOTTOM_FAILED  0x8006
+
+extern int vx185_snor_panic_reinit(void);
+extern struct mtd_info *fusiv_tffs_mtd[2];
+
+static unsigned int init_done = 0;
+
+int tffs_spi_read(unsigned int address, unsigned int mtd_id, unsigned char *pdata, unsigned int len)
+{
+    struct mtd_info *mtd;
+    size_t retlen;
+    int result;
+
+    mtd = fusiv_tffs_mtd[mtd_id];
+    retlen = 0;
+
+    result = mtd->read(mtd, address, len, &retlen, pdata);
+
+    return retlen;
+}
+
+/*------------------------------------------------------------------------------------------*\
+\*------------------------------------------------------------------------------------------*/
+int tffs_spi_write(unsigned int address, unsigned int mtd_id, unsigned char *pdata, unsigned int len)
+{
+    struct mtd_info *mtd;
+    size_t retlen;
+    int result;
+
+    mtd = fusiv_tffs_mtd[mtd_id];
+    retlen = 0;
+
+    result = mtd->write(mtd, address, len, &retlen, pdata);
+
+    return retlen;
+}
+
+int tffs_spi_init(void)
+{
+    int result = 0;
+    
+    if(!init_done){
+        if(fusiv_tffs_mtd[0] == NULL || fusiv_tffs_mtd[1] == NULL){
+            result = -ENODEV;
+        } else {
+            result = vx185_snor_panic_reinit();
+        }
+    }
+
+    return result;
+}
--- linux-2.6.28/drivers/char/tffs-2.0/tffs_local.h
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_local.h
@@ -41,7 +41,7 @@
 #endif
 #endif/*--- #if defined(CONFIG_AVM_EVENTNODE_PUMA6) ---*/
 extern unsigned int tffs_panic_mode;
-#if defined(CONFIG_TFFS_PANIC_LOG) && (defined(CONFIG_ARCH_PUMA5) || defined(CONFIG_VR9))
+#if defined(CONFIG_TFFS_PANIC_LOG) && (defined(CONFIG_ARCH_PUMA5) || defined(CONFIG_VR9) || defined(CONFIG_FUSIV_VX185))
 #define SPI_PANIC_LOG
 #endif
 
--- linux-2.6.28/drivers/char/tffs-2.0/tffs_open.c
+++ linux-2.6.28/drivers/char/tffs-2.0/tffs_open.c
@@ -56,10 +56,10 @@
 unsigned int tffs_panic_mode = 0;
 
 #ifdef DIRECT_NOR_PANIC_LOG
-unsigned int tffs_direct_nor_init(void);
+extern int tffs_direct_nor_init(void);
 #endif 
 #ifdef SPI_PANIC_LOG
-unsigned int tffs_spi_init(void);
+extern int tffs_spi_init(void);
 #endif
 
 extern struct semaphore tffs_mtd_sema;
@@ -166,7 +166,7 @@
             if(tffs_spi_init() < 0)
                 printk(KERN_ERR "[%s] ERROR: reinit of SPI Flash for failed. No panic log written!\n", __FUNCTION__);
 #endif
-#if defined(SPI_PANIC_LOG) && defined(CONFIG_VR9)
+#if defined(SPI_PANIC_LOG) && (defined(CONFIG_VR9) || defined(CONFIG_FUSIV_VX185))
             if(tffs_spi_mode) {
                 if(tffs_spi_init() < 0)
                     printk(KERN_ERR "[%s] ERROR: reinit of SPI Flash failed. No panic log written!\n", __FUNCTION__);
--- linux-2.6.28/drivers/isdn/avm_dect/init_avm_dect
+++ linux-2.6.28/drivers/isdn/avm_dect/init_avm_dect
@@ -9,7 +9,7 @@
 
 for i in `find . -name Makefile.$KERNEL_CLASS` ; do
     dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
+    source="${i##*/}"
     rm -f $dest
     ln -fvs $source $dest
 done
--- linux-2.6.28/drivers/isdn/capi_oslib/capi_pipe.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/capi_pipe.c
@@ -16,6 +16,7 @@
 #include "appl.h"
 #include "ca.h"
 
+extern void capi_oslib_trigger_rxwork(struct workqueue_struct *rxwork, void *conn);
 DEFINE_SPINLOCK(send_capi_pipe);
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
@@ -236,9 +237,9 @@
         wake_up_interruptible(P->rx_wait_queue);
         /*--- wake_up(P->rx_wait_queue); ---*/
 
-    if(P->scheduler_rx_work && pipe_workqueue)
-        queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, pipe_workqueue, P->scheduler_rx_work);
-
+    if(P->Conn && pipe_workqueue) { 
+		capi_oslib_trigger_rxwork(pipe_workqueue, P->Conn);  /*--- remote-capi  ---*/
+	}
     return 0;
 }
 
--- linux-2.6.28/drivers/isdn/capi_oslib/capi_pipe.h
+++ linux-2.6.28/drivers/isdn/capi_oslib/capi_pipe.h
@@ -28,7 +28,7 @@
     struct completion complete;
     wait_queue_head_t *rx_wait_queue;
     wait_queue_head_t *tx_wait_queue;
-    struct work_struct *scheduler_rx_work;
+    void *Conn;
 };
 
 #define CAPI_VARIABLE_SIZE           0
--- linux-2.6.28/drivers/isdn/capi_oslib/ca_sched.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/ca_sched.c
@@ -538,14 +538,16 @@
  * recursion allowed
 \*---------------------------------------------------------------------------*/
 unsigned long  __attribute__((warn_unused_result)) EnterCritical (void) {
-    int cpu = smp_processor_id();
+    int cpu;
     unsigned long flags;
-
+	preempt_disable();
+    cpu = smp_processor_id();
     local_irq_save(flags); /*--- be sure that not interrupted on this cpu ---*/
     if(per_cpu_recursion_level[cpu] == 0) {
         spin_lock(&critical_section); /*--- per-cpu-protect ---*/
     }
     per_cpu_recursion_level[cpu]++;
+	preempt_enable();
     return flags;
 }
 /*------------------------------------------------------------------------------------------*\
@@ -556,6 +558,8 @@
 /*---------------------------------------------------------------------------*\
 \*---------------------------------------------------------------------------*/
 void LeaveCritical(unsigned long flags) {
+    int cpu;
+	preempt_disable();
     int cpu = smp_processor_id();
     BUG_ON(per_cpu_recursion_level[cpu] <= 0); 
     per_cpu_recursion_level[cpu]--;
@@ -563,6 +567,7 @@
         spin_unlock(&critical_section);
     }
     local_irq_restore(flags);
+	preempt_enable();
 }
 EXPORT_SYMBOL(LeaveCritical);
 /*------------------------------------------------------------------------------------------*\
--- linux-2.6.28/drivers/isdn/capi_oslib/file.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/file.c
@@ -1088,7 +1088,7 @@
 
                 if (status != ERR_NoError) {
                     open_data->last_error = status;
-                    DEB_ERR("capi_installed failed status=%d\n", status);
+                    DEB_ERR("capi_installed failed status=0x%x\n", status);
                     return -EIO;
                 }
             }
--- linux-2.6.28/drivers/isdn/capi_oslib/init_capi_oslib
+++ linux-2.6.28/drivers/isdn/capi_oslib/init_capi_oslib
@@ -35,6 +35,10 @@
 ln -vfs `pwd`/linux_capi_oslib.h ../../../include/linux/capi_oslib.h 
 ln -vfs `pwd`/linux_new_capi.h ../../../include/linux/new_capi.h 
 ln -vfs `pwd`/linux_zugriff.h ../../../include/linux/zugriff.h 
+
+ln -vfs `pwd`/linux_capi_oslib.h ../../../include/uapi/linux/capi_oslib.h 
+ln -vfs `pwd`/linux_new_capi.h ../../../include/uapi/linux/new_capi.h 
+ln -vfs `pwd`/linux_zugriff.h ../../../include/uapi/linux/zugriff.h 
 # ln -fs `pwd`/linux_avm_led.h ../../../include/linux/avm_led.h 
 # ln -fs `pwd`/linux_ar7wdt.h  ../../../include/linux/ar7wdt.h 
 # ln -fs `pwd`/linux_avm_profile.h  ../../../include/linux/avm_profile.h 
--- /dev/null
+++ linux-2.6.28/drivers/isdn/capi_oslib/Kconfig
@@ -0,0 +1,19 @@
+#
+# AVM CAPI-OSLIB
+# 
+
+menu "AVM CAPI-OSLIB"
+
+config CAPI_OSLIB
+	tristate "split CAPI2.0 oslib"
+	depends on ISDN
+	help
+        split oslib for fbox isdn drivers
+
+config CAPI_OSLIB_DEBUG
+    bool "capi oslib debug version"
+    depends on CAPI_OSLIB
+	help
+        debug version of capi-oslib 
+
+endmenu
--- linux-2.6.28/drivers/isdn/capi_oslib/local_capi.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/local_capi.c
@@ -383,14 +383,14 @@
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-unsigned int LOCAL_CAPI_SET_NOTIFY(enum _capi_source capi_source, unsigned int ApplId, struct work_struct *scheduler_rx_work) {
+unsigned int LOCAL_CAPI_SET_NOTIFY(enum _capi_source capi_source, unsigned int ApplId, void *Conn) {
     struct _local_capi_appl *LA;
 
     LA = &LocalCapiAppl[capi_source][ApplId - 1];
     if(LA->InUse != _entry_in_use_) {
         return ERR_IllegalApplId;
     }
-    LA->Pipe->scheduler_rx_work = scheduler_rx_work;
+    LA->Pipe->Conn = Conn;
     return ERR_NoError;
 }
 
--- linux-2.6.28/drivers/isdn/capi_oslib/local_capi.h
+++ linux-2.6.28/drivers/isdn/capi_oslib/local_capi.h
@@ -56,6 +56,6 @@
 unsigned int LOCAL_CAPI_GET_MESSAGE(enum _capi_source capi_source, unsigned int ApplId, unsigned char **pCapiMessage, unsigned int Suspend);
 struct capi_pipe *LOCAL_CAPI_GET_MESSAGE_WAIT_QUEUE(enum _capi_source capi_source, unsigned int ApplId, wait_queue_head_t *rx_wait_queue, wait_queue_head_t *tx_wait_queue);
 int LOCAL_CAPI_REGISTER_B3_BUFFER(enum _capi_source capi_source, unsigned int ApplId, struct _adr_b3_ind_data *b3Buffers, unsigned int BufferAnzahl, void (*release_buffers)(void *), void *context);
-unsigned int LOCAL_CAPI_SET_NOTIFY(enum _capi_source capi_source, unsigned int ApplId, struct work_struct *scheduler_rx_work);
+unsigned int LOCAL_CAPI_SET_NOTIFY(enum _capi_source capi_source, unsigned int ApplId, void *Conn);
 
 #endif /*--- #ifndef _local_capi_h_ ---*/
--- linux-2.6.28/drivers/isdn/capi_oslib/main.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/main.c
@@ -15,41 +15,24 @@
 #include "capi_pipe.h"
 #include "socket_if.h"
 
+#define ETH_P_RCAPI		0x8888
+#define ETH_DEV_RCAPI	"lan"
+
 /*---------------------------------------------------------------------------*\
 \*---------------------------------------------------------------------------*/
 int		io_addr		= 0;
 int		irq_num		= 0;
-static int		dect_hw		= 0;
-static int		dect_on		= 1;
-static int		local_ec	= 0;
-static int		debug_mode	= 0;
 static int		trace_mode	= 0;
-int		capi_oslib_dect_hw		= 0;
-int		capi_oslib_dect_on		= 1;
-int		capi_oslib_local_ec    = 0;
-int		capi_oslib_debug_mode	= 0;
 int		capi_oslib_trace_mode	= 0;
 
-EXPORT_SYMBOL(capi_oslib_dect_hw);
-EXPORT_SYMBOL(capi_oslib_dect_on);
-EXPORT_SYMBOL(capi_oslib_debug_mode);
 EXPORT_SYMBOL(capi_oslib_trace_mode);
-EXPORT_SYMBOL(capi_oslib_local_ec);
 
 module_param (io_addr, int, 0 );
 module_param (irq_num, int, 0 );
-module_param (dect_hw, int, 0 );
-module_param (dect_on, int, 1 );
-module_param (local_ec, int, 0 );
-module_param (debug_mode, int, 0 );
 module_param (trace_mode, int, 0 );
 
 MODULE_PARM_DESC (io_addr, "io_addr: I/O address");
 MODULE_PARM_DESC (irq_num, "irq_num: IRQ number");
-MODULE_PARM_DESC (dect_hw, "dect_hw: DECT_HW_Version");
-MODULE_PARM_DESC (dect_on, "dect_on: DECT activation");
-MODULE_PARM_DESC (local_ec, "local_ec: 1: echo-canceler 2: dtmf-scanner 3: all");
-MODULE_PARM_DESC (debug_mode, "debug mode");
 MODULE_PARM_DESC (trace_mode, "trace mode");
 
 struct _stack_init_params  *capi_oslib_init_params;
@@ -109,7 +92,7 @@
 int avm_stack_attach(lib_callback_t *stack_library, struct _stack_interrupt_library *irq_library, struct _stack_init_params *p_params) {
 
 #if defined(CONFIG_SMP)
-    printk("%s: cpu%d -> cpu%d\n", __func__, smp_processor_id(), PCMLINK_TASKLET_CONTROL_CPU);
+    printk(KERN_INFO"[capi_oslib]%s: cpu%d -> cpu%d\n", __func__, raw_smp_processor_id(), PCMLINK_TASKLET_CONTROL_CPU);
 #endif/*--- #if defined(CONFIG_SMP) ---*/
 
     capi_oslib_init_params        = p_params;
@@ -117,19 +100,11 @@
     capi_oslib_stack              = stack_library;
 
     if(p_params) {
-        printk(KERN_INFO "driver params overwritten io_addr=0x%x irq_num=%u\n", p_params->io_addr, p_params->irq_num);
+        /*--- printk(KERN_INFO "driver params overwritten io_addr=0x%x irq_num=%u\n", p_params->io_addr, p_params->irq_num); ---*/
         io_addr = p_params->io_addr;
         irq_num = p_params->irq_num;
-        dect_hw = p_params->dect_hw;
-        dect_on = p_params->dect_on;
-        local_ec = p_params->local_ec;
-        debug_mode = p_params->debug_mode;
         trace_mode = p_params->trace_mode;
 
-        capi_oslib_dect_hw	  = dect_hw;
-        capi_oslib_dect_on	  = dect_on;
-        capi_oslib_local_ec   = local_ec;
-        capi_oslib_debug_mode = debug_mode;
         capi_oslib_trace_mode = trace_mode;
     }
 #if defined(CONFIG_SMP)
@@ -142,12 +117,8 @@
  * auf definierter CPU wegen PCMLINK_TASKLET_CONTROL_CPU
 \*--------------------------------------------------------------------------------*/
 static long int lavm_stack_attach_oncpu(lib_callback_t *stack_library){
-    char *hwrev;
     char *Version;
 
-#if defined(CONFIG_SMP)
-    printk("%s: cpu%d\n", __func__, smp_processor_id());
-#endif/*--- #if defined(CONFIG_SMP) ---*/
     Capi_Pipe_Init();
 
     HOST_INIT(SOURCE_UNKNOWN, 25 /* max APPLs */, 100 /* max NCCIs */, 0 /* CAPI_INDEX */);
@@ -157,15 +128,10 @@
 
     DEB_INFO("[avm_stack_attach] capi_oslib_file_activate\n");
     capi_oslib_file_activate();
-
-    hwrev = prom_getenv("HWRevision");
-    if(hwrev) {
-        if ((strcmp(hwrev, "103") == 0) || (strcmp(hwrev, "104") == 0)) {
-            /* 5144 || 5188 */
-            DEB_INFO("[avm_stack_attach] capi_oslib_socket_init\n");
-            capi_oslib_socket_init();
-        }
-    }
+#if defined(CONFIG_MACH_PUMA6)
+    printk(KERN_INFO"[capi_oslib] remote-capi dev=%s eth_proto=0x%x\n", ETH_DEV_RCAPI, ETH_P_RCAPI);
+    capi_oslib_socket_init(ETH_DEV_RCAPI, ETH_P_RCAPI);
+#endif/*--- #if defined(CONFIG_MACH_PUMA6) ---*/
 
     DEB_INFO("[avm_stack_attach] CAPI_INIT\n");
     CAPI_INIT(); /*--- kernel capi init ---*/
@@ -198,7 +164,7 @@
 
     os_trigger_scheduler();
 
-    DEB_INFO("%s: cpu%d done\n", __func__, smp_processor_id());
+    DEB_INFO("%s: cpu%d done\n", __func__, raw_smp_processor_id());
     return 0;
 } /* fritz_init */
 EXPORT_SYMBOL(avm_stack_attach);
--- linux-2.6.28/drivers/isdn/capi_oslib/socket_if.c
+++ linux-2.6.28/drivers/isdn/capi_oslib/socket_if.c
@@ -29,6 +29,7 @@
 struct _capi_connections {
     struct list_head list;
     unsigned ApplId;
+	atomic_t link;
     u8 conindex;
     u16 send_seqnr;
     u16 recv_seqnr;
@@ -43,119 +44,161 @@
 
 static struct workqueue_struct *capi_remote_put_workqueue;
 
-struct rcapihdr {
-   u8 type;                     /* RCAPI_TYPE_APPL */
+struct remotedev_hdr {
+   u8 type;                     /* REMOTEDEV_TYPE_APPL */
    u8 conindex;                 /* application identifier */
    u16 seqnr;                   /* Sequence Number */
    u16 len;                     /* Payload length */
 };
 
-#define RCAPI_RESERVE   16      /* reserve for cpmac */
-#define RCAPI_HEADROOM	(sizeof(struct ethhdr)+sizeof(struct rcapihdr))
-#define ETH_P_RCAPI		0x8888
+#define REMOTEDEV_RESERVE   16      /* reserve for cpmac */
+#define REMOTEDEV_HEADROOM	(sizeof(struct ethhdr)+sizeof(struct remotedev_hdr))
 
-#define RCAPI_TYPE_RESERVED	    0
-#define RCAPI_TYPE_APPL		    1       /* vollst. Message */
-#define RCAPI_TYPE_APPL_CONT    2       /* unvollst. Message */
-#define RCAPI_TYPE_APPL_END     3       /* Abschluss einer Message */
-#define RCAPI_TYPE_PING         4
-#define RCAPI_SEND_BUFSIZ       (128+2048)
-#define RCAPI_MAX_FRAME_SIZE    1500
+#define REMOTEDEV_TYPE_RESERVED	     0x00
+#define REMOTEDEV_TYPE_APPL			 0x01   /* Message */
+#define REMOTEDEV_TYPE_PING          0x02
+#define REMOTEDEV_TYPE_APPL_BYE		 0x03
+#define REMOTE_TYP(a)				((a) & 0x3F)
 
-LIST_HEAD(capi_conn_list);
-static struct net_device *capi_netdev;   /* interface "cpmac0", if it is there */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-#else
-#define get_fast_time(x) do_gettimeofday(x)
-#endif
+#define REMOTEDEV_TYPE_START		0x80   /* verodert Start-Indikator */
+#define REMOTEDEV_TYPE_END			0x40   /* verodert End-Indikator */
+#define REMOTEDEV_TYPE_COMLETE		(REMOTEDEV_TYPE_START | REMOTEDEV_TYPE_END)
+
+#define REMOTEDEV_SEND_BUFSIZ       (128+2048)
+#define REMOTEDEV_MAX_FRAME_SIZE    1500
+
+#define MSG_TYPE_PROFILE    0
+#define MSG_TYPE_CAPI       1
+
+static LIST_HEAD(capi_conn_list);
+static  DEFINE_SPINLOCK(list_lock);
+static struct net_device *capi_netdev;   /* interface if it is there */
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-static void capi_oslib_socket_get(void* arg);
-#else/*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
 static void capi_oslib_socket_get(struct work_struct *work);
-#endif/*--- #else ---*//*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
+static int capi_oslib_netdev_notifier_event(struct notifier_block *notifier, unsigned long event, void *ptr);
+static int capi_oslib_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt __attribute__((unused)), struct net_device* orig_dev);
 static unsigned int capi_oslib_init_done; 
+static char g_remote_device[128];
+
+static struct notifier_block capi_oslib_netdev_notifier = {
+   .notifier_call = capi_oslib_netdev_notifier_event
+};
+static struct packet_type rcapi_packet_type = {
+	func:	capi_oslib_recv,
+};
+/*--- #define SOCKET_IF_LOCK_TRC(args...)	printk(KERN_DEBUG args) ---*/
+#define SOCKET_IF_LOCK_TRC(args...)
+
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void __capi_oslib_conn_get(struct _capi_connections *conn, int count, const char *text __maybe_unused) {
+	atomic_add(count, &conn->link);
+	if(atomic_read(&conn->link) < 4) {
+		SOCKET_IF_LOCK_TRC("%s conn=%p conindex=%d link=%d: %s\n", __func__, conn, conn->conindex, atomic_read(&conn->link), text);
+	}
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void capi_oslib_conn_get(struct _capi_connections *conn, const char *text) {
+	__capi_oslib_conn_get(conn, 1, text);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static void capi_oslib_conn_put(struct _capi_connections *conn, const char *text __maybe_unused) {
+
+	if(atomic_read(&conn->link) == 0) {
+		printk(KERN_ERR"%s conn=%p conindex=%d error on link=%d: %s\n", __func__, conn, conn->conindex, atomic_read(&conn->link), text);
+		return;
+	}
+	if (atomic_dec_and_test(&conn->link)) {
+		SOCKET_IF_LOCK_TRC("%s conn=%p conindex=%d free! %s\n", __func__, conn, conn->conindex, text);
+		if (conn->recombine_buffer) {
+			kfree(conn->recombine_buffer);
+		}
+		kfree(conn);
+		return;
+	}
+	if(atomic_read(&conn->link) < 3) {
+		SOCKET_IF_LOCK_TRC("%s conn=%p conindex=%d link=%d: %s\n", __func__, conn, conn->conindex, atomic_read(&conn->link), text);
+	}
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+void capi_oslib_trigger_rxwork(struct workqueue_struct *rxwork, void *_conn) {
+	struct _capi_connections *conn = (struct _capi_connections *)_conn;
+
+	capi_oslib_conn_get(conn, __func__);
+    if(queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, rxwork, &conn->rx_work) == 0) {
+		capi_oslib_conn_put(conn, __func__);
+	}
+}
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-static inline struct net_device *capi_device(void)
-{
-   if (capi_netdev)
+static inline struct net_device *capi_device(void) {
+   if (capi_netdev) {
       return capi_netdev;
-   capi_netdev = dev_get_by_name(
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24)
-           &init_net,
-#endif
-           "cpmac0");
-   if (capi_netdev)
+   }
+   capi_netdev = dev_get_by_name( &init_net, g_remote_device);
+   if (capi_netdev) {
       printk(KERN_NOTICE "capi_oslib: device %s now there.\n", capi_netdev->name);
+   }
    return capi_netdev;
 }
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-static void capi_oslib_remove_conn
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-    (void* arg) {
-    struct _capi_connections *conn = (struct _capi_connections*)arg;
-#else
-    (struct work_struct *work) {
+static void capi_oslib_remove_conn(struct work_struct *work) {
 	struct _capi_connections *conn = container_of(work, struct _capi_connections, remove);
-#endif/*--- #else ---*/
 
-    /*--- printk(KERN_DEBUG "capi_oslib_remove_conn for conn %d\n", conn->conindex); ---*/
+    SOCKET_IF_LOCK_TRC(KERN_DEBUG "capi_oslib_remove_conn for %p connindex %d link %d\n", conn, conn->conindex, conn->link);
     skb_queue_purge(&conn->recvqueue);
+	spin_lock_bh(&list_lock);
     list_del(&conn->list);
+	spin_unlock_bh(&list_lock);
+	capi_oslib_conn_put(conn, "list_del");
     if (conn->ApplId != (unsigned)-1) {
         LOCAL_CAPI_SET_NOTIFY(SOURCE_SOCKET_CAPI, conn->ApplId, NULL);
         LOCAL_CAPI_RELEASE(SOURCE_SOCKET_CAPI, conn->ApplId);
+		capi_oslib_conn_put(conn, "LOCAL_CAPI_SET_NOTIFY(0)");
         conn->ApplId = (unsigned)-1;
     }
-    if (conn->recombine_buffer) {
-        kfree(conn->recombine_buffer);
-    }
-    kfree(conn);
+	capi_oslib_conn_put(conn, "capi_oslib_remove_conn() done"); /*--- end workqueue ---*/
+	capi_oslib_conn_put(conn, "free"); /*--- kfree ---*/
 }
-
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
 static struct sk_buff* capi_oslib_allocskb(unsigned size, unsigned char type, unsigned char connindex, unsigned int seqnr, struct net_device *dev, unsigned char** dataptr, int priority)
 {
     struct sk_buff* skb;
     struct ethhdr *ethh;
-    struct rcapihdr *rhdr;
+    struct remotedev_hdr *rhdr;
     u8 *data;
 
-    skb = alloc_skb(RCAPI_RESERVE + RCAPI_HEADROOM + size, priority);
+    skb = alloc_skb(REMOTEDEV_RESERVE + REMOTEDEV_HEADROOM + size, priority);
     if (unlikely(!skb)) return NULL;
 
-    skb_reserve(skb, RCAPI_RESERVE);                        /* reserve headroom for cpmac */
-    (void)skb_put(skb, RCAPI_HEADROOM + size);              /* set length */
+    skb_reserve(skb, REMOTEDEV_RESERVE);                        /* reserve headroom for cpmac */
+    (void)skb_put(skb, REMOTEDEV_HEADROOM + size);              /* set length */
     ethh = (struct ethhdr *)skb->data;
     memset(ethh->h_dest, 0xff, ETH_ALEN);
     memcpy(ethh->h_source, dev->dev_addr, ETH_ALEN);
-    ethh->h_proto = __constant_htons(ETH_P_RCAPI);
-    rhdr = (struct rcapihdr *) (ethh + 1);
-    rhdr->type = type;
+    ethh->h_proto  = rcapi_packet_type.type;  
+    rhdr = (struct remotedev_hdr *) (ethh + 1);
+    rhdr->type     = type;
     rhdr->conindex = connindex;
-    rhdr->seqnr = seqnr;
-    rhdr->len = size;
+    rhdr->seqnr	   = htons(seqnr);
+    rhdr->len      = htons(size);
     data = (u8 *) (rhdr + 1);
     skb->dev = dev;
     skb->protocol = ethh->h_proto;
     skb->pkt_type = PACKET_OUTGOING;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-    skb->nh.raw = skb->data;
-#else/*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
     skb_reset_network_header(skb);
-#endif/*--- #else ---*//*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
 
     if (dataptr) {
         *dataptr = data;
     }
-
     return skb;
 }
-
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
 static void capi_oslib_send_too_big_conf(unsigned char* msg, struct _capi_connections *conn)
@@ -170,8 +213,7 @@
         printk(KERN_WARNING "capi_oslib: send data conf but no dev!\n");
         return;
     }
-    
-    skb = capi_oslib_allocskb(17, RCAPI_TYPE_APPL, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
+    skb = capi_oslib_allocskb(17, REMOTEDEV_TYPE_APPL | REMOTEDEV_TYPE_COMLETE, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
     if (unlikely(!skb)) {
         printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
         return;
@@ -195,33 +237,30 @@
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-static void capi_oslib_socket_put
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-    (void* arg) {
-    struct _capi_connections *conn = (struct _capi_connections*)arg;
-#else
-    (struct work_struct *work) {
+static void capi_oslib_socket_put (struct work_struct *work) {
 	struct _capi_connections *conn = container_of(work, struct _capi_connections, tx_work);
-#endif
     unsigned int status = ERR_SendBusy;
     struct sk_buff *skb;
     unsigned short ApplId;
-    struct rcapihdr *rhdr;
-    
+    struct remotedev_hdr *rhdr;
+
     while ((skb = skb_dequeue(&conn->recvqueue))) {
         /*--- printk(KERN_DEBUG "capi_oslib_socket_put: skb %p\n", skb); ---*/
-        rhdr = (struct rcapihdr *) skb->data;
-        if ((rhdr->type == RCAPI_TYPE_APPL) || (rhdr->type == RCAPI_TYPE_APPL_END)) {
+        rhdr = (struct remotedev_hdr *) skb->data;
+        if ((rhdr->type & REMOTEDEV_TYPE_END) == REMOTEDEV_TYPE_END) {
             unsigned msg_len = 0;
             struct __attribute__ ((packed)) _capi_message *C;
             unsigned char* buffer;
     
-            if (rhdr->type == RCAPI_TYPE_APPL_END) {
-                /*--- printk(KERN_DEBUG "capi_oslib_socket_put: got RCAPI_TYPE_APPL_END\n"); ---*/
-                skb_pull(skb, sizeof(struct rcapihdr)); /* strip headers */
+            if ((rhdr->type & REMOTEDEV_TYPE_START) == REMOTEDEV_TYPE_START) {
+                skb_pull(skb, sizeof(struct remotedev_hdr) + 1); /* strip header + MSG_TYPE_CAPI/MSG_TYPE_PROFILE */
+                buffer = (unsigned char*)skb->data;
+			} else {
+                /*--- printk(KERN_DEBUG "capi_oslib_socket_put: got REMOTEDEV_TYPE_APPL_END\n"); ---*/
+                skb_pull(skb, sizeof(struct remotedev_hdr)); /* strip headers */
                 /*--- printk(KERN_DEBUG "capi_oslib: appending to recombine buffer\n"); ---*/
-                if (conn->recombine_buffer && (conn->recombine_len + rhdr->len < RCAPI_SEND_BUFSIZ)) {
-                    memcpy(&conn->recombine_buffer[conn->recombine_len], skb->data, rhdr->len);
+                if (conn->recombine_buffer && (conn->recombine_len + ntohs(rhdr->len) < REMOTEDEV_SEND_BUFSIZ)) {
+                    memcpy(&conn->recombine_buffer[conn->recombine_len], skb->data, ntohs(rhdr->len));
                     conn->recombine_len = 0;
                     buffer = conn->recombine_buffer;
                 } else {
@@ -229,27 +268,22 @@
                     conn->recombine_len = 0;
                     break;
                 }
-            } else {
-                /*--- printk(KERN_DEBUG "capi_oslib_socket_put: got RCAPI_TYPE_APPL\n"); ---*/
-                skb_pull(skb, sizeof(struct rcapihdr) + 1); /* strip headers */
-                buffer = (unsigned char*)skb->data;
             }
             C = (struct __attribute__ ((packed)) _capi_message *)buffer;
-            msg_len = copy_word_from_le_aligned((unsigned char *)&C->capi_message_header.Length);
+            msg_len = copy_word_from_le_unaligned((unsigned char *)&C->capi_message_header.Length);
   
-            switch (buffer[4])
-            {
+            switch (buffer[4]) {
                 case 0x86:    /* DATA_B3_REQ */
                     if (buffer[5] == 0x80) {
                         struct __attribute__ ((packed)) _capi_message *C = (struct __attribute__ ((packed)) _capi_message *)buffer;
                         unsigned char* data_buffer = NULL;
       
-                        if (conn->B3BlockSize >= copy_word_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_req.DataLen)) {
+                        if (conn->B3BlockSize >= copy_word_from_le_unaligned((unsigned char *)&C->capi_message_part.data_b3_req.DataLen)) {
                             data_buffer = LOCAL_CAPI_NEW_DATA_B3_REQ_BUFFER(SOURCE_SOCKET_CAPI, 
-                                    copy_word_from_le_aligned((unsigned char *)&C->capi_message_header.ApplId), copy_dword_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_req.NCCI));
+                                    copy_word_from_le_unaligned((unsigned char *)&C->capi_message_header.ApplId), copy_dword_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_req.NCCI));
                             if (data_buffer) {
-                                memcpy(data_buffer, &buffer[msg_len], copy_word_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_req.DataLen));
-                                C->capi_message_part.data_b3_req.Data = data_buffer;
+                                memcpy(data_buffer, &buffer[msg_len], copy_word_from_le_unaligned((unsigned char *)&C->capi_message_part.data_b3_req.DataLen));
+                                set_le_unaligned_dword(&C->capi_message_part.data_b3_req.Data, (unsigned long)data_buffer);
 #if defined(CAPIOSLIB_CHECK_LATENCY)
                                 /*--- capi_generate_timestamp(0x20 + (conn->ApplId & 0x1F), data_buffer, copy_word_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_req.DataLen)); ---*/
 #endif/*--- #if defined(CAPIOSLIB_CHECK_LATENCY) ---*/
@@ -284,27 +318,26 @@
                             printk(KERN_WARNING "capi_oslib: register but conn %d already has ApplId %d\n", conn->conindex, conn->ApplId);
                             LOCAL_CAPI_SET_NOTIFY(SOURCE_SOCKET_CAPI, conn->ApplId, NULL);
                             LOCAL_CAPI_RELEASE(SOURCE_SOCKET_CAPI, conn->ApplId);
+							capi_oslib_conn_put(conn, "re-register");
                             conn->ApplId = (unsigned)-1;
                             skb_queue_purge(&conn->recvqueue);
                         }
-                        maxNCCIs = buffer[8] | (buffer[9] << 8) | (buffer[10] << 16) | (buffer[11] << 24);
-                        windowsize = buffer[12] | (buffer[13] << 8) | (buffer[14] << 16) | (buffer[15] << 24);
-                        b3_blocksize = buffer[16] | (buffer[17] << 8) | (buffer[18] << 16) | (buffer[19] << 24);
+						maxNCCIs	 = copy_dword_from_le_unaligned(&buffer[8]);
+                        windowsize   = copy_dword_from_le_unaligned(&buffer[12]);
+                        b3_blocksize = copy_dword_from_le_unaligned(&buffer[16]);
                         conn->B3BlockSize = b3_blocksize;
+                        /*--- printk(KERN_DEBUG "%s: b3_blocksize=%x windowsize=%x maxNCCIs=%x\n", __func__, b3_blocksize, windowsize, maxNCCIs); ---*/
                         result = LOCAL_CAPI_REGISTER(SOURCE_SOCKET_CAPI, 1024 + (1024 * maxNCCIs), maxNCCIs, windowsize, b3_blocksize, &conn->ApplId);
                         /*--- printk(KERN_DEBUG "register result: %d\n", result); ---*/
                         if (result == ERR_NoError) {
                             unsigned char response[10];
-                            /*--- list_add(&conn->list, &capi_conn_list); ---*/
                             
                             /* Antwort mit ApplID schicken */
                             memcpy((void*)response, buffer, 10);
-                            response[2] = (conn->ApplId & 0xFF);         /* ApplID einsetzen */
-                            response[3] = (conn->ApplId >> 8) & 0xFF;
-                            response[8] = 0;
-                            response[9] = 0;
+                            set_le_unaligned_word(&response[2], conn->ApplId);         /* ApplID einsetzen */
+                            set_le_unaligned_word(&response[8], 0);
 
-                            response_skb = capi_oslib_allocskb(11, RCAPI_TYPE_APPL, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
+                            response_skb = capi_oslib_allocskb(11, REMOTEDEV_TYPE_APPL | REMOTEDEV_TYPE_COMLETE, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
                             if (unlikely(!response_skb)) {
                                 printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
                                 goto next_message;
@@ -323,22 +356,18 @@
       
                             /*--- printk(KERN_DEBUG "register success result sent\n"); ---*/
                             /* workqueue item erzeugen und einhängen */
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-                            INIT_WORK(&conn->rx_work, capi_oslib_socket_get, (void*)conn);
-#else
                             INIT_WORK(&conn->rx_work, capi_oslib_socket_get);
-#endif
-                            result = LOCAL_CAPI_SET_NOTIFY(SOURCE_SOCKET_CAPI, conn->ApplId, &conn->rx_work);
+							capi_oslib_conn_get(conn, "LOCAL_CAPI_SET_NOTIFY");
+                            result = LOCAL_CAPI_SET_NOTIFY(SOURCE_SOCKET_CAPI, conn->ApplId, conn);
                         } else {
                             unsigned char response[10];
       
                             conn->ApplId = (unsigned)-1;
                             /* Fehlerwert zurückschicken */
                             memcpy((void*)response, buffer, 10);
-                            response[8] = (result & 0xFF);
-                            response[9] = (result >> 8) & 0xFF;
+                            set_le_unaligned_word(&response[8], result);
       
-                            response_skb = capi_oslib_allocskb(11, RCAPI_TYPE_APPL, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
+                            response_skb = capi_oslib_allocskb(11, REMOTEDEV_TYPE_APPL | REMOTEDEV_TYPE_COMLETE, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
                             if (unlikely(!response_skb)) {
                                 printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
                                 goto next_message;
@@ -360,13 +389,14 @@
                 default:
                     break;
             }
-            ApplId = buffer[2] | (buffer[3] << 8);
+            ApplId = copy_word_from_le_unaligned(&buffer[2]);
             status = LOCAL_CAPI_PUT_MESSAGE(SOURCE_SOCKET_CAPI, ApplId, buffer);
             if ((status == ERR_SendBusy) || (status == ERR_QueueFull)) {
-                if (rhdr->type == RCAPI_TYPE_APPL_END) {
-                    conn->recombine_len -= rhdr->len;
+                if (rhdr->type == REMOTEDEV_TYPE_END) {
+                    conn->recombine_len -= ntohs(rhdr->len);
                 }
                 skb_queue_head(&conn->recvqueue, skb);
+				capi_oslib_conn_put(conn, "capi_oslib_socket_put() done(#1)");
                 return;
             }
             if (status == ERR_OS_Resource) {
@@ -374,18 +404,22 @@
                 len = buffer[0] | (buffer[1] << 8);
                 printk(KERN_ERR "capi_oslib_socket_put got ERR_OS_Resource for ApplId %d, Len=%d!\n", ApplId, len);
             }
-        } else if (rhdr->type == RCAPI_TYPE_APPL_CONT) {
-            /*--- printk(KERN_DEBUG "got RCAPI_TYPE_APPL_CONT\n"); ---*/
-            if (conn->recombine_len == 0) {
-                /*--- printk(KERN_DEBUG "erster Block buffer=%p len=%d\n", conn->recombine_buffer, rhdr->len); ---*/
-                skb_pull(skb, sizeof(struct rcapihdr) + 1); /* strip headers */
-                rhdr->len -= 1;
+        } else {
+			int pkt_len = ntohs(rhdr->len);
+            if ((rhdr->type & REMOTEDEV_TYPE_START) == REMOTEDEV_TYPE_START) {
+				if(conn->recombine_len) {
+					printk(KERN_DEBUG "illegal recombine_len=%d\n", conn->recombine_len);
+					conn->recombine_len = 0;
+				}
+                /*--- printk(KERN_DEBUG "erster Block buffer=%p len=%d\n", conn->recombine_buffer, ntohs(rhdr->len)); ---*/
+                skb_pull(skb, sizeof(struct remotedev_hdr) + 1); /* strip headers */
+                pkt_len--;
             } else {
-                /*--- printk(KERN_DEBUG "weiterer Block len=%d\n", rhdr->len); ---*/
-                skb_pull(skb, sizeof(struct rcapihdr)); /* strip headers */
+                /*--- printk(KERN_DEBUG "weiterer Block len=%d\n", ntohs(rhdr->len)); ---*/
+                skb_pull(skb, sizeof(struct remotedev_hdr)); /* strip headers */
             }
             if (conn->recombine_buffer == NULL) {
-                conn->recombine_buffer = kmalloc(RCAPI_SEND_BUFSIZ, GFP_KERNEL);
+                conn->recombine_buffer = kmalloc(REMOTEDEV_SEND_BUFSIZ, GFP_KERNEL);
                 if (conn->recombine_buffer == NULL) {
                     printk(KERN_ERR "capi_oslib: kmalloc failed\n");
                     goto next_message;
@@ -393,9 +427,9 @@
                     /*--- printk(KERN_DEBUG "capi_oslib: buffer %p alloced\n", conn->recombine_buffer); ---*/
                 }
             }
-            if (conn->recombine_len + rhdr->len <= RCAPI_SEND_BUFSIZ) {
-                memcpy(&conn->recombine_buffer[conn->recombine_len], skb->data, rhdr->len);
-                conn->recombine_len += rhdr->len;
+            if ((conn->recombine_len + pkt_len) <= REMOTEDEV_SEND_BUFSIZ) {
+                memcpy(&conn->recombine_buffer[conn->recombine_len], skb->data, pkt_len);
+                conn->recombine_len += pkt_len;
             } else {
                 printk(KERN_ERR "capi_oslib: recombine buffer too small!\n");
             }
@@ -403,27 +437,20 @@
 next_message:
         kfree_skb(skb);
     }
+	capi_oslib_conn_put(conn, "capi_oslib_socket_put() done");
+	return;
 }
- 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-static void capi_oslib_socket_get
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-            (void* arg){
-            struct _capi_connections *conn = (struct _capi_connections*)arg;
-#else/*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
-            (struct work_struct *work){
-            struct _capi_connections *conn = container_of(work, struct _capi_connections, rx_work);
-#endif/*--- #else ---*//*--- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19) ---*/
+static void capi_oslib_socket_get (struct work_struct *work){
+    struct _capi_connections *conn = container_of(work, struct _capi_connections, rx_work);
     unsigned int status = ERR_NoError;
     unsigned char* buffer = NULL;
 
-    /*--- printk(KERN_DEBUG "capi_oslib_socket_get %p\n", arg); ---*/
-    if (conn == NULL) return;
-    /*--- printk(KERN_DEBUG "capi_oslib_socket_get for Appl %d\n", conn->ApplId); ---*/
-    if (conn->ApplId == (unsigned)-1) return;
-
-
+    if (conn->ApplId == (unsigned)-1) {
+		capi_oslib_conn_put(conn, "capi_oslib_socket_get() done(#1)");
+		return;
+	}
     while (status == ERR_NoError) {
         status = LOCAL_CAPI_GET_MESSAGE(SOURCE_SOCKET_CAPI, conn->ApplId, &buffer, CAPI_NO_SUSPEND);
         DEB_INFO("LOCAL_CAPI_GET_MESSAGE(%d, CAPI_NO_SUSPEND) -> %04x, %p\n", conn->ApplId, status, buffer);
@@ -454,53 +481,51 @@
                     unsigned int tocopy = 0;
                     unsigned char type;
 
-                    thissize = min((unsigned int)left, (unsigned int)(RCAPI_MAX_FRAME_SIZE - RCAPI_HEADROOM));
+                    thissize = min((unsigned int)left, (unsigned int)(REMOTEDEV_MAX_FRAME_SIZE - REMOTEDEV_HEADROOM));
+                    type = REMOTEDEV_TYPE_APPL;
                     if (thissize == total_msg_len) {
-                        type = RCAPI_TYPE_APPL;
+					    type |= REMOTEDEV_TYPE_COMLETE;
                     } else if (left > thissize) {
-                        type = RCAPI_TYPE_APPL_CONT;
+						type |= (left == total_msg_len) ? REMOTEDEV_TYPE_START : 0;
                     } else {
-                        type = RCAPI_TYPE_APPL_END;
+						type |= REMOTEDEV_TYPE_END;
                     }
                     skb = capi_oslib_allocskb(thissize, type, conn->conindex, conn->send_seqnr, dev, &data, GFP_KERNEL);
                     if (unlikely(!skb)) {
                         printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
                         break;
-                    } else {
-                        left -= thissize;
-                        if (msg_left == copy_word_from_le_aligned((unsigned char *)&C->capi_message_header.Length)) {
-                            *data++ = 1;    /* normal CAPI Message */
-                            thissize -= 1;
-                        }
-
-                        if (msg_left) {
-                            /* noch Message übrig */
-                            tocopy = min((unsigned int)thissize, msg_left);
-                            memcpy(data, &buffer[copy_word_from_le_aligned((unsigned char *)&C->capi_message_header.Length) - msg_left], tocopy);
-                            msg_left -= tocopy;
-                            data += tocopy;
-                            thissize -= tocopy;
-                        }
-                        
-                        if (CA_IS_DATA_B3_IND(buffer)) {
-                            if ((data_left) && (thissize > 0)) {
-                                /* Message komplett && noch Platz für Daten übrig */
-                                tocopy = min((unsigned int)thissize, data_left);
-                                memcpy(data, &C->capi_message_part.data_b3_ind.Data[copy_word_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_ind.DataLen) - data_left], tocopy);
-#if defined(CAPIOSLIB_CHECK_LATENCY)
-                                /*--- capi_parse_timestamp(0x20 + (conn->ApplId & 0x1F), (char *)__func__, data, tocopy); ---*/
-#endif/*--- #if defined(CAPIOSLIB_CHECK_LATENCY) ---*/
-                                data_left -= tocopy;
-                            }
-                        }
+                    } 
+					left -= thissize;
+					if ((type & REMOTEDEV_TYPE_START) == REMOTEDEV_TYPE_START) {
+						*data++   = MSG_TYPE_CAPI;    /* normale CAPI Message */
+						thissize -= 1;
+					}
+					if (msg_left) {
+						/* noch Message übrig */
+						tocopy = min((unsigned int)thissize, msg_left);
+						memcpy(data, &buffer[copy_word_from_le_aligned((unsigned char *)&C->capi_message_header.Length) - msg_left], tocopy);
+						msg_left -= tocopy;
+						data += tocopy;
+						thissize -= tocopy;
+					}
+					
+					if (CA_IS_DATA_B3_IND(buffer)) {
+						if ((data_left) && (thissize > 0)) {
+							unsigned char *pdata_ind = (unsigned char *)copy_dword_from_le_aligned(&C->capi_message_part.data_b3_ind.Data);
+							unsigned int   offset =  copy_word_from_le_aligned((unsigned char *)&C->capi_message_part.data_b3_ind.DataLen);
+							/* Message komplett && noch Platz für Daten übrig */
+							tocopy = min((unsigned int)thissize, data_left);
+							memcpy(data, &pdata_ind[offset - data_left], tocopy);
+							data_left -= tocopy;
+						}
+					}
 
-                        rc = dev_queue_xmit(skb); /* queue paket for transmitting */
+					rc = dev_queue_xmit(skb); /* queue paket for transmitting */
 
-                        if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
-                            printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
-                        }
-                        conn->send_seqnr++;
-                    }
+					if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
+						printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
+					}
+					conn->send_seqnr++;
                 }
             } else {
                 printk(KERN_WARNING "capi_oslib: drop msg, no dev\n");
@@ -508,37 +533,154 @@
         }
         /*--- printk(KERN_DEBUG "get done\n"); ---*/
     }
+	capi_oslib_conn_put(conn, "capi_oslib_socket_get() done");
+	return;
 }
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static struct _capi_connections *get_capioslib_connection(int conn_index, int alloc) {
+	struct _capi_connections *conn = NULL;
+	struct list_head *lp;
 
+	spin_lock_bh(&list_lock);
+	list_for_each(lp, &capi_conn_list) {
+		conn = list_entry(lp, struct _capi_connections, list);
+		if (conn->conindex == conn_index) {
+			capi_oslib_conn_get(conn, "get_capioslib_connection");
+			spin_unlock_bh(&list_lock);
+			return conn;
+		}
+	}
+	spin_unlock_bh(&list_lock);
+	if(alloc == 0) {
+		return NULL;
+	}
+	conn = kzalloc(sizeof(struct _capi_connections), GFP_KERNEL);
+	if (conn == NULL) {
+		return NULL;
+	}
+	conn->conindex		   = conn_index;
+	conn->ApplId		   = (unsigned)-1;
+	__capi_oslib_conn_get(conn, 3, "alloc+list_add+first_get");
+	skb_queue_head_init(&conn->recvqueue);
+
+	spin_lock_bh(&list_lock);
+	list_add(&conn->list, &capi_conn_list);
+	spin_unlock_bh(&list_lock);
+
+	INIT_WORK(&conn->tx_work, capi_oslib_socket_put);
+	return conn;
+}
 /*-------------------------------------------------------------------------------------*\
+ * CAPI Profile etc.pp rüberschicken
+ *
+ * 4 Bytes Num. Controllers
+ *      64 Bytes Manufacturer
+ *      4  Bytes CAPI Major
+ *      4  Bytes CAPI Minor
+ *      4  Bytes Manu Major
+ *      4  Bytes Manu Minor
+ *      8  Bytes Serial No.
+ *      64 Bytes Profile
 \*-------------------------------------------------------------------------------------*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-static int capi_oslib_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt __attribute__((unused)), struct net_device* orig_dev __attribute__((unused)))
-#else
-static int capi_oslib_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
-#endif
-{
-   struct rcapihdr *rhdr;
-   struct _capi_connections *conn = NULL;
-   struct list_head *lp;
+static int capioslib_send_profile(struct _capi_connections *conn) {
+	unsigned char info[64];
+	unsigned int num_controllers, i;
+	struct sk_buff *skb;
+	unsigned total_msg_len;
+	u8 *data;
+	int rc;
+	struct net_device *dev;
 
-    if (dev != capi_device())
-        goto freeskb;
- 
+	dev = capi_device();
+	if (unlikely(!dev)) {
+		printk(KERN_WARNING "capi_oslib: send profile but no dev!\n");
+		return -1;
+	}
+	CAPI_GET_PROFILE(info, 0);
+	num_controllers = EXTRACT_DWORD(info);
+
+	total_msg_len = 4 + (num_controllers * 152) + 1;
+	skb = capi_oslib_allocskb(total_msg_len, REMOTEDEV_TYPE_APPL | REMOTEDEV_TYPE_COMLETE, conn->conindex, conn->send_seqnr, dev, &data, GFP_ATOMIC);
+	if (unlikely(!skb)) {
+		printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
+		return -1;
+	}
+	*data++ = MSG_TYPE_PROFILE;    /* keine CAPI Message */
+	memcpy(data, info, sizeof(unsigned int));
+	data += sizeof(unsigned int);
+	for (i = 1; i <= num_controllers; i++) {
+		CAPI_GET_MANUFACTURER(info);
+		DEB_INFO("start info controller %d\n", i);
+		memcpy(data, info, 64);
+		data += 64;
+
+		CAPI_GET_VERSION((unsigned int*)&info[0], (unsigned int*)&info[4], (unsigned int*)&info[8],
+						 (unsigned int*)&info[12]);
+		memcpy(data, info, 16);
+		data += 16;
+
+		CAPI_GET_SERIAL_NUMBER(i, info);
+		memcpy(data, info, 8);
+		data += 8;
+
+		CAPI_GET_PROFILE(info, i);
+		memcpy(data, info, 64);
+		data += 64;
+	}
+	rc = dev_queue_xmit(skb); /* queue paket for transmitting */
+	if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
+		printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
+	}
+	conn->send_seqnr++;
+	return 0;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static void send_pong(void) {
+	struct sk_buff *pong_skb;
+	int rc;
+	struct net_device *dev;
+
+	dev = capi_device();
+	if (unlikely(!dev)) {
+		printk(KERN_WARNING "capi_oslib: got ping but have no dev!\n");
+		return;
+	}
+	pong_skb = capi_oslib_allocskb(0, REMOTEDEV_TYPE_PING, 0, 0, dev, NULL, GFP_ATOMIC);
+	if (unlikely(!pong_skb)) {
+		printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
+		return;
+	}
+	rc = dev_queue_xmit(pong_skb); /* queue paket for transmitting */
+
+	if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
+		printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
+	}
+}
+/*-------------------------------------------------------------------------------------*\
+\*-------------------------------------------------------------------------------------*/
+static int capi_oslib_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt __attribute__((unused)), struct net_device* orig_dev __attribute__((unused))) {
+	int ret = NET_RX_SUCCESS;
+	struct timeval tv;
+	struct remotedev_hdr *rhdr;
+	struct _capi_connections *conn = NULL;
+
+	if (dev != capi_device()) {
+        kfree_skb(skb);
+        return NET_RX_DROP;
+	}
 #ifndef this_checks_are_not_really_needed_in_our_environment
     if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
         printk(KERN_ERR "capi_oslib: recv: skb_share_check failed\n");
-        goto out_of_mem;
+		kfree_skb(skb);
+        return NET_RX_DROP;
     }
- 
     if (skb_is_nonlinear(skb)) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
         if (skb_linearize(skb) != 0) {
-#else
-        if (skb_linearize(skb, GFP_ATOMIC) != 0) {
-#endif
             printk(KERN_ERR "capi_oslib: recv: skb_linearize failed\n");
-            goto freeskb;
+			kfree_skb(skb);
+			return NET_RX_DROP;
         }
     }
     if (skb_cloned(skb) && !skb->sk) {
@@ -546,256 +688,108 @@
  
         if (!nskb) {
             printk(KERN_ERR "capi_oslib: recv: skb_copy failed\n");
-            goto freeskb;
+			kfree_skb(skb);
+			return NET_RX_DROP;
         }
         kfree_skb(skb);
         skb = nskb;
     }
 #endif
-
-    if (unlikely(skb->len < sizeof(struct rcapihdr))) {
+    if (unlikely(skb->len < sizeof(struct remotedev_hdr))) {
         printk(KERN_ERR "capi_oslib: recv: packet too small\n");
-        goto freeskb;
-    }
-    rhdr = (struct rcapihdr *) skb->data;
-
-    switch (rhdr->type)
-    {
-        case RCAPI_TYPE_APPL:
-        case RCAPI_TYPE_APPL_CONT:
-        case RCAPI_TYPE_APPL_END:
-            list_for_each(lp, &capi_conn_list) {
-                conn = list_entry(lp, struct _capi_connections, list);
-                if (conn->conindex == rhdr->conindex) break;
-            }
-            if ((conn == NULL) || (conn->conindex != rhdr->conindex)) {
-                if (rhdr->type == RCAPI_TYPE_APPL) {
-                    /*--- printk(KERN_WARNING "capi_oslib: recv: conindex %d not in use\n", rhdr->conindex); ---*/
-
-                    conn = kmalloc(sizeof(struct _capi_connections), GFP_KERNEL);
-                    if (conn == NULL) {
-                        goto freeskb;
-                    }
-                    conn->conindex = rhdr->conindex;
-                    conn->send_seqnr = 0;
-                    conn->recv_seqnr = 0;
-                    conn->ApplId = (unsigned)-1;
-                    conn->recombine_buffer = NULL;
-                    conn->recombine_len = 0;
-                    conn->B3BlockSize = 0;
-                    skb_queue_head_init(&conn->recvqueue);
-                    list_add(&conn->list, &capi_conn_list);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-                    INIT_WORK(&conn->tx_work, capi_oslib_socket_put, (void*)conn);
-#else
-                    INIT_WORK(&conn->tx_work, capi_oslib_socket_put);
-#endif
-                } else {
-                    printk(KERN_ERR "capi_oslib: got APPL_CONT or _END w/o conn!\n");
-                    goto freeskb;
-                }
-            }
-        default:
-            break;
+		kfree_skb(skb);
+		return NET_RX_DROP;
     }
+    rhdr = (struct remotedev_hdr *) skb->data;
 
-    switch (rhdr->type) {
-        case RCAPI_TYPE_APPL:
-#if 0
-            if (unlikely(rhdr->conindex >= RCAPIMAXAPPL)) {
-                printk(KERN_ERR "capi_oslib: recv: illegal conindex %d\n", rhdr->conindex);
-                goto freeskb;
-            }
-#endif
-            if (rhdr->seqnr != conn->recv_seqnr) {
-                printk(KERN_WARNING "capi_oslib: recv: conn %d lost packet(s)!\n", conn->conindex);
-            }
-            conn->recv_seqnr = rhdr->seqnr + 1;
-
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 19)
-            if (skb->tstamp.off_sec == 0) {
-                struct timeval tv;
-                do_gettimeofday(&tv);
-                skb->tstamp.off_sec = tv.tv_sec;
-                skb->tstamp.off_usec = tv.tv_usec;
+    switch (REMOTE_TYP(rhdr->type)) {
+        case REMOTEDEV_TYPE_APPL:
+			conn = get_capioslib_connection(rhdr->conindex, 1);
+			if(conn == NULL) {
+				ret = NET_RX_DROP;
+				break;
+			}
+            if(ntohs(rhdr->seqnr) != conn->recv_seqnr) {
+                printk(KERN_WARNING "capi_oslib: recv: conn %d lost packet(s) seq-nr %d != %d(cdev) !\n", conn->conindex, ntohs(rhdr->seqnr), conn->recv_seqnr);
             }
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-            {
-            struct timeval tv;
+            conn->recv_seqnr = ntohs(rhdr->seqnr) + 1;
             skb_get_timestamp(skb, &tv);
             if (tv.tv_sec == 0) {
                 __net_timestamp(skb);
             }
-            }
-#else
-            if (skb->stamp.tv_sec == 0) {
-                get_fast_time(&skb->stamp);
-            }
-#endif/*--- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ---*/
-
-            /*--- printk(KERN_DEBUG "skb->len now %d\n", skb->len); ---*/
-
-            if (skb->len > 0) {
-                unsigned char type = skb->data[sizeof(struct rcapihdr)];
-                switch (type) {
-                    case 0:
-                        skb_pull(skb, sizeof(struct rcapihdr)); /* strip headers */
-                        if (rhdr->type != RCAPI_TYPE_APPL) {
-                            printk(KERN_ERR "capi_oslib: non-msg type only supported for RCAPI_TYPE_APPL!\n");
-                            goto freeskb;
-                        }
-                        if ((skb->len >= 4) && (memcmp(skb->data, "\0Bye", 4) == 0)) {
-                            /*--- printk(KERN_DEBUG "capi_oslib: client %d waves good-bye\n", conn->conindex); ---*/
-                            goto exit_reader_thread;
-                        } else
-                        if ((skb->len >= 6) && (memcmp(skb->data, "\0Hallo", 6) == 0)) {
-                            /*--- printk(KERN_DEBUG "capi_oslib: got greetings, send profile\n"); ---*/
-                            /*-------------------------------------------------------------------------------------*\
-                             * CAPI Profile etc.pp rüberschicken
-                             *
-                             * 4 Bytes Num. Controllers
-                             *      64 Bytes Manufacturer
-                             *      4  Bytes CAPI Major
-                             *      4  Bytes CAPI Minor
-                             *      4  Bytes Manu Major
-                             *      4  Bytes Manu Minor
-                             *      8  Bytes Serial No.
-                             *      64 Bytes Profile
-                            \*-------------------------------------------------------------------------------------*/
-                            unsigned char info[64];
-                            unsigned int num_controllers, i;
-                            struct sk_buff *skb;
-                            unsigned total_msg_len;
-                            u8 *data;
-                            int rc;
-                            struct net_device *dev;
-
-                            dev = capi_device();
-                            if (unlikely(!dev)) {
-                                printk(KERN_WARNING "capi_oslib: send profile but no dev!\n");
-                                break;
-                            }
-                            CAPI_GET_PROFILE(info, 0);
-                            num_controllers = EXTRACT_DWORD(info);
-
-                            total_msg_len = 4 + (num_controllers * 152) + 1;
-                            skb = capi_oslib_allocskb(total_msg_len, RCAPI_TYPE_APPL, conn->conindex, conn->send_seqnr, dev, &data, GFP_ATOMIC);
-                            if (unlikely(!skb)) {
-                                printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
-                                goto exit_reader_thread;
-                            } else {
-                                *data++ = 0;    /* keine CAPI Message */
-                                memcpy(data, info, sizeof(unsigned int));
-                                data += sizeof(unsigned int);
-                                for (i = 1; i <= num_controllers; i++) {
-                                    CAPI_GET_MANUFACTURER(info);
-                                    DEB_INFO("start info controller %d\n", i);
-                                    memcpy(data, info, 64);
-                                    data += 64;
-
-                                    CAPI_GET_VERSION((unsigned int*)&info[0], (unsigned int*)&info[4], (unsigned int*)&info[8],
-                                                     (unsigned int*)&info[12]);
-                                    memcpy(data, info, 16);
-                                    data += 16;
-
-                                    CAPI_GET_SERIAL_NUMBER(i, info);
-                                    memcpy(data, info, 8);
-                                    data += 8;
-
-                                    CAPI_GET_PROFILE(info, i);
-                                    memcpy(data, info, 64);
-                                    data += 64;
-                                }
-
-                                rc = dev_queue_xmit(skb); /* queue paket for transmitting */
-
-                                if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
-                                    printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
-                                }
-                                conn->send_seqnr++;
-                            }
-                        }
-                        kfree_skb(skb);
-                        return NET_RX_SUCCESS;
-                        break;
-                    case 1:
-                        skb_queue_tail(&conn->recvqueue, skb); /* add to receive queue */
-                        queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->tx_work);
-                        return NET_RX_SUCCESS;
-                        break;
-                    default:
-                        printk(KERN_ERR "capi_oslib: unknown type2 %d\n", type);
-                        goto freeskb;
-                        break;
-                }
-            } else {
-                goto freeskb;
-            }
-            break;
-
-        case RCAPI_TYPE_APPL_CONT:
-        case RCAPI_TYPE_APPL_END:
-            skb_queue_tail(&conn->recvqueue, skb); /* add to receive queue */
-            queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->tx_work);
-            return NET_RX_SUCCESS;
-        case RCAPI_TYPE_RESERVED:
-            printk(KERN_WARNING "capi_oslib: got msg of type RCAPI_TYPE_RESERVED\n");
-            goto freeskb;
-        case RCAPI_TYPE_PING:
-            /*--- printk(KERN_DEBUG "capi_oslib: got PING!\n"); ---*/
-            {
-                struct sk_buff *pong_skb;
-                int rc;
-                struct net_device *dev;
-
-                dev = capi_device();
-                if (unlikely(!dev)) {
-                    printk(KERN_WARNING "capi_oslib: got ping but have no dev!\n");
-                    goto freeskb;
-                }
-                pong_skb = capi_oslib_allocskb(0, RCAPI_TYPE_PING, 0, 0, dev, NULL, GFP_ATOMIC);
-                if (unlikely(!pong_skb)) {
-                    printk(KERN_ERR "capi_oslib: cannot allocate skb!\n");
-                } else {
-                    rc = dev_queue_xmit(pong_skb); /* queue paket for transmitting */
+			if(likely((rhdr->type & REMOTEDEV_TYPE_START) == REMOTEDEV_TYPE_START)) {
+				unsigned char type;
+				if (skb->len  <= 0) {
+					capi_oslib_conn_put(conn, "false skb_len");
+					break;
+				}
+				type = skb->data[sizeof(struct remotedev_hdr)];
+				switch (type) {
+					case MSG_TYPE_PROFILE:
+						skb_pull(skb, sizeof(struct remotedev_hdr)); /* strip headers */
+						if ((skb->len >= 6) && (memcmp(skb->data, "\0Hallo", 6) == 0)) {
+							/*--- printk(KERN_DEBUG "capi_oslib: got greetings, send profile\n"); ---*/
 
-                    if (unlikely(!(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN))) {
-                        printk(KERN_ERR "capi_oslib: dev_queue_xmit()=%d\n", rc);
-                    }
-                }
-            }
-            kfree_skb(skb);
-            return NET_RX_SUCCESS;
+							if(capioslib_send_profile(conn)) {
+								INIT_WORK(&conn->remove, capi_oslib_remove_conn);
+								if(queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->remove) == 0) {
+									capi_oslib_conn_put(conn, "capi_oslib_recv() pending remove-wkq(#0)");
+								}
+								break;
+							}
+						}
+						capi_oslib_conn_put(conn, "MSG_TYPE_PROFILE end");
+						break;
+					case MSG_TYPE_CAPI:
+						skb_queue_tail(&conn->recvqueue, skb); /* add to receive queue */
+						skb = NULL;
+						if(queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->tx_work) == 0) {
+							capi_oslib_conn_put(conn, "capi_oslib_recv() pending tx-wkq(#0)");
+						}
+						break;
+					default:
+						printk(KERN_ERR "capi_oslib: unknown type2 %d\n", type);
+						capi_oslib_conn_put(conn, "MSG_TYPE_unknown");
+						break;
+				}
+				break;
+			}
+			skb_queue_tail(&conn->recvqueue, skb); /* add to receive queue */
+			skb = NULL;
+			if(queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->tx_work) == 0) {
+				capi_oslib_conn_put(conn, "capi_oslib_recv() pending tx-wkq(#1)");
+			}
+			break;
+		case REMOTEDEV_TYPE_APPL_BYE:
+			conn = get_capioslib_connection(rhdr->conindex, 0);
+			if(conn == NULL) {
+				ret = NET_RX_DROP;
+				break;
+			}
+            SOCKET_IF_LOCK_TRC(KERN_DEBUG "capi_oslib: bye received conindex=%d\n", conn->conindex);
+			INIT_WORK(&conn->remove, capi_oslib_remove_conn);
+			if(queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->remove) == 0) {
+				capi_oslib_conn_put(conn, "capi_oslib_recv() pending remove-wkq(#1)");
+			}
+			break;
+        case REMOTEDEV_TYPE_PING:
+            /*--- printk(KERN_DEBUG "capi_oslib: ping received %d\n", REMOTE_TYP(rhdr->type)); ---*/
+			send_pong();
             break;
         default:
-            printk(KERN_ERR "capi_oslib: recv: type %d not implemented\n", rhdr->type);
-            goto freeskb;
-   }
-
-exit_reader_thread:
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
-    INIT_WORK(&conn->remove, capi_oslib_remove_conn, (void*)conn);
-#else
-    INIT_WORK(&conn->remove, capi_oslib_remove_conn);
-#endif
-    queue_work_on(PCMLINK_TASKLET_CONTROL_CPU, capi_remote_put_workqueue, &conn->remove);
-freeskb:
-   kfree_skb(skb);
-out_of_mem:
-   return NET_RX_DROP;
+            printk(KERN_ERR "capi_oslib: recv: type %x not implemented\n", REMOTE_TYP(rhdr->type));
+            break;
+    }
+	if(skb) {
+		kfree_skb(skb);
+	}
+	return ret;
 }
 
-static struct packet_type rcapi_packet_type = {
- type:__constant_htons(ETH_P_RCAPI),
- func:capi_oslib_recv,
-};
-
-
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
 static int capi_oslib_netdev_notifier_event(struct notifier_block *notifier __attribute__((unused)),
-                                       unsigned long event, void *ptr)
-{
+                                       unsigned long event, void *ptr) {
    struct net_device *dev = (struct net_device *) ptr;
 
    switch (event) {
@@ -807,53 +801,20 @@
          break;
 
       case NETDEV_REGISTER:
-         (void) capi_device();
+         /*--- printk(KERN_NOTICE "capi_oslib: device %s NETDEV_REGISTER.\n", dev->name); ---*/
+         capi_device();
          break;
    }
    return NOTIFY_DONE;
 }
 
-static struct notifier_block capi_oslib_netdev_notifier = {
-   .notifier_call = capi_oslib_netdev_notifier_event
-};
-
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-void capi_oslib_socket_init(void)
-{
-#if 0
-    struct sockaddr_in addr;
-    
-    if (sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &capi_socket) < 0)
-    {
-        DEB_INFO("capi_oslib_socket_init(): Error during creation of socket\n");
-        capi_socket = NULL;
-    }
-
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons((unsigned short)1234);
-    addr.sin_addr.s_addr = 0;
-
-    if (capi_socket->ops->bind(capi_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
-    {
-        DEB_INFO("capi_oslib_socket_init(): bind failed\n");
-        sock_release(capi_socket);
-        capi_socket = NULL;
-        return;
-    }
-
-    if (capi_socket->ops->listen(capi_socket, 1) < 0)
-    {
-        DEB_INFO("capi_oslib_socket_init(): listen failed\n");
-        sock_release(capi_socket);
-        capi_socket = NULL;
-        return;
-    }
-#endif
-
+void capi_oslib_socket_init(char *remote_device, unsigned short h_proto){
     LOCAL_CAPI_INIT(SOURCE_SOCKET_CAPI);
-
+	snprintf(g_remote_device, sizeof(g_remote_device), "%s", remote_device);
     register_netdevice_notifier(&capi_oslib_netdev_notifier);
+	rcapi_packet_type.type = htons(h_proto);
     dev_add_pack(&rcapi_packet_type);
     /*--- kernel_thread(capi_oslib_socket_accept_thread, NULL, 0); ---*/
     capi_remote_put_workqueue = create_workqueue("capi_remote_put");
--- linux-2.6.28/drivers/isdn/capi_oslib/socket_if.h
+++ linux-2.6.28/drivers/isdn/capi_oslib/socket_if.h
@@ -3,7 +3,7 @@
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-void capi_oslib_socket_init(void);
+void capi_oslib_socket_init(char *remote_device, unsigned short h_proto);
 
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
--- linux-2.6.28/drivers/isdn/isdn_fon5/init_isdn
+++ linux-2.6.28/drivers/isdn/isdn_fon5/init_isdn
@@ -9,7 +9,7 @@
 
 for i in `find . -name Makefile.$KERNEL_CLASS` ; do
     dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
+    source="${i##*/}"
     rm -f $dest
     ln -fvs $source $dest
 done
--- linux-2.6.28/drivers/mtd/devices/vx185_snor.c
+++ linux-2.6.28/drivers/mtd/devices/vx185_snor.c
@@ -135,14 +135,21 @@
 static int vx185_snor_rdsr(unsigned int *sr);
 
 static DECLARE_MUTEX(vx185_snor_sem);
+static unsigned int panic_mode = 0;
 
 /* GLOBAL FUNCTIONS */
-static void vx185_snor_spi_down(void) {
-    down(&vx185_snor_sem);
+static void vx185_snor_spi_down(void)
+{
+    if(!panic_mode){
+        down(&vx185_snor_sem);
+    }
 }
 
-static void vx185_snor_spi_up(void) {
-    up(&vx185_snor_sem);
+static void vx185_snor_spi_up(void)
+{
+    if(!panic_mode){
+        up(&vx185_snor_sem);
+    }
 }
 
 static int vx185_snor_rdsr(unsigned int *sr)
@@ -180,7 +187,7 @@
 
     if(ioread32(registers_ptr + VX185_SPI0_INT_STATUS_OFF) & SPI0_INT_TRNF_ERR){
         status = -EFAULT;
-        printk(KERN_ERR "[%s] Reading RSR failed!\n", __func__);
+        pr_err("[%s] Reading RSR failed!\n", __func__);
     } else {
         *sr = ioread32(registers_ptr + VX185_SPI0_DEV_RSR_OFF) & 0xff;
     }
@@ -201,8 +208,10 @@
     vx185_snor_wait();
 
     while(!(ioread32(registers_ptr + VX185_SPI0_STATUS_OFF) & SPI0_STATUS_RF_RST_DONE)){
-//        printk(KERN_ERR "[%s] Waiting for RX_FIFO reset completion\n", __func__);
-        schedule();
+//        pr_err("[%s] Waiting for RX_FIFO reset completion\n", __func__);
+        if(!panic_mode){
+            schedule();
+        }
     }
 
     reg = ioread32(registers_ptr + VX185_SPI0_PORT_CONFIG_OFF);
@@ -218,8 +227,10 @@
     vx185_snor_wait();
 
     while(!(ioread32(registers_ptr + VX185_SPI0_STATUS_OFF) & SPI0_STATUS_TF_RST_DONE)){
-//        printk(KERN_ERR "[%s] Waiting for TX_FIFO reset completion\n", __func__);
-        schedule();
+//        pr_err("[%s] Waiting for TX_FIFO reset completion\n", __func__);
+        if(!panic_mode){
+            schedule();
+        }
     }
     reg = ioread32(registers_ptr + VX185_SPI0_PORT_CONFIG_OFF);
     reg &= ~SPI0_PORT_CONFIG_TF_RST;
@@ -256,11 +267,11 @@
 
         if(sec_start == blk_start && end >= blk_end){
             // erase region covers the whole next block
-            printk(KERN_ERR "[%s] Erasing Block %#x\n", __func__, blk_start);
+            pr_debug("[%s] Erasing Block %#x\n", __func__, blk_start);
             status = vx185_snor_sector_erase(blk_start, cmd_table->be);
             start += layout->block_size;
         } else {
-            printk(KERN_ERR "[%s] Erasing Sector %#x\n", __func__, sec_start);
+            pr_debug("[%s] Erasing Sector %#x\n", __func__, sec_start);
             status = vx185_snor_sector_erase(sec_start, cmd_table->se);
             start += layout->sector_size;
         }
@@ -291,7 +302,7 @@
     volatile u_int32_t reg, int_status, received;
 
     if(len > RX_FIFO_SIZE){
-        printk(KERN_ERR "[%s] len %d > RX_FIFO_SIZE\n", __func__, len);
+        pr_err("[%s] len %d > RX_FIFO_SIZE\n", __func__, len);
         *retlen = 0;
         return -EINVAL;
     }
@@ -336,7 +347,7 @@
     int_status = ioread32(registers_ptr + VX185_SPI0_INT_STATUS_OFF);
 
     if(int_status & SPI0_INT_TRNF_ERR){
-        printk(KERN_ERR "[%s] SPI transfer error.\n", __func__);
+        pr_err("[%s] SPI transfer error.\n", __func__);
         *retlen = 0;
         return -EIO;
     }
@@ -344,23 +355,9 @@
 
     received = 0;
     while(!(ioread32(registers_ptr + VX185_SPI0_INT_STATUS_OFF) & SPI0_INT_RF_EMPTY) && (received < ARRAY_SIZE(mybuf))){
-#if 0
-        if(received % 16 == 0){
-            printk(KERN_ERR "[%s] ", __func__);
-        }
-#endif
         mybuf[received] = ioread32(rx_ptr);
-#if 0
-        printk("%08x ", mybuf[received]);
-        if(received % 16 == 15){
-            printk("\n");
-        }
-#endif
         ++received;
     }
-#if 0
-    printk("\n");
-#endif
 
     if(received > 0){
         memcpy(buf, &(mybuf[0]), len);
@@ -429,7 +426,7 @@
         result = vx185_snor_rdsr(&rdsr);
     } while(result == 0 && (rdsr & SPI0_DEV_RSR_WIP));
 
-//    printk(KERN_ERR "[%s] rdsr: %#x\n", __func__, rdsr);
+//    pr_err("[%s] rdsr: %#x\n", __func__, rdsr);
 
     if(rdsr < 0){
         return result;
@@ -445,7 +442,7 @@
     vx185_snor_wait();
 
     result = vx185_snor_rdsr(&rdsr);
-//    printk(KERN_ERR "[%s] rdsr: %#x\n", __func__, rdsr);
+//    pr_err("[%s] rdsr: %#x\n", __func__, rdsr);
 
     vx185_snor_wait();
 
@@ -486,7 +483,7 @@
         if(padding != 0){
             ++chunksize;
             padding = sizeof(mybuf[0]) - padding;
-            printk(KERN_ERR "[%s] padding: %d\n", __func__, padding);
+//            pr_err("[%s] padding: %d\n", __func__, padding);
         }
     }
 
@@ -496,21 +493,9 @@
     iowrite32(0, registers_ptr + VX185_SPI0_INT_STATUS_OFF);
     sent = 0;
     while(sent < chunksize && !(ioread32(registers_ptr + VX185_SPI0_INT_STATUS_OFF) & SPI0_INT_TF_FULL)){
-#if 0
-        if(sent % 16 == 0){
-            printk(KERN_ERR "[%s] ", __func__);
-        }
-        printk("%08x ", mybuf[sent]);
-        if(sent % 16 == 15){
-            printk("\n");
-        }
-#endif
         iowrite32(mybuf[sent], tx_ptr);
         ++sent;
     }
-#if 0
-    printk("\n");
-#endif
 
     reg = ioread32(registers_ptr + VX185_SPI0_PORT_CONFIG_OFF);
     reg |= SPI0_PORT_CONFIG_START;
@@ -595,7 +580,9 @@
     while(   (ioread32(registers_ptr + VX185_SPI0_STATUS_OFF) & SPI0_STATUS_BUSY)
           || (ioread32(registers_ptr + VX185_SPI0_PORT_CONFIG_OFF) & SPI0_PORT_CONFIG_START))
     {
-        schedule();
+        if(!panic_mode){
+            schedule();
+        }
     }
 }
 
@@ -637,7 +624,7 @@
 
     status = vx185_snor_rdsr(&rdsr);
     if(status < 0 || !(rdsr & SPI0_DEV_RSR_WEL)){
-        printk(KERN_ERR "[%s] Setting WREN failed.\n", __func__);
+        pr_err("[%s] Setting WREN failed.\n", __func__);
         status = -EFAULT;
     }
 
@@ -719,7 +706,7 @@
     iowrite32(reg, registers_ptr + VX185_SPI0_PORT_CONFIG_OFF);
 
     if(ioread32(registers_ptr + VX185_SPI0_INT_STATUS_OFF) & SPI0_INT_TRNF_ERR){
-        printk(KERN_ERR "[%s] Illegal SPI instruction.\n", __func__);
+        pr_err("[%s] Illegal SPI instruction.\n", __func__);
         status = -EFAULT;
     }
 
@@ -731,7 +718,7 @@
     }while(status == 0 && (rdsr & SPI0_DEV_RSR_WIP));
 
     if(status < 0 || (rdsr & SPI0_DEV_RSR_E_RR)){
-        printk(KERN_ERR "[%s] Erasing sector %#x failed!\n", __func__, addr);
+        pr_err("[%s] Erasing sector %#x failed!\n", __func__, addr);
         status = -EFAULT;
     }
 
@@ -757,24 +744,24 @@
 {
     u_int32_t gpio_func;
 
-    printk(KERN_INFO "%s, Version %s (c) 2012 AVM GmbH.\n", DRIVER_DESC, DRIVER_VERSION);
+    pr_info("%s, Version %s (c) 2012 AVM GmbH.\n", DRIVER_DESC, DRIVER_VERSION);
 
     spi_registers = request_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs), "vx185_snor_io");
     if(spi_registers == NULL){
-        printk(KERN_ERR "[%s] request_mem_region for spi_rx_fifo failed!\n", __func__);
+        pr_err("[%s] request_mem_region for spi_rx_fifo failed!\n", __func__);
         return -EFAULT;
     }
 
     registers_ptr = ioremap_nocache(spi_registers->start, (spi_registers->end - spi_registers->start + 1));
     if(registers_ptr == NULL){
-        printk(KERN_ERR "[%s] ioremap_nocache for registers_ptr failed!\n", __func__);
+        pr_err("[%s] ioremap_nocache for registers_ptr failed!\n", __func__);
         release_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs));
         return -EFAULT;
     }
 
     spi_rx_fifo = request_mem_region(VX185_SPI0_RX_FIFO, sizeof(u_int32_t), "vx185_snor_rx");
     if(spi_rx_fifo == NULL){
-        printk(KERN_ERR "[%s] request_mem_region for spi_rx_fifo failed!\n", __func__);
+        pr_err("[%s] request_mem_region for spi_rx_fifo failed!\n", __func__);
         iounmap(registers_ptr);
         release_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs));
         return -EFAULT;
@@ -782,7 +769,7 @@
 
     rx_ptr = ioremap_nocache(spi_rx_fifo->start, sizeof(u_int32_t));
     if(rx_ptr == NULL){
-        printk(KERN_ERR "[%s] ioremap_nocache for rx_ptr failed!\n", __func__);
+        pr_err("[%s] ioremap_nocache for rx_ptr failed!\n", __func__);
         iounmap(registers_ptr);
         release_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs));
         release_mem_region(VX185_SPI0_RX_FIFO, sizeof(u_int32_t));
@@ -791,7 +778,7 @@
 
     spi_tx_fifo = request_mem_region(VX185_SPI0_TX_FIFO, sizeof(u_int32_t), "vx185_snor_tx");
     if(spi_tx_fifo == NULL){
-        printk(KERN_ERR "[%s] request_mem_region for spi_tx_fifo failed!\n", __func__);
+        pr_err("[%s] request_mem_region for spi_tx_fifo failed!\n", __func__);
         iounmap(registers_ptr);
         release_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs));
         iounmap(rx_ptr);
@@ -801,7 +788,7 @@
 
     tx_ptr = ioremap_nocache(spi_tx_fifo->start, sizeof(u_int32_t));
     if(tx_ptr == NULL){
-        printk(KERN_ERR "[%s] ioremap_nocache for tx_ptr failed!\n", __func__);
+        pr_err("[%s] ioremap_nocache for tx_ptr failed!\n", __func__);
         iounmap(registers_ptr);
         release_mem_region(VX185_SPI0_BASE, sizeof(struct __vx185_spi0_regs));
         iounmap(rx_ptr);
@@ -811,7 +798,7 @@
     }
 
 
-    printk(KERN_ERR "[%s] regs: %p rx_ptr: %p tx_ptr: %p\n", __func__, registers_ptr, rx_ptr, tx_ptr);
+    pr_err("[%s] regs: %p rx_ptr: %p tx_ptr: %p\n", __func__, registers_ptr, rx_ptr, tx_ptr);
 
 #if 0
     gpio_func = IKS_REG_R32(VX185_GPIO_MODE1);
@@ -854,7 +841,7 @@
     unsigned int flash_id, manufact_id, device_id, device_size;
 
     flash_id = vx185_snor_read_id();
-    printk(KERN_ERR "[%s] Chip-ID: %08x\n", __func__, flash_id);
+    pr_err("[%s] Chip-ID: %08x\n", __func__, flash_id);
 
     manufact_id = (flash_id >> 16) & 0xff;
     device_id = (flash_id >> 8) & 0xff;
@@ -863,21 +850,21 @@
     switch(manufact_id){
     case MANUFACT_ID_SPANSION:
         if(flash_id == 0x00010215){
-            printk(KERN_ERR "[%s] found 4MB Spansion flash.\n", __func__);
+            pr_err("[%s] found 4MB Spansion flash.\n", __func__);
         } else {
-            printk(KERN_ERR "[%s] found unknown Spansion flash, assuming 4MB.\n", __func__);
+            pr_err("[%s] found unknown Spansion flash, assuming 4MB.\n", __func__);
         }
         layout = &layout_spansion;
         cmd_table = &spansion_cmd_table;
         break;
     case MANUFACT_ID_MACRONIX:
-        printk(KERN_ERR "[%s] found Macronix flash.\n", __func__);
+        pr_err("[%s] found Macronix flash.\n", __func__);
         layout = &layout_macronix;
         layout->size = 1 << device_size;
         cmd_table = &macronix_cmd_table;
         break;
     default:
-        printk(KERN_ERR "[%s] unknown flash found, assuming 256k.\n", __func__);
+        pr_err("[%s] unknown flash found, assuming 256k.\n", __func__);
         layout = &layout_spansion;
         layout->size = 256 << 10;
         cmd_table = &spansion_cmd_table;
@@ -915,6 +902,21 @@
     return status;
 }
 
+int vx185_snor_panic_reinit(void)
+{
+    int result = 0;
+
+    if(down_trylock(&vx185_snor_sem)){
+        result = -EBUSY;
+    } else {
+        panic_mode = 1;
+    }
+
+    return result;
+}
+
+EXPORT_SYMBOL(vx185_snor_panic_reinit);
+
 module_init(vx185_snor_init);
 module_exit(vx185_snor_exit);
 
--- linux-2.6.28/drivers/mtd/mtdpart.c
+++ linux-2.6.28/drivers/mtd/mtdpart.c
@@ -566,7 +566,7 @@
 	int ret = 0;
 
 	for ( ; ret <= 0 && *types; types++) {
-printk("[%s] types=%s\n", __FUNCTION__, *types);
+	    printk("[%s] types=%s\n", __FUNCTION__, *types);
 		parser = get_partition_parser(*types);
 		if (!parser && !request_module("%s", *types))
 				parser = get_partition_parser(*types);
--- linux-2.6.28/drivers/mtd/nand/direct_avm.c
+++ linux-2.6.28/drivers/mtd/nand/direct_avm.c
@@ -828,7 +828,7 @@
 };
 
 static int __init direct_avm_nand_init(void) {
-	printk(KERN_INFO "AVM Direct NAND driver, Â© 2008 AVM Berlin\n");
+	printk(KERN_INFO "AVM Direct NAND driver, (c) 2008 AVM Berlin\n");
 #if defined(DIRECT_NAND_USE_READY_SEMA)
     sema_init(&direct_nand_ready_sema, 0);
 #endif /*--- #if defined(DIRECT_NAND_USE_READY_SEMA) ---*/
--- linux-2.6.28/drivers/mtd/nand/fusiv_nand.c
+++ linux-2.6.28/drivers/mtd/nand/fusiv_nand.c
@@ -703,16 +703,6 @@
             mtd->ecc_stats.failed++;
     }
 
-#if 0
-    if(buf[0] != 0xff){
-        printk(KERN_ERR "[%s] page: %08x\n", __func__, fusiv_nfc_readl(NFC_INDEX) >> 12);
-        print_buf(__func__, buf, mtd->writesize);
-        printk(KERN_ERR "[%s] oob:\n", __func__);
-        print_buf(__func__, chip->oob_poi, mtd->oobsize);
-
-    }
-#endif
-
     return 0;
 }
 #endif
--- linux-2.6.28/drivers/mtd/nand/nand_base.c
+++ linux-2.6.28/drivers/mtd/nand/nand_base.c
@@ -1059,7 +1059,7 @@
 	}
 	return NULL;
 }
-
+#if defined(CONFIG_FUSIV_VX180)
 static int avmCorrectNotWrittenECC(struct mtd_info *mtd, struct nand_chip *chip, int page) {
     // copy buf for compare
     static uint8_t buf[2048]; // maximale GrÃ¶ÃŸe einer Page
@@ -1153,6 +1153,7 @@
 
     return -1;
 }
+#endif // !defined(CONFIG_FUSIV_VX180)
 
 /**
  * nand_do_read_ops - [Internal] Read data with ECC
@@ -1202,6 +1203,18 @@
 				sndcmd = 0;
 			}
 
+#if !defined(CONFIG_FUSIV_VX180)
+			/* Now read the page into the buffer */
+           if (unlikely(ops->mode == MTD_OOB_RAW))
+                   ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+           else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+                   ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
+           else
+                   ret = chip->ecc.read_page(mtd, chip, bufpoi);
+           if (ret < 0)
+                   break;
+#else //
+
 			/* Now read the page into the buffer */
             {
                 if (unlikely(ops->mode == MTD_OOB_RAW))
@@ -1253,7 +1266,7 @@
                 if (ret < 0)
                     break;
             }
-
+#endif // defined(CONFIG_FUSIV_VX180)
 			/* Transfer not aligned data */
 			if (!aligned) {
 				if (!NAND_SUBPAGE_READ(chip) && !oob)
--- linux-2.6.28/drivers/net/avm_cpmac/cpmacconfig.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpmacconfig.c
@@ -40,20 +40,26 @@
     "  cpmacconfig <device> mode special (<dev name>,<port>[,<port>...] [optional VIDs]",
     "                       ports start at 0",
     "  cpmacconfig <device> addporttowan <port> [<optional decimal VID>]",
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_SET_TRUNK_PORTS)
     "  cpmacconfig <device> settrunkports <portset> <name> <decimal VID range start> <decimal VID range end>",
+#   endif /*--- #if defined(AVM_CPMAC_IOCTL_CONFIG_SET_TRUNK_PORTS) ---*/
     "  cpmacconfig <device> power <on interval> <off interval> <5 * (on|off|save)>",
     "  cpmacconfig <device> setreg <hex register> <hex value>",
     "  cpmacconfig <device> getreg <hex register>",
     "  cpmacconfig <device> setphy <hex phy> <hex register> <hex value>",
     "  cpmacconfig <device> getphy <hex phy> <hex register>",
     "  cpmacconfig <device> regdump",
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_SET_IGMP_FWD)
     "  cpmacconfig <device> set_igmp_fwd <portmask>",
+#   endif /*--- #if defined(AVM_CPMAC_IOCTL_CONFIG_SET_IGMP_FWD) ---*/
     "  cpmacconfig <device> support",
     "  cpmacconfig <device> test <value>",
     "  cpmacconfig <device> peek <location> [length [size]]",
     "  cpmacconfig <device> poke <location> <value> [size]",
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_MIRROR_PORT)
     "  cpmacconfig <device> mirror <from_port> <to_port> <enable_ingress> <enable_egress>",
     "                       enable_* should be 0 or 1",
+#   endif #if defined(AVM_CPMAC_IOCTL_CONFIG_MIRROR_PORT)
     "  cpmacconfig <device> vlanadd <decimal VID>",
     "                       <device> must be shorter than 16 characters",
     "  cpmacconfig <device> vlanrem",
@@ -246,6 +252,7 @@
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
 
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_SET_TRUNK_PORTS)
     } else if(strcasecmp(cmd, "settrunkports") == 0) {
         /* Set trunk ports */
         if(argc != 7)
@@ -262,6 +269,7 @@
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
 
+#   endif /*--- #if defined(AVM_CPMAC_IOCTL_CONFIG_SET_TRUNK_PORTS) ---*/
     } else if(strcasecmp(cmd, "power") == 0) {
         /* Configure power settings */
         if(argc != 9)
@@ -356,6 +364,7 @@
 
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_SET_IGMP_FWD)
     } else if(strcasecmp(cmd, "set_igmp_fwd") == 0) {
         /* Execute set_igmp_fwd function in driver */
         if(argc != 4)
@@ -365,6 +374,7 @@
 
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
+#   endif /*--- #if defined(AVM_CPMAC_IOCTL_CONFIG_SET_IGMP_FWD) ---*/
     } else if(strcasecmp(cmd, "support") == 0) {
         /* Print support data of the driver */
         if(argc != 3)
@@ -413,6 +423,7 @@
         }
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
+#   if defined(AVM_CPMAC_IOCTL_CONFIG_MIRROR_PORT)
     } else if(strcasecmp(cmd, "mirror") == 0) {
         /* Configure port mirror */
         if(argc != 7)
@@ -428,6 +439,7 @@
         config.u.mirror_port.enable_egress = (unsigned char) value;
         if(ioctl(fd, AVM_CPMAC_IOCTL_GENERIC, (caddr_t) &ifr) < 0)
             goto ioctl_failed;
+#   endif /*--- #if defined(AVM_CPMAC_IOCTL_CONFIG_MIRROR_PORT) ---*/
     } else if(strcasecmp(cmd, "vlanadd") == 0) {
         /* Add VLAN tagged device */
         struct vlan_ioctl_args if_request;
--- linux-2.6.28/drivers/net/avm_cpmac/cpmac_eth.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpmac_eth.c
@@ -226,6 +226,8 @@
     struct cpmac_devinfo *devinfo = netdev_priv(dev);
     struct net_device_stats *stats = &devinfo->stats;
 
+    skb_track_caller(skb);
+
 #   ifdef CONFIG_AVM_RTP_TIMESTAMP
     rtp_timestamp_trace_session_from_skb_data(skb, 1);
 #   endif
@@ -263,7 +265,8 @@
     /*--- DEB_TRC("[%s] %s (%u) %*pB ... \n", __FUNCTION__, skb->dev->name, skb->len, min(24u, skb->len), skb->data); ---*/
     skb->dev = devinfo->real_dev;
     dev->trans_start = jiffies;
-    return dev_queue_xmit(skb);
+    dev_queue_xmit(skb);
+    return NETDEV_TX_OK;
 }
 
 
@@ -273,6 +276,8 @@
     struct cpmac_devinfo *devinfo = netdev_priv(dev);
     struct net_device_stats *stats = &devinfo->stats;
 
+    skb_track_caller(skb);
+
 #   ifdef CONFIG_AVM_RTP_TIMESTAMP
     rtp_timestamp_trace_session_from_skb_data(skb, 1);
 #   endif
@@ -313,7 +318,8 @@
     /*--- DEB_TRC("[%s] (%u) %:24B ... \n", __FUNCTION__, skb->len, skb->data, skb->len); ---*/
     skb->dev = devinfo->real_dev;
     dev->trans_start = jiffies;
-    return dev_queue_xmit(skb);
+    dev_queue_xmit(skb);
+    return NETDEV_TX_OK;
 }
 
 
@@ -353,7 +359,7 @@
     struct ifreq ifrr;
     int err = -EOPNOTSUPP;
 
-    strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ);
+    strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ - 1);
     ifrr.ifr_ifru = ifr->ifr_ifru;
 
     switch(cmd) {
--- linux-2.6.28/drivers/net/avm_cpmac/cpmac_main.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpmac_main.c
@@ -314,6 +314,8 @@
 
     DEB_DEBUG("[%s] (%u) %*pB ...\n", __FUNCTION__, skb->len, min(24u, skb->len), skb->data);
 
+    skb_track_caller(skb);
+
 #   ifdef CONFIG_AVM_RTP_TIMESTAMP
     rtp_timestamp_trace_session_from_skb_data(skb, 1);
 #   endif
@@ -592,7 +594,7 @@
     struct cpmac_event_struct *event_struct;
 
     if(avm_event_source_check_id(cpmac_event_handle, avm_event_id_ethernet_connect_status)) {
-        if(!(event_struct = (struct cpmac_event_struct *) kmalloc(sizeof(struct cpmac_event_struct), GFP_ATOMIC))) {
+        if(!(event_struct = kmalloc(sizeof(struct cpmac_event_struct), GFP_ATOMIC))) {
             DEB_ERR("[%s] nomem for status update\n", __FUNCTION__);
         } else {
             cpmac_global.event_data.ports = cpmac_global.ports;
--- linux-2.6.28/drivers/net/avm_cpmac/cpmac_product_conf.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpmac_product_conf.c
@@ -1,7 +1,7 @@
 #include "cpphy_types.h"
 
 cpmac_product_struct cpmac_products = {
-    42,
+    43,
     {
         { /* Fritz_Box_3270 */
             "137 ",
@@ -403,7 +403,7 @@
                 }
             }
         },
-        { /* Fritz_Box_HW18310 */
+        { /* Fritz_Box_HW185 */
             "185 ",
             1,
             {
@@ -643,46 +643,6 @@
                 }
             }
         },
-        { /* Fritz_Box_HW204a */
-            "204a ",
-            2,
-            {
-                {
-                    CPMAC_PHY_TYPE_AR8316,
-                    CPMAC_PHY_MODE_MAGPIE,
-                    0x3f,
-                    28,
-                    0x20
-                },
-                {
-                    CPMAC_PHY_TYPE_NONE,
-                    CPMAC_PHY_MODE_DEFAULT,
-                    0x1,
-                    0xffff,
-                    0x0
-                }
-            }
-        },
-        { /* Fritz_Box_HW204x */
-            "204x ",
-            2,
-            {
-                {
-                    CPMAC_PHY_TYPE_AR8316,
-                    CPMAC_PHY_MODE_MAGPIE,
-                    0x3f,
-                    28,
-                    0x20
-                },
-                {
-                    CPMAC_PHY_TYPE_NONE,
-                    CPMAC_PHY_MODE_DEFAULT,
-                    0x1,
-                    0xffff,
-                    0x0
-                }
-            }
-        },
         { /* Fritz_Box_HW209 */
             "209 ",
             0,
@@ -783,16 +743,36 @@
                 }
             }
         },
-        { /* Fritz_Box_QCA_ARM */
-            "299 ",
+        { /* Fritz_Box_HW223 */
+            "223 ",
+            1,
+            {
+                {
+                    CPMAC_PHY_TYPE_NONE,
+                    CPMAC_PHY_MODE_DEFAULT,
+                    0x1,
+                    0xffff,
+                    0x0
+                },
+                {
+                    CPMAC_PHY_TYPE_NONE,
+                    CPMAC_PHY_MODE_DEFAULT,
+                    0x1,
+                    0xffff,
+                    0x0
+                }
+            }
+        },
+        { /* Fritz_Box_HW224 */
+            "224 ",
             2,
             {
                 {
-                    CPMAC_PHY_TYPE_AR8316,
-                    CPMAC_PHY_MODE_MAGPIE,
-                    0x3f,
-                    28,
-                    0x20
+                    CPMAC_PHY_TYPE_AR8327,
+                    CPMAC_PHY_MODE_AR8216,
+                    0x1f,
+                    10,
+                    0x0
                 },
                 {
                     CPMAC_PHY_TYPE_NONE,
--- linux-2.6.28/drivers/net/avm_cpmac/cpphy_ar8216_ar.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpphy_ar8216_ar.c
@@ -624,8 +624,8 @@
 \*---------------------------------------------------------------------------*/
 unsigned long ar8216_ar_work_item(cpphy_mdio_t *mdio) {
     unsigned long flags;
-    int maxskbs __attribute__ ((unused));
 #   if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG
+    int maxskbs;
     unsigned long old_skb_dropped;
 #   endif /*--- #if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG ---*/
 
@@ -640,9 +640,15 @@
               /*--- atomic_read(&cpmac_global.macportmap.nskbs)); ---*/
 
     if(cpmac_global.cpphy[mdio->phy_num].config->type == CPMAC_PHY_TYPE_AR8327) {
-        maxskbs = ar8327_read_mac_table(mdio);
+#       if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG
+        maxskbs = 
+#       endif /*--- #if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG ---*/
+        ar8327_read_mac_table(mdio);
     } else {
-        maxskbs = ar8216_read_mac_table(mdio);
+#       if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG
+        maxskbs = 
+#       endif /*--- #if CPMAC_DEBUG_LEVEL & CPMAC_DEBUG_LEVEL_DEBUG ---*/
+        ar8216_read_mac_table(mdio);
     }
 
     /*
--- linux-2.6.28/drivers/net/avm_cpmac/cpphy_cppi.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpphy_cppi.c
@@ -353,7 +353,7 @@
     if(!(AllTcb = cppi->TcbStart)) {
         DEB_TRC("[%s] Allocating block for tcbs\n", __func__);
         /* malloc all TCBs at once */
-        if(!(AllTcb = (char *) kmalloc (size_malloc, GFP_KERNEL))) {
+        if(!(AllTcb = kmalloc(size_malloc, GFP_KERNEL))) {
             ret = CPMAC_ERR_NOMEM;
         } else {
             dma_cache_wback_inv((unsigned long) AllTcb, size_malloc);
--- linux-2.6.28/drivers/net/avm_cpmac/cpphy_if.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpphy_if.c
@@ -180,6 +180,7 @@
 #   if defined(CONFIG_AVM_SIMPLE_PROFILING)
     skb_trace(skb, 20);
 #   endif /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/
+    skb_track_func(skb);
     dev_kfree_skb_any(skb);
 }
 
--- linux-2.6.28/drivers/net/avm_cpmac/cpphy_switch.c
+++ linux-2.6.28/drivers/net/avm_cpmac/cpphy_switch.c
@@ -1,5 +1,5 @@
 /*------------------------------------------------------------------------------------------*\
- *   Copyright (C) 2008,2009,...,2012 AVM GmbH <fritzbox_info@avm.de>
+ *   Copyright (C) 2008,2009,...,2014 AVM GmbH <fritzbox_info@avm.de>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -721,7 +721,9 @@
     switch_config->wanport_keeptags = 0;
 
     /* Make sure to unregister wan fast forward, before the port info is gone */
-    cpphy_switch_unregister_ffw_port(cpmac_global.cpphy[0].mdio.switch_config.wanport);
+    if(cpmac_global.cpphy[0].mdio.switch_config.wanport != 255) {
+        cpphy_switch_unregister_ffw_port(cpmac_global.cpphy[0].mdio.switch_config.wanport);
+    }
 
     /* Now start configuration */
     switch_config->enable_vlan = 1; /* TODO Consider old 7170 and other hardware! */
--- linux-2.6.28/drivers/net/avm_cpmac/cpphy_switch.h
+++ linux-2.6.28/drivers/net/avm_cpmac/cpphy_switch.h
@@ -46,7 +46,7 @@
 } cpmac_vid_range_t;
 
 typedef struct {
-  char               name[AVM_CPMAC_MAX_DEVICE_NAME_LENGTH]; /* Name of device */
+  char               name[AVM_CPMAC_MAX_DEVICE_NAME_LENGTH + 1]; /* Name of device */
   unsigned char      target_mask; /* Mask for the ports that should receive tagged packets */
   cpmac_vid_range_t *vid_range;
 } cpmac_device_new_t;
--- linux-2.6.28/drivers/net/avm_cpmac/Makefile
+++ linux-2.6.28/drivers/net/avm_cpmac/Makefile
@@ -12,7 +12,8 @@
 #EXTRA_CFLAGS += -Wpadded
 #EXTRA_CFLAGS += -Wunreachable-code
 EXTRA_CFLAGS += -Wall -Wextra -Werror
-EXTRA_CFLAGS += -DAVM_CPMAC_VERSION="\"`svn info $(src) | grep URL | sed -e "s/^.*\/\([0-9.]\+\)-[^\/]*/\1/g"`  -  Revision `svnversion -cn $(src)`  -  `date +\"%a  %e.%m.%Y  %H:%M:%S\"` \""
+avm_version := $(shell svn info $(src) | grep -e ^URL | sed -e "s/^.*\/\([0-9.]\+\)-[^\/]*/\1/g")  -  Revision $(shell svnversion -cn $(src))  -  $(shell date +'%a  %e.%m.%Y  %H:%M:%S')
+EXTRA_CFLAGS += -DAVM_CPMAC_VERSION='"$(avm_version)"'
 
 # declare multi-module main driver.
 obj-$(CONFIG_AVM_CPMAC)	+= avm_cpmac.o
--- linux-2.6.28/drivers/net/avm_cpmac/Makefile.26
+++ linux-2.6.28/drivers/net/avm_cpmac/Makefile.26
@@ -12,7 +12,8 @@
 #EXTRA_CFLAGS += -Wpadded
 #EXTRA_CFLAGS += -Wunreachable-code
 EXTRA_CFLAGS += -Wall -Wextra -Werror
-EXTRA_CFLAGS += -DAVM_CPMAC_VERSION="\"`svn info $(src) | grep URL | sed -e "s/^.*\/\([0-9.]\+\)-[^\/]*/\1/g"`  -  Revision `svnversion -cn $(src)`  -  `date +\"%a  %e.%m.%Y  %H:%M:%S\"` \""
+avm_version := $(shell svn info $(src) | grep -e ^URL | sed -e "s/^.*\/\([0-9.]\+\)-[^\/]*/\1/g")  -  Revision $(shell svnversion -cn $(src))  -  $(shell date +'%a  %e.%m.%Y  %H:%M:%S')
+EXTRA_CFLAGS += -DAVM_CPMAC_VERSION='"$(avm_version)"'
 
 # declare multi-module main driver.
 obj-$(CONFIG_AVM_CPMAC)	+= avm_cpmac.o
--- linux-2.6.28/drivers/serial/serial_core.c
+++ linux-2.6.28/drivers/serial/serial_core.c
@@ -489,6 +489,23 @@
 	uart_start(tty);
 }
 
+unsigned int enable_avm_console;
+static int uart_avm_console(struct tty_struct *tty) {
+
+	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->port;
+
+    if (port->cons) {
+        if (port->cons->flags & (CON_ENABLED | CON_CONSDEV)) {
+            if (enable_avm_console)
+                return 0;
+            else
+                return 1;
+        }
+    }
+    return 0;
+}
+
 static int
 uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
@@ -2274,12 +2291,20 @@
 	struct uart_driver *drv = driver->driver_state;
 	struct uart_state *state = drv->state + line;
 	struct uart_port *port;
+    int ch;
 
 	if (!state || !state->port)
 		return -1;
 
 	port = state->port;
-	return port->ops->poll_get_char(port);
+    ch = port->ops->poll_get_char(port);
+
+    if (port->cons->flags & (CON_ENABLED | CON_CONSDEV)) {
+        if (ch == 0xD) {
+            enable_avm_console = 1;
+        }
+    }
+	return ch;
 }
 
 static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
@@ -2326,6 +2351,7 @@
 	.poll_get_char	= uart_poll_get_char,
 	.poll_put_char	= uart_poll_put_char,
 #endif
+    .is_avm_console    = uart_avm_console,
 };
 
 /**
--- linux-2.6.28/include/asm-mips/mach_avm.h
+++ linux-2.6.28/include/asm-mips/mach_avm.h
@@ -686,4 +686,10 @@
 
 #endif /*--- #ifdef CONFIG_MIPS_FUSIV ---*/
 
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+#define avm_get_cycles()             get_cycles()
+#define avm_get_cyclefreq()          (avm_get_clock(avm_clock_id_cpu) / 2 )
+#define avm_cycles_cpuclock_depend() (1)
+
 #endif /*--- #ifndef _mach_avm_h_ ---*/
--- linux-2.6.28/include/linux/avm_led_event.h
+++ linux-2.6.28/include/linux/avm_led_event.h
@@ -1,11 +1,11 @@
-/*** LED-Events Version 2.11 ***/
+/*** LED-Events Version 2.16 ***/
 
 #ifndef _avm_led_event_h_
 #define _avm_led_event_h_
 
 #ifndef LED_EVENT_VERSION
 #define LED_EVENT_VERSION 2
-#define LED_EVENT_SUBVERSION 11
+#define LED_EVENT_SUBVERSION 16
 #endif
 
 #ifndef AVM_LED_INTERNAL
@@ -16,6 +16,8 @@
 	event_update_fw_available = 6,
 	event_update_running = 7,
 	event_update_error = 8,
+	event_ipclient_disable = 9,
+	event_ipclient_enable = 10,
 	event_ata_disable = 11,
 	event_ata_enable = 12,
 	event_tr69_no_message = 13,
@@ -139,6 +141,8 @@
 	event_wlan_guest_device_allgone = 181,
 	event_wlan_device_max_reached = 182,
 	event_wlan_device_max_not_reached = 183,
+	event_wlan_macfilter_max_reached = 171,
+	event_wlan_macfilter_max_not_reached = 172,
 	event_usb_host_stick_and_surf_start = 184,
 	event_usb_host_stick_and_surf_error = 185,
 	event_usb_host_stick_and_surf_done = 186,
@@ -176,6 +180,10 @@
 	event_lan3_inactive = 243,
 	event_lan4_active = 244,
 	event_lan4_inactive = 245,
+	event_lan5_active = 370,
+	event_lan5_inactive = 371,
+	event_wan_active = 374,
+	event_wan_inactive = 375,
 	event_device_init_start = 247,
 	event_device_init_end = 248,
 	event_device_reset = 249,
@@ -236,9 +244,24 @@
 	event_acmeter_ctrl_prog_run = 343,
 	event_lte_antenna_external = 350,
 	event_lte_antenna_internal = 351,
+	event_lte_power = 352,
+	event_lte_disable = 353,
+	event_lte_map_info_on = 345,
+	event_lte_map_info_off = 346,
+	event_lte_map_mode_rssi = 347,
+	event_lte_map_mode_type = 348,
+	event_lte_map_mode_rssi_all_leds = 349,
+	event_lte_type_no_signal = 356,
+	event_lte_type_2g = 357,
+	event_lte_type_3g = 358,
+	event_lte_type_4g = 359,
 	event_button_events_enable = 360,
 	event_button_events_disable = 361,
-	LastEvent = 362
+	event_message_warning_high_priority = 380,
+	event_message_warning_medium_priority = 381,
+	event_message_warning_low_priority = 382,
+	event_message_warning_off = 383,
+	LastEvent = 384
 };
 #endif /*--- #ifndef AVM_LED_INTERNAL ---*/
 
--- linux-2.6.28/include/linux/avm_pa.h
+++ linux-2.6.28/include/linux/avm_pa.h
@@ -41,6 +41,7 @@
 
 /* ------------------------------------------------------------------------ */
 #define AVM_PA_HAS_LISP_SUPPORT
+#define AVM_PA_RECVHOOK_AVAILABLE
 /* ------------------------------------------------------------------------ */
 
 typedef unsigned char  avm_pid_handle;     /* 1 - AVM_PA_MAX_PID */
@@ -184,6 +185,9 @@
 	u64 tx_bytes;
 	u32 tx_error;
 	u32 tx_discard;
+
+#define AVM_PA_VIDSTATS_HAS_HARDWARE_REPORT_TIMESTAMP
+	unsigned long hardware_report_timestamp; /* jiffies, 0 if unknown */
 };
 
 #define AVM_PA_MAX_PRIOS       10
@@ -741,4 +745,20 @@
  */
 void avm_pa_telefon_state(int state);
 
+/*
+ * avm_pa_register_recvhook()
+ *   add a receive hook callback
+ *   prepend != 0, prepend the callback
+ *   prepend == 0, append the callback
+ *   recvhook, callback function to add
+*/
+int avm_pa_register_recvhook(int prepend, int (*recvhook)(struct sk_buff *skb, int framing));
+
+/*
+ * avm_pa_unregister_recvhook()
+ *   remove a receive hook callback
+ *   recvhook, callback function remove
+*/
+void avm_pa_unregister_recvhook(int (*recvhook)(struct sk_buff *skb, int framing));
+
 #endif /* _LINUX_AVM_PA_H */
--- linux-2.6.28/include/linux/if_vlan.h
+++ linux-2.6.28/include/linux/if_vlan.h
@@ -63,7 +63,12 @@
 	return (struct vlan_ethhdr *)skb_mac_header(skb);
 }
 
-#define VLAN_VID_MASK	0xfff
+#define VLAN_PRIO_MASK      0xe000 /* Priority Code Point */
+#define VLAN_PRIO_SHIFT     13
+#define VLAN_CFI_MASK       0x1000 /* Canonical Format Indicator */
+#define VLAN_TAG_PRESENT    VLAN_CFI_MASK
+#define VLAN_VID_MASK       0x0fff /* VLAN Identifier */
+#define VLAN_N_VID      4096
 
 /* found in socket.c */
 extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
--- /dev/null
+++ linux-2.6.28/include/linux/kconfig.h
@@ -0,0 +1,46 @@
+#ifndef __LINUX_KCONFIG_H
+#define __LINUX_KCONFIG_H
+
+#include <linux/autoconf.h>
+
+/*
+ * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
+ * these only work with boolean and tristate options.
+ */
+
+/*
+ * Getting something that works in C and CPP for an arg that may or may
+ * not be defined is tricky.  Here, if we have "#define CONFIG_BOOGER 1"
+ * we match on the placeholder define, insert the "0," for arg1 and generate
+ * the triplet (0, 1, 0).  Then the last step cherry picks the 2nd arg (a one).
+ * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
+ * the last step cherry picks the 2nd arg, we get a zero.
+ */
+#define __ARG_PLACEHOLDER_1 0,
+#define config_enabled(cfg) _config_enabled(cfg)
+#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
+#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
+#define ___config_enabled(__ignored, val, ...) val
+
+/*
+ * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
+ * 0 otherwise.
+ *
+ */
+#define IS_ENABLED(option) \
+	(config_enabled(option) || config_enabled(option##_MODULE))
+
+/*
+ * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
+ * otherwise. For boolean options, this is equivalent to
+ * IS_ENABLED(CONFIG_FOO).
+ */
+#define IS_BUILTIN(option) config_enabled(option)
+
+/*
+ * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
+ * otherwise.
+ */
+#define IS_MODULE(option) config_enabled(option##_MODULE)
+
+#endif /* __LINUX_KCONFIG_H */
--- linux-2.6.28/include/linux/serial_core.h
+++ linux-2.6.28/include/linux/serial_core.h
@@ -521,6 +521,8 @@
 }
 
 #include <linux/tty_flip.h>
+#include <linux/console.h>
+extern unsigned int enable_avm_console;
 
 static inline void
 uart_insert_char(struct uart_port *port, unsigned int status,
@@ -537,6 +539,13 @@
 	 */
 	if (status & ~port->ignore_status_mask & overrun)
 		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+    if (port->cons->flags & (CON_ENABLED | CON_CONSDEV)) {
+        if (ch == 0xD) {
+            enable_avm_console = 1;
+        }
+    }
+
 }
 
 /*
--- linux-2.6.28/include/linux/tty_driver.h
+++ linux-2.6.28/include/linux/tty_driver.h
@@ -266,6 +266,7 @@
 	int (*poll_get_char)(struct tty_driver *driver, int line);
 	void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
 #endif
+    int (*is_avm_console)(struct tty_struct *tty);
 };
 
 struct tty_driver {
--- linux-2.6.28/Makefile
+++ linux-2.6.28/Makefile
@@ -218,6 +218,7 @@
 ARCH		?= $(SUBARCH)
 CROSS_COMPILE	?=
 
+-include $(obj)/.kernelvariables
 $(warning use: CROSS_COMPILE=$(CROSS_COMPILE))
 
 # Architecture as present in compile.h
@@ -374,6 +375,7 @@
                    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
                    -I$(srctree)/arch/$(hdr-arch)/include               \
                    -include include/linux/autoconf.h \
+                   -include $(srctree)/include/linux/kconfig.h \
 				   $(EXTRALINUXINCLUDE)
 
 ifeq ($(BUILD_FUSIV),yes)
@@ -1465,6 +1467,7 @@
                   include/linux/utsrelease.h                            \
                   include/linux/bounds.h include/asm*/asm-offsets.h     \
 		  Module.symvers Module.markers tags TAGS cscope*
+MRPROPER_FILES += $(patsubst %,% %.old,.kernelvariables .kernelshell .kernelshellrc)
 
 # clean - Delete most, but leave enough to build external modules
 #
--- linux-2.6.28/net/avm_pa/avm_pa.c
+++ linux-2.6.28/net/avm_pa/avm_pa.c
@@ -1,4 +1,4 @@
-#define AVM_PA_VERSION "4.3.10 2014-09-21"
+#define AVM_PA_VERSION "4.3.11 2015-09-23"
 /*
  * Packet Accelerator Interface
  *
@@ -83,6 +83,10 @@
  *   ACTIVE -> pa_kill_session()     -> DEAD
  *   DEAD   -> pa_session_gc()       -> FREE
  *
+ * Changes for 4.3.11:
+ * - New Funktions: avm_pa_register_recvhook(),
+ *                  avm_pa_unregister_recvhook().
+ *
  * Changes for 4.3.10:
  * - pa_session_get lieferte sessions mit session_id 0
  *   => alte Sessions in /proc/net/avm_pa/bessions
@@ -387,6 +391,10 @@
 
 /* ------------------------------------------------------------------------ */
 
+#define AVM_PA_MAX_RECVHOOK   8
+
+/* ------------------------------------------------------------------------ */
+
 struct avm_pa_pid {
    struct avm_pa_pid_cfg      cfg;
    struct avm_pa_pid_ecfg     ecfg;
@@ -443,10 +451,14 @@
    psched_time_t  t_c;
 };
 
+struct avm_pa_recvhook {
+   int (*cb_recvhook)(struct sk_buff *skb, int framing);
+};
+
 struct avm_pa_global {
    int                       disabled;
    int                       fw_disabled;
-   int                       misc_is_open; /* means fw_disabled */
+   atomic_t                  misc_is_open; /* means fw_disabled */
    int                       dbgcapture;
    int                       dbgsession;
    int                       dbgnosession;
@@ -528,6 +540,9 @@
    unsigned                  prioack_ratio;
    struct avm_hardware_pa    hardware_pa;
    int                       hw_ppa_disabled;
+   
+   struct avm_pa_recvhook    recvhook[AVM_PA_MAX_RECVHOOK];
+   int                       recvhook_counter;
 } pa_glob = {
 #ifdef CONFIG_MIPS_UR8
    .disabled = 1,
@@ -589,6 +604,16 @@
 static int avm_pa_pid_receive(avm_pid_handle pid_handle, PKT *pkt);
 
 /* ------------------------------------------------------------------------ */
+
+static inline int avm_pa_capture_running(void)
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   if (ctx->dbgcapture)
+      return 0;
+   return atomic_read(&ctx->misc_is_open);
+}
+
+/* ------------------------------------------------------------------------ */
 /* -------- utilities ----------------------------------------------------- */
 /* ------------------------------------------------------------------------ */
 
@@ -1924,6 +1949,13 @@
    PACKET_BROADCAST
 };
 
+/* we dont want 0 as a valid timestamp */
+static unsigned long NOT_ZERO(unsigned long n)
+{
+	if (!n) return 1;
+	return n;
+}
+
 static inline void _pa_transmit(struct avm_pa_egress *egress, PKT *pkt, int in_hw)
 {
    struct avm_pa_global *ctx = &pa_glob;
@@ -3664,6 +3696,15 @@
             }
          }
 #endif
+         if (ctx->fw_disabled || avm_pa_capture_running()) {
+#if AVM_PA_TRACE
+            if (ctx->dbgtrace)
+               pa_printk(KERN_DEBUG, "avm_pa: %lu - avm_pa_pid_receive(%s) - %s\n",
+                     pkt->uniq_id & 0xffffff, pid->cfg.name,
+                     "forward disabled");
+#endif
+            info->can_be_accelerated = 0;
+         }
          return AVM_PA_RX_OK;
       }
 
@@ -3713,7 +3754,7 @@
 accelerate:
       pa_session_update(session);
 
-      if (ctx->fw_disabled || ctx->misc_is_open) {
+      if (ctx->fw_disabled) {
          if (session->timeout == 0)
             pa_kill_session(session, "fast timeout");
 #if AVM_PA_TRACE
@@ -3819,11 +3860,102 @@
    AVM_PKT_INFO(pkt)->ingress_vpid_handle = handle;
 }
 
+inline int prepend_recvhook(int (*recvhook)(struct sk_buff *skb, int framing))
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   int pos;
+
+   for (pos = 0; pos < ctx->recvhook_counter; pos++) {
+      if (ctx->recvhook[pos].cb_recvhook == recvhook)
+         return -1;
+   }
+   
+   for (pos = ctx->recvhook_counter; pos > 0; pos--)
+      ctx->recvhook[pos].cb_recvhook = ctx->recvhook[pos-1].cb_recvhook;
+
+   ctx->recvhook[0].cb_recvhook = recvhook;
+   ctx->recvhook_counter++;
+   return 0;
+}
+
+inline int append_recvhook(int (*recvhook)(struct sk_buff *skb, int framing))
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   int pos;
+
+   for (pos = 0; pos < ctx->recvhook_counter; pos++) {
+      if (ctx->recvhook[pos].cb_recvhook == recvhook)
+         return -1;
+   }
+   ctx->recvhook[ctx->recvhook_counter].cb_recvhook = recvhook;
+   ctx->recvhook_counter++;
+   return 0;
+}
+
+inline void remove_recvhook(int (*recvhook)(struct sk_buff *skb, int framing))
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   int found = 0;
+   int pos;
+
+   if (ctx->recvhook_counter == 0) return;
+
+   for (pos = 0; pos < ctx->recvhook_counter; pos++) {
+      if (found == 0 && ctx->recvhook[pos].cb_recvhook != recvhook)
+         continue;
+      ctx->recvhook[pos].cb_recvhook = pos+1 < ctx->recvhook_counter ? ctx->recvhook[pos+1].cb_recvhook : 0;
+      found = 1;
+   }
+   if (found) ctx->recvhook_counter--;
+
+}
+
+int avm_pa_register_recvhook(int prepend, int (*recvhook)(struct sk_buff *skb, int framing))
+{
+   struct avm_pa_global *ctx = &pa_glob;
+
+   if (ctx->recvhook_counter >= AVM_PA_MAX_RECVHOOK)
+      return -1;
+
+   if (prepend) {
+      if (prepend_recvhook(recvhook) < 0)
+         return -1;
+   }  else {
+      if (append_recvhook(recvhook) < 0)
+         return -1;
+   }
+   return 0;
+
+}
+EXPORT_SYMBOL(avm_pa_register_recvhook);
+
+void avm_pa_unregister_recvhook(int (*recvhook)(struct sk_buff *skb, int framing))
+{
+   remove_recvhook(recvhook);
+}
+EXPORT_SYMBOL(avm_pa_unregister_recvhook);
+
+static int call_cb_recvhooks(PKT *pkt, int framing)
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   int pos;
+
+   for (pos = 0; pos < ctx->recvhook_counter; pos++) {
+      if (likely((ctx->recvhook[pos].cb_recvhook(pkt, framing) == 0))) {
+         return AVM_PA_RX_STOLEN;
+      }
+   }
+   return -1;
+}
 
 int avm_pa_dev_receive(struct avm_pa_dev_info *devinfo, PKT *pkt)
 {
    int rc = AVM_PA_RX_OK;
    if (devinfo->pid_handle) {
+      struct avm_pa_global *ctx = &pa_glob;
+      struct avm_pa_pid *pid = PA_PID(ctx, devinfo->pid_handle);
+      if (likely(call_cb_recvhooks(pkt, pid->ingress_framing) == AVM_PA_RX_STOLEN))
+         return AVM_PA_RX_STOLEN;
       rc = avm_pa_pid_receive(devinfo->pid_handle, pkt);
       if (rc == AVM_PA_RX_ACCELERATED)
          return rc;
@@ -3840,6 +3972,9 @@
    int rc = AVM_PA_RX_OK;
    if (devinfo->pid_handle) {
       struct avm_hardware_pa *hwpa = &ctx->hardware_pa;
+      struct avm_pa_pid *pid = PA_PID(ctx, devinfo->pid_handle);
+      if (likely(call_cb_recvhooks(pkt, pid->ingress_framing) == AVM_PA_RX_STOLEN))
+         return AVM_PA_RX_STOLEN;
       if (!ctx->hw_ppa_disabled && hwpa && hwpa->try_to_accelerate) {
          struct avm_pa_pid *pid = PA_PID(ctx, devinfo->pid_handle);
          if (pid->rx_channel_activated) {
@@ -4668,6 +4803,7 @@
       vpid = PA_VPID(ctx, session->ingress_vpid_handle);
       ((u32 *)(&vpid->stats.rx_unicast_pkt))[session->ingress.casttype] += pkts;
       ((u64 *)(&vpid->stats.rx_bytes))[session->ingress.casttype] += bytes;
+      vpid->stats.hardware_report_timestamp = NOT_ZERO(jiffies);
    }
 
    for (i = 0; i < session->negress; i++) {
@@ -4680,6 +4816,7 @@
          vpid = PA_VPID(ctx, egress->vpid_handle);
          ((u32 *)(&vpid->stats.tx_unicast_pkt))[egress->match.casttype] += pkts;
          vpid->stats.tx_bytes += bytes;
+         vpid->stats.hardware_report_timestamp = NOT_ZERO(jiffies);
          vpid->hwstats[prio].tx_pkts += pkts;
          vpid->hwstats[prio].tx_bytes += bytes;
       }
@@ -4746,7 +4883,7 @@
 
    if (ctx->disabled) mode = "disabled";
    else if (ctx->fw_disabled) mode = "testmode";
-   else if (ctx->misc_is_open) mode = "capture";
+   else if (avm_pa_capture_running()) mode = "capture";
    else mode = "enabled";
 
    (*fprintffunc)(arg, "State          : %s\n", mode);
@@ -4817,7 +4954,7 @@
 
    if (ctx->disabled) mode = "disabled";
    else if (ctx->fw_disabled) mode = "testmode";
-   else if (ctx->misc_is_open) mode = "capture";
+   else if (avm_pa_capture_running()) mode = "capture";
    else mode = "enabled";
 
    (*fprintffunc)(arg, "State          : %s\n", mode);
@@ -6447,7 +6584,6 @@
    /* dbgcapture | nodbgcapture */
    } else if (strcmp(argv[0], "dbgcapture") == 0) {
       ctx->dbgcapture = 1;
-      ctx->misc_is_open = 0;
       printk(KERN_DEBUG "avm_pa: %s\n", argv[0]);
    } else if (strcmp(argv[0], "nodbgcapture") == 0) {
       ctx->dbgcapture = 0;
@@ -6675,15 +6811,15 @@
 static int avm_pa_misc_open(struct inode *inode, struct file *file)
 {
    struct avm_pa_global *ctx = &pa_glob;
-   if (ctx->dbgcapture == 0)
-      ctx->misc_is_open = 1;
+   atomic_inc(&ctx->misc_is_open);
    return 0;
 }
 
 static int avm_pa_misc_release(struct inode *inode, struct file *file)
 {
    struct avm_pa_global *ctx = &pa_glob;
-   ctx->misc_is_open = 0;
+   if (atomic_read(&ctx->misc_is_open) > 0)
+      atomic_dec(&ctx->misc_is_open);
    return 0;
 }
 
--- linux-2.6.28/net/core/sock.c
+++ linux-2.6.28/net/core/sock.c
@@ -474,6 +474,8 @@
 		sk->sk_reuse = valbool;
 		break;
 	case SO_TYPE:
+	case SO_PROTOCOL:
+	case SO_DOMAIN:
 	case SO_ERROR:
 		ret = -ENOPROTOOPT;
 		break;
@@ -739,6 +741,14 @@
 		v.val = sk->sk_type;
 		break;
 
+	case SO_PROTOCOL:
+		v.val = sk->sk_protocol;
+		break;
+
+	case SO_DOMAIN:
+		v.val = sk->sk_family;
+		break;
+
 	case SO_ERROR:
 		v.val = -sock_error(sk);
 		if (v.val==0)
--- linux-2.6.28/net/ipv4/mcfastforward.c
+++ linux-2.6.28/net/ipv4/mcfastforward.c
@@ -966,7 +966,7 @@
 	  p->groupmac[2] = 0x5e;
 	  p->groupmac[3] = (u8)(ntohl(group) >> 16) & 0x7f;
 	  p->groupmac[4] = (u8)(ntohl(group) >> 8) & 0xff;
-	  p->groupmac[5] = (u8)(ntohl(group)) % 0xff;
+	  p->groupmac[5] = (u8)(ntohl(group)) & 0xff;
 	  init_timer(&p->checking_timer);
 	  p->checking_timer.function = mcgroup_checking_timer_handler;
 	  p->checking_timer.data = group;
--- linux-2.6.28/net/kspeedtest/kspeedtest.c
+++ linux-2.6.28/net/kspeedtest/kspeedtest.c
@@ -1,3 +1,5 @@
+#define KSPEEDTEST_VERSION "2.0.0 2014-20-03"
+
 /*-------------------------------------------------------------------------------
  *
  *   Copyright (C) 2006-2014 AVM GmbH <fritzbox_info@avm.de>
@@ -71,7 +73,6 @@
 #include <linux/inet.h>
 #include <linux/in6.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 
 #include <linux/delay.h>
 #include <linux/socket.h>
@@ -89,6 +90,7 @@
 #define DEFAULT_SPEEDTEST_DURATION_DOWN 20
 #define DEFAULT_SPEEDTEST_DURATION_UP 10
 #define MAXIMUM_SPEEDTEST_DURATION 120
+#define MAXIMUM_TCP_PARALLEL_CONNECTIONS 8
 #define DEFAULT_TCP_PORT 4711
 #define MODULE_NAME "kspeedtest"
 
@@ -98,6 +100,8 @@
 
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(kspeedtest_mutex);
+
 static struct timer_list ktimer;
 
 static void Second(unsigned long param);
@@ -679,10 +683,23 @@
 	  struct sk_buff_head *rcvq = &sock->sk->sk_receive_queue;
 	  struct sk_buff *skb;
 
-	  spin_lock_bh(rcvq->lock);
+	  spin_lock_bh(&rcvq->lock);
 	  while ((skb = skb_peek(rcvq)) != NULL) {
 #ifdef CONFIG_TI_PACKET_PROCESSOR
 		   // create null vpid
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		   struct net_device* dev = __dev_get_by_index (&init_net,skb->skb_iif);
+		   if (kspeedtest.null_vpid == -1
+				 && dev && dev->vpid_handle != -1) {
+			   kspeedtest.null_vpid = 
+				  ti_ppm_create_vpid(&dev->vpid_block);
+			   if (kspeedtest.null_vpid < 0)
+				  printk(KERN_ERR "creating null vpid failed \n");
+			   else {
+				  ti_ppm_set_vpid_flags( kspeedtest.null_vpid, TI_PP_VPID_FLG_RX_DISBL );
+			   }
+		   }
+#else
 		   if (kspeedtest.null_vpid == -1
 				 && skb->input_dev->vpid_handle != -1) {
 			   kspeedtest.null_vpid = 
@@ -693,6 +710,7 @@
 				  ti_ppm_set_vpid_flags( kspeedtest.null_vpid, TI_PP_VPID_FLG_RX_DISBL );
 			   }
 		   }
+#endif
 		   if (kspeedtest.null_vpid != -1) {
 			   skb->pp_packet_info.ti_pp_flags |= TI_PPM_SESSION_ROUTED;
 			   ti_hil_null_hook(skb, kspeedtest.null_vpid);
@@ -702,7 +720,7 @@
 		   __skb_unlink(skb, rcvq);
 		   kfree_skb(skb);
 	   }
-	   spin_unlock_bh(rcvq->lock);
+	   spin_unlock_bh(&rcvq->lock);
    }
    return size;
 }
@@ -945,14 +963,14 @@
    printk(KERN_ERR "kspeedtest_tcp_worker fired\n");
 
 
-   lock_kernel();
+   mutex_lock(&kspeedtest_mutex);
    {
 		tcp_thread->running = 1;
 		current->flags |= PF_NOFREEZE;
 		daemonize("kspeedtest_tcp");
 		allow_signal(SIGKILL);
    }
-   unlock_kernel();
+   mutex_unlock(&kspeedtest_mutex);
 
 
    while (tcp_thread && tcp_thread->running == 1) {
@@ -988,10 +1006,10 @@
 	int rwin = 256000;
 #endif
    struct inet_connection_sock *isock;
-
+   struct timeval tv;
 	DECLARE_WAITQUEUE(wait, current);
 
-	lock_kernel();
+    mutex_lock(&kspeedtest_mutex);
 	{
 		/* kernel thread initialization */
 		tcp_thread->running = 1;
@@ -1000,13 +1018,16 @@
 		daemonize(MODULE_NAME);
 		allow_signal(SIGKILL);
 	}
-	unlock_kernel();
+    mutex_unlock(&kspeedtest_mutex);
 
 	/* create a tcp socket */
 	if ((err = sock_create_kern(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &tcp_thread->sock)) < 0) {
 		printk(KERN_ERR MODULE_NAME": Could not create a stream socket, error = %d\n", -ENXIO);
 		goto out;
 	}
+	if (!tcp_thread->sock) {
+		goto out;
+	}
 
 	memset(&tcp_thread->addr, 0, sizeof(struct sockaddr));
 	tcp_thread->addr.sin6_family      = AF_INET6;
@@ -1019,7 +1040,18 @@
 			(char *)&rwin, sizeof(rwin)); 
 	printk(KERN_INFO MODULE_NAME":  rwin %d ret=%d\n", rwin, err);
 #endif
-
+	
+	if (err >=0) {
+		tv.tv_sec = 2; // Timeout of 2 seconds
+		tv.tv_usec = 0;
+		if ((err = sock_setsockopt(tcp_thread->sock, SOL_SOCKET, SO_RCVTIMEO,(char *)&tv,sizeof(struct timeval))) < 0) {
+			printk(KERN_ERR MODULE_NAME": Couldn't set receive-timeout on socket, error = %d\n", -err);
+		}
+		if ((err = sock_setsockopt(tcp_thread->sock, SOL_SOCKET, SO_SNDTIMEO,(char *)&tv,sizeof(struct timeval))) < 0) {
+			printk(KERN_ERR MODULE_NAME": Couldn't set send-timeout on socket, error = %d\n", -err);
+		}		
+	}
+	
 	if ( (err = tcp_thread->sock->ops->bind(tcp_thread->sock, 
 					(struct sockaddr *)&tcp_thread->addr, sizeof(struct sockaddr_in6) ) ) < 0) {
 		printk(KERN_ERR MODULE_NAME": Could not bind or connect to tcp socket, error = %d\n", -err);
@@ -1037,18 +1069,34 @@
 	isock = inet_csk(tcp_thread->sock->sk);
 
 	while (err >= 0) {
+		int clientCnt = 0;
 	    struct socket *client_sock;
 		struct socket_list **pp, *p;
 
 		if (signal_pending(current)) 
 			break;
 
+		// count sockets first - there is a maximum
+		for (pp = &tcp_thread->clients; *pp; pp = &(*pp)->next) clientCnt++;
+		if (clientCnt >= MAXIMUM_TCP_PARALLEL_CONNECTIONS) {
+			msleep(300);
+			continue;
+		}
+
 		if (reqsk_queue_empty(&isock->icsk_accept_queue)) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+			add_wait_queue(sk_sleep(tcp_thread->sock->sk), &wait);
+#else
 			add_wait_queue(tcp_thread->sock->sk->sk_sleep, &wait);
+#endif
 			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ);
 			__set_current_state(TASK_RUNNING);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+			remove_wait_queue(sk_sleep(tcp_thread->sock->sk), &wait);
+#else
 			remove_wait_queue(tcp_thread->sock->sk->sk_sleep, &wait);
+#endif
 			continue;
 		}
         err = sock_create_lite(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &client_sock);
@@ -1121,15 +1169,6 @@
 
 	if (tcp_thread == NULL) return 0;
 
-    for(sl = tcp_thread->clients; sl; sl = sl->next) {
-	   struct socket_list *tmp;
-	   if (sl->sock)
-		  sock_release(sl->sock);
-	   tmp = sl;
-	   sl = sl->next;
-	   kfree(tmp);
-	}
-
 	if (tcp_thread->thread) {
 	   (void)send_sig(SIGKILL, tcp_thread->thread, 1);
 	}
@@ -1144,6 +1183,15 @@
 		while(tcp_thread->running) msleep(10);
 		printk(KERN_INFO MODULE_NAME": successfully killed kernel tcp thread\n");
 	}
+	
+	for(sl = tcp_thread->clients; sl;) {
+	   struct socket_list *tmp = sl;
+	   if (tmp->sock)
+		  sock_release(tmp->sock);
+	   sl = sl->next;
+	   kfree(tmp);
+	}
+	
 	kfree(tcp_thread);
 	tcp_thread = NULL;
 	return 0;
--- linux-2.6.28/net/l2tp/l2tp_core.c
+++ linux-2.6.28/net/l2tp/l2tp_core.c
@@ -145,7 +145,7 @@
 		 atomic_read(&_t->ref_count));				\
 		l2tp_tunnel_inc_refcount_1(_t);				\
 	} while (0)
-#define l2tp_tunnel_dec_refcount(_t)
+#define l2tp_tunnel_dec_refcount(_t)	\
 do {									\
 	pr_debug("l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n",	\
 		 __func__, __LINE__, (_t)->name,			\
@@ -1384,7 +1384,7 @@
 	tunnel = container_of(work, struct l2tp_tunnel, del_work);
 	sk = l2tp_tunnel_sock_lookup(tunnel);
 	if (!sk)
-		return;
+		goto out;
 
 	sock = sk->sk_socket;
 
@@ -1405,6 +1405,9 @@
 	}
 
 	l2tp_tunnel_sock_put(sk);
+out:
+	l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: del work done...\n", tunnel->name);
+	l2tp_tunnel_dec_refcount(tunnel); /* work */
 }
 
 /* Create a socket for the tunnel, if one isn't set up by
@@ -1685,6 +1688,7 @@
 	list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
 	spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
 
+	l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: alloc...\n", tunnel->name);
 	err = 0;
 err:
 	if (tunnelp)
@@ -1706,8 +1710,13 @@
 {
 	if (tunnel->deleted == 0) {
 		tunnel->deleted = 1;
+		l2tp_tunnel_inc_refcount(tunnel); /* work */
 		l2tp_tunnel_closeall(tunnel);
-		return (false == queue_work(l2tp_wq, &tunnel->del_work));
+		if (queue_work(l2tp_wq, &tunnel->del_work) == false) {
+			l2tp_tunnel_dec_refcount(tunnel); /* work */
+			return 1;
+	    }
+	    l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: del work queued...\n", tunnel->name);
 	}
 	return 0;
 }
--- linux-2.6.28/net/netlink/genetlink.c
+++ linux-2.6.28/net/netlink/genetlink.c
@@ -227,6 +227,7 @@
 	__genl_unregister_mc_group(family, grp);
 	genl_unlock();
 }
+EXPORT_SYMBOL(genl_unregister_mc_group);
 
 static void genl_unregister_mc_groups(struct genl_family *family)
 {
