diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index afbfc0f656f331e82d4c8a528134ff892e2a8635..c72beba2907887b096e5e252dbe337c4ff6fb506 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -65,6 +65,17 @@ static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
 static struct usb_driver cdc_ncm_driver;
+/*
+ * use cdc_ncm.dstmac=00:20:30:40:50:60 from boot command or module load
+ */
+static int destMacSet;
+static char *dstmac = "FF:FF:FF:FF:FF:FF";
+static unsigned char destMac[6];
+module_param(dstmac, charp, 0);
+MODULE_PARM_DESC(dstmac, "Forced MAC in Downlink");
+MODULE_DEVICE_TABLE(usb, cdc_devs);
+
+#define MEMCPY_FOR_ZERO_GAP
 
 struct cdc_ncm_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -89,6 +100,25 @@ static const struct cdc_ncm_stats cdc_ncm_gstrings_stats[] = {
 	CDC_NCM_SIMPLE_STAT(rx_ntbs),
 };
 
+static void cdc_ncm_init_dstmac(void)
+{
+	unsigned int iMac[6];
+	int i;
+
+	//To check if we assign the value to dstmac when inserting module.Default value of dstmac is "FF:FF:FF:FF:FF:FF"
+	if ('F' != *dstmac) {
+		/* we got a parameter */
+		printk(KERN_INFO KBUILD_MODNAME ": Ethernet address for downlink dstmac=%s\n", dstmac);
+		sscanf(dstmac, "%x:%x:%x:%x:%x:%x", &iMac[0], &iMac[1], &iMac[2], &iMac[3], &iMac[4], &iMac[5]);
+		for (i = 0; i < 6; i++)
+			destMac[i] = (unsigned char)iMac[i];
+
+		destMacSet = 1;
+	} else {
+		printk(KERN_INFO KBUILD_MODNAME ": Default Ethernet address for downlink\n");
+	}
+}
+
 static int cdc_ncm_get_sset_count(struct net_device __always_unused *netdev, int sset)
 {
 	switch (sset) {
@@ -1492,11 +1522,28 @@ next_ndp:
 			break;
 
 		} else {
+#ifdef MEMCPY_FOR_ZERO_GAP
+#define PPA_ALIGN	8
+			/* Do the skb_reserve 8 bits for PMAC/CMB buffer. */
+			skb = alloc_skb(len + PPA_ALIGN, GFP_ATOMIC);
+			if (!skb)
+				goto error;
+			skb_reserve(skb, PPA_ALIGN);
+			skb->len = len;
+			memcpy(skb->data, skb_in->data + offset, len);
+			if (destMacSet && skb->data)
+				memcpy(skb->data, destMac, 6);
+
+			skb_set_tail_pointer(skb, len);
+#else
 			/* create a fresh copy to reduce truesize */
 			skb = netdev_alloc_skb_ip_align(dev->net,  len);
 			if (!skb)
 				goto error;
 			memcpy(skb_put(skb, len), skb_in->data + offset, len);
+			if (destMacSet && skb->data)
+				memcpy(skb->data, destMac, 6);
+#endif
 			usbnet_skb_return(dev, skb);
 			payload += len;	/* count payload bytes in this NTB */
 		}
@@ -1590,6 +1637,13 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
 	}
 }
 
