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

    diff -durN --no-dereference 7330.06.50 7312.06.55 > this.patch

--- linux-2.6.32/drivers/char/avm_new/Makefile	2016-04-22 16:15:44.000000000 +0200
+++ linux-2.6.32/drivers/char/avm_new/Makefile	2019-08-12 14:01:36.000000000 +0200
@@ -1,6 +1,6 @@
 #############################################
 # Makefile: automaticly generated by ./init_avm
-#           Fr 22. Apr 16:15:44 CEST 2016
+#           Mo 12. Aug 14:01:36 CEST 2019
 #############################################
 
 #############################################
--- linux-2.6.32/drivers/char/Piglet_noemif/init_Piglet	2006-01-17 13:00:39.000000000 +0100
+++ linux-2.6.32/drivers/char/Piglet_noemif/init_Piglet	1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-#! /bin/sh
-
-KERNEL_CLASS=$1
-DRIVER_NAME=$2
-
-if [ -z "$KERNEL_CLASS" ] ; then
-    KERNEL_CLASS=26
-fi
-
-for i in `find . -name Makefile.$KERNEL_CLASS` ; do
-    dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
-    rm -f $dest
-    ln -fvs $source $dest
-done
-
-exit 0
--- linux-2.6.32/drivers/char/Piglet_noemif/init_Piglet_noemif	2007-06-13 19:35:58.000000000 +0200
+++ linux-2.6.32/drivers/char/Piglet_noemif/init_Piglet_noemif	1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-#! /bin/sh
-
-KERNEL_CLASS=$1
-DRIVER_NAME=$2
-
-if [ -z "$KERNEL_CLASS" ] ; then
-    KERNEL_CLASS=26
-fi
-
-for i in `find . -name Makefile.$KERNEL_CLASS` ; do
-    dest=${i%.$KERNEL_CLASS}
-    source="`pwd`/$i"
-    rm -f $dest
-    ln -fvs $source $dest
-done
-
-exit 0
--- linux-2.6.32/drivers/char/Piglet_noemif/Kbuild	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/drivers/char/Piglet_noemif/Kbuild	2018-10-09 08:53:53.000000000 +0200
@@ -0,0 +1 @@
+# Empty kbuild dummy
--- linux-2.6.32/drivers/char/Piglet_noemif/Makefile.24	2005-11-04 09:41:12.000000000 +0100
+++ linux-2.6.32/drivers/char/Piglet_noemif/Makefile.24	1970-01-01 01:00:00.000000000 +0100
@@ -1,9 +0,0 @@
-###################################################################################################################
-#
-#   vim: noexpandtab
-#
-#	dummy Makefile with no function
-#
-###################################################################################################################
-
-include $(TOPDIR)/Rules.make
--- linux-2.6.32/drivers/char/Piglet_noemif/Makefile.26	2005-11-04 09:18:32.000000000 +0100
+++ linux-2.6.32/drivers/char/Piglet_noemif/Makefile.26	1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-###################################################################################################################
-#
-#   vim: noexpandtab
-#
-#	dummy Makefile with no function
-#
-###################################################################################################################
-
--- linux-2.6.32/drivers/char/ubik2/Kconfig	2010-03-05 11:04:06.000000000 +0100
+++ linux-2.6.32/drivers/char/ubik2/Kconfig	2016-08-22 16:41:35.000000000 +0200
@@ -0,0 +1,4 @@
+config UBIK2_ISDNSTACK_ON_CPU
+    int
+	default 0
+
--- linux-2.6.32/drivers/char/ubik2/linux_pcmlink_ul.h	2012-08-13 18:36:23.000000000 +0200
+++ linux-2.6.32/drivers/char/ubik2/linux_pcmlink_ul.h	2017-02-06 14:38:06.000000000 +0100
@@ -4,11 +4,10 @@
 #define __linux_pcmlink_ul_h__
 
 #include <linux/types.h> 
-/*--------------------------------------------------------------------------------*\
-\*--------------------------------------------------------------------------------*/
-enum _logic_chan_ll {
-   logic_chan_isdn = 0
-};
+#include <linux/module.h> 
+#include <linux/sched.h> 
+#include <linux/interrupt.h>
+#include <linux/slab.h> 
 
 /*------------------------------------------------------------------------------------------*\
 \*------------------------------------------------------------------------------------------*/
@@ -35,7 +34,7 @@
 #define PCMLINK_MAX_DYNHW_CHAN      3
 /*-------------------------------------------------------------------------------------*\
 \*-------------------------------------------------------------------------------------*/