+static int
+cdc_ncm_probe(struct usb_interface *udev, const struct usb_device_id *prod)
+{
+	cdc_ncm_init_dstmac();
+	return usbnet_probe(udev, prod);
+}
+
 static const struct driver_info cdc_ncm_info = {
 	.description = "CDC NCM",
 	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
@@ -1712,7 +1766,7 @@ MODULE_DEVICE_TABLE(usb, cdc_devs);
 static struct usb_driver cdc_ncm_driver = {
 	.name = "cdc_ncm",
 	.id_table = cdc_devs,
-	.probe = usbnet_probe,
+	.probe = cdc_ncm_probe,
 	.disconnect = usbnet_disconnect,
 	.suspend = usbnet_suspend,
 	.resume = usbnet_resume,
@@ -1722,7 +1776,6 @@ static struct usb_driver cdc_ncm_driver = {
 };
 
 module_usb_driver(cdc_ncm_driver);
-
 MODULE_AUTHOR("Hans Petter Selasky");
 MODULE_DESCRIPTION("USB CDC NCM host driver");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d5071e364d40e1dba629a887d67a07c4ff66825c..42afc8d60badc1f796b98a288417061e08b350bf 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -31,7 +31,6 @@
 
 // #define	DEBUG			// error path messages, extra info
 // #define	VERBOSE			// more; success messages
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
@@ -45,6 +44,11 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/pm_runtime.h>
+#ifdef CONFIG_PPA
+#include <net/ppa/ppa_api.h>
+#include <net/ppa/ppa_hook.h>
+#include <net/ppa/ppa_api_directpath.h>
+#endif
 
 #define DRIVER_VERSION		"22-Aug-2005"
 
@@ -89,6 +93,70 @@ static int msg_level = -1;
 module_param (msg_level, int, 0);
 MODULE_PARM_DESC (msg_level, "Override default message level");
 
+#ifdef CONFIG_PPA
+static int usbnet_addr_monitor;
+static int ppa_startup_hook = 1;
+module_param(ppa_startup_hook, int, 0);
+MODULE_PARM_DESC(ppa_startup_hook, "0: don't hook ppa at startup, other: do hook");
+
+PPA_DIRECTPATH_CB usbnet_ppafp_cb;
+int32_t usbnet_ppafp_pause_rx(PPA_NETIF *dev);
+int32_t usbnet_ppafp_resume_rx(PPA_NETIF *dev);
+int32_t usbnet_ppafp_start_xmit(PPA_NETIF *rxif, PPA_NETIF *txif, PPA_BUF *skb, int32_t len);
+
+int	usbnet_ppadp_occupied = -1;
+
+static int  ppafp_enable = -1;
+module_param (ppafp_enable, int, 1);
+MODULE_PARM_DESC (ppafp_enable, "Override default ppafp_enable");
+
+static void register_ppadp_sub(struct net_device *net)
+{
+	uint32_t status;
+	uint32_t if_id;
+	struct usbnet *dev = netdev_priv(net);
+
+	if (!dev->usbnet_ppadp_on || !ppa_hook_directpath_register_dev_fn) {
+		dev->usbnet_ppadp_ifid = -1;
+		return;
+	}
+
+	if (dev->usbnet_ppadp_ifid >= 0)
+		return;
+
+	usbnet_ppafp_cb.stop_tx_fn = usbnet_ppafp_pause_rx;
+	usbnet_ppafp_cb.start_tx_fn = usbnet_ppafp_resume_rx;
+	usbnet_ppafp_cb.rx_fn = usbnet_ppafp_start_xmit;
+
+	status = ppa_hook_directpath_register_dev_fn(
+					&if_id, net,
+					&usbnet_ppafp_cb,
+					PPA_F_DIRECTPATH_REGISTER
+					| PPA_F_DIRECTPATH_ETH_IF
+#ifdef PPA_F_DIRECTPATH_WAN
+					| PPA_F_DIRECTPATH_WAN
+#endif
+			);
+
+	if (status == PPA_SUCCESS)
+		dev->usbnet_ppadp_ifid = if_id;
+	else
+		dev->usbnet_ppadp_ifid = -1;
+}
+
+static void register_ppadp(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	if (!dev->usbnet_ppadp_on || (dev->usbnet_ppadp_ifid >= 0) || !ppa_hook_directpath_register_dev_fn)
+		return;
+
+	if (in_interrupt())
+		usbnet_defer_kevent(dev, EVENT_REREG_PPA);
+	else
+		register_ppadp_sub(net);
+}
+#endif
 /*-------------------------------------------------------------------------*/
 
 /* handles CDC Ethernet and many other network "bulk data" interfaces */
@@ -323,6 +391,20 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
 		return;
 	}
 
+#ifdef CONFIG_PPA
+	if (usbnet_addr_monitor) {
+		const struct iphdr *ih;
+		struct iphdr _iph;
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+
+		printk(KERN_INFO "usbnet_skb_return() INPUT SRC[%pi4/%pM] DST[%pi4/%pM]\n"
+				, eth_hdr(skb)->h_source
+				, &ih->saddr
+				, eth_hdr(skb)->h_dest
+				, &ih->daddr);
+	}
+#endif
+
 	/* only update if unset to allow minidriver rx_fixup override */
 	if (skb->protocol == 0)
 		skb->protocol = eth_type_trans (skb, dev->net);
@@ -337,10 +419,41 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
 	if (skb_defer_rx_timestamp(skb))
 		return;
 
+#ifdef CONFIG_PPA
+	if ( dev->usbnet_ppadp_on){
+		register_ppadp(dev->net);
+		if ((dev->usbnet_ppadp_ifid >= 0)
+			&& ppa_hook_directpath_send_fn
+			&& ppa_hook_get_ifid_for_netif_fn) {
+				uint32_t    fpstatus;
+				skb_push(skb, ETH_HLEN);
+				skb->mac_header = skb->data;
+				fpstatus = ppa_hook_directpath_send_fn(dev->usbnet_ppadp_ifid, (PPA_BUF *)skb, skb->len, 0);
+				if (!fpstatus) {
+					if (usbnet_addr_monitor)
+						printk(KERN_INFO "     Go PPA OK\n");
+				return;
+				}
+				dev_dbg(&dev->udev->dev, "ppa_hook_directpath_send_fn status %d", fpstatus);
+				/* should not touch the unavailable skb anymore since
+				   ppa_hook_directpath_send_fn will call netif_rx after
+				   failed acceleration. */
+				skb_pull(skb, ETH_HLEN);
+				if (usbnet_addr_monitor)
+					printk(KERN_INFO "Go PPA NOK %d  Try kernel\n", fpstatus);
+				return;
+			}
+		}
+#endif
+
 	status = netif_rx (skb);
 	if (status != NET_RX_SUCCESS)
 		netif_dbg(dev, rx_err, dev->net,
 			  "netif_rx status %d\n", status);
+#ifdef CONFIG_PPA
+    if (usbnet_addr_monitor)
+		printk(KERN_INFO "Go KERNEL status:%d \n", status);
+#endif
 }
 EXPORT_SYMBOL_GPL(usbnet_skb_return);
 
@@ -479,6 +592,24 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
 	unsigned long		lockflags;
 	size_t			size = dev->rx_urb_size;
 
+/*
+ * Calculate how many extra headroom is needed then allocate the
+ * skb with the proper length
+ */
+#if !defined(USBNET_NOOFFSET) || defined(USBNET_EXTRAOFFSET)
+	size_t headroom = 0;
+#if defined(CONFIG_PPA) && defined(USBNET_NOOFFSET)
+	headroom += ((dev->usbnet_ppadp_on) ? 0 : NET_IP_ALIGN);
+#else
+	headroom += NET_IP_ALIGN;
+#endif
+#if defined(USBNET_EXTRAOFFSET)
+	headroom += USBNET_EXTRAOFFSET;
+#endif
+	size += headroom;
+#endif
+
+
 	/* prevent rx skb allocation when error ratio is high */
 	if (test_bit(EVENT_RX_KILL, &dev->flags)) {
 		usb_free_urb(urb);
@@ -585,6 +716,9 @@ static void rx_complete (struct urb *urb)
 	skb_put (skb, urb->actual_length);
 	state = rx_done;
 	entry->urb = NULL;
+#ifdef CONFIG_PPA
+	register_ppadp(dev->net);
+#endif
 
 	switch (urb_status) {
 	/* success */
@@ -666,6 +800,44 @@ block:
 }
 
 /*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PPA
+int32_t usbnet_ppafp_pause_rx(PPA_NETIF *dev)
+{
+	struct usbnet *net = netdev_priv(dev);
+
+	set_bit(EVENT_RX_PAUSED, &net->flags);
+
+	if (netif_msg_rx_status(net))
+		dev_dbg(&net->udev->dev, "paused rx queue enabled");
+
+	return PPA_SUCCESS;
+}
+
+int32_t usbnet_ppafp_resume_rx(PPA_NETIF *dev)
+{
+	struct usbnet *net = netdev_priv(dev);
+	struct sk_buff *skb;
+	int num = 0;
+
+	clear_bit(EVENT_RX_PAUSED, &net->flags);
+
+	while ((skb = skb_dequeue(&net->rxq_pause)) != NULL) {
+			usbnet_skb_return(net, skb);
+			num++;
+	}
+
+	tasklet_schedule(&net->bh);
+
+	if (netif_msg_rx_status(net))
+		dev_dbg(&net->udev->dev, "paused rx queue disabled, %d skbs requeued", num);
+
+	return PPA_SUCCESS;
+}
+#endif
+
+
+
 void usbnet_pause_rx(struct usbnet *dev)
 {
 	set_bit(EVENT_RX_PAUSED, &dev->flags);
@@ -762,6 +934,63 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PPA
+static DEVICE_BOOL_ATTR(addr_monitor, S_IRUGO | S_IWUSR, usbnet_addr_monitor);
+
+static ssize_t show_ppa_dp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	struct usbnet     *udev = netdev_priv(netdev);
+
+	return sprintf(buf, "itf_ppadp_on:%d ppadp_ifid:%d ppadp_occupied:%d\n",
+					udev->usbnet_ppadp_on,
+					udev->usbnet_ppadp_ifid,
+					usbnet_ppadp_occupied);
+}
+
+static ssize_t store_ppa_dp(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	struct usbnet     *udev = netdev_priv(netdev);
+	char *endp;
+	unsigned long target;
+
+	target = simple_strtoul(buf, &endp, 0);
+
+	if (endp == buf)
+		return -EBADMSG;
+
+	if (target == 0) {
+		if (udev->usbnet_ppadp_ifid >= 0) {
+			uint32_t if_id;
+			if (ppa_hook_directpath_rx_stop_fn)
+				ppa_hook_directpath_rx_stop_fn(udev->usbnet_ppadp_ifid, 0);
+			if (ppa_hook_directpath_register_dev_fn)
+				ppa_hook_directpath_register_dev_fn(&if_id, netdev, &usbnet_ppafp_cb, 0);
+		}
+		udev->usbnet_ppadp_on = 0;
+		udev->usbnet_ppadp_ifid = -1;
+		usbnet_ppadp_occupied = 0;
+		return len;
+	} else if (target == 1) {
+		if (ppafp_enable
+			&& usbnet_ppadp_occupied == 0
+			&& udev->usbnet_ppadp_on == 0) {
+			udev->usbnet_ppadp_on = 1;
+			usbnet_ppadp_occupied = 1;
+			register_ppadp(netdev);
+		}
+		return len;
+	 } else
+		return -EBADMSG;
+}
+
+/* extern struct device_attribute dev_attr_ppa_dp;*/
+static DEVICE_ATTR(ppa_dp, S_IRUGO|S_IWUSR, show_ppa_dp, store_ppa_dp);
+
+#endif
+/*--------------------------------------------------------------------------*/
+
 static void wait_skb_queue_empty(struct sk_buff_head *q)
 {
 	unsigned long flags;
@@ -807,6 +1036,20 @@ int usbnet_stop (struct net_device *net)
 	clear_bit(EVENT_DEV_OPEN, &dev->flags);
 	netif_stop_queue (net);
 
+#ifdef CONFIG_PPA
+	if (dev->usbnet_ppadp_ifid >= 0) {
+		uint32_t if_id;
+		if_id = dev->usbnet_ppadp_ifid;
+		printk(KERN_INFO "<%s> Unregister if_id: %d\n", __func__, if_id);
+		if (ppa_hook_directpath_rx_stop_fn)
+			ppa_hook_directpath_rx_stop_fn(dev->usbnet_ppadp_ifid, 0);
+		if (ppa_hook_directpath_register_dev_fn)
+			ppa_hook_directpath_register_dev_fn(&if_id, net, &usbnet_ppafp_cb, 0);
+	}
+	dev->usbnet_ppadp_ifid = -1;
+
+#endif
+
 	netif_info(dev, ifdown, dev->net,
 		   "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
 		   net->stats.rx_packets, net->stats.tx_packets,
@@ -890,6 +1133,15 @@ int usbnet_open (struct net_device *net)
 	/* hard_mtu or rx_urb_size may change in reset() */
 	usbnet_update_max_qlen(dev);
 
+#ifdef CONFIG_PPA
+	if(ppa_startup_hook && usbnet_ppadp_occupied == -1) {
+		dev->usbnet_ppadp_on = 1;
+		usbnet_ppadp_occupied = 1;
+	}
+	dev->usbnet_ppadp_ifid = -1;
+	register_ppadp(net);
+#endif
+
 	// insist peer be connected
 	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
 		netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval);
@@ -908,6 +1160,10 @@ int usbnet_open (struct net_device *net)
 
 	set_bit(EVENT_DEV_OPEN, &dev->flags);
 	netif_start_queue (net);
+#ifdef CONFIG_PPA
+	if (dev->usbnet_ppadp_on && (dev->usbnet_ppadp_ifid >= 0) && ppa_hook_directpath_rx_restart_fn)
+		ppa_hook_directpath_rx_restart_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 	netif_info(dev, ifup, dev->net,
 		   "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n",
 		   (int)RX_QLEN(dev), (int)TX_QLEN(dev),
@@ -1103,6 +1359,13 @@ usbnet_deferred_kevent (struct work_struct *work)
 		container_of(work, struct usbnet, kevent);
 	int			status;
 
+
+#ifdef CONFIG_PPA
+	if (test_bit(EVENT_REREG_PPA, &dev->flags)) {
+		clear_bit(EVENT_REREG_PPA, &dev->flags);
+		register_ppadp_sub(dev->net);
+	}
+#endif
 	/* usb_clear_halt() needs a thread context */
 	if (test_bit (EVENT_TX_HALT, &dev->flags)) {
 		unlink_urbs (dev, &dev->txq);
@@ -1120,8 +1383,13 @@ fail_pipe:
 					   status);
 		} else {
 			clear_bit (EVENT_TX_HALT, &dev->flags);
-			if (status != -ESHUTDOWN)
+			if (status != -ESHUTDOWN) {
+#ifdef CONFIG_PPA
+				if (dev->usbnet_ppadp_on && dev->usbnet_ppadp_ifid >= 0 && ppa_hook_directpath_rx_restart_fn)
+					ppa_hook_directpath_rx_restart_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 				netif_wake_queue (dev->net);
+			}
 		}
 	}
 	if (test_bit (EVENT_RX_HALT, &dev->flags)) {
@@ -1206,7 +1474,7 @@ skip_reset:
 
 /*-------------------------------------------------------------------------*/
 
-static void tx_complete (struct urb *urb)
+static void tx_complete(struct urb *urb)
 {
 	struct sk_buff		*skb = (struct sk_buff *) urb->context;
 	struct skb_data		*entry = (struct skb_data *) skb->cb;
@@ -1241,6 +1509,10 @@ static void tx_complete (struct urb *urb)
 				netif_dbg(dev, link, dev->net,
 					  "tx throttle %d\n", urb->status);
 			}
+#ifdef CONFIG_PPA
+			if (dev->usbnet_ppadp_on && dev->usbnet_ppadp_ifid >= 0 && ppa_hook_directpath_rx_stop_fn)
+				ppa_hook_directpath_rx_stop_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 			netif_stop_queue (dev->net);
 			break;
 		default:
@@ -1273,6 +1545,55 @@ EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PPA
+int32_t usbnet_ppafp_start_xmit(PPA_NETIF *rxif, PPA_NETIF *txif, PPA_BUF *skb, int32_t len)
+{
+	int pktlen;
+
+	if (usbnet_addr_monitor) {
+		const struct iphdr *ih;
+		struct iphdr _iph;
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+
+		printk(KERN_INFO "usbnet_ppafp_start_xmit() INPUT SRC[%pi4/%pM] DST[%pi4/%pM]\n"
+				, eth_hdr(skb)->h_source
+				, &ih->saddr
+				, eth_hdr(skb)->h_dest
+				, &ih->daddr);
+	}
+
+	if (rxif) {
+		if (usbnet_addr_monitor)
+			printk(KERN_INFO "Kicked back\n");
+		if (netif_running(rxif)) {
+			pktlen = skb->len;
+			skb->dev = rxif;
+			skb->protocol = eth_type_trans(skb, rxif);
+			if ( netif_rx(skb) == NET_RX_DROP )
+				rxif->stats.rx_dropped++;
+			else {
+				if (usbnet_addr_monitor)
+					printk(KERN_INFO "Failed drop\n");
+				rxif->stats.rx_packets++;
+				rxif->stats.rx_bytes += pktlen;
+			}
+			return 0;
+		}
+		if (usbnet_addr_monitor)
+			printk(KERN_INFO "No run\n");
+	} else if (txif) {
+		skb->dev = txif;
+		dev_queue_xmit(skb);
+		if (usbnet_addr_monitor)
+			printk(KERN_INFO "Go Tx\n");
+		return 0;
+	}
+
+	dev_kfree_skb_any(skb);
+}
+#endif
+
+
 static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
 {
 	unsigned num_sgs, total_len = 0;
@@ -1306,7 +1627,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
 	return 1;
 }
 
-netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
+netdev_tx_t usbnet_start_xmit(struct sk_buff *skb,
 				     struct net_device *net)
 {
 	struct usbnet		*dev = netdev_priv(net);
@@ -1317,6 +1638,22 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
 	unsigned long		flags;
 	int retval;
 
+#ifdef CONFIG_PPA
+	if (usbnet_addr_monitor) {
+		/* NCM/MBIM tx_timer_cb will send with NULL skb for starting the transmission of remain SKBs */
+		if (skb != NULL) {
+			const struct iphdr *ih;
+			struct iphdr _iph;
+			ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+
+			printk(KERN_INFO "usbnet_start_xmit() INPUT SRC[%pi4/%pM] DST[%pi4/%pM]\n"
+				, eth_hdr(skb)->h_source
+				, &ih->saddr
+				, eth_hdr(skb)->h_dest
+				, &ih->daddr);
+		}
+	}
+#endif
 	if (skb)
 		skb_tx_timestamp(skb);
 
@@ -1406,8 +1743,16 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
 	}
 #endif
 
+#ifdef CONFIG_PPA
+	register_ppadp(dev->net);
+#endif
+
 	switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) {
 	case -EPIPE:
+#ifdef CONFIG_PPA
+		if (dev->usbnet_ppadp_on && dev->usbnet_ppadp_ifid >= 0 && ppa_hook_directpath_rx_stop_fn)
+			ppa_hook_directpath_rx_stop_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 		netif_stop_queue (net);
 		usbnet_defer_kevent (dev, EVENT_TX_HALT);
 		usb_autopm_put_interface_async(dev->intf);
@@ -1420,8 +1765,13 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
 	case 0:
 		netif_trans_update(net);
 		__usbnet_queue_skb(&dev->txq, skb, tx_start);
-		if (dev->txq.qlen >= TX_QLEN (dev))
+		if (dev->txq.qlen >= TX_QLEN (dev)) {
+#ifdef CONFIG_PPA
+			if (dev->usbnet_ppadp_on && dev->usbnet_ppadp_ifid >= 0 && ppa_hook_directpath_rx_stop_fn)
+				ppa_hook_directpath_rx_stop_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 			netif_stop_queue (net);
+		}
 	}
 	spin_unlock_irqrestore (&dev->txq.lock, flags);
 
@@ -1525,8 +1875,13 @@ static void usbnet_bh (unsigned long param)
 			if (dev->rxq.qlen < RX_QLEN(dev))
 				tasklet_schedule (&dev->bh);
 		}