-enum _chan_message_voip_config{
+enum _chan_message_voip_config {
     voip_chanx_off           = 0,
     voip_chanx_8khz          = 1,
     voip_chanx_8khz_only_rcv = 2
@@ -93,8 +92,8 @@
 #define PCMBUS_MAX_AUDIOCHAN(a) ((((a)->SupportFlag) >> 26) & 0x03)
 #define PCMBUS_MAX_ECCHAN(a)    ((((a)->SupportFlag) >> 22) & 0x0F)
 #define PCMBUS_MAX_CODECCHAN(a) ((((a)->SupportFlag) >> 17) & 0x1F)
-#define PCMBUS_MAX_TECHAN(a)    ((((a)->SupportFlag) >> 13) & 0x0F)
-#define PCMBUS_MAX_NTCHAN(a)    ((((a)->SupportFlag) >>  9) & 0x0F)
+#define PCMBUS_MAX_NTCHAN(a)    ((((a)->SupportFlag) >> 13) & 0x0F)
+#define PCMBUS_MAX_TECHAN(a)    ((((a)->SupportFlag) >>  9) & 0x0F)
 #define PCMBUS_MAX_DECTCHAN(a)  ((((a)->SupportFlag) >>  5) & 0x0F)
 #define PCMBUS_MAX_SLICCHAN(a)  ((((a)->SupportFlag) >>  2) & 0x07)
 #define PCMBUS_MAX_POTSCHAN(a)  ((((a)->SupportFlag) >>  1) & 0x01)
@@ -174,14 +173,21 @@
 void pcmlink_ul_dspfwversion_pcmrouter(struct _chan_configmsg_dsptomips **fwversion);
 
 /*--------------------------------------------------------------------------------*\
+ * nur fuer ISDN-Treiber: liefere Codecnames (TDM-Bus abhaengig)
+\*--------------------------------------------------------------------------------*/
+int pcmlink_ul_codectdmbus(char *table[], unsigned int maxentries);
+
+/*--------------------------------------------------------------------------------*\
  * nur fuer dect-Treiber:
  * maxslotlen: liefert maximale Slotlaenge
  * p[maxdectslots] : Pointertabelle: hier Daten hineinschreiben/lesen - Pointer nicht modifizieren!
  * Achtung es muessen immer auch die (Dummy-)Daten fuer Tx komplett geschrieben werden!
  * Returnwert: Handle
+ *
+ * Returnwert der RxTxCallback: 0 success, 1 fehlerhafte Daten detektiert
 \*--------------------------------------------------------------------------------*/
 void *pcmlink_ul_register_dectcontrol(unsigned int *maxslotlen, unsigned int *maxdectslots,
-                                      void RxTxCallback(unsigned char **p_rx, unsigned char **p_tx));
+                                      int RxTxCallback(unsigned char **p_rx, unsigned char **p_tx));
 
 /*--------------------------------------------------------------------------------*\
  * nur fuer dect-Treiber:
@@ -204,12 +210,14 @@
  *              ptxslottab[]: Slotzeigertabelle fuer zum PCM-Bus zu verschickende Daten - 
  *                            im Aufruf zu fuellen 
  *              slotlen:      Laenge der Daten pro Slot in Byte
+ *              flag:         0x0: alles ok
+ *                            0x1: trigger too late erkannt (CELT-Resync-notwendig)  
  *
  *  Returnparameter: Slothandle            
  *              NULL: falls Slots bereits belegt/Konflikte mit vergebenen Slots/der Isdn-Treiber nicht laeuft
 \*--------------------------------------------------------------------------------*/
 void *pcmlink_ul_openslots(void *linkhandle, void *ref, 
-                           void (*RxTxCallback)(void *ref, short slotentries, unsigned char *prxslottab[], unsigned char *ptxslottab[], size_t slotlen),
+                           void (*RxTxCallback)(void *ref, short slotentries, unsigned char *prxslottab[], unsigned char *ptxslottab[], size_t slotlen, unsigned int flag),
                            unsigned int transp_flag
                           );
 
@@ -279,5 +287,300 @@
  * Meldet HwChannel-Support am PCM-Router ab
 \*--------------------------------------------------------------------------------*/
 void pcmlink_ul_release_dynhwchannel_control(void *handle);
+
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+enum _pcmlink_status_operation {
+    slic_check,
+    slic_status,
+    slic_frequency,
+    slic_coefficients,
+    set_hw_cross,
+    unset_hw_cross,
+    hw_cross_noavail,
+	codecs_onoff,
+    dect_slotlen,
+    slot_mute,
+};
+/*--------------------------------------------------------------------------------*\
+ * slic_check:         ret: Anzahl der Slics (falls so ermittelbar)
+ * slic_status:        arg1: Slot
+ *                     arg2: veroderte Bits (s.u. SLIC_CODEC_... )
+ * slic_frequency:     Setze Slic-Klingelfrequenz arg1: Frequenz 
+ * slic_coefficients:  arg1: Koeffizienten-Index
+ * set_hw_cross: arg1 = ulchan1
+ *				 arg2 = ulchan2
+ *				 ret: -1 Hw-Cross Einstellungen muessen nach "alter" registerbasierter Loesung erfolgen
+ *				 0: ok
+ *				 1: dieser Channel kann nicht per HWCross geschaltet werden
+ * unset_hw_cross:   arg1 = ulchan1 (ret s.o.)
+ * hw_cross_noavail: ret: 0 Anbindung ist Hw-Cross-faehig
+ * codecs_onoff: arg1 ulchan arg2 veroderbar Bit0: rx Bit1 tx
+ * Hw-abhaengiger Support: 
+ * slic_check          pef
+ * slic_status         pef, adsp
+ * slic_frequency      pef( 25 Hz, 50 Hz), adsp (fast beliebige Frequenz)
+ * slic_coefficients:  pef (Koeffizienten-Index 0: 3 dB 1: 0 dB)
+\*--------------------------------------------------------------------------------*/
+#define SLIC_CODEC_POWERDOWN                                 0x0000
+#define SLIC_CODEC_POWERUP                                   0x0001
+#define SLIC_CODEC_RING                                      0x0002
+#define SLIC_CODEC_CLIP                                      0x0004
+#define SLIC_CODEC_POLREV                                    0x0008
+
+/*--------------------------------------------------------------------------------*\
+ * generelle Funktion fuer ISDN-Treiber um Stati abzufragen/setzen
+ * Diese Funktion soll langfristig das Setzen von Registern abloesen
+ * Returnwert: Operations-spezifisch
+ *			   generell: < 0 nicht supported 
+\*--------------------------------------------------------------------------------*/
+int pcmlink_ul_status(enum _pcmlink_status_operation operation, unsigned int arg1, unsigned int arg2);
+
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#if defined(CONFIG_AVM_IPI_YIELD)
+#include <asm/yield_context.h>
+#include <linux/simple_mempool.h>
+#endif/*--- #if defined(CONFIG_AVM_IPI_YIELD) ---*/
+
+#if defined(CONFIG_AVM_IPI_YIELD)
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_lock_init(spinlock_t *lock) {
+  yield_spin_lock_init(lock);
+}
+/*--------------------------------------------------------------------------------*\
+ * Speziallock: ist auch aus non-Linux-TC-Kontext aufrufbar 
+ * (soweit von Hardware unterstuetzt)
+ * wenn flags == NULL: keine Irqs sperren
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_lock(spinlock_t *lock, unsigned long *flags) {
+    if(flags) {
+        yield_spin_lock_irqsave(lock, *flags);
+    } else {
+        yield_spin_lock(lock);
+    }
+}
+/*--------------------------------------------------------------------------------*\
+ * wenn flags == NULL: keine Irqs restoren 
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_unlock(spinlock_t *lock, unsigned long *flags) {
+    if(flags) {
+        yield_spin_unlock_irqrestore(lock, *flags);
+    } else {
+        yield_spin_unlock(lock);
+    }
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline int pcmlink_ul_yieldcontext(void) {
+    return !yield_is_linux_context();
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline int pcmlink_ul_assert_on_yield_context(void) {
+    if(pcmlink_ul_yieldcontext()) {
+        printk(KERN_ERR"\nGREAT-ERROR: Do not use in Yield-Context pc=%pS ra=%pS\n", (void *)_THIS_IP_, (void *)_RET_IP_);
+        return 1;
+    }
+    return 0;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_malloc(void *memhandle, unsigned int size) {
+    return simplemempool_alloc(memhandle, size, 0, (void *)_RET_IP_);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_zalloc(void *memhandle, unsigned int size) {
+    return simplemempool_alloc(memhandle, size, 1, (void *)_RET_IP_);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_mfree(void *memhandle, void *ptr) {
+    simplemempool_free(memhandle, ptr, (void *)_RET_IP_);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_wake_up_interruptible(wait_queue_head_t *q){
+    yield_wake_up_interruptible(q);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_wake_up(wait_queue_head_t *q){
+    yield_wake_up(q);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_schedule_work(struct work_struct *work) {
+    return yield_schedule_work(work);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work){
+    return yield_queue_work_on(cpu, wq, work);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay) {
+    return yield_schedule_delayed_work(dwork, delay);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_tasklet_hi_schedule(struct tasklet_struct *t) {
+    yield_tasklet_hi_schedule(t);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_try_module_get(struct module *module) {
+    return yield_try_module_get(module);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_module_put(struct module *module) {
+    yield_module_put(module);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_alloc_init(char *pool_name, unsigned int pool_size){
+    return simplemempool_alloc_init(pool_name, pool_size);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_alloc_exit(void *pmp){
+    simplemempool_alloc_exit(pmp);
+}
+
+#else /*--- #if defined(CONFIG_AVM_IPI_YIELD) ---*/
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_lock_init(spinlock_t *lock) {
+  spin_lock_init(lock);
+}
+/*--------------------------------------------------------------------------------*\
+ * Speziallock: ist auch aus non-Linux-TC-Kontext aufrufbar 
+ * (soweit von Hardware unterstuetzt)
+ * wenn flags == NULL: keine Irqs sperren
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_lock(spinlock_t *lock, unsigned long *flags) {
+    if(flags) {
+        spin_lock_irqsave(lock, *flags);
+    } else {
+        spin_lock(lock);
+    }
+}
+/*--------------------------------------------------------------------------------*\
+ * wenn flags == NULL: keine Irqs restoren 
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_unlock(spinlock_t *lock, unsigned long *flags) {
+    if(flags) {
+        spin_unlock_irqrestore(lock, *flags);
+    } else {
+        spin_unlock(lock);
+    }
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline int pcmlink_ul_yieldcontext(void) {
+    return 0;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline int pcmlink_ul_assert_on_yield_context(void) {
+    return 0;
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_malloc(void *dummy __maybe_unused, unsigned int size) {
+    return kmalloc(size, GFP_ATOMIC);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_zalloc(void *dummy __maybe_unused, unsigned int size) {
+    return kzalloc(size, GFP_ATOMIC);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_mfree(void *dummy __maybe_unused, void *ptr) {
+    kfree(ptr);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_wake_up_interruptible(wait_queue_head_t *q){
+    wake_up_interruptible(q);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_wake_up(wait_queue_head_t *q){
+    wake_up(q);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_schedule_work(struct work_struct *work) {
+    return schedule_work(work);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work){
+    return queue_work_on(cpu, wq, work);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay) {
+    return schedule_delayed_work(dwork, delay);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_tasklet_hi_schedule(struct tasklet_struct *t) {
+    tasklet_hi_schedule(t);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline bool pcmlink_ul_try_module_get(struct module *module) {
+    return try_module_get(module);
+}
+/*--------------------------------------------------------------------------------*\
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_module_put(struct module *module) {
+    module_put(module);
+}
+/*--------------------------------------------------------------------------------*\
+ * nur dummy - aber handle zurueckliefern
+\*--------------------------------------------------------------------------------*/
+static inline void *pcmlink_ul_alloc_init(char *pool_name __maybe_unused, unsigned int pool_size __maybe_unused){
+    return kmalloc(4, GFP_KERNEL);
+}
+/*--------------------------------------------------------------------------------*\
+ * nur dummy
+\*--------------------------------------------------------------------------------*/
+static inline void pcmlink_ul_alloc_exit(void *pmp){
+    kfree(pmp);
+}
+#endif/*--- #else  ---*//*--- #if defined(CONFIG_AVM_IPI_YIELD) ---*/
+
+/*--------------------------------------------------------------------------------*\
+ * Registriert die DECT-Slot-Callback fuer den DECT-Daten-Pfad (non-PCM)
+ * ref: private Data (!=NULL)
+ * DECTSlotIngressCallback: Callback Daten zum Stub
+ * DECTSlotEgressCallback:  Callback Daten vom Stub
+ *
+ * Return-Parameter: > = Laenge der Daten pro Slot in Byte
+ *                       sonst Fehler
+ * Callbacks mit folgenden Parametern:
+ *          ref:            private Data
+ *          slot:           beginnend mit 1 !
+ *          ingress_data:   Pointer auf Daten zum DECT-Stub (umkopieren erforderlich)
+ *          eggress_data:   hier die Daten reinkopieren
+ * 
+ * Format der Daten: bei G722 alle 16 Bit Werte verdoppelt ( 128 kBit)
+\*--------------------------------------------------------------------------------*/
+int Register_DECTSlot_Callback(void *ref,
+                               void (*DECTSlotIngressCallback)(void *ref, unsigned int dectslot, const unsigned short *ingress_data),
+                               void (*DECTSlotEgressCallback)(void *ref, unsigned int dectslot, const unsigned short *egress_data));
+
+/*--------------------------------------------------------------------------------*\
+ * DECT-Slot-Callbacks abmelden
+\*--------------------------------------------------------------------------------*/
+void Release_DECTSlot_Callback(void *ref);
 #endif/*--- #if defined(__KERNEL__) ---*/
 #endif/*--- #ifndef __linux_pcmlink_ul_h__ ---*/
--- linux-2.6.32/include/linux/avm_pa.h	2015-11-11 14:59:51.000000000 +0100
+++ linux-2.6.32/include/linux/avm_pa.h	2017-02-15 10:47:14.000000000 +0100
@@ -42,6 +42,7 @@
 /* ------------------------------------------------------------------------ */
 #define AVM_PA_HAS_LISP_SUPPORT
 #define AVM_PA_RECVHOOK_AVAILABLE
+#define AVM_PA_RTP_SESSION_AVAILABLE
 /* ------------------------------------------------------------------------ */
 
 typedef unsigned char  avm_pid_handle;     /* 1 - AVM_PA_MAX_PID */
@@ -78,7 +79,10 @@
    u32 rx_irqdropped;
    u32 rx_headroom_too_small;
    u32 rx_realloc_headroom_failed;
+   u32 fw_output;
    u32 fw_local;
+   u32 fw_rtp;
+   u32 fw_ill;
    /* in avm_pa_pid_snoop_transmit */
    u32 tx_accelerated;
    u32 tx_local;
@@ -93,6 +97,10 @@
    u32 local_sess_error;
    u32 local_sess_ok;
    u32 local_sess_exists;
+   /* in avm_pa_add_rtp_session */
+   u32 rtp_sess_error;
+   u32 rtp_sess_ok;
+   u32 rtp_sess_exists;
    /* in pa_transmit() */
    u32 fw_pkts;
    u32 fw_frags;
@@ -483,6 +491,12 @@
 void avm_pa_flush_lispencap_sessions(void);
 
 /*
+ * avm_pa_flush_rtp_session()
+ *    flushes a rtp session
+ */
+void avm_pa_flush_rtp_session(struct sock *sk);
+
+/*
  * avm_pa_flush_multicast_sessions()
  *    flushes multicast sessions
  */
@@ -741,6 +755,15 @@
  */
 void _avm_pa_add_local_session(PKT *pkt, struct sock *sk);
 
+/*
+ * avm_pa_add_rtp_session()
+ *   local session for this packet must exist.
+ * session is rewritten to rtp session
+ */
+void avm_pa_add_rtp_session(PKT *pkt,
+                            struct sock *sk,
+                            void (*transmit)(struct sock *sk, PKT *pkt));
+
 void avm_pa_filter_packet(PKT *pkt);
 
 /*
--- linux-2.6.32/include/linux/avm_pa_hw.h	2016-03-30 14:36:52.000000000 +0200
+++ linux-2.6.32/include/linux/avm_pa_hw.h	2017-02-15 10:47:14.000000000 +0100
@@ -97,6 +97,12 @@
    unsigned long          refcount;
 };
 
+enum avm_pa_egresstype {
+   avm_pa_egresstype_output,
+   avm_pa_egresstype_local,
+   avm_pa_egresstype_rtp
+} __attribute__((packed));
+
 #define AVM_PA_SESSION_STATS_VALID_HIT      0x01
 #define AVM_PA_SESSION_STATS_VALID_PKTS     0x02
 #define AVM_PA_SESSION_STATS_VALID_BYTES    0x04
@@ -113,7 +119,7 @@
    unsigned char                   push_l2_len;
    unsigned char                   pppoe_offset;
    unsigned char                   pppoe_hdrlen; /* L2 up to PPPoE payload */
-   u8                              not_local;
+   enum avm_pa_egresstype          type;
    u16                             mtu;
    union {
       struct avm_pa_outputinfo {
@@ -121,12 +127,21 @@
          u16                       tc_index;
          u32                       priority;
          u32                       hw_priority;
-		 u8                        cb[48];
+         u8                        cb[48];
+         int                       skb_iif;
       } output;
       struct avm_pa_localinfo {
          struct net_device        *dev;
          struct dst_entry         *dst;
+         int                       skb_iif;
       } local;
+      struct avm_pa_rtpinfo {
+         struct net_device        *dev;
+         int                       skb_iif;
+         struct sock              *sk;
+         void                    (*transmit)(struct sock *sk,
+                                             struct sk_buff *skb);
+      } rtp;
    };
    struct avm_pa_macaddr          *destmac;
    /* statistic */
--- linux-2.6.32/net/avm_pa/avm_pa.c	2015-11-11 14:59:51.000000000 +0100
+++ linux-2.6.32/net/avm_pa/avm_pa.c	2017-04-28 14:26:42.000000000 +0200
@@ -191,10 +191,17 @@
 #ifndef cputime64_zero
 #define cputime64_zero 0ULL
 #endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
 #define PDE_DATA(_inode) (PDE(_inode)->data)
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#define SKB_IFF(skb) ((skb)->skb_iif)
+#else
+#define SKB_IFF(skb) ((skb)->iif)
+#endif
+
 /* ------------------------------------------------------------------------ */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
@@ -207,6 +214,23 @@
 {
    skb->dst = dst;
 }
+
+static inline int kstrtol(const char *s, unsigned int base, long *res)
+{
+    if (isdigit(*s)) {
+       *res = simple_strtol(s, 0, base);
+       return 0;
+    }
+    return -EINVAL;
+}
+static inline int kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+    if (isdigit(*s)) {
+       *res = simple_strtoul(s, 0, base);
+       return 0;
+    }
+    return -EINVAL;
+}
 #endif
 
 /* ------------------------------------------------------------------------ */
@@ -1962,7 +1986,7 @@
    struct avm_pa_pid *pid = PA_PID(ctx, egress->pid_handle);
    struct avm_pa_pkt_info *info = AVM_PKT_INFO(pkt);
 
-   if (egress->not_local) {
+   if (egress->type == avm_pa_egresstype_output) {
       if (pid->prioack_enabled) {
          if (info->match.ack_only) {
             egress->tcpack_pkts++;
@@ -1988,7 +2012,7 @@
       }
    }
    if (egress->vpid_handle) {
-      unsigned int prio  = egress->not_local ? pkt->priority : egress->output.priority;
+      unsigned int prio  = egress->type == avm_pa_egresstype_output ? pkt->priority : egress->output.priority;
       struct avm_pa_vpid *vpid = PA_VPID(ctx, egress->vpid_handle);
       prio = (prio & TC_H_MIN_MASK);
       if (prio >= AVM_PA_MAX_PRIOS) prio = AVM_PA_MAX_PRIOS - 1;
@@ -2003,44 +2027,75 @@
    egress->tx_pkts++;
    pid->tx_pkts++;
 
-   if (egress->not_local) {
-      if (egress->push_l2_len) {
-         memcpy(PKT_PUSH(pkt, egress->push_l2_len),
-                HDRCOPY(&egress->match), egress->push_l2_len);
-         if (egress->pppoe_offset != AVM_PA_OFFSET_NOT_SET) {
-            unsigned char *data = PKT_DATA(pkt) + egress->pppoe_offset;
-            struct pppoehdr *pppoehdr = (struct pppoehdr *)data;
-            pppoehdr->length = htons(PKT_LEN(pkt) - egress->pppoe_hdrlen);
+   switch (egress->type) {
+      case avm_pa_egresstype_output:
+         if (egress->push_l2_len) {
+            memcpy(PKT_PUSH(pkt, egress->push_l2_len),
+                   HDRCOPY(&egress->match), egress->push_l2_len);
+            if (egress->pppoe_offset != AVM_PA_OFFSET_NOT_SET) {
+               unsigned char *data = PKT_DATA(pkt) + egress->pppoe_offset;
+               struct pppoehdr *pppoehdr = (struct pppoehdr *)data;
+               pppoehdr->length = htons(PKT_LEN(pkt) - egress->pppoe_hdrlen);
+            }
          }
-      }
-      pkt->tc_index = egress->output.tc_index;
-      if (pid->ecfg.cb_len) {
-         memcpy(&pkt->cb[pid->ecfg.cb_start],
-                egress->output.cb, pid->ecfg.cb_len);
-      }
-      pkt->uniq_id &= 0xffffff;
-      pkt->uniq_id |= ((unsigned long)egress->output.cpmac_prio) << 24;
+         pkt->tc_index = egress->output.tc_index;
+         if (pid->ecfg.cb_len) {
+            memcpy(&pkt->cb[pid->ecfg.cb_start],
+                   egress->output.cb, pid->ecfg.cb_len);
+         }
+         SKB_IFF(pkt) = egress->output.skb_iif;
+         pkt->uniq_id &= 0xffffff;
+         pkt->uniq_id |= ((unsigned long)egress->output.cpmac_prio) << 24;
 
-      pkt->pkt_type = PACKET_OUTGOING;
-      pkt->ip_summed = CHECKSUM_NONE;
-      skb_reset_mac_header(pkt);
-      skb_set_network_header(pkt, egress->push_l2_len);
+         pkt->pkt_type = PACKET_OUTGOING;
+         pkt->ip_summed = CHECKSUM_NONE;
+         skb_reset_mac_header(pkt);
+         skb_set_network_header(pkt, egress->push_l2_len);
 #if AVM_PA_TRACE
-      if (ctx->dbgtrace)
-         pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s), prio=0x%X, info->match.ack_only=%d\n",
-                               pkt->uniq_id & 0xffffff, pid->cfg.name, pkt->priority, info->match.ack_only);
+         if (ctx->dbgtrace)
+            pa_printk(KERN_DEBUG, "avm_pa: %lu - _pa_transmit(%s), prio=0x%X, info->match.ack_only=%d\n",
+                                  pkt->uniq_id & 0xffffff, pid->cfg.name, pkt->priority, info->match.ack_only);
 #endif
-      (*pid->cfg.tx_func)(pid->cfg.tx_arg, pkt);
-   } else {
-      struct packet_type *ptype = pid->cfg.ptype;
-      skb_set_network_header(pkt, 0);
-      pkt->pkt_type = casttype2pkt_type[egress->match.casttype];
-      if (egress->local.dst)
-         skb_dst_set(pkt, dst_clone(egress->local.dst));
-      pkt->dev = egress->local.dev;
-      ctx->stats.fw_local++;
-      (*ptype->func)(pkt, pkt->dev, ptype, 0);
+            (*pid->cfg.tx_func)(pid->cfg.tx_arg, pkt);
+         ctx->stats.fw_output++;
+         return;
+
+      case avm_pa_egresstype_local:
+         {
+            struct packet_type *ptype = pid->cfg.ptype;
+            skb_set_network_header(pkt, 0);
+            pkt->pkt_type = casttype2pkt_type[egress->match.casttype];
+            if (egress->local.dst)
+               skb_dst_set(pkt, dst_clone(egress->local.dst));
+            pkt->dev = egress->local.dev;
+            SKB_IFF(pkt) = egress->local.skb_iif;
+            ctx->stats.fw_local++;
+            (*ptype->func)(pkt, pkt->dev, ptype, 0);
+            return;
+         }
+
+      case avm_pa_egresstype_rtp:
+         {
+            size_t hsize;
+            skb_set_network_header(pkt, 0);
+            if (pkt->protocol == constant_htons(ETH_P_IP)) {
+               struct iphdr *iph = (struct iphdr *)pkt->data;
+               hsize = iph->ihl*4;
+            } else {
+               hsize = sizeof(struct ipv6hdr);
+            }
+            skb_pull(pkt, hsize); /* skb->data points to udphdr */
+            skb_set_transport_header(pkt, 0);
+            pkt->pkt_type = casttype2pkt_type[egress->match.casttype];
+            pkt->dev = egress->rtp.dev;
+            SKB_IFF(pkt) = egress->rtp.skb_iif;
+            ctx->stats.fw_rtp++;
+            (*egress->rtp.transmit)(egress->rtp.sk, pkt);
+            return;
+         }
    }
+   ctx->stats.fw_ill++;
+   kfree_skb(pkt);
 }
 
 static inline u16 calc_frag_size(u16 mtu, u16 len)
@@ -2962,43 +3017,55 @@
       if (egress->destmac)
          pa_show_macaddr(egress->destmac, fprintffunc, arg);
 
-      if (egress->not_local) {
-         struct avm_pa_pid *pid = PA_PID(ctx, egress->pid_handle);
-         prompt = "Prio";
-         snprintf(buf, sizeof(buf), "%hx:%hx",
-                                    TC_H_MAJ(egress->output.priority)>>16,
-                                    TC_H_MIN(egress->output.priority));
-         (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         prompt = "HW-Prio";
-         snprintf(buf, sizeof(buf), "%hx:%hx",
-                                    TC_H_MAJ(egress->output.hw_priority)>>16,
-                                    TC_H_MIN(egress->output.hw_priority));
-         (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         prompt = "TC index";
-         snprintf(buf, sizeof(buf), "%u", (unsigned)egress->output.tc_index);
-         (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         prompt = "cpmac prio";
-         snprintf(buf, sizeof(buf), "%u", (unsigned)egress->output.cpmac_prio);
-         (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         if (pid->prioack_enabled) {
-            /*--- prompt = "ack prio pkts"; ---*/
-            snprintf(buf, sizeof(buf), "%u (accl acks %u)", pid->prioack_acks, pid->prioack_accl_acks);
-            (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         }
-         if (pid->tget_enabled) {
-            /*--- prompt = "ack prio pkts"; ---*/
-            snprintf(buf, sizeof(buf), "accl %u", pid->tget_accl);
+      switch (egress->type) {
+         case avm_pa_egresstype_output:
+            {
+               struct avm_pa_pid *pid = PA_PID(ctx, egress->pid_handle);
+               prompt = "Prio";
+               snprintf(buf, sizeof(buf), "%hx:%hx",
+                                          TC_H_MAJ(egress->output.priority)>>16,
+                                          TC_H_MIN(egress->output.priority));
+               (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               prompt = "HW-Prio";
+               snprintf(buf, sizeof(buf), "%hx:%hx",
+                                          TC_H_MAJ(egress->output.hw_priority)>>16,
+                                          TC_H_MIN(egress->output.hw_priority));
+               (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               prompt = "TC index";
+               snprintf(buf, sizeof(buf), "%u", (unsigned)egress->output.tc_index);
+               (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               prompt = "cpmac prio";
+               snprintf(buf, sizeof(buf), "%u", (unsigned)egress->output.cpmac_prio);
+               (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               if (pid->prioack_enabled) {
+                  /*--- prompt = "ack prio pkts"; ---*/
+                  snprintf(buf, sizeof(buf), "%u (accl acks %u)", pid->prioack_acks, pid->prioack_accl_acks);
+                  (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               }
+               if (pid->tget_enabled) {
+                  /*--- prompt = "ack prio pkts"; ---*/
+                  snprintf(buf, sizeof(buf), "accl %u", pid->tget_accl);
+                  (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
+               }
+            }
+            break;
+
+         case avm_pa_egresstype_local:
+            prompt = "Dest";
+            sprint_symbol(buf, (unsigned long)egress->local.dst->input);
             (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         }
-      } else {
-         prompt = "Dest";
-         sprint_symbol(buf, (unsigned long)egress->local.dst->input);
-         (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         if (egress->local.dev) {
             prompt = "Input Dev";
             snprintf(buf, sizeof(buf), "%s", egress->local.dev->name);
             (*fprintffunc)(arg, "%-10s: %s\n", prompt, buf);
-         }
+            break;
+         case avm_pa_egresstype_rtp:
+            sprint_symbol(buf, (unsigned long)egress->rtp.transmit);
+            (*fprintffunc)(arg, "transmitfunc   : %s\n", buf);
+            if (egress->rtp.dev) {
+               (*fprintffunc)(arg, "Input Dev      : %s\n",
+                              egress->rtp.dev->name);
+            }
+            break;
       }
       prompt = "tx pkts";
       snprintf(buf, sizeof(buf), "%lu/%lu", (unsigned long)egress->tx_pkts, (unsigned long)egress->tcpack_pkts);
@@ -3043,12 +3110,18 @@
          pa_macaddr_unlink(egress->destmac);
          egress->destmac = 0;
       }
-      if (egress->not_local == 0) {
+      if (egress->type == avm_pa_egresstype_local) {
          if (egress->local.dst) {
             dst_release(egress->local.dst);
             egress->local.dst = 0;
          }
       }
+      if (egress->type == avm_pa_egresstype_rtp) {
+         if (egress->rtp.sk) {
+            sock_put(egress->rtp.sk);
+            egress->rtp.sk = 0;
+         }
+      }
    }
    pa_session_lru_update(AVM_PA_LRU_FREE, session);
 }
@@ -3087,6 +3160,13 @@
       session->hw_session = 0;
    }
 
+   if (   session->negress == 1
+       && session->egress[0].type == avm_pa_egresstype_rtp
+       && session->egress[0].rtp.sk) {
+       sock_put(session->egress[0].rtp.sk);
+       session->egress[0].rtp.sk = 0;
+   }
+
 #ifdef CONFIG_GENERIC_CONNTRACK
    if (session->generic_ct) {
       struct generic_ct *ct = session->generic_ct;
@@ -3289,8 +3369,14 @@
                        (unsigned long)ctx->stats.rx_realloc_headroom_failed);
    (*fprintffunc)(arg, "Fw pakets      : %lu\n",
                        (unsigned long)ctx->stats.fw_pkts);
+   (*fprintffunc)(arg, "Fw output      : %lu\n",
+                       (unsigned long)ctx->stats.fw_output);
    (*fprintffunc)(arg, "Fw local       : %lu\n",
                        (unsigned long)ctx->stats.fw_local);
+   (*fprintffunc)(arg, "Fw rtp         : %lu\n",
+                       (unsigned long)ctx->stats.fw_rtp);
+   (*fprintffunc)(arg, "Fw illegal     : %lu\n",
+                       (unsigned long)ctx->stats.fw_ill);
    (*fprintffunc)(arg, "Fw frags       : %lu\n",
                        (unsigned long)ctx->stats.fw_frags);
    (*fprintffunc)(arg, "Fw drop        : %lu\n",
@@ -3327,6 +3413,13 @@
    (*fprintffunc)(arg, "Loc sess exists: %lu\n",
                        (unsigned long)ctx->stats.local_sess_exists);
 
+   (*fprintffunc)(arg, "RTP sess error : %lu\n",
+                       (unsigned long)ctx->stats.rtp_sess_error);
+   (*fprintffunc)(arg, "RTP sess ok    : %lu\n",
+                       (unsigned long)ctx->stats.rtp_sess_ok);
+   (*fprintffunc)(arg, "RTP sess exists: %lu\n",
+                       (unsigned long)ctx->stats.rtp_sess_exists);
+
    (*fprintffunc)(arg, "TBF schedule   : %lu\n",
                        (unsigned long)ctx->stats.tbf_schedule);
    (*fprintffunc)(arg, "TBF reschedule : %lu\n",
@@ -3613,6 +3706,7 @@
       for (i = 0; i < session->negress; i++) {
          struct avm_pa_egress *egress = &session->egress[i];
          if (egress->pid_handle == pid_handle) {
+            skb->protocol = session->mod.protocol; // 2016-03-01, calle
             skb_reset_mac_header(skb);
             if (session->bsession == 0)
                skb_pull(skb, ETH_HLEN);
@@ -4231,15 +4325,17 @@
       if (sk) {
          if (avm_pa_sock_is_realtime(sk))
             session->realtime = 1;
-         egress->not_local = 0;
+         egress->type = avm_pa_egresstype_local;
          egress->local.dev = pkt->dev;
          egress->local.dst = dst_clone(skb_dst(pkt));
+         egress->local.skb_iif = SKB_IFF(pkt);
       } else {
-         egress->not_local = 1;
+         egress->type = avm_pa_egresstype_output;
          egress->output.priority = orig_packet_prio;
          egress->output.hw_priority = orig_packet_prio;
          egress->output.tc_index = pkt->tc_index;
          egress->output.cpmac_prio = (u8)(pkt->uniq_id >> 24);
+         egress->output.skb_iif = SKB_IFF(pkt);
          if (epid->ecfg.cb_len) {
             memcpy(egress->output.cb,
                    &pkt->cb[epid->ecfg.cb_start], epid->ecfg.cb_len);
@@ -4304,8 +4400,9 @@
       }
 #endif
       if (!ctx->hw_ppa_disabled && ctx->hardware_pa.add_session) {
-         if (epid->prioack_enabled && egress->not_local 
-               && (session->mod.pkttype & AVM_PA_PKTTYPE_PROTO_MASK) == IPPROTO_TCP) {
+         if (   epid->prioack_enabled
+             && egress->type == avm_pa_egresstype_output
+             && (session->mod.pkttype & AVM_PA_PKTTYPE_PROTO_MASK) == IPPROTO_TCP) {
             session->prioack_check = 1; /* add to HW after TCP-ACK-Check */
          } else if ((*ctx->hardware_pa.add_session)(session) == AVM_PA_TX_SESSION_ADDED) {
             session->in_hw = 1;
@@ -4341,15 +4438,17 @@
       if (sk) {
          if (avm_pa_sock_is_realtime(sk))
             session->realtime = 1;
-         egress->not_local = 0;
+         egress->type = avm_pa_egresstype_local;
          egress->local.dev = pkt->dev;
          egress->local.dst = dst_clone(skb_dst(pkt));
+         egress->local.skb_iif = SKB_IFF(pkt);
       } else {
-         egress->not_local = 1;
+         egress->type = avm_pa_egresstype_output;
          egress->output.priority = orig_packet_prio;
          egress->output.hw_priority = orig_packet_prio;
          egress->output.tc_index = pkt->tc_index;
          egress->output.cpmac_prio = (u8)(pkt->uniq_id >> 24);
+         egress->output.skb_iif = SKB_IFF(pkt);
       }
       if (ethh)
          egress->destmac = pa_macaddr_link(ethh->h_dest, pid_handle);
@@ -4418,6 +4517,42 @@
 }
 EXPORT_SYMBOL(_avm_pa_add_local_session);
 
+void avm_pa_add_rtp_session(PKT *pkt,
+                            struct sock *sk,
+                            void (*transmit)(struct sock *sk, PKT *pkt))
+{ 
+   struct avm_pa_global *ctx = &pa_glob;
+   struct avm_pa_pkt_info *info = AVM_PKT_INFO(pkt);
+   struct avm_pa_session *session;
+   struct avm_pa_egress *egress;
+   AVM_PA_LOCK_DECLARE;
+
+   AVM_PA_WRITE_LOCK();
+   session = pa_session_get_unlocked(info->session_handle);
+   if (session == 0 || session->negress != 1) 
+      goto unlock;
+   egress = &session->egress[0];
+   if (egress->type != avm_pa_egresstype_local) {
+      if (egress->type == avm_pa_egresstype_rtp)
+         ctx->stats.rtp_sess_exists++;
+      else
+         ctx->stats.rtp_sess_error++;
+      goto unlock;
+   }
+   session->realtime = 1;
+   egress->type = avm_pa_egresstype_rtp;
+   egress->rtp.dev = pkt->dev;
+   egress->rtp.skb_iif = SKB_IFF(pkt);
+   sock_hold(sk);
+   egress->rtp.sk = sk;
+   egress->rtp.transmit = transmit;
+   ctx->stats.rtp_sess_ok++;
+unlock:
+   AVM_PA_WRITE_UNLOCK();
+
+}
+EXPORT_SYMBOL(avm_pa_add_rtp_session);
+
 void avm_pa_filter_packet(PKT *pkt)
 {
    (void)avm_pa_pid_snoop_transmit(AVM_PKT_INFO(pkt)->ptype_pid_handle, pkt, 0);
@@ -4486,6 +4621,16 @@
    }
    PA_PID(ctx, n)->hw = 0;
    devinfo->pid_handle = n;
+   /*
+    * JZ-34538:
+    * AR9: no hardware acceleration for local sessions (avm_pa_framing_ptype)
+    *
+    * 2017-04-28, SKJ
+    */
+#ifndef CONFIG_AR9
+   if (PA_PID(ctx, n)->egress_framing == avm_pa_framing_ptype)
+      avm_pa_pid_activate_hw_accelaration(n);
+#endif
 
    return 0;
 }
@@ -4609,10 +4754,6 @@
                              (unsigned long)pid->tx_pkts,
                              pid->cfg.name,
                              pidflags2str(pid->ecfg.flags, buf, sizeof(buf)));
-         if (pid->prioack_enabled)
-            (*fprintffunc)(arg, " ack prio 0x%x (tget=%d, tget prio 0x%x)\n", pid->prioack_priority, pid->tget_enabled, pid->tget_priority);
-         else
-            (*fprintffunc)(arg, "\n");
       } else {
          (*fprintffunc)(arg, "PID%-3d: (%5d) %-5s %-5s %10lu %s (ingress %d %s) %s", 
                              pid->pid_handle,
@@ -4624,10 +4765,16 @@
                              pid->ingress_pid_handle,
                              PA_PID(ctx, pid->ingress_pid_handle)->cfg.name,
                              pidflags2str(pid->ecfg.flags, buf, sizeof(buf)));
-         if (pid->prioack_enabled)
-            (*fprintffunc)(arg, " ack prio 0x%x (tget=%d, tget prio 0x%x)\n", pid->prioack_priority, pid->tget_enabled, pid->tget_priority);
-         else
-            (*fprintffunc)(arg, "\n");
+      }
+
+      if (pid->prioack_enabled)
+         (*fprintffunc)(arg, " ack prio 0x%x (tget=%d, tget prio 0x%x)\n", pid->prioack_priority, pid->tget_enabled, pid->tget_priority);
+      else
+         (*fprintffunc)(arg, "\n");
+      if (pid->rx_channel_activated || pid->tx_channel_activated) {
+         (*fprintffunc)(arg, "      rx_channel %d tx_channel %d\n",
+                             pid->rx_channel_activated ? 1 : 0,
+                             pid->tx_channel_activated ? 1 : 0);
       }
    }
 }
@@ -4690,11 +4837,11 @@
          struct avm_hardware_pa *hwpa = &ctx->hardware_pa;
          avm_pid_handle n;
          /* free virtual channels */
-         if (pid->tx_channel_activated && hwpa && hwpa->free_tx_channel) {
+         if (pid->tx_channel_activated && hwpa->free_tx_channel) {
              hwpa->free_tx_channel( pid->pid_handle );
              pid->tx_channel_activated = 0;
          }
-         if (pid->rx_channel_activated && hwpa && hwpa->free_rx_channel) {
+         if (pid->rx_channel_activated && hwpa->free_rx_channel) {
              hwpa->free_rx_channel( pid->pid_handle );
              pid->rx_channel_activated = 0;
          }
@@ -4772,21 +4919,34 @@
                       pid_handle);
       return -1;
    }
+   printk(KERN_INFO "avm_pa: try to activate hw accelaration for pid %u (%s)\n",
+                    pid_handle, pid->cfg.name);
    hwpa = &ctx->hardware_pa;
    if (   pid->rx_channel_activated == 0
        && pid->ingress_framing == avm_pa_framing_ether
        && pid->ecfg.rx_slow
        && hwpa->alloc_rx_channel) {
-      if ((*hwpa->alloc_rx_channel)(pid_handle) == 0)
-         pid->rx_channel_activated = 1;
+      if ((*hwpa->alloc_rx_channel)(pid_handle) < 0) {
+         printk(KERN_ERR "avm_pa: can't activate rx channel, pid %u (%s)\n",
+                          pid_handle, pid->cfg.name);
    }else {
-       printk(KERN_ERR "don_t alloc_rx_channel: %d, %d, %pF, %pF\n", pid->rx_channel_activated, pid->ingress_framing,pid->ecfg.rx_slow, hwpa->alloc_rx_channel );
+         pid->rx_channel_activated = 1;
+         printk(KERN_INFO "avm_pa: rx channel activated, pid %u (%s)\n",
+                          pid_handle, pid->cfg.name);
+      }
    }
    if (   pid->tx_channel_activated == 0
-       && pid->ingress_framing == avm_pa_framing_ether
+       && (   pid->egress_framing == avm_pa_framing_ether
+           || pid->egress_framing == avm_pa_framing_ptype)
        && hwpa->alloc_tx_channel) {
-      if ((*hwpa->alloc_tx_channel)(pid_handle) == 0)
+      if ((*hwpa->alloc_tx_channel)(pid_handle) < 0) {
+         printk(KERN_ERR "avm_pa: can't activate tx channel, pid %u (%s)\n",
+                          pid_handle, pid->cfg.name);
+      } else {
          pid->tx_channel_activated = 1;
+         printk(KERN_INFO "avm_pa: tx channel activated, pid %u (%s)\n",
+                          pid_handle, pid->cfg.name);
+      }
    }
    return 0;
 }
@@ -4886,9 +5046,27 @@
 void avm_pa_register_hardware_pa(struct avm_hardware_pa *pa_functions)
 {
    struct avm_pa_global *ctx = &pa_glob;
-   if (pa_functions)
+   if (pa_functions) {
       ctx->hardware_pa = *pa_functions;
-   else {
+      /*
+       * JZ-34538:
+       * AR9: no hardware acceleration for local sessions (avm_pa_framing_ptype)
+       *
+       * 2017-04-28, SKJ
+       */
+#ifndef CONFIG_AR9
+      if (pa_functions->alloc_tx_channel || pa_functions->alloc_rx_channel) {
+         avm_pid_handle n;
+         for (n=1; n < CONFIG_AVM_PA_MAX_PID; n++) {
+            struct avm_pa_pid *pid = PA_PID(ctx, n);
+            if (   pid->pid_handle == n
+                && pid->egress_framing == avm_pa_framing_ptype) {
+               avm_pa_pid_activate_hw_accelaration(n);
+            }
+         }
+      }
+#endif
+   } else {
       struct avm_pa_global *ctx = &pa_glob;
       struct avm_pa_session *session, *next;
       AVM_PA_LOCK_DECLARE;
@@ -5190,6 +5368,30 @@
 }
 EXPORT_SYMBOL(avm_pa_flush_lispencap_sessions);
 
+void avm_pa_flush_rtp_session(struct sock *sk)
+{
+   struct avm_pa_global *ctx = &pa_glob;
+   struct avm_pa_session *session, *next;
+   AVM_PA_LOCK_DECLARE;
+
+   AVM_PA_WRITE_LOCK();
+
+   session = ctx->sess_lru[AVM_PA_LRU_ACTIVE].lru_head;
+   while (session) {
+      next = session->lru_next;
+      if (   session->negress == 1
+          && session->egress[0].type == avm_pa_egresstype_rtp
+          && session->egress[0].rtp.sk == sk) {
+         pa_kill_session_unlocked(session, "rtp flush");
+         ctx->stats.sess_flushed++;
+      }
+      session = next;
+   }
+
+   AVM_PA_WRITE_UNLOCK();
+}
+EXPORT_SYMBOL(avm_pa_flush_rtp_session);
+
 void avm_pa_flush_multicast_sessions(void)
 {
    struct avm_pa_global *ctx = &pa_glob;
--- linux-2.6.32/net/ipv4/tcp_input.c	2013-02-12 12:29:49.000000000 +0100
+++ linux-2.6.32/net/ipv4/tcp_input.c	2019-07-09 15:37:57.000000000 +0200
@@ -74,7 +74,7 @@
 
 int sysctl_tcp_timestamps __read_mostly = 1;
 int sysctl_tcp_window_scaling __read_mostly = 1;
-int sysctl_tcp_sack __read_mostly = 1;
+int sysctl_tcp_sack __read_mostly = 0;
 int sysctl_tcp_fack __read_mostly = 1;
 int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH;
 int sysctl_tcp_ecn __read_mostly = 2;
--- linux-2.6.32/net/ipv4/tcp_output.c	2013-10-22 18:53:31.000000000 +0200
+++ linux-2.6.32/net/ipv4/tcp_output.c	2019-07-09 15:37:58.000000000 +0200
@@ -983,6 +983,9 @@
 	/* Now subtract TCP options size, not including SACKs */
 	mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
 
+	/* CVE-2019-11479: set mss to 536 minimum */
+	mss_now = max(mss_now, 536);
+
 	return mss_now;
 }
 
--- linux-2.6.32/net/ipv4/tcp_timer.c	2011-05-25 15:51:48.000000000 +0200
+++ linux-2.6.32/net/ipv4/tcp_timer.c	2019-07-09 15:37:58.000000000 +0200
@@ -126,6 +126,8 @@
 			mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1;
 			mss = min(sysctl_tcp_base_mss, mss);
 			mss = max(mss, 68 - tp->tcp_header_len);
+			/* CVE-2019-11479: set mss to 536 minimum */
+			mss = max(mss, 536);
 			icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
 			tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 		}