-		if (dev->txq.qlen < TX_QLEN (dev))
+		if (dev->txq.qlen < TX_QLEN (dev)) {
+#ifdef CONFIG_PPA
+			if(dev->usbnet_ppadp_on && dev->usbnet_ppadp_ifid >= 0 && ppa_hook_directpath_rx_restart_fn)
+				ppa_hook_directpath_rx_restart_fn(dev->usbnet_ppadp_ifid, 0);
+#endif
 			netif_wake_queue (dev->net);
+		}
 	}
 }
 
@@ -1558,6 +1913,13 @@ void usbnet_disconnect (struct usb_interface *intf)
 		   dev->driver_info->description);
 
 	net = dev->net;
+
+#ifdef CONFIG_PPA
+	device_remove_file(&net->dev, &dev_attr_ppa_dp);
+	device_remove_file(&net->dev, &(dev_attr_addr_monitor.attr));
+	usbnet_ppadp_occupied = (ppa_startup_hook)? -1:0;
+#endif
+
 	unregister_netdev (net);
 
 	cancel_work_sync(&dev->kevent);
@@ -1662,6 +2024,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 	dev->interrupt_count = 0;
 
 	dev->net = net;
+
+#ifdef CONFIG_PPA
+	dev->usbnet_ppadp_on   =  0;
+	dev->usbnet_ppadp_ifid = -1;
+#endif
 	strcpy (net->name, "usb%d");
 	memcpy (net->dev_addr, node_id, sizeof node_id);
 
@@ -1758,6 +2125,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 	// ok, it's ready to go.
 	usb_set_intfdata (udev, dev);
 
+#ifdef CONFIG_PPA
+	device_create_file(&net->dev, &dev_attr_ppa_dp);
+	device_create_file(&net->dev, &(dev_attr_addr_monitor.attr));
+#endif
+
 	netif_device_attach (net);
 
 	if (dev->driver_info->flags & FLAG_LINK_INTR)
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 6e0ce8c7b8cb5a9fcb985a5a5078f82267d03092..890aa104604d27e1122143301e643073971d8889 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -79,6 +79,9 @@ struct usbnet {
 #		define EVENT_RX_KILL	10
 #		define EVENT_LINK_CHANGE	11
 #		define EVENT_SET_RX_MODE	12
+#       define EVENT_REREG_PPA 13
+	int usbnet_ppadp_on;
+	int usbnet_ppadp_ifid;
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)