Merge remote-tracking branch 'remotes/gfiber-internal/vendor_drops' into merge2

Conflicts:
	arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
	arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
	arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
	arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
	arch/arm/mach-feroceon-kw2/sysmap.c
	arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
	arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
	arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
	arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c

Change-Id: I05dd1583e129989d259d9cd72814c5454040a576
diff --git a/Documentation/DocBook/dvb/dvbstb.pdf b/Documentation/DocBook/dvb/dvbstb.pdf
deleted file mode 100644
index 0fa75d9..0000000
--- a/Documentation/DocBook/dvb/dvbstb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/crop.pdf b/Documentation/DocBook/v4l/crop.pdf
deleted file mode 100644
index c9fb81c..0000000
--- a/Documentation/DocBook/v4l/crop.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/fieldseq_bt.pdf b/Documentation/DocBook/v4l/fieldseq_bt.pdf
deleted file mode 100644
index 26598b2..0000000
--- a/Documentation/DocBook/v4l/fieldseq_bt.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/fieldseq_tb.pdf b/Documentation/DocBook/v4l/fieldseq_tb.pdf
deleted file mode 100644
index 4965b22..0000000
--- a/Documentation/DocBook/v4l/fieldseq_tb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/vbi_525.pdf b/Documentation/DocBook/v4l/vbi_525.pdf
deleted file mode 100644
index 9e72c25..0000000
--- a/Documentation/DocBook/v4l/vbi_525.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/vbi_625.pdf b/Documentation/DocBook/v4l/vbi_625.pdf
deleted file mode 100644
index 765235e..0000000
--- a/Documentation/DocBook/v4l/vbi_625.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/v4l/vbi_hsync.pdf b/Documentation/DocBook/v4l/vbi_hsync.pdf
deleted file mode 100644
index 200b668..0000000
--- a/Documentation/DocBook/v4l/vbi_hsync.pdf
+++ /dev/null
Binary files differ
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 30ae0ba..746ecfd 100755
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -130,6 +130,102 @@
 1:		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
+#ifndef CONFIG_MV_DRAM_DEFAULT_ACCESS_CFG
+		b	2f
+internal_regs:	.word 	0xf1000000
+2:		mov	r0, #0
+		mcr	p15, 0, r0, c7, c5, 0	@ invalidate I-Cache
+		mrc 	p15, 0, r0, c1, c0, 0	@ read cr
+		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
+		orr	r0, r0, #0x4		@ D-cache enable
+		mcr 	p15, 0, r0, c1, c0, 0	@ update cr
+		
+		ldr	r0, internal_regs
+		add	r5, r0, #0x18000
+		add	r5, r5, #0x200		@ device and vendor ID register(A-MC)
+
+		ldr	r5, [r5]
+		mov	r5, r5, lsr #16
+		mov	r4, #0x6600
+		add	r4, r4, #0x1
+		cmp	r5, r4			@ check for 88F6601 SoC
+		bne	5f
+
+		add	r1, r0, #0x20000	@ mbus ctrl address register
+		add	r2, r1, #0x4		@ mbus base address register
+		add	r3, r0, #0x1500		@ ddr base address register
+		add	r4, r3, #0x4		@ ddr size address register
+		mov	r0, #0
+		ldr     r5, 6f			@ we must run from I-Cache
+		mcr p15,0,r5,c7,c13,1		@ when DRAM window is disabled,
+		ldr     r5, 7f			@ so preloading 2 consective cache
+		mcr p15,0,r5,c7,c13,1		@ lines will do the job.
+
+#ifdef CONFIG_MV_DRAM_XBAR_ACCESS_CFG
+		ldr	r5, [r1]
+		tst	r5, #1
+		bne	5f			@ test if xbar window already enabled
+
+		ldr	r5, [r3]		@ ddr base register value
+		and	r5, r5, #0xff000000	@ extract window base
+		str	r5, [r2]
+
+		ldr	r5, [r4]
+		mov	r5, r5, lsr #16
+		mov	r5, r5, lsl #16		@ extract window size
+		orr	r5, r5, #0x0e00		@ set target id
+		orr	r5, r5, #1		@ set window enable
+		str	r5, [r1]
+		mcr 	p15, 0, r0, c7, c10, 4	@ drain write-buffer
+
+3:		ldr	r5, [r1]
+		tst	r5, #1
+		beq	3b
+
+		ldr	r5, [r4]
+6:		bic	r5, r5, #1
+		.align 5
+7:		str	r5, [r4]
+
+4:		ldr	r5, [r4]
+		tst	r5, #1
+		bne	4b
+#else
+		ldr	r5, [r4]
+		tst	r5, #1
+		bne	5f			@ test if ddr window already enabled
+
+		ldr	r5, [r2]		@ ddr base register value
+		and	r5, r5, #0xff000000	@ extract window base
+		str	r5, [r3]
+
+		ldr	r5, [r1]
+		mov	r5, r5, lsr #16
+		mov	r5, r5, lsl #16		@ extract window size
+		orr	r5, r5, #1		@ set window enable
+		str	r5, [r4]
+		mcr 	p15, 0, r0, c7, c10, 4	@ drain write-buffer
+
+3:		ldr	r5, [r4]
+		tst	r5, #1
+		beq	3b
+
+		ldr	r5, [r1]
+6:		bic	r5, r5, #1
+		.align 5
+7:		str	r5, [r1]
+
+4:		ldr	r5, [r1]
+		tst	r5, #1
+		bne	4b
+#endif
+5:		mcr 	p15, 0, r0, c7, c10, 4	@ drain write-buffer
+		mrc 	p15, 0, r0, c1, c0, 0	@ read cr 
+		bic	r0, r0, #0x5000		@ disable I-cache and RR cache replacement
+		bic	r0, r0, #0x4		@ disable D-cache
+		mcr 	p15, 0, r0, c1, c0, 0	@ update cr
+#endif
+
 #ifndef __ARM_ARCH_2__
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h
index 630dcdf..30d73df 100755
--- a/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h
@@ -92,6 +92,10 @@
 	#define MV_TDM_USE_DCO
 #endif
 
+#ifdef CONFIG_MV_TDM_EXT_STATS
+	#define MV_TDM_EXT_STATS
+#endif
+
 /* SLIC vendor */
 #if defined(CONFIG_SILABS_SLIC_SUPPORT)
 	#define SILABS_SLIC_SUPPORT
diff --git a/arch/arm/mach-feroceon-kw2/core.c b/arch/arm/mach-feroceon-kw2/core.c
index 3b1afd1..4dcb811 100755
--- a/arch/arm/mach-feroceon-kw2/core.c
+++ b/arch/arm/mach-feroceon-kw2/core.c
@@ -127,7 +127,7 @@
 u8	mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][6];
 u16	mvMtu[CONFIG_MV_ETH_PORTS_NUM] = {0};
 #endif
-extern MV_U32 gBoardId; 
+extern MV_U32 gBoardId;
 extern unsigned int elf_hwcap;
 
 #ifdef CONFIG_MTD_NAND_LNC
@@ -145,14 +145,14 @@
 
 static int __init parse_tag_mv_uboot(const struct tag *tag)
 {
-    	unsigned int mvUbootVer = 0;
+	unsigned int mvUbootVer = 0;
 	int i = 0;
- 
+
 	mvUbootVer = tag->u.mv_uboot.uboot_version;
 	mvIsUsbHost = tag->u.mv_uboot.isUsbHost;
 
-        printk("Using UBoot passing parameters structure\n");
-  
+	printk("Using UBoot passing parameters structure\n");
+
 	gBoardId =  (mvUbootVer & 0xff);
 #ifdef CONFIG_MV_INCLUDE_GIG_ETH
 	for (i = 0; i < CONFIG_MV_ETH_PORTS_NUM; i++) {
@@ -166,11 +166,11 @@
 	}
 #endif
 #ifdef CONFIG_MTD_NAND_LNC
-               /* get NAND ECC type(1-bit or 4-bit) */
-               if((mvUbootVer >> 8) >= 0x3040c)
-                       mv_nand_ecc = tag->u.mv_uboot.nand_ecc;
-               else
-                       mv_nand_ecc = 1; /* fallback to 1-bit ECC */
+	/* get NAND ECC type(1-bit or 4-bit) */
+	if((mvUbootVer >> 8) >= 0x3040c)
+		mv_nand_ecc = tag->u.mv_uboot.nand_ecc;
+	else
+		mv_nand_ecc = 1; /* fallback to 1-bit ECC */
 #endif
 
 	mod_config = tag->u.mv_uboot.mod_bitmask;
@@ -516,6 +516,19 @@
 {
 	MV_U32 boardId;
 
+#ifndef CONFIG_MV_DRAM_DEFAULT_ACCESS_CFG
+        /* Support DRAM access configuration for Avanta-MC only */
+        if (gBoardId == DB_88F6601_BP_ID || gBoardId == RD_88F6601_MC_ID ||
+	    gBoardId == RD_88F6601_MC2L_ID) {
+                printk("DRAM access: ");
+#ifdef CONFIG_MV_DRAM_XBAR_ACCESS_CFG
+                printk("XBAR\n");
+#else
+                printk("fast-path\n");
+#endif
+        }
+#endif
+
 #ifdef CONFIG_CACHE_FEROCEON_L2
 	if ((noL2 == 0) && (mvCpuL2Exists() == MV_TRUE))
 		kirkwood_l2_init();
@@ -523,27 +536,26 @@
 		printk("No L2-Cache.\n");
 #endif
 
-        /* init the Board environment */
-       	mvBoardEnvInit();
+	/* init the Board environment */
+	mvBoardEnvInit();
 
-        /* init the controller environment */
-        if( mvCtrlEnvInit() ) {
-            printk( "Controller env initialization failed.\n" );
-            return;
-        }
-
-	/* Init the CPU windows setting and the access protection windows. */
-	if( mvCpuIfInit(mv_sys_map()) ) {
-
-		printk( "Cpu Interface initialization failed.\n" );
+	/* init the controller environment */
+	if (mvCtrlEnvInit()) {
+		printk("Controller env initialization failed.\n");
 		return;
 	}
 
-    	/* Init Tclk & SysClk */
-    	mvTclk = mvBoardTclkGet();
-   	mvSysclk = mvBoardSysClkGet();
+	/* Init the CPU windows setting and the access protection windows. */
+	if (mvCpuIfInit(mv_sys_map())) {
+		printk("Cpu Interface initialization failed.\n");
+		return;
+	}
 
-        support_wait_for_interrupt = 1;
+	/* Init Tclk & SysClk */
+	mvTclk = mvBoardTclkGet();
+	mvSysclk = mvBoardSysClkGet();
+
+	support_wait_for_interrupt = 1;
 
 #ifdef CONFIG_JTAG_DEBUG
 	support_wait_for_interrupt = 0; /*  for Lauterbach */
@@ -562,7 +574,6 @@
 	mv_gpio_init();
 
 #ifdef CONFIG_MV_INCLUDE_SPI
-	/* SPI */
 	mvSysSpiInit(0, _16M);
 #endif
 
@@ -574,7 +585,7 @@
 
 #ifdef CONFIG_MV_PMU_PROC
 	mv_pm_proc_entry = proc_mkdir("mv_pm", NULL);
-#endif /* CONFIG_MV_PMU_PROC */
+#endif
 
 #if defined(CONFIG_MV_INCLUDE_SDIO)
 	if (mvCtrlSdioSupport()) {
@@ -599,17 +610,15 @@
 #endif
 
 #ifdef CONFIG_MV_ETHERNET
-	/* Ethernet */
 #if defined(CONFIG_MV_ETH_LEGACY)
 	platform_device_register(&mv88fx_eth);
 #elif defined(CONFIG_MV_ETH_NETA)
 	mv88fx_neta.dev.platform_data = NULL;
 	platform_device_register(&mv88fx_neta);
-#endif /* Ethernet mode: legacy or NETA */
-#endif /* CONFIG_MV_ETHERNET */
+#endif
+#endif
 
 #ifdef CONFIG_THERMAL_SENSOR_KW2
-	/* SoC hwmon Thermal Sensor */
 	platform_device_register_simple("KW2Thermal", 0, NULL, 0);
 #endif
 
@@ -618,18 +627,15 @@
 	platform_device_register(&kw2_nfc);
 #endif
 
-       /* WATCHDOG */
-       mv_wdt_init();
+	/* Watchdog */
+	mv_wdt_init();
 
-	/* CPU Idle driver. */
+	/* CPU idle driver */
 	boardId = mvBoardIdGet();
-	if ((boardId == DB_88F6535_BP_ID) || (boardId == RD_88F6560_GW_ID))
+	if (boardId == DB_88F6535_BP_ID || boardId == RD_88F6560_GW_ID)
 		platform_device_register_simple("kw_cpuidle", 0, NULL, 0);
-
-	return;
 }
 
-
 MACHINE_START(FEROCEON_KW2 ,"Feroceon-KW2")
 	/* MAINTAINER("MARVELL") */
 	.phys_io = 0xf1000000,
@@ -640,4 +646,3 @@
 	.timer = &mv_timer,
 	.init_machine = mv_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/system.h b/arch/arm/mach-feroceon-kw2/include/mach/system.h
index 38c484d..8133fe0 100755
--- a/arch/arm/mach-feroceon-kw2/include/mach/system.h
+++ b/arch/arm/mach-feroceon-kw2/include/mach/system.h
@@ -19,7 +19,7 @@
 
 #include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
 
-#define LSP_VERSION "KW2_LSP_3.3.1_p4_PQ"
+#define LSP_VERSION "KW2_LSP_3.3.1_p12_PQ"
 
 
 static inline void arch_idle(void)
@@ -31,7 +31,7 @@
 	cpu_do_idle();
 }
 
-#define UPON_SDK_VERSION "uPON_2.6.25_RC1"
+#define UPON_SDK_VERSION "uPON_2.6.25_RC74"
 
 #ifdef __BIG_ENDIAN
 #define MV_ARM_32BIT_LE(X) ((((X)&0xff)<<24) |                       \
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
index 546f73d..727fe51 100755
--- a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
@@ -134,6 +134,7 @@
 		mvOsPrintf("mvBoardEnvInit:Board unknown.\n");
 		return;
 	}
+
 	nandDev = boardGetDevCSNum(0, BOARD_DEV_NAND_FLASH);
 	if (nandDev != 0xFFFFFFFF) {
 		/* Set NAND interface access parameters */
@@ -152,29 +153,26 @@
 	/* Set GPP Out value */
 	MV_REG_WRITE(GPP_DATA_OUT_REG(0), BOARD_INFO(boardId)->gppOutValLow);
 	MV_REG_WRITE(GPP_DATA_OUT_REG(1), BOARD_INFO(boardId)->gppOutValMid);
-	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID)
-		&& (boardId != GFLT200_ID) && (boardId != GFLT110_ID))
+	if (boardId != DB_88F6601_BP_ID && boardId != RD_88F6601_MC_ID &&
+	   boardId != RD_88F6601_MC2L_ID &&
+	   boardId != GFLT200_ID && boardId != GFLT110_ID)
 		MV_REG_WRITE(GPP_DATA_OUT_REG(2), BOARD_INFO(boardId)->gppOutValHigh);
 
 	/* set GPP polarity */
 	mvGppPolaritySet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValLow);
 	mvGppPolaritySet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValMid);
-	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID)
-		&& (boardId != GFLT200_ID) && (boardId != GFLT110_ID))
+	if (boardId != DB_88F6601_BP_ID && boardId != RD_88F6601_MC_ID &&
+	   boardId != RD_88F6601_MC2L_ID &&
+	   boardId != GFLT200_ID && boardId != GFLT110_ID)
 		mvGppPolaritySet(2, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValHigh);
 
 	/* Set GPP Out Enable */
 	mvGppTypeSet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValLow);
 	mvGppTypeSet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValMid);
-	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID)
-		&& (boardId != GFLT200_ID) && (boardId != GFLT110_ID))
+	if (boardId != DB_88F6601_BP_ID && boardId != RD_88F6601_MC_ID &&
+	    boardId != RD_88F6601_MC2L_ID &&
+	    boardId != GFLT200_ID && boardId != GFLT110_ID)
 		mvGppTypeSet(2, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValHigh);
-
-	/* Nand CE */
-#if 0
-	if (nandDev != 0xFFFFFFFF)
-		mvDevNandDevCsSet(nandDev, MV_TRUE);
-#endif
 }
 
 /*******************************************************************************
@@ -333,6 +331,7 @@
 *******************************************************************************/
 MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum)
 {
+	MV_U32 boardId = mvBoardIdGet();
 	MV_U32 ethCompOpt;
 
 	if (ethPortNum >= BOARD_ETH_PORT_NUM) {
@@ -340,7 +339,7 @@
 		return MV_FALSE;
 	}
 	ethCompOpt = mvBoardEthComplexConfigGet();
-	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+	if (boardId == DB_88F6601_BP_ID) {
 		if (ethPortNum == 0) {
 			if (ethCompOpt & ESC_OPT_GEPHY_MAC0)
 				return MV_FALSE;
@@ -350,8 +349,8 @@
 			return MV_TRUE;
 		return MV_FALSE;
 	}
-	if ((RD_88F6601_MC_ID == mvBoardIdGet())
-		|| (GFLT200_ID == mvBoardIdGet()) || (GFLT110_ID == mvBoardIdGet()))
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    GFLT200_ID == boardId || GFLT110_ID == boardId)
 		return MV_FALSE;
 
 	if ((ethPortNum > 0) || (ethCompOpt & ESC_OPT_SGMII_2_SW_P1))
@@ -649,11 +648,10 @@
 		mvOsPrintf("mvBoardSwitchNumPortsGet: Board unknown.\n");
 		return MV_ERROR;
 	}
-	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-		|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId))
-	{
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    boardId == DB_88F6601_BP_ID ||
+            GFLT200_ID == boardId || GFLT110_ID == boardId)
 		return 0;
-	}
 
 
 	/* Check if internal switch is connected */
@@ -1250,10 +1248,11 @@
 	MV_U32 boardId = mvBoardIdGet();
 
 	tmpTClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
-	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-		|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId)){
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    boardId == DB_88F6601_BP_ID ||
+	    GFLT200_ID == boardId || GFLT110_ID == boardId) {
 		tmpTClkRate &= MSAR_TCLCK_6601_MASK;
-		if (tmpTClkRate )
+		if (tmpTClkRate)
 			return MV_BOARD_TCLK_200MHZ;
 		else
 			return MV_BOARD_TCLK_166MHZ;
@@ -1306,8 +1305,9 @@
 	sar0 = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
 	clockSatr = MSAR_CPU_DDR_L2_CLCK_EXTRACT(sar0);
 	i = 0;
-	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-		|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId)){
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    boardId == DB_88F6601_BP_ID ||
+	    GFLT200_ID == boardId || GFLT110_ID == boardId) {
 		while (cpuDdrTbl6601[i].satrValue != -1) {
 			if (cpuDdrTbl6601[i].satrValue == clockSatr) {
 				res = i;
@@ -1715,9 +1715,10 @@
 	/* Set ethernet complex configuration. */
 	BOARD_INFO(boardId)->pBoardMppTypeValue->ethSataComplexOpt = ethConfig;
 
-	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID)
-		&& (boardId != GFLT200_ID) && (boardId != GFLT110_ID))
-	{	/* KW2 only */
+	if (boardId != DB_88F6601_BP_ID && boardId != RD_88F6601_MC_ID &&
+	    boardId != RD_88F6601_MC2L_ID &&
+	    boardId != GFLT200_ID && boardId != GFLT110_ID) {
+		/* KW2 only */
 		/* Update link speed for MAC0 / 1 */
 		/* If MAC 0 is connected to switch, then set to speed 1000Mbps */
 		if (mvBoardIsInternalSwitchConnected(0))
@@ -2332,6 +2333,7 @@
 *******************************************************************************/
 MV_BOOL mvBoardIsGbEPortConnected(MV_U32 ethPortNum)
 {
+	MV_U32 boardId = mvBoardIdGet();
 	MV_U32 ethConfig;
 
 	ethConfig = mvBoardEthComplexConfigGet();
@@ -2339,15 +2341,15 @@
 	if (ethConfig & ESC_OPT_ILLEGAL)
 		return MV_FALSE;
 
-	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+	if (boardId == DB_88F6601_BP_ID) {
 		if (ethPortNum == 0)
 			return MV_TRUE;
 		if (ethConfig & ESC_OPT_GEPHY_MAC0)
 			return MV_TRUE;
 		return MV_FALSE;
 	}
-	if ((RD_88F6601_MC_ID == mvBoardIdGet())
-		|| (GFLT200_ID == mvBoardIdGet()) || (GFLT110_ID == mvBoardIdGet())) {
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    GFLT200_ID == boardId || GFLT110_ID == boardId) {
 		if (ethPortNum == 0)
 			return MV_TRUE;
 		return MV_FALSE;
@@ -2748,6 +2750,9 @@
 		tmpBoardId = DB_88F6601_BP_ID;
 #elif defined(RD_88F6601)
 		tmpBoardId = RD_88F6601_MC_ID;
+#elif defined(RD_88F6601MC2L)
+		tmpBoardId = RD_88F6601_MC2L_ID;
+
 #elif defined(DB_CUSTOMER)
 		tmpBoardId = DB_CUSTOMER_ID;
 #elif defined(GFLT200)
@@ -3122,7 +3127,7 @@
 	/* Avanta-MC */
 	mvOsPrintf(" mvBoardEthSataModulesScan: mvTwsiRead return jumper = 0x%x\n",boardCfg );
     	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
-		MV_U8 xcvrValue = 0x4;
+		MV_U8 xcvrValue=4;
 		if (0 == MV_BOARD_6601_CFG_MAC_SRC(boardCfg))
 			ethSrcCfg->feGeSrc = EC_MAC0_SRC;   /* MAC0 --> GbE PHY, MAC1 --> LP SERDES */ 
 		else
@@ -3429,12 +3434,6 @@
 		}
 	}
 
-#if 0
-	/* TDM-890 - no auto detection */
-	BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_890;
-	result = 1;
-
-#endif
 	if (result == 0) {
 		/* No device is found */
 		BOARD_INFO(boardId)->boardTdmInfoIndex = (MV_8)-1;
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
index 93417a4..c8e2400 100755
--- a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
@@ -911,19 +911,6 @@
 	 }
 };
 
-/*
-MV_BOARD_SPEC_INIT rd88f6601BoardSpecInit[] = {
-	{
-		.reg = PMU_POWER_IF_POLARITY_REG,
-		.mask = (BIT1),
-		.val = 0
-	},
-	{
-		.reg = TBL_TERM,
-		.val = TBL_TERM
-	}
-};
-*/
 MV_BOARD_INFO rd88f6601Info = {
 	.boardName = "RD-88F6601-BP",
 	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6601InfoBoardMppTypeInfo),
@@ -975,7 +962,125 @@
 	.pBoardTdmInt2CsInfo = {NULL},
 	.boardTdmInfoIndex = -1,
 
-	.pBoardSpecInit = NULL,			/* rd88f6601BoardSpecInit, */
+	.pBoardSpecInit = NULL,
+
+	.deepIdlePwrUpDelay = 2400,	/* 12uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_FALSE,
+	.nandFlashReadParams = 0,
+	.nandFlashWriteParams = 0,
+	.nandFlashControl = 0,
+	.pBoardTdmSpiInfo = NULL,
+
+	/* Enable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** RD-88F6601MC2L Avanta
+****************************************************************************/
+/* NAND not supported  */
+
+MV_BOARD_TWSI_INFO rd88f6601MC2LInfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO rd88f6601MC2LInfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_AUTO, 0x0},
+	{N_A, N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO rd88f6601MC2LInfoBoardMppTypeInfo[] = {
+	{
+		.boardMppTdm = MV_BOARD_AUTO,
+		.ethSataComplexOpt = ESC_OPT_GEPHY_MAC0,
+		.ethPortsMode = 0x0,
+	}
+};
+
+MV_BOARD_GPP_INFO rd88f6601MC2LInfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_PON_XVR_TX, 17},
+	{BOARD_GPP_PON_XVR_TX_POWER, 37},
+	{BOARD_GPP_PON_XVR_TX_IND, 24},	
+};
+
+MV_DEV_CS_INFO rd88f6601MC2LInfoBoardDeCsInfo[] = {
+	/* {deviceCS, params, devType, devWidth} */
+#ifdef MV_SPI
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},	/* SPI DEV */
+#endif
+#if !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO rd88f6601MC2LInfoBoardMppConfigValue[] = {
+	{
+	{
+	  RD_88F6601MC2L_MPP0_7,
+	  RD_88F6601MC2L_MPP8_15,
+	  RD_88F6601MC2L_MPP16_23,
+	  RD_88F6601MC2L_MPP24_31,
+	  RD_88F6601MC2L_MPP32_37,
+	}
+	}
+};
+
+MV_BOARD_INFO rd88f6601MC2LInfo = {
+	.boardName = "RD-88F6601-MC2L",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = rd88f6601MC2LInfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardMppConfigValue),
+	.pBoardMppConfigValue = rd88f6601MC2LInfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardDeCsInfo),
+	.pDevCsInfo = rd88f6601MC2LInfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardTwsiDev),
+	.pBoardTwsiDev = rd88f6601MC2LInfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardMacInfo),
+	.pBoardMacInfo = rd88f6601MC2LInfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(rd88f6601MC2LInfoBoardGppInfo),
+	.pBoardGppInfo = rd88f6601MC2LInfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+ 
+	/* GPP values */
+	.gppOutEnValLow = RD_88F6601MC2L_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = RD_88F6601MC2L_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = 0,
+	.gppOutValLow = RD_88F6601MC2L_GPP_OUT_VAL_LOW,
+	.gppOutValMid = RD_88F6601MC2L_GPP_OUT_VAL_MID,
+	.gppOutValHigh = 0,
+	.gppPolarityValLow = RD_88F6601MC2L_GPP_POL_LOW,
+	.gppPolarityValMid = RD_88F6601MC2L_GPP_POL_MID,
+	.gppPolarityValHigh = 0,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = NULL,
+	.switchInfoNum = 0,
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_GPON_CONFIG,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {0},
+	.pBoardTdmInt2CsInfo = {NULL},
+	.boardTdmInfoIndex = -1,
+
+	.pBoardSpecInit = NULL,
 
 	.deepIdlePwrUpDelay = 2400,	/* 12uS */
 
@@ -1449,4 +1554,5 @@
 	&rd88f6601Info,
 	&gflt200Info,
 	&gflt110Info,
+	&rd88f6601MC2LInfo,
 };
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
index bf66ed3..01ccfec 100755
--- a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
@@ -107,10 +107,20 @@
 #define DB_88F6560_PCAC_ID		(BOARD_ID_BASE+0x4)
 #define DB_88F6601_BP_ID		(BOARD_ID_BASE+0x5)
 #define RD_88F6601_MC_ID		(BOARD_ID_BASE+0x6)
+// TODO(jnewlin): These ids need to match what is in UBOOT
+// and because Marvell added a new id, things are sort of broken
+// I am leaving the ids the way they were so that _out_ boards
+// work.
 #define DB_CUSTOMER_ID			(BOARD_ID_BASE+0x7)
 #define GFLT200_ID			DB_CUSTOMER_ID
-#define GFLT110_ID			DB_CUSTOMER_ID + 1
-#define MV_MAX_BOARD_ID			(DB_CUSTOMER_ID + 2)
+#define GFLT110_ID			(BOARD_ID_BASE+0x8)
+#define RD_88F6601_MC2L_ID		(BOARD_ID_BASE+0x9)
+#define MV_MAX_BOARD_ID			(DB_CUSTOMER_ID + 3)
+// These are Marvells defines, we should switch to match these in
+// uboot to make future merges easier.
+//#define DB_CUSTOMER_ID			(BOARD_ID_BASE+0x8)
+//#define MV_MAX_BOARD_ID			(DB_CUSTOMER_ID + 1)
+
 
 /***************************************************************************
 ** RD-88F6510-SFU
@@ -347,7 +357,6 @@
 #define DB_88F6535_GPP_POL_MID		0x0
 #define DB_88F6535_GPP_POL_HIGH		0x0
 
-
 /***************************************************************************
 ** DB-CUSTOMER
 ****************************************************************************/
@@ -421,9 +430,6 @@
 #define DB_88F6601_GPP_POL_LOW		0x0
 #define DB_88F6601_GPP_POL_MID		0x0
 
-
-
-
 /***************************************************************************
 ** RD-88F6601
 ****************************************************************************/
@@ -435,7 +441,7 @@
 
 /* GPPs
  1 SPI0_MOSI (out)
- 2 SPI0_SCK (out)	
+ 2 SPI0_SCK (out)
  3 SPI0_CSn[0] (out)
  4 SPI0_MISO (in)
  5 I2C0_SDA (inout)
@@ -446,15 +452,14 @@
 21 PON_BEN (out)
 24 XVR_Tx_IND
 25 LED_G
-26 LED_Y 
+26 LED_Y
 28 NF&SPI_WP
 29 XVR_SD (in)
 33 TX_Fault/TX_indication
 37 TX_PD
-
-
 */
-#define RD_88F6601_GPP_OUT_ENA_LOW	(BIT0 | BIT13 | BIT14 | BIT16 | BIT17 | BIT18 | BIT19 | BIT22 | BIT23 | BIT24 | BIT27| BIT30 | BIT31) 
+
+#define RD_88F6601_GPP_OUT_ENA_LOW	(BIT0 | BIT13 | BIT14 | BIT16 | BIT17 | BIT18 | BIT19 | BIT22 | BIT23 | BIT24 | BIT27| BIT30 | BIT31)
 #define RD_88F6601_GPP_OUT_ENA_MID	(BIT0 | BIT3 | BIT4)
 
 #define RD_88F6601_GPP_OUT_VAL_LOW	0x0
@@ -511,4 +516,50 @@
 #define GFLT200_GPP_POL_LOW		0x0
 #define GFLT200_GPP_POL_MID		0x0
 
+/***************************************************************************
+** RD-88F6601MC2L
+****************************************************************************/
+#define RD_88F6601MC2L_MPP0_7		0x22222222
+#define RD_88F6601MC2L_MPP8_15		0x02222222
+#define RD_88F6601MC2L_MPP16_23		0x00005555
+#define RD_88F6601MC2L_MPP24_31		0x04000550
+#define RD_88F6601MC2L_MPP32_37		0x00050020
+
+/* GPPs
+ 0 NC
+ 1 SPI0_MOSI (out)
+ 2 SPI0_SCK (out)
+ 3 SPI0_CSn[0] (out)
+ 4 SPI0_MISO (in)
+ 5 I2C0_SDA (inout)
+ 6 I2C0_SCK (inout)
+ 7 UA0_TXD (out)
+ 8 UA0_RXD (in)
+15 TXfault_RST (GPI)
+16 TDM_SPI
+17 TDM_SPI
+18 TDM_SPI
+19 TDM_SPI
+20-24 NC SET at GPI
+25 LED_G  MPP = 5
+26 LED_Y  MPP = 5
+27 PON LED (GPO)
+28-29, 31, 32, 34 NC SET at GPI
+30 XVR_SD (in)
+
+33 Dying Gasp
+35 NC (because of bug on board)
+36 PON_BEN
+37 TX_PD (GPO)
+*/
+
+#define RD_88F6601MC2L_GPP_OUT_ENA_LOW		(0xffffffff^(BIT27))
+#define RD_88F6601MC2L_GPP_OUT_ENA_MID		(0xfffffff^(BIT5))
+
+#define RD_88F6601MC2L_GPP_OUT_VAL_LOW		0x0
+#define RD_88F6601MC2L_GPP_OUT_VAL_MID		0x0
+
+#define RD_88F6601MC2L_GPP_POL_LOW		(BIT15)
+#define RD_88F6601MC2L_GPP_POL_MID		0x0
+
 #endif /* __INCmvBoardEnvSpech */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
index 69d0624..b20b1cb 100755
--- a/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
@@ -111,8 +111,9 @@
 
 	/* Search for a matching entry */
 	i = 0;
-	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-		|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId)){
+	if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+	    boardId == DB_88F6601_BP_ID ||
+	    GFLT200_ID == boardId || GFLT110_ID == boardId) {
 		while (cpuDdrTbl6601[i].satrValue != -1) {
 			if (cpuDdrTbl6601[i].satrValue == clockSatr) {
 				res = i;
@@ -160,8 +161,9 @@
 	if (idx == 0xFFFFFFFF)
 		return 0;
 	else {
-		if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-			|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId))
+		if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+		    boardId == DB_88F6601_BP_ID ||
+			(GFLT200_ID == boardId) || (GFLT110_ID == boardId))
 			return cpuDdrTbl6601[idx].cpuClk;
 		else
 			return cpuDdrL2Tbl[idx].cpuClk;
@@ -194,8 +196,9 @@
 	if (idx == 0xFFFFFFFF)
 		return 0;
 	else {
-		if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)
-			|| (GFLT200_ID == boardId) || (GFLT110_ID == boardId))
+		if (boardId == RD_88F6601_MC_ID || boardId == RD_88F6601_MC2L_ID ||
+		    boardId == RD_88F6601_MC_ID ||
+			(GFLT200_ID == boardId) || (GFLT110_ID == boardId))
 			return cpuDdrTbl6601[idx].l2Clk;
 		else
 			return cpuDdrL2Tbl[idx].l2Clk;
@@ -219,13 +222,11 @@
 MV_BOOL mvCpuL2Exists(MV_VOID)
 {
 	MV_U32 sar0;
-	MV_U32 mvBoardId = mvBoardIdGet();
+	MV_U32 id = mvBoardIdGet();
 
-	if ((RD_88F6510_SFU_ID == mvBoardId) ||
-		(RD_88F6601_MC_ID == mvBoardId) ||
-		(DB_88F6601_BP_ID == mvBoardId) ||
-		(GFLT200_ID == mvBoardId) ||
-		(GFLT110_ID == mvBoardId))
+	if (id == RD_88F6510_SFU_ID || id == DB_88F6601_BP_ID ||
+	    id == RD_88F6601_MC_ID || id == RD_88F6601_MC2L_ID ||
+	    GFLT200_ID == id || id == GFLT110_ID)
 		return MV_FALSE;
 
 	/* Read S@R register value */
diff --git a/arch/arm/mach-feroceon-kw2/sysmap.c b/arch/arm/mach-feroceon-kw2/sysmap.c
index 5e2ef60..3224c2b 100755
--- a/arch/arm/mach-feroceon-kw2/sysmap.c
+++ b/arch/arm/mach-feroceon-kw2/sysmap.c
@@ -221,15 +221,16 @@
 		case RD_88F6560_GW_ID:
 		case RD_88F6530_MDU_ID:
 			return SYSMAP_88F6500;
- 		case DB_88F6601_BP_ID:
+		case DB_88F6601_BP_ID:
 		case RD_88F6601_MC_ID:
+		case RD_88F6601_MC2L_ID:
 		case GFLT200_ID:
 		case GFLT110_ID:
 			return SYSMAP_88F6601;
 		default:
 			printk("ERROR: can't find system address map\n");
 			return NULL;
-        }
+	}
 }
 
 #if defined(CONFIG_MV_INCLUDE_CESA)
diff --git a/arch/arm/mach-feroceon-kw2/time.c b/arch/arm/mach-feroceon-kw2/time.c
index 8920b88..6d4df6a 100755
--- a/arch/arm/mach-feroceon-kw2/time.c
+++ b/arch/arm/mach-feroceon-kw2/time.c
@@ -23,27 +23,35 @@
 #include "ctrlEnv/mvCtrlEnvLib.h"
 #include "boardEnv/mvBoardEnvLib.h"
 #include "cntmr/mvCntmrRegs.h"
+#include "dbg-trace.h"
 
 /*
  * Timer0: clock_event_device, Tick.
  * Timer1: clocksource, Free running.
  * WatchDog: Not used.
+ * Timer2: SW Flow Control events
+ * Timer3: Not used
  *
  * Timers are counting down.
  */
 #define CLOCKEVENT	0
 #define CLOCKSOURCE	1
+#define FCTRLEVENT  3 /* CPU timer 2 */
 
 /*
  * Timers bits
  */
-#define BRIDGE_INT_TIMER(x)	(1 << ((x) + 1))
-#define TIMER_EN(x)		(1 << ((x) * 2))
-#define TIMER_RELOAD_EN(x)	(1 << (((x) * 2) + 1))
+#define BRIDGE_INT_TIMER(x)	(1 << ((x) + (((x) < 3) ? 1 : 3)))
+#define TIMER_EN(x)			(1 << ((((x) < 3) ? (x):((x) + 1)) * 2))
+#define TIMER_RELOAD_EN(x)	(1 << ((((x) < 3) ? (x):((x) + 1)) * 2 + 1))
+
 #define BRIDGE_INT_TIMER_WD	(1 << 3)
-#define TIMER_WD_EN		(1 << 4)
+#define TIMER_WD_EN			(1 << 4)
 #define TIMER_WD_RELOAD_EN	(1 << 5)
 
+static unsigned long (*mv_fc_event_handler)(void) = 0;
+static int fc_disabled = 1;
+
 static cycle_t kw_clksrc_read(struct clocksource *cs)
 {
 	return (0xffffffff - MV_REG_READ(CNTMR_VAL_REG(CLOCKSOURCE)));
@@ -131,12 +139,24 @@
 extern void mv_leds_hearbeat(void);
 static irqreturn_t kw_timer_interrupt(int irq, void *dev_id)
 {
+	unsigned long irq_cause = MV_REG_READ(BRIDGE_INT_CAUSE_REG);
+
+	/* Handle FC events if any */
+	if (irq_cause & BRIDGE_INT_TIMER(FCTRLEVENT)) {
+		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(FCTRLEVENT));
+		if (mv_fc_event_handler)
+			mv_fc_event_handler();
+	}
+
 	/*
-	 * Clear cause bit and do event
+	 * Clear clock event cause bit and do event
 	 */
-	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
-	kw_clkevt.event_handler(&kw_clkevt);
-	mv_leds_hearbeat();
+	if (irq_cause & BRIDGE_INT_TIMER(CLOCKEVENT)) {
+		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+		kw_clkevt.event_handler(&kw_clkevt);
+		mv_leds_hearbeat();
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -192,3 +212,52 @@
         .init           = mv_init_timer,
 };
 
+int mv_enable_fc_events(void *fc_event_handler, unsigned long period_ns)
+{
+	unsigned long flags;
+	uint64_t  clock_ticks = period_ns;
+
+	if (fc_event_handler == 0)
+		return -1;
+
+	local_irq_save(flags);
+
+	mv_fc_event_handler = fc_event_handler;
+
+	clock_ticks *= kw_clkevt.mult;
+	clock_ticks >>= kw_clkevt.shift;
+
+	/* Setup timer value */
+	MV_REG_WRITE(CNTMR_RELOAD_REG(FCTRLEVENT), (unsigned long)clock_ticks);
+	MV_REG_WRITE(CNTMR_VAL_REG(FCTRLEVENT), (unsigned long)clock_ticks);
+
+	/* Enable periodic timer and timer interrupt */
+	MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(FCTRLEVENT));
+	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(FCTRLEVENT) | TIMER_EN(FCTRLEVENT));
+
+	fc_disabled = 0;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void mv_disable_fc_events(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* Disable timer */
+	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_EN(FCTRLEVENT));
+	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(FCTRLEVENT));
+
+	/* Clear and disable interrupt */
+	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(FCTRLEVENT));
+	MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(FCTRLEVENT));
+
+	fc_disabled = 1;
+
+	local_irq_restore(flags);
+}
+
diff --git a/arch/arm/plat-feroceon/Kconfig b/arch/arm/plat-feroceon/Kconfig
index 27399df..a99448e 100755
--- a/arch/arm/plat-feroceon/Kconfig
+++ b/arch/arm/plat-feroceon/Kconfig
@@ -449,10 +449,28 @@
         ---help---
         Select printk buffer chunk granularity.
 
+choice
+	prompt "DRAM Access Configuration for 88F6601 SoC"
+	default MV_DRAM_DEFAULT_ACCESS_CFG
+
+config MV_DRAM_DEFAULT_ACCESS_CFG
+	bool "Default DRAM access configuration(by bootloader)"
+	---help---
+	Choosing this option keeps bootloader DRAM access configuration. 
+
+config MV_DRAM_FASTPATH_ACCESS_CFG
+	bool "DRAM fast-path access configuration"
+	---help---
+	Choosing this option will enable DRAM fast-path access configuration.
+
+config MV_DRAM_XBAR_ACCESS_CFG
+	bool "DRAM XBAR access configuration"
+	---help---
+	Choosing this option will enable DRAM XBAR access configuration.
+
+endchoice
 
 endmenu
 
 
 endif
-
-
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
index 401c3b7..12c6a42 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
@@ -2,15 +2,25 @@
 depends on MV_INCLUDE_CUST
 
 config  MV_CUST
-	bool "Support for Marvell Customer Driver"
-      	default y
-	---help---
+        bool "Support for Marvell Customer Driver"
+        default y
+        ---help---
 
 config  MV_CUST_IGMP_HANDLE
         bool "Enable MV_CUST IGMP handling"
         default y
         ---help---
 
+config  MV_CUST_MLD_HANDLE
+        bool "Enable MV_CUST MLD handling"
+        default y
+        ---help---
+
+config  MV_CUST_LPBK_DETECT_HANDLE
+        bool "Enable MV_CUST UNI loopback detect handling"
+        default y
+        ---help---
+        
 config  MV_CUST_UDP_SAMPLE_HANDLE
         bool "Enable MV_CUST sample UDP handling"
         default n
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c
index 2f78724..39f93ac 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c
@@ -133,7 +133,8 @@
     mv_cust_ioctl_omci_set_t      cust_omci_set;
     mv_cust_ioctl_llid_set_t      cust_llid_set;
     mv_cust_ioctl_flow_map_t      cust_flow_map;
-    mv_cust_ioctl_dscp_map_t      cust_dscp_map;    
+    mv_cust_ioctl_dscp_map_t      cust_dscp_map;
+    mv_cust_ioctl_app_etype_t     cust_app_etype;
     int                           enable;
     int                           rc;
 
@@ -165,7 +166,7 @@
             MVCUST_ERR_PRINT("copy_from_user failed\n");
             goto ioctlErr;
           }
-          mv_cust_omci_enable(enable);
+          mv_cust_app_flag_set(MV_CUST_APP_TYPE_OMCI, enable);
           ret = 0;
           break;
 
@@ -176,7 +177,7 @@
             MVCUST_ERR_PRINT("copy_from_user failed\n");
             goto ioctlErr;
           }
-          mv_cust_eoam_enable(enable);
+          mv_cust_app_flag_set(MV_CUST_APP_TYPE_OAM, enable);
           ret = 0;
           break;
 
@@ -269,6 +270,17 @@
           }          
           break;
 
+      case MV_CUST_IOCTL_APP_ETH_TYPE_SET:
+          if(copy_from_user(&cust_app_etype, (mv_cust_ioctl_app_etype_t *)arg, sizeof(mv_cust_ioctl_app_etype_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          mv_cust_app_etype_set(cust_app_etype.app_type, cust_app_etype.eth_type);\
+          ret = 0;
+          break; 
+
       default:
           ret = -EINVAL;
   }
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h
index ee49477..e42503c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h
@@ -63,13 +63,6 @@
 int     mvcust_sysfs_init      (void);
 void    mvcust_sysfs_delete    (void);
 
-void    mv_cust_omci_print         (void);
-void    mv_cust_eoam_print         (void);
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-void    mv_cust_igmp_print         (void);
-#endif
-void    mv_cust_loopdet_print      (void);
-
 #ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
 void    mv_cust_udp_spec_print_all (void);
 #endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c
index a50854c..97733e9 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c
@@ -57,6 +57,9 @@
 
 static uint32_t gs_mv_cust_trace_flag = 0;
 
+/* Defined to support T-CONT state */
+static bool gs_tcont_state[CPH_MAX_TCONT_NUM];
+
 
 /****************************************************************************** 
 *                           External Declarations                                                                                                                                 
@@ -197,7 +200,7 @@
     dir       =  cust_flow->dir;
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==%s: vid[%d], pbits[%d], mod_vid[%d], mod_pbits[%d], T-CONT[%d], SWF queue[%d], HWF queue[%d], GEM port[%d], dir[%d]\n\r",
                             __FUNCTION__, vid, pbits, mod_vid, mod_pbits,
                            ((pkt_fwd!= NULL)? pkt_fwd->trg_port:0), 
@@ -308,7 +311,7 @@
         }
         /* In case to disable packet forwarding */
         else {
-            /* CLear forwarding information */        
+            /* Clear forwarding information */        
             pPbitsMap->pkt_fwd[pbits].trg_port      = 0;
             pPbitsMap->pkt_fwd[pbits].trg_queue     = 0;
             pPbitsMap->pkt_fwd[pbits].trg_hwf_queue = 0;
@@ -381,7 +384,7 @@
     }
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT== %s:\n\r",__FUNCTION__);
     }
 
@@ -409,7 +412,7 @@
 int mv_cust_dscp_map_set(mv_cust_dscp_pbits_t *dscp_map)
 {
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==%s: in_use[%d]\n\r", __FUNCTION__,
                            ((dscp_map!= NULL)? dscp_map->in_use:0));
     }
@@ -432,7 +435,7 @@
     }
     
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT== %s:\n\r",__FUNCTION__);
     }
     
@@ -464,7 +467,7 @@
     mv_cust_pbits_map_t  *pPbitsMap  = NULL;
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==: vid[%d],pbits[%d]\n\r", vid, pbits);
     }
 
@@ -490,7 +493,7 @@
     pVidEntry = &gs_vid_index_table[dir].pbits_map_index[vid];
 
     if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
-         MVCUST_TRACE_PRINT(KERN_INFO "%s, pVidEntry[%d], does not need to delete \n\r",__FUNCTION__, *pVidEntry);    
+         MVCUST_TRACE_PRINT(KERN_INFO,"%s, pVidEntry[%d], does not need to delete \n\r",__FUNCTION__, *pVidEntry);    
         return MV_CUST_OK;                      
     }
 
@@ -512,7 +515,7 @@
     }
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT==:\n\r");
     }
 
@@ -540,7 +543,7 @@
 int mv_cust_dscp_map_del(void)
 {
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==\n\r");
     }
 
@@ -551,7 +554,7 @@
     }
     
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT==\n\r");
     }
     
@@ -581,7 +584,7 @@
     uint32_t pbits_index = 0;
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==\n\r");
     }
 
@@ -597,7 +600,7 @@
     }
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT==\n\r");
     }
 
@@ -641,7 +644,7 @@
     pkt_fwd = &cust_flow->pkt_frwd;
     
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==: vid[%d], pbits[%d], dir[%d]\n\r", vid, pbits, dir);
     }
 
@@ -675,7 +678,7 @@
 
         pkt_fwd->in_use = 0;
         if (gs_mv_cust_trace_flag) {
-            MVCUST_TRACE_PRINT(KERN_INFO
+            MVCUST_TRACE_PRINT(KERN_INFO,
                                "==EXIT==\n\r");
         }
 
@@ -691,17 +694,20 @@
     pPktFrwd = &pPbitsMap->pkt_fwd[index];
 
     /* If specific flow mapping rule exists */
-    if (pPktFrwd->in_use != 0) { 
+    if (pPktFrwd->in_use != 0) {
         pkt_fwd->trg_port      = pPktFrwd->trg_port;
-        pkt_fwd->trg_queue     = pPktFrwd->trg_queue;
+        if (false == mv_cust_get_tcont_state(pPktFrwd->trg_port))
+            pkt_fwd->trg_queue = CPH_INVALID_TRGT_QUEUE;
+         else
+            pkt_fwd->trg_queue = pPktFrwd->trg_queue;
         pkt_fwd->trg_hwf_queue = pPktFrwd->trg_hwf_queue;
         pkt_fwd->gem_port      = pPktFrwd->gem_port;
         cust_flow->mod_vid     = pPbitsMap->mod_vid[index];
-        cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];       
+        cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];
         pkt_fwd->in_use        = 1;
         
         if (gs_mv_cust_trace_flag) {
-            MVCUST_TRACE_PRINT(KERN_INFO
+            MVCUST_TRACE_PRINT(KERN_INFO,
                                "trg_port(%d), trg_queue(%d) trg_hwf_queue(%d) gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
                                 cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue, 
                                 cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
@@ -714,17 +720,20 @@
         pPktFrwd = &pPbitsMap->pkt_fwd[index];
 
         /* If default flow mapping rule exists */
-        if (pPktFrwd->in_use != 0) { 
+        if (pPktFrwd->in_use != 0) {
             pkt_fwd->trg_port      = pPktFrwd->trg_port;
-            pkt_fwd->trg_queue     = pPktFrwd->trg_queue;
+            if (false == mv_cust_get_tcont_state(pPktFrwd->trg_port))
+                pkt_fwd->trg_queue = CPH_INVALID_TRGT_QUEUE;
+             else
+                pkt_fwd->trg_queue = pPktFrwd->trg_queue;
             pkt_fwd->trg_hwf_queue = pPktFrwd->trg_hwf_queue;
             pkt_fwd->gem_port      = pPktFrwd->gem_port;
             cust_flow->mod_vid     = pPbitsMap->mod_vid[index];
-            cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];       
+            cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];
             pkt_fwd->in_use        = 1;
             
             if (gs_mv_cust_trace_flag) {
-                MVCUST_TRACE_PRINT(KERN_INFO
+                MVCUST_TRACE_PRINT(KERN_INFO,
                                    "trg_port(%d), trg_queue(%d) trg_hwf_queue(%d) gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
                                     cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue, 
                                     cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
@@ -735,7 +744,7 @@
         
             pkt_fwd->in_use      = 0;
             if (gs_mv_cust_trace_flag) {
-                MVCUST_TRACE_PRINT(KERN_INFO
+                MVCUST_TRACE_PRINT(KERN_INFO,
                                    "==EXIT==\n\r");
             }        
             return MV_CUST_FAIL;
@@ -743,7 +752,7 @@
     }
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT==\n\r");
     }
 
@@ -778,7 +787,7 @@
     uint32_t              dscp       = 0;
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO 
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==ENTER==: dscp[%d] \n\r", dscp);
     }
 
@@ -812,7 +821,7 @@
     pVidEntry = &gs_vid_index_table[dir].pbits_map_index[MV_CUST_DEFAULT_UNTAG_RULE];
 
     if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
-        //MVCUST_TRACE_PRINT(KERN_INFO "%s, pVidEntry[%d], does not exist \n\r",__FUNCTION__, *pVidEntry);                 
+        //MVCUST_TRACE_PRINT(KERN_INFO,"%s, pVidEntry[%d], does not exist \n\r",__FUNCTION__, *pVidEntry);                 
     }
     else {
         
@@ -822,8 +831,11 @@
 
             pPktFrwd  = &pPbitsMap->pkt_fwd[pbitsIndex];
             if (pPktFrwd->in_use != 0) {
-                cust_flow->pkt_frwd.trg_port      = pPktFrwd->trg_port;
-                cust_flow->pkt_frwd.trg_queue     = pPktFrwd->trg_queue;
+                cust_flow->pkt_frwd.trg_port      = pPktFrwd->trg_port;               
+                if (false == mv_cust_get_tcont_state(pPktFrwd->trg_port))
+                    cust_flow->pkt_frwd.trg_queue = CPH_INVALID_TRGT_QUEUE;
+                 else
+                    cust_flow->pkt_frwd.trg_queue = pPktFrwd->trg_queue;
                 cust_flow->pkt_frwd.trg_hwf_queue = pPktFrwd->trg_hwf_queue;
                 cust_flow->pkt_frwd.gem_port      = pPktFrwd->gem_port;
                 cust_flow->mod_vid                = pPbitsMap->mod_vid[pbitsIndex];
@@ -831,11 +843,11 @@
                 cust_flow->pkt_frwd.in_use        = 1;
                 
                 if (gs_mv_cust_trace_flag) {
-                    MVCUST_TRACE_PRINT(KERN_INFO
+                    MVCUST_TRACE_PRINT(KERN_INFO,
                                        "trg_port(%d), trg_queue(%d), trg_hwf_queue(%d), gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
                                         cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue,
                                         cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
-                    MVCUST_TRACE_PRINT(KERN_INFO
+                    MVCUST_TRACE_PRINT(KERN_INFO,
                                        "==EXIT==:\n\r");                                            
                 }
                 
@@ -845,7 +857,7 @@
     }
 
     if (gs_mv_cust_trace_flag) {
-        MVCUST_TRACE_PRINT(KERN_INFO
+        MVCUST_TRACE_PRINT(KERN_INFO,
                            "==EXIT==:\n\r");
     }
 
@@ -876,7 +888,7 @@
     uint32_t  index = 0;
     uint32_t  table_index = 0;
 
-    //MVCUST_TRACE_PRINT(KERN_INFO "==ENTER==\n\r");
+    //MVCUST_TRACE_PRINT(KERN_INFO,"==ENTER==\n\r");
 
     /* Print Valid VID index entries */
     printk(KERN_INFO "In Upstream Direction      \n----------------------------------\n"); 
@@ -923,17 +935,15 @@
     for (table_index=0; table_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; table_index++) {
         if(gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].in_use != 0) {
                 printk(KERN_INFO "P-bits Flow Mapping Table %d\n----------------------------\n", table_index); 
-                printk(KERN_INFO "P-bits  in_use  mod_vid mod_pbits trg_port  trg_queue  trg_hwf_queue  gem_port\n"); 
+                printk(KERN_INFO "P-bits  in_use  mod_vid mod_pbits trg_queue  trg_hwf_queue  \n"); 
                 for (index=0; index<MV_CUST_PBITS_MAP_MAX_ENTRY_NUM; index++) 
-                    printk(KERN_INFO "%1.1d       %3.3s     %4.4d    %1.1d        %2.2d        %2.2d         %2.2d              %4.4d\n", 
+                    printk(KERN_INFO "%1.1d       %3.3s     %4.4d    %1.1d        %2.2d         %2.2d              \n", 
                                        index,
                                        (gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].in_use!=0)? "YES":"",
                                        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].mod_vid[index],
                                        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].mod_pbits[index],
-                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].trg_port, 
                                        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].trg_queue,
-                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].trg_hwf_queue,
-                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].gem_port);    
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].trg_hwf_queue);    
         
         }
     }
@@ -953,7 +963,7 @@
     }
     printk(KERN_INFO "\n\n");
 
-    //MVCUST_TRACE_PRINT(KERN_INFO "==EXIT==\n\r");    
+    //MVCUST_TRACE_PRINT(KERN_INFO,"==EXIT==\n\r");    
     return MV_CUST_OK; 
 }
 
@@ -977,22 +987,90 @@
 *******************************************************************************/    
 int mv_cust_flow_map_init(void)
 {
-    uint32_t pbits_index = 0;
+    uint32_t index = 0;
     
     /* Initializes VID index table              */
     memset((uint8_t *)&gs_vid_index_table, MV_CUST_INVALID_PBITS_TABLE_INDEX, sizeof(gs_vid_index_table));
 
     /* Initializes P-bits mapping tables        */
-    for (pbits_index=0; pbits_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; pbits_index++) {
-        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
-        gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index].in_use = 0;
-        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
-        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index].in_use = 0;        
+    for (index = 0; index < MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; index++) {
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_US][index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_US][index].in_use = 0;
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][index].in_use = 0;        
     }
 
     /* Initializes DSCP to P-bits mapping table */
     memset((uint8_t *)&gs_dscp_map_table, 0, sizeof(mv_cust_dscp_pbits_t));
     gs_dscp_map_table.in_use = 0;
-    
+
+    /* Initializes T-CONT state, default value is false */
+    for (index = 0; index < CPH_MAX_TCONT_NUM; index++)
+        gs_tcont_state[index] = false;
+        
     return MV_CUST_OK;
 }
+
+/*******************************************************************************
+**
+** mv_cust_get_tcont_state
+** ___________________________________________________________________________
+**
+** DESCRIPTION: The function get T-CONT state
+**
+** INPUTS:
+**   tcont - T-CONT
+**
+** OUTPUTS:
+**   None. 
+**
+** RETURNS:     
+**   state - State of T-CONT, enabled or disabled.  
+**
+*******************************************************************************/
+bool mv_cust_get_tcont_state(uint32_t tcont)
+{
+    /* Check tcont */
+    if (tcont >= CPH_MAX_TCONT_NUM)
+    {
+        MVCUST_TRACE_PRINT(KERN_ERR,"tcont[%d] is illegal, should be less than [%d]\n", tcont, CPH_MAX_TCONT_NUM); 
+        return false;
+    }
+
+    return gs_tcont_state[tcont];
+}
+
+/*******************************************************************************
+**
+** mv_cust_set_tcont_state
+** ___________________________________________________________________________
+**
+** DESCRIPTION: The function sets T-CONT state in mv_cust
+**
+** INPUTS:
+**   tcont - T-CONT
+**   state - State of T-CONT, enabled or disabled.
+**
+** OUTPUTS:
+**   None. 
+**
+** RETURNS:     
+**  On success, the function returns (MV_OK). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+MV_STATUS mv_cust_set_tcont_state(uint32_t tcont, bool state)
+{
+    /* Check tcont */
+    if (tcont >= CPH_MAX_TCONT_NUM)
+    {
+        MVCUST_TRACE_PRINT(KERN_ERR,"tcont[%d] is illegal, should be less than [%d]\n", tcont, CPH_MAX_TCONT_NUM); 
+        return MV_FAIL;
+    }
+
+    /* Apply t-cont state to mv_cust */
+    gs_tcont_state[tcont] = state;
+
+    return MV_OK;
+}
+EXPORT_SYMBOL(mv_cust_set_tcont_state);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h
index 5880b9a..787542a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h
@@ -36,17 +36,19 @@
 /****************************************************************************** 
  *                        Data Enum and Structure                                                                                                                                  
  ******************************************************************************/
-#define MVCUST_TRACE_PRINT(format, ...)   printk("%s(%d):  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__)
+#define MVCUST_TRACE_PRINT(level, format, ...)   printk(level "%s(%d):"format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
 
 #define MV_CUST_OK                        (0)
 #define MV_CUST_FAIL                      (1)
 
+#define CPH_MAX_TCONT_NUM                 (8)    /* Maximum T-CONT number    */
+#define CPH_INVALID_TRGT_QUEUE            (0xFF) /* Invalid target queue number  */
 
 #define MV_CUST_VID_NOT_CARE_VALUE        (4096) /* Does not care for VID    */
-#define MV_CUST_PBITS_NOT_CARE_VALUE      (8)     /* Does not care for P-bits */
-#define MV_CUST_DSCP_NOT_CARE_VALUE       (64)     /* Does not care for DSCP   */
+#define MV_CUST_PBITS_NOT_CARE_VALUE      (8)    /* Does not care for P-bits */
+#define MV_CUST_DSCP_NOT_CARE_VALUE       (64)   /* Does not care for DSCP   */
 
-#define MV_CUST_MAX_TRG_PORT_VALUE        (2+8-1)/* Maximum target port value, T-CONT7 */
+#define MV_CUST_MAX_TRG_PORT_VALUE        (8-1)  /* Maximum target port value, T-CONT7 */
 #define MV_CUST_MAX_TRG_QUEUE_VALUE       (7)    /* Maximum target queue value         */
 #define MV_CUST_MAX_GEM_PORT_VALUE        (4095) /* Maximum GEM port value             */
 
@@ -314,5 +316,44 @@
 *******************************************************************************/    
 int mv_cust_flow_map_init(void);
 
+/*******************************************************************************
+**
+** mv_cust_get_tcont_state
+** ___________________________________________________________________________
+**
+** DESCRIPTION: The function get T-CONT state
+**
+** INPUTS:
+**   tcont - T-CONT
+**
+** OUTPUTS:
+**   None. 
+**
+** RETURNS:     
+**   state - State of T-CONT, enabled or disabled.  
+**
+*******************************************************************************/
+bool mv_cust_get_tcont_state(uint32_t tcont);
+
+/*******************************************************************************
+**
+** mv_cust_set_tcont_state
+** ___________________________________________________________________________
+**
+** DESCRIPTION: The function sets T-CONT state in mv_cust
+**
+** INPUTS:
+**   tcont - T-CONT
+**   state - State of T-CONT, enabled or disabled.
+**
+** OUTPUTS:
+**   None. 
+**
+** RETURNS:     
+**  On success, the function returns (MV_OK). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+MV_STATUS mv_cust_set_tcont_state(uint32_t tcont, bool state);
 
 #endif /* __mv_cust_flow_map_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h
index 9556bfe..470a81c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h
@@ -47,10 +47,7 @@
 #define MV_CUST_IOCTL_MAP_RULE_CLEAR          _IOW(MV_CUST_IOCTL_MAGIC,  9,  unsigned int)
 #define MV_CUST_IOCTL_TAG_MAP_RULE_GET        _IOR(MV_CUST_IOCTL_MAGIC,  10, unsigned int)
 #define MV_CUST_IOCTL_UNTAG_MAP_RULE_GET      _IOR(MV_CUST_IOCTL_MAGIC,  11, unsigned int)
-
-
-
-
+#define MV_CUST_IOCTL_APP_ETH_TYPE_SET        _IOW(MV_CUST_IOCTL_MAGIC,  12, unsigned int)
 
 /* Enums
 ------------------------------------------------------------------------------*/
@@ -77,6 +74,12 @@
     mv_cust_dscp_pbits_t dscp_map;
 } mv_cust_ioctl_dscp_map_t;
 
+typedef struct
+{
+    mv_cust_app_type_e app_type;
+    uint16_t           eth_type;
+} mv_cust_ioctl_app_etype_t;
+
 /* MV_CUST Char Device Structure */
 /* ========================= */
 typedef struct
@@ -85,6 +88,7 @@
   mv_cust_ioctl_llid_set_t      mv_cust_ioctl_llid_set;
   mv_cust_ioctl_flow_map_t      mv_cust_ioctl_flow_map;
   mv_cust_ioctl_dscp_map_t      mv_cust_ioctl_dscp_map;
+  mv_cust_ioctl_app_etype_t     mv_cust_ioctl_app_etype;
 
   struct cdev  cdev;
 } mv_cust_cdev_t;
@@ -105,23 +109,3 @@
 ------------------------------------------------------------------------------*/
 
 #endif /* _MV_CUST_MNG_IF_H_ */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c
index 7c9055b..c57b076 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c
@@ -39,6 +39,9 @@
 #include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#ifdef CONFIG_MV_CUST_MLD_HANDLE
+#include <linux/icmpv6.h>
+#endif
 
 #include <mvOs.h>
 #include <ctrlEnv/mvCtrlEnvLib.h>
@@ -48,167 +51,179 @@
 #include "mv_cust_flow_map.h"
 #include "mv_cust_mng_if.h"
 
+/*----------------------------------------------------------------------------*/
+/* External  declaration                                                      */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Global static definition                                                   */
+/*----------------------------------------------------------------------------*/
 /* YUVAL - update to pnc define */
 #define     MH_GEM_PORT_MASK                (0x0FFF)
 #define     MH_EPON_OAM_TYPE                (0x8809)
 #define     ETY_IPV4                        (0x0800)
 #define     IPV4_PROTO_OFFSET               (9)
+#define     MV_CUST_SWF_TX_QUEUE            (6)
 
 #define     CUST_TBL_NUM_ENTRIES(a)         (sizeof(a)/sizeof(a[0]))
 
 /*Static Declarations */
-static int    mv_eth_ports_num = 0;
+static int    mv_eth_ports_num     = 0;
+static int    mv_cust_debug_code   = 0;
+
 static int    mv_cust_omci_gemport = 0;
-
-static int    mv_cust_omci_valid = 0;
-static int    mv_cust_eoam_valid = 0;
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-static int    mv_cust_igmp_detect = 1;
-static uint16_t mv_cust_igmp_type;
-static struct mv_eth_tx_spec     igmp_tx_spec = {0, MV_ETH_F_MH, 0, 0};
-#endif
-static int    mv_cust_port_loopback_detect = 1;
-static int    mv_cust_debug_code = 0;
-static int    mv_cust_xpon_oam_rx_gh = 0;
-
-static uint16_t mv_cust_xpon_oam_type;
-static uint16_t mv_cust_loopdet_type;
+static int    mv_cust_omci_rx_gh   = 0;
+static int    mv_cust_oam_rx_gh    = 0;
 
 /* Protocol definitions */
-static struct mv_eth_tx_spec     omci_mgmt_tx_spec = {0};
+static struct mv_eth_tx_spec     omci_mgmt_tx_spec = {0, 0, 0, MV_CUST_SWF_TX_QUEUE};
 static struct mv_eoam_llid_spec  epon_mgmt_tx_spec[MV_CUST_NUM_LLID];
+#define EPON_MGMT_ENTRIES   CUST_TBL_NUM_ENTRIES(epon_mgmt_tx_spec)
 
 #ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
-static struct mv_port_tx_spec    port_spec_cfg[CONFIG_MV_ETH_PORTS_NUM];
+static struct mv_port_tx_spec    udp_port_spec_cfg[CONFIG_MV_ETH_PORTS_NUM];
+#define PORT_ENTRIES        CUST_TBL_NUM_ENTRIES(udp_port_spec_cfg)
 #endif
 
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
 static int    mv_cust_flow_map = 0;
-static int    mv_cust_flow_map_parse(uint8_t *data, uint16_t *vlan, uint8_t *pbits, uint8_t dir);
-static int    mv_cust_flow_map_mod(uint8_t *data, uint16_t vid, uint8_t pbits, uint8_t dir);
 #endif
 
+/* Default Application Ethernet type used for socket and skb */
+#define MV_CUST_ETH_TYPE_IGMP      (0xA000)
+#define MV_CUST_ETH_TYPE_MLD       (0xAB00)
+#define MV_CUST_ETH_TYPE_LPBK      (0xFFFA)
+#define MV_CUST_ETH_TYPE_OAM       (0xBABA)
+/* The Ethernet tpye of OAM/OMCI could be same since they will not use at the same time*/
+#define MV_CUST_ETH_TYPE_OMCI      (0xBABA)
 
-#define     PORT_ENTRIES                    CUST_TBL_NUM_ENTRIES(port_spec_cfg)
-#define     EPON_MGMT_ENTRIES               CUST_TBL_NUM_ENTRIES(epon_mgmt_tx_spec)
-
-
-void mv_cust_omci_print(void)
+/* Global cust configuration*/
+/* Pay attention that the order could be be changed and the entry could not be removed */
+static mv_cust_app_config_t gCustConfig[] =
 {
-    printk("************* OMCI Configuration *****************\n\n");
-    printk("OMCI: valid = %d, gemport = %d, ethtype = 0x%04x, gh_keep = %d\n",
-           mv_cust_omci_valid, mv_cust_omci_gemport, ntohs(mv_cust_xpon_oam_type), mv_cust_xpon_oam_rx_gh);
-    printk("OMCI: txp   = %d, txq = %d, hw_cmd = 0x%08x, flags = 0x%04x on TX \n",
-           omci_mgmt_tx_spec.txp, omci_mgmt_tx_spec.txq, omci_mgmt_tx_spec.hw_cmd, omci_mgmt_tx_spec.flags);
-    printk("\n");
+    /* Application Type */   /* Enable Flag */   /*Application Eth type*/   /* Application Description*/
+    {MV_CUST_APP_TYPE_IGMP,  MV_CUST_APP_DISABLE, MV_CUST_ETH_TYPE_IGMP,     "IGMP application"},
+    {MV_CUST_APP_TYPE_MLD,   MV_CUST_APP_DISABLE, MV_CUST_ETH_TYPE_MLD,      "MLD application"},
+    {MV_CUST_APP_TYPE_LPBK,  MV_CUST_APP_DISABLE, MV_CUST_ETH_TYPE_LPBK,     "Loopback detection application"},
+    {MV_CUST_APP_TYPE_OAM,   MV_CUST_APP_DISABLE, MV_CUST_ETH_TYPE_OAM,      "eOAM application"},
+    {MV_CUST_APP_TYPE_OMCI,  MV_CUST_APP_DISABLE, MV_CUST_ETH_TYPE_OMCI,     "OMCI application"},    
+};
+
+/*----------------------------------------------------------------------------*/
+/* Function implementation                                                    */
+/*----------------------------------------------------------------------------*/
+
+void mv_cust_debug_info_set(int val)
+{
+    mv_cust_debug_code = val;
+    return;
 }
 
 
-void mv_cust_eoam_print(void)
+void mv_cust_app_flag_set(mv_cust_app_type_e app_type, uint16_t enable)
 {
-    int i;
-    printk("************* eOAM Configuration *****************\n\n");
-    printk("EOAM: valid = %d, ethtype = 0x%04x, gh_keep = %d\n",
-           mv_cust_eoam_valid, ntohs(mv_cust_xpon_oam_type), mv_cust_xpon_oam_rx_gh);
-    for (i=0;i <(EPON_MGMT_ENTRIES);i++) {
-        printk("llid%d: mac=%02x:%02x:%02x:%02x:%02x:%02x, txp=%d, txq=%d, hw_cmd=0x%08x, flags = 0x%04x\n",
-               i,
-               epon_mgmt_tx_spec[i].llid_mac_address[0],epon_mgmt_tx_spec[i].llid_mac_address[1],
-               epon_mgmt_tx_spec[i].llid_mac_address[2],epon_mgmt_tx_spec[i].llid_mac_address[3],
-               epon_mgmt_tx_spec[i].llid_mac_address[4],epon_mgmt_tx_spec[i].llid_mac_address[5],
-               epon_mgmt_tx_spec[i].tx_spec.txp, epon_mgmt_tx_spec[i].tx_spec.txq,
-               epon_mgmt_tx_spec[i].tx_spec.hw_cmd, epon_mgmt_tx_spec[i].tx_spec.flags);
-        printk("\n");
+    if (mv_cust_debug_code)
+        printk("%s() In, app_type[%d], enable[%d] \n", __func__, app_type, enable);
+    
+    if (app_type > (MV_CUST_APP_TYPE_MAX-1))
+    {
+        printk("%s: illegal application type[%d], allowed max type[%d]  \n",
+                __func__, app_type, MV_CUST_APP_TYPE_MAX-1);
+        return;
     }
-}
 
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-void mv_cust_igmp_print(void)
-{
-    printk("************* IGMP Configuration *****************\n\n");
-    printk("IGMP valid = %d,  ethtype = 0x%04x, on RX\n",
-           mv_cust_igmp_detect, ntohs(mv_cust_igmp_type));
-    printk("IGMP txp = %d, txq = %d, , hw_cmd = 0x%08x on TX\n",
-           igmp_tx_spec.txp, igmp_tx_spec.txq, igmp_tx_spec.hw_cmd);
-    printk("\n");
-}
-#endif
-
-void mv_cust_loopdet_print(void)
-{
-    printk("************* Port Loopback Configuration *****************\n\n");
-    printk("Port Loopback valid = %d,  ethtype = 0x%04x, on RX\n",
-           mv_cust_port_loopback_detect, ntohs(mv_cust_loopdet_type));
-}
-
-
-#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
-int mv_cust_udp_spec_print(int port)
-{
-    int i;
-    struct eth_port *pp = mv_eth_port_by_id(port);
-    struct mv_udp_port_tx_spec *udp_spec;
-
-    if (!pp)
-        return -ENODEV;
-
-    udp_spec = &(port_spec_cfg[port].udp_dst[0]);
-
-    printk("\n**** port #%d - TX UDP Dest Port configuration *****\n", port);
-    printk("----------------------------------------------------\n");
-    printk("ID udp_dst   txp    txq    flags    hw_cmd     func_add\n");
-    for (i = 0; i < sizeof(port_spec_cfg[port].udp_dst)/sizeof(port_spec_cfg[port].udp_dst[0]); i++) {
-        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
-            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
-                   i, ntohs(udp_spec[i].udp_port),
-                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
-                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
-                   udp_spec[i].tx_spec.tx_func);
-    }
-    printk("-----------------------------------------------------\n");
-
-    udp_spec = &(port_spec_cfg[port].udp_src[0]);
-
-    printk("**** port #%d - TX UDP Source Port configuration *****\n", port);
-    printk("-----------------------------------------------------\n");
-    printk("ID udp_src   txp    txq     flags    hw_cmd     func_add\n");
-    for (i = 0; i < sizeof(port_spec_cfg[port].udp_src)/sizeof(port_spec_cfg[port].udp_src[0]); i++) {
-        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
-            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
-                   i, ntohs(udp_spec[i].udp_port),
-                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
-                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
-                   udp_spec[i].tx_spec.tx_func);
-    }
-    printk("**************************************************************\n");
-
-
-    return 0;
-}
-
-void mv_cust_udp_spec_print_all(void)
-{
-    int port;
-
-    for (port=0;port < CONFIG_MV_ETH_PORTS_NUM ;port++) {
-        mv_cust_udp_spec_print(port);
-    }
-}
-#endif
-
+    if (app_type == MV_CUST_APP_TYPE_OMCI)
+    {
+        if (enable) 
+        {
+            if (gCustConfig[MV_CUST_APP_TYPE_OAM].enable) 
+            {
+                MVCUST_ERR_PRINT("EPON is already valid\n");
+                return;
+            }
+            gCustConfig[MV_CUST_APP_TYPE_OMCI].enable = MV_CUST_APP_ENABLE;
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-void mv_cust_flow_map_print(void)
-{
-    printk("************* Flow Mapping Configuration *****************\n\n");
-    printk("FLow mapping valid = %d\n", mv_cust_flow_map);
-}
+            mv_cust_flow_map   = 1;
 #endif
+        }
+        else 
+        {
+            gCustConfig[MV_CUST_APP_TYPE_OMCI].enable = MV_CUST_APP_DISABLE;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+            mv_cust_flow_map   = 0;
+#endif
+        }
+    }
+    else if(app_type == MV_CUST_APP_TYPE_OAM)
+    {
+        if (enable) 
+        {
+            if (gCustConfig[MV_CUST_APP_TYPE_OMCI].enable) 
+            {
+                MVCUST_ERR_PRINT("GPON is already valid\n");
+                return;
+            }
+            gCustConfig[MV_CUST_APP_TYPE_OAM].enable = MV_CUST_APP_ENABLE;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+            mv_cust_flow_map   = 0;
+#endif
+        }
+        else 
+        {
+            gCustConfig[MV_CUST_APP_TYPE_OAM].enable = MV_CUST_APP_DISABLE;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+            mv_cust_flow_map   = 0;
+#endif
+        }
 
-void mv_cust_omci_hw_cmd_set(uint32_t hw_cmd)
-{
-    omci_mgmt_tx_spec.hw_cmd = hw_cmd;
+    }
+    else
+    {
+        if (enable == MV_CUST_APP_ENABLE)
+            gCustConfig[app_type].enable = MV_CUST_APP_ENABLE;
+        else
+            gCustConfig[app_type].enable = MV_CUST_APP_DISABLE;
+    }
+
+    return;
 }
-EXPORT_SYMBOL(mv_cust_omci_hw_cmd_set);
+EXPORT_SYMBOL(mv_cust_app_flag_set);
+
+
+void mv_cust_app_etype_set(mv_cust_app_type_e app_type, uint16_t eth_type)
+{
+    if (mv_cust_debug_code)
+        printk("%s() In, app_type[%d], eth_type[%d] \n", __func__, app_type, eth_type);
+    
+    if (app_type > (MV_CUST_APP_TYPE_MAX-1))
+    {
+        printk("%s: illegal application type[%d], allowed max type[%d]  \n",
+                __func__, app_type, MV_CUST_APP_TYPE_MAX-1);
+        return;
+    }
+
+    gCustConfig[app_type].eth_type = eth_type;
+
+    return;
+}
+EXPORT_SYMBOL(mv_cust_app_etype_set);
+
+
+void mv_cust_rec_skb(int port, struct sk_buff *skb)
+{
+    uint32_t rx_status;
+    struct eth_port *pp;
+
+    rx_status = netif_receive_skb(skb);
+    pp = mv_eth_port_by_id(port);
+    STAT_DBG(if (rx_status) (pp->stats.rx_drop_sw++));
+}
+
+void mv_cust_omci_rx_gh_set(int val)
+{
+    mv_cust_omci_rx_gh = val;
+    return;
+}
 
 int mv_cust_omci_tx_set(int tcont, int txq)
 {
@@ -226,6 +241,16 @@
     return 0;
 }
 
+void mv_cust_omci_gemport_set(int gemport)
+{
+    mv_cust_omci_gemport = gemport;
+    return;
+}
+
+void mv_cust_omci_hw_cmd_set(uint32_t hw_cmd)
+{
+    omci_mgmt_tx_spec.hw_cmd = hw_cmd;
+}
 
 int mv_cust_omci_set(int tcont, int txq, int gem_port, int keep_rx_mh)
 {
@@ -243,14 +268,91 @@
     mv_cust_omci_gemport_set(gem_port);
     hw_cmd = ((gem_port << 8) | 0x0010);
     mv_cust_omci_hw_cmd_set(hw_cmd);
-    mv_cust_xpon_oam_rx_gh_set(keep_rx_mh);
+    mv_cust_omci_rx_gh_set(keep_rx_mh);
 
-    mv_cust_omci_enable(1);
+    mv_cust_app_flag_set(MV_CUST_APP_TYPE_OMCI, MV_CUST_APP_ENABLE);
 
     return 0;
 }
 EXPORT_SYMBOL(mv_cust_omci_set);
 
+void mv_cust_omci_print(void)
+{
+    printk("************* OMCI Configuration *****************\n\n");
+    printk("OMCI: valid = %d, gemport = %d, ethtype = 0x%04x, gh_keep = %d\n",
+           gCustConfig[MV_CUST_APP_TYPE_OMCI].enable,
+           mv_cust_omci_gemport, 
+           ntohs(gCustConfig[MV_CUST_APP_TYPE_OMCI].eth_type), 
+           mv_cust_omci_rx_gh);
+    printk("OMCI: txp   = %d, txq = %d, hw_cmd = 0x%08x, flags = 0x%04x on TX \n",
+           omci_mgmt_tx_spec.txp, omci_mgmt_tx_spec.txq, omci_mgmt_tx_spec.hw_cmd, omci_mgmt_tx_spec.flags);
+    printk("\n");
+}
+
+static int mv_cust_omci_gem_parse(uint8_t *data)
+{
+    uint16_t gh;
+
+    gh = ntohs(*(uint16_t *)data);
+
+    if(mv_cust_debug_code)
+        printk("%s:gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
+
+    /* Compare GH for omci_gemport */
+    if ( (gh & MH_GEM_PORT_MASK) != mv_cust_omci_gemport ) {
+        if(mv_cust_debug_code)
+            printk("%s: compare GH for OMCI_gemport failed: gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
+        return(0);
+    }
+
+    return(1);
+}
+
+static int mv_cust_omci_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_omci_gem_parse(skb->data))
+        return 0;
+    if (mv_cust_omci_rx_gh) {
+        rx_bytes = rx_desc->dataSize;
+    }
+    else {
+        skb->data += MV_ETH_MH_SIZE;
+        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
+    }
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = htons(gCustConfig[MV_CUST_APP_TYPE_OMCI].eth_type);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+int mv_cust_omci_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                   struct mv_eth_tx_spec *tx_spec_out)
+{
+    if ((skb->protocol == htons(gCustConfig[MV_CUST_APP_TYPE_OMCI].eth_type))
+        && (MV_CUST_APP_ENABLE == gCustConfig[MV_CUST_APP_TYPE_OMCI].enable)
+        && (port == MV_PON_PORT_ID)) {
+        memcpy (tx_spec_out, &omci_mgmt_tx_spec, sizeof(struct mv_eth_tx_spec));
+        if(mv_cust_debug_code)
+            printk("%s", __func__);
+        return 1;
+    }
+    return 0;
+}
+
+
+void mv_cust_oam_rx_gh_set(int val)
+{
+    mv_cust_oam_rx_gh = val;
+    return;
+}
 
 int mv_cust_eoam_llid_set(int llid, uint8_t *llid_mac, int txq)
 {
@@ -272,31 +374,6 @@
 }
 EXPORT_SYMBOL(mv_cust_eoam_llid_set);
 
-
-MV_STATUS mv_cust_omci_enable(int enable)
-{
-    if (enable) {
-
-        if (mv_cust_eoam_valid) {
-            MVCUST_ERR_PRINT("EPON is already valid\n");
-            return MV_ERROR;
-        }
-        mv_cust_omci_valid = 1;
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-        mv_cust_flow_map   = 1;
-#endif
-    }
-    else {
-        mv_cust_omci_valid = 0;
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-        mv_cust_flow_map   = 0;
-#endif
-    }
-
-    return MV_OK;
-}
-
-
 void mv_cust_eoam_init(void)
 {
     int i;
@@ -312,63 +389,407 @@
     }
 
     /* In Rx, keep the MH for EOAM */
-    mv_cust_xpon_oam_rx_gh_set(1);
+    mv_cust_oam_rx_gh_set(1);
     return ;
 }
-EXPORT_SYMBOL(mv_cust_eoam_init);
 
-
-MV_STATUS mv_cust_eoam_enable(int enable)
+void mv_cust_eoam_print(void)
 {
+    int i;
+    printk("************* eOAM Configuration *****************\n\n");
+    printk("EOAM: valid = %d, ethtype = 0x%04x, gh_keep = %d\n",
+           gCustConfig[MV_CUST_APP_TYPE_OAM].enable, 
+           ntohs(gCustConfig[MV_CUST_APP_TYPE_OAM].eth_type), 
+           mv_cust_oam_rx_gh);
+    for (i=0;i <(EPON_MGMT_ENTRIES);i++) {
+        printk("llid%d: mac=%02x:%02x:%02x:%02x:%02x:%02x, txp=%d, txq=%d, hw_cmd=0x%08x, flags = 0x%04x\n",
+               i,
+               epon_mgmt_tx_spec[i].llid_mac_address[0],epon_mgmt_tx_spec[i].llid_mac_address[1],
+               epon_mgmt_tx_spec[i].llid_mac_address[2],epon_mgmt_tx_spec[i].llid_mac_address[3],
+               epon_mgmt_tx_spec[i].llid_mac_address[4],epon_mgmt_tx_spec[i].llid_mac_address[5],
+               epon_mgmt_tx_spec[i].tx_spec.txp, epon_mgmt_tx_spec[i].tx_spec.txq,
+               epon_mgmt_tx_spec[i].tx_spec.hw_cmd, epon_mgmt_tx_spec[i].tx_spec.flags);
+        printk("\n");
+    }
+}
+
+static int mv_cust_eoam_type_parse(uint8_t *data)
+{
+    uint16_t ety;
+
+    ety = ntohs(*(uint16_t *)(data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN));
 
     if(mv_cust_debug_code)
-        printk("%s: enable = %d\n", __func__, enable);
+        printk("%s: ety 0x(%04x)\n", __func__, ety);
 
-    if (enable) {
-        if (mv_cust_omci_valid) {
-            MVCUST_ERR_PRINT("OMCI is already valid\n");
-            return MV_ERROR;
-        }
-        mv_cust_eoam_valid = 1;
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-        mv_cust_flow_map   = 0;
-#endif
+    /* Compare EPON OAM ether_type */
+    if (ety == MH_EPON_OAM_TYPE)
+        return(1);
+
+    return(0);
+}
+
+static int mv_cust_epon_oam_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_eoam_type_parse(skb->data))
+        return 0;
+
+    if (mv_cust_oam_rx_gh) {
+        rx_bytes = rx_desc->dataSize;
     }
     else {
-        mv_cust_eoam_valid = 0;
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-        mv_cust_flow_map   = 0;
-#endif
+        skb->data += MV_ETH_MH_SIZE;
+        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
     }
 
-    return MV_OK;
-}
-EXPORT_SYMBOL(mv_cust_eoam_enable);
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = htons(gCustConfig[MV_CUST_APP_TYPE_OAM].eth_type);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
 
-#if 0
-MV_STATUS mv_cust_eoam_tx_func_set(void (*tx_func) (uint8_t *data, int size, struct mv_eth_tx_spec *tx_spec))
+    return 1;
+}
+
+int mv_cust_eoam_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                    struct mv_eth_tx_spec *tx_spec_out)
 {
+    int mac_match, i;
 
-    if (mv_cust_debug_code)
-        printk("%s: \n", __func__);
-
-    /* System cannot be OMCI_valid */
-    if (mv_cust_omci_valid) {
-        MVCUST_ERR_PRINT("EPON is valid\n");
-        return MV_ERROR;
+    if ((skb->protocol == htons(gCustConfig[MV_CUST_APP_TYPE_OAM].eth_type))
+        && (MV_CUST_APP_ENABLE == gCustConfig[MV_CUST_APP_TYPE_OAM].enable)
+        && port == MV_PON_PORT_ID) {
+        /* Lookup MAC Address */
+        for (i=0; i<(EPON_MGMT_ENTRIES);i++) {
+            mac_match = memcmp((void *) &(epon_mgmt_tx_spec[i].llid_mac_address[0]),
+                               (void *)(skb->data + /*MV_ETH_MH_SIZE +*/ ETH_ALEN),
+                               ETH_ALEN);
+            if (!mac_match) {
+                memcpy (tx_spec_out, &epon_mgmt_tx_spec[i].tx_spec, sizeof(struct mv_eth_tx_spec));
+                if(mv_cust_debug_code)
+                    printk("%s, llid = %d", __func__, i);
+                return 1;
+            }
+        }
+        /* Source MAC Address not found */
+        if(mv_cust_debug_code) {
+            printk("(%s)Input Packet first bytes:\n", __func__);
+            for (i=0;i<24;i++) {
+                if (i%8== 0)
+                    printk("\n");
+                printk ("%02x ", *(skb->data + i));
+            }
+        }
     }
-    /*Pointer cannot be null */
-    if (!tx_func) {
-        MVCUST_ERR_PRINT("NULL pointer\n");
-    }
-
-    xpon_mgmt_tx_spec.tx_func = tx_func;
-
-    return MV_OK;
+    return 0;
 }
-EXPORT_SYMBOL(mv_cust_eoam_tx_func_set);
+
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+void mv_cust_igmp_print(void)
+{
+    printk("************* IGMP Configuration *****************\n\n");
+    printk("IGMP valid = %d,  ethtype = 0x%04x \n",
+           gCustConfig[MV_CUST_APP_TYPE_IGMP].enable, 
+           gCustConfig[MV_CUST_APP_TYPE_IGMP].eth_type);
+    printk("IGMP default txq = %d\n",MV_CUST_SWF_TX_QUEUE);
+    printk("\n");
+}
+
+static int mv_cust_igmp_parse(uint8_t *data)
+{
+    uint16_t ety;
+    uint8_t  proto;
+    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    while (ety == 0x8100 || ety == 0x9100 || ety == 0x88A8) {
+        fieldp+= VLAN_HLEN;
+        ety = ntohs(*(uint16_t *)fieldp);
+    }
+
+    if(mv_cust_debug_code)
+        printk("%s:ety 0x(%04x)\n", __func__, ety);
+
+    if (ety == ETY_IPV4) {
+        fieldp+= 2;
+        fieldp+= IPV4_PROTO_OFFSET;
+        proto = *fieldp;
+        if (mv_cust_debug_code)
+            printk("%s:proto 0x(%02x)\n", __func__, proto);
+
+        if (proto == IPPROTO_IGMP)
+            return(1);
+    }
+
+    return(0);
+}
+
+static int mv_cust_igmp_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_igmp_parse(skb->data))
+        return 0;
+
+    /* To Indicate the source GMAC */
+    skb->data[0] = port;
+
+    rx_bytes = rx_desc->dataSize;
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = htons(gCustConfig[MV_CUST_APP_TYPE_IGMP].eth_type);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+int mv_cust_igmp_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                    struct mv_eth_tx_spec *tx_spec_out)
+{
+    if (gCustConfig[MV_CUST_APP_TYPE_IGMP].enable == MV_CUST_APP_ENABLE) {
+        /* Check application Ethernet type */
+        if (skb->protocol == htons(gCustConfig[MV_CUST_APP_TYPE_IGMP].eth_type)) {
+
+            /* The Mapping and VLAN mod should be support in next phase */
+            if (MV_PON_PORT_ID == port)
+            {
+                tx_spec_out->flags = MV_ETH_F_MH;
+            }
+            else
+            {
+                tx_spec_out->flags = 0;
+            }
+            
+            tx_spec_out->txp     = 0;
+            tx_spec_out->txq     = MV_CUST_SWF_TX_QUEUE;
+            tx_spec_out->hw_cmd  = 0;
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+            tx_spec_out->tx_func = NULL;
+#endif
+            return 1;
+        }
+    }
+    return 0;
+}
+
 #endif
 
+
+#ifdef CONFIG_MV_CUST_MLD_HANDLE
+void mv_cust_mld_print(void)
+{
+    printk("************* MLD Configuration *****************\n\n");
+    printk("MLD valid = %d,  ethtype = 0x%04x \n",
+           gCustConfig[MV_CUST_APP_TYPE_MLD].enable, 
+           gCustConfig[MV_CUST_APP_TYPE_MLD].eth_type);
+    printk("MLD default txq = %d\n",MV_CUST_SWF_TX_QUEUE);
+    printk("\n");
+}
+
+static int mv_cust_mld_parse(uint8_t *data)
+{
+    uint16_t ety;
+    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
+
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    while (ety == 0x8100 || ety == 0x9100 ||ety == 0x88A8) {
+        fieldp+= VLAN_HLEN;
+        ety = ntohs(*(uint16_t *)fieldp);
+    }
+
+    if(mv_cust_debug_code)
+        printk("%s:ety 0x(%04x)\n", __func__, ety);
+
+    if (ety == ETH_P_IPV6) 
+    {
+        struct ipv6hdr *hdr = (struct ipv6hdr *)(fieldp+2);
+        struct ipv6_hopopt_hdr *hopopthdr ;
+        struct icmp6hdr *pic;
+
+        if (hdr->nexthdr != NEXTHDR_HOP )
+          return 0;
+
+        hopopthdr = (struct ipv6_hopopt_hdr *)((uint8_t *)hdr+ sizeof(struct ipv6hdr));
+
+        if ( hopopthdr->nexthdr != IPPROTO_ICMPV6)
+            return 0;
+
+        pic =  (struct icmp6hdr *)((uint8_t *)hopopthdr+ipv6_optlen(hopopthdr));
+
+        switch (pic->icmp6_type) {
+        case ICMPV6_MGM_QUERY:
+        case ICMPV6_MGM_REPORT:
+        case ICMPV6_MGM_REDUCTION:
+        case ICMPV6_MLD2_REPORT:
+            return 1;
+        default:
+            break;
+        }
+        
+    }
+    
+    return(0);
+}
+
+static int mv_cust_mld_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_mld_parse(skb->data))
+        return 0;
+
+    /* To Indicate the source GMAC */
+    skb->data[0] = port;
+
+    rx_bytes = rx_desc->dataSize;
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = htons(gCustConfig[MV_CUST_APP_TYPE_MLD].eth_type);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+int mv_cust_mld_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                   struct mv_eth_tx_spec *tx_spec_out)
+{
+    if (gCustConfig[MV_CUST_APP_TYPE_MLD].enable == MV_CUST_APP_ENABLE) {
+        /* Check application Ethernet type */
+        if (skb->protocol == htons(gCustConfig[MV_CUST_APP_TYPE_MLD].eth_type)) {
+
+            /* The Mapping and VLAN mod should be support in next phase */
+            if (MV_PON_PORT_ID == port)
+            {
+                tx_spec_out->flags = MV_ETH_F_MH;
+            }
+            else
+            {
+                tx_spec_out->flags = 0;
+            }
+            
+            tx_spec_out->txp     = 0;
+            tx_spec_out->txq     = MV_CUST_SWF_TX_QUEUE;
+            tx_spec_out->hw_cmd  = 0;
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+            tx_spec_out->tx_func = NULL;
+#endif
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#endif
+
+
+#ifdef CONFIG_MV_CUST_LPBK_DETECT_HANDLE
+void mv_cust_loopdet_print(void)
+{
+    printk("************* UNI loopback detection Configuration *****************\n\n");
+    printk("Lpbk detect valid = %d,  ethtype = 0x%04x \n",
+           gCustConfig[MV_CUST_APP_TYPE_LPBK].enable, 
+           gCustConfig[MV_CUST_APP_TYPE_LPBK].eth_type);
+    printk("Lpbk detect default txq = %d\n",MV_CUST_SWF_TX_QUEUE);
+    printk("\n");
+}
+
+static int mv_cust_loopdet_parse(uint8_t *data)
+{
+    uint16_t ety;
+    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    while (ety == 0x8100 || ety == 0x9100 ||ety == 0x88A8) {
+        fieldp+= VLAN_HLEN;
+        ety = ntohs(*(uint16_t *)fieldp);
+    }
+    if(mv_cust_debug_code)
+        printk("%s: ety 0x(%04x)\n", __func__, ety);
+
+    /* Compare EPON OAM ether_type */
+    if (ety == gCustConfig[MV_CUST_APP_TYPE_LPBK].eth_type)
+        return(1);
+
+    return(0);
+}
+
+static int mv_cust_loopdet_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_loopdet_parse(skb->data))
+        return 0;
+    
+    /* To Indicate the source GMAC */
+    skb->data[0] = port;
+
+    rx_bytes = rx_desc->dataSize;
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = htons(gCustConfig[MV_CUST_APP_TYPE_LPBK].eth_type);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+int mv_cust_loopdet_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                       struct mv_eth_tx_spec *tx_spec_out)
+{
+    if (MV_CUST_APP_ENABLE == gCustConfig[MV_CUST_APP_TYPE_LPBK].enable) {
+        /* Check application Ethernet type */
+        if (skb->protocol == htons(gCustConfig[MV_CUST_APP_TYPE_LPBK].eth_type)) {
+         
+            if (MV_PON_PORT_ID == port)
+            {
+                tx_spec_out->flags = MV_ETH_F_MH;
+            }
+            else
+            {
+                tx_spec_out->flags = 0;
+            }
+            
+            tx_spec_out->txp     = 0;
+            tx_spec_out->txq     = MV_CUST_SWF_TX_QUEUE;
+            tx_spec_out->hw_cmd  = 0;
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+            tx_spec_out->tx_func = NULL;
+#endif          
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#endif
+
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
 static inline void mv_cust_copy_tx_spec(struct mv_eth_tx_spec * tx_spec,
                                         uint8_t txp, uint8_t txq,
                                         uint16_t flags, uint32_t hw_cmd)
@@ -379,9 +800,58 @@
     tx_spec->flags = flags;
 }
 
+int mv_cust_udp_spec_print(int port)
+{
+    int i;
+    struct eth_port *pp = mv_eth_port_by_id(port);
+    struct mv_udp_port_tx_spec *udp_spec;
+
+    if (!pp)
+        return -ENODEV;
+
+    udp_spec = &(udp_port_spec_cfg[port].udp_dst[0]);
+
+    printk("\n**** port #%d - TX UDP Dest Port configuration *****\n", port);
+    printk("----------------------------------------------------\n");
+    printk("ID udp_dst   txp    txq    flags    hw_cmd     func_add\n");
+    for (i = 0; i < sizeof(udp_port_spec_cfg[port].udp_dst)/sizeof(udp_port_spec_cfg[port].udp_dst[0]); i++) {
+        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
+            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
+                   i, ntohs(udp_spec[i].udp_port),
+                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
+                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
+                   udp_spec[i].tx_spec.tx_func);
+    }
+    printk("-----------------------------------------------------\n");
+
+    udp_spec = &(udp_port_spec_cfg[port].udp_src[0]);
+
+    printk("**** port #%d - TX UDP Source Port configuration *****\n", port);
+    printk("-----------------------------------------------------\n");
+    printk("ID udp_src   txp    txq     flags    hw_cmd     func_add\n");
+    for (i = 0; i < sizeof(udp_port_spec_cfg[port].udp_src)/sizeof(udp_port_spec_cfg[port].udp_src[0]); i++) {
+        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
+            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
+                   i, ntohs(udp_spec[i].udp_port),
+                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
+                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
+                   udp_spec[i].tx_spec.tx_func);
+    }
+    printk("**************************************************************\n");
+
+    return 0;
+}
 
 
-#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+void mv_cust_udp_spec_print_all(void)
+{
+    int port;
+
+    for (port=0;port < CONFIG_MV_ETH_PORTS_NUM ;port++) {
+        mv_cust_udp_spec_print(port);
+    }
+}
+
 MV_STATUS  mv_cust_udp_int_spec_set(struct mv_udp_port_tx_spec *udp_spec, uint16_t udp_port, int table_size,
                                     uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
 {
@@ -411,14 +881,14 @@
 MV_STATUS  mv_cust_udp_src_spec_set(int tx_port, uint16_t udp_src_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
 {
     struct eth_port *pp = mv_eth_port_by_id(tx_port);
-    struct mv_udp_port_tx_spec *udp_src_spec = port_spec_cfg[tx_port].udp_src;
+    struct mv_udp_port_tx_spec *udp_src_spec = udp_port_spec_cfg[tx_port].udp_src;
     MV_STATUS mv_status;
 
     if (!pp)
         return -ENODEV;
 
     mv_status = mv_cust_udp_int_spec_set(udp_src_spec, udp_src_port,
-                                         sizeof(port_spec_cfg[tx_port].udp_src)/sizeof(port_spec_cfg[tx_port].udp_src[0]),
+                                         sizeof(udp_port_spec_cfg[tx_port].udp_src)/sizeof(udp_port_spec_cfg[tx_port].udp_src[0]),
                                          txp, txq, flags, hw_cmd);
 
     if (mv_status != MV_OK)
@@ -432,14 +902,14 @@
 MV_STATUS  mv_cust_udp_dest_spec_set(int tx_port, uint16_t udp_dest_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
 {
     struct eth_port *pp = mv_eth_port_by_id(tx_port);
-    struct mv_udp_port_tx_spec *udp_dst_spec = port_spec_cfg[tx_port].udp_dst;
+    struct mv_udp_port_tx_spec *udp_dst_spec = udp_port_spec_cfg[tx_port].udp_dst;
     MV_STATUS mv_status;
 
     if (!pp)
         return -ENODEV;
 
     mv_status = mv_cust_udp_int_spec_set(udp_dst_spec, udp_dest_port,
-                                         sizeof(port_spec_cfg[tx_port].udp_dst)/sizeof(port_spec_cfg[tx_port].udp_dst[0]),
+                                         sizeof(udp_port_spec_cfg[tx_port].udp_dst)/sizeof(udp_port_spec_cfg[tx_port].udp_dst[0]),
                                          txp, txq, flags, hw_cmd);
 
     if (mv_status != MV_OK)
@@ -462,101 +932,21 @@
     for (tx_port=0; tx_port<num_ports;tx_port++) {
 
         /* Invalidate UDP Dest ports, set txq=invalid  */
-        for (i=0;i<(sizeof(port_spec_cfg[tx_port].udp_dst)/sizeof(port_spec_cfg[tx_port].udp_dst[0]));i++) {
-            memset(&(port_spec_cfg[tx_port].udp_dst[i]), 0, sizeof(struct mv_udp_port_tx_spec));
-            port_spec_cfg[tx_port].udp_dst[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
+        for (i=0;i<(sizeof(udp_port_spec_cfg[tx_port].udp_dst)/sizeof(udp_port_spec_cfg[tx_port].udp_dst[0]));i++) {
+            memset(&(udp_port_spec_cfg[tx_port].udp_dst[i]), 0, sizeof(struct mv_udp_port_tx_spec));
+            udp_port_spec_cfg[tx_port].udp_dst[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
         }
 
         /* Invalidate UDP Source ports, , set txq=invalid */
-        for (i=0;i<(sizeof(port_spec_cfg[tx_port].udp_src)/sizeof(port_spec_cfg[tx_port].udp_src[0]));i++) {
-            memset(&(port_spec_cfg[tx_port].udp_src[i]), 0, sizeof(struct mv_udp_port_tx_spec));
-            port_spec_cfg[tx_port].udp_src[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
+        for (i=0;i<(sizeof(udp_port_spec_cfg[tx_port].udp_src)/sizeof(udp_port_spec_cfg[tx_port].udp_src[0]));i++) {
+            memset(&(udp_port_spec_cfg[tx_port].udp_src[i]), 0, sizeof(struct mv_udp_port_tx_spec));
+            udp_port_spec_cfg[tx_port].udp_src[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
         }
 
     }
     return;
 }
-#endif
 
-int mv_cust_omci_tx(int port, struct net_device *dev, struct sk_buff *skb,
-                   struct mv_eth_tx_spec *tx_spec_out)
-{
-    if ( (skb->protocol == mv_cust_xpon_oam_type)
-        && mv_cust_omci_valid
-        && port == MV_PON_PORT_ID) {
-        memcpy (tx_spec_out, &omci_mgmt_tx_spec, sizeof(struct mv_eth_tx_spec));
-        if(mv_cust_debug_code)
-            printk("%s", __func__);
-        return 1;
-    }
-    return 0;
-}
-
-
-int mv_cust_eoam_tx(int port, struct net_device *dev, struct sk_buff *skb,
-                    struct mv_eth_tx_spec *tx_spec_out)
-{
-    int mac_match, i;
-
-    if (skb->protocol == mv_cust_xpon_oam_type
-        && mv_cust_eoam_valid
-        && port == MV_PON_PORT_ID) {
-        /* Lookup MAC Address */
-        for (i=0; i<(EPON_MGMT_ENTRIES);i++) {
-            mac_match = memcmp((void *) &(epon_mgmt_tx_spec[i].llid_mac_address[0]),
-                               (void *)(skb->data + /*MV_ETH_MH_SIZE +*/ ETH_ALEN),
-                               ETH_ALEN);
-            if (!mac_match) {
-                memcpy (tx_spec_out, &epon_mgmt_tx_spec[i].tx_spec, sizeof(struct mv_eth_tx_spec));
-                if(mv_cust_debug_code)
-                    printk("%s, llid = %d", __func__, i);
-                return 1;
-            }
-        }
-        /* Source MAC Address not found */
-        if(mv_cust_debug_code) {
-            printk("(%s)Input Packet first bytes:\n", __func__);
-            for (i=0;i<24;i++) {
-                if (i%8== 0)
-                    printk("\n");
-                printk ("%02x ", *(skb->data + i));
-            }
-        }
-    }
-    return 0;
-}
-
-
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-int mv_cust_igmp_tx(int port, struct net_device *dev, struct sk_buff *skb,
-                    struct mv_eth_tx_spec *tx_spec_out)
-{
-    if (mv_cust_igmp_detect) {
-        /* Check Tx XPON Type */
-        if (skb->protocol == mv_cust_igmp_type) {
-            memcpy (tx_spec_out, &igmp_tx_spec, sizeof(struct mv_eth_tx_spec));
-
-            /* MH should not be set */
-            tx_spec_out->flags = 0;
-            if (2 == port)
-            {
-                tx_spec_out->txp = skb->data[0];
-                tx_spec_out->hw_cmd = ((skb->data[2] << 8) | skb->data[3]) << 8;
-                skb->data[2] |= 0x80;
-            }
-            tx_spec_out->txq = skb->data[1];
-
-            skb_pull(skb, 2);
-
-            return 1;
-        }
-    }
-    return 0;
-}
-#endif
-
-
-#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
 int mv_cust_udp_port_tx(int port, struct net_device *dev, struct sk_buff *skb,
                         struct mv_eth_tx_spec *tx_spec_out)
 {
@@ -572,14 +962,14 @@
     if (skb->protocol == ETY_IPV4) {
         /* Get UDP Port */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
-	iphdrp = skb->nh.iph;
+    iphdrp = skb->nh.iph;
 #else
-	iphdrp = ip_hdr(skb);
+    iphdrp = ip_hdr(skb);
 #endif
 
         if ((iphdrp) && (iphdrp->protocol == IPPROTO_UDP)) {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
-	    udphdrp = skb->h.uh;
+        udphdrp = skb->h.uh;
 #else
         udphdrp = udp_hdr(skb);
 #endif
@@ -588,20 +978,20 @@
                     udphdrp = (struct udphdr *)((char *)udphdrp + (4*(iphdrp->ihl)));
                 }
                 /* Find configured UDP Source Port*/
-                for (i=0; i < sizeof(port_spec_cfg[port].udp_src)/sizeof(port_spec_cfg[port].udp_src[0]);i++) {
-                    if ((udphdrp->source == port_spec_cfg[port].udp_src[i].udp_port) &&
-                        (port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
-                        memcpy (tx_spec_out, &(port_spec_cfg[port].udp_src[i].tx_spec), sizeof(struct mv_eth_tx_spec));
+                for (i=0; i < sizeof(udp_port_spec_cfg[port].udp_src)/sizeof(udp_port_spec_cfg[port].udp_src[0]);i++) {
+                    if ((udphdrp->source == udp_port_spec_cfg[port].udp_src[i].udp_port) &&
+                        (udp_port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
+                        memcpy (tx_spec_out, &(udp_port_spec_cfg[port].udp_src[i].tx_spec), sizeof(struct mv_eth_tx_spec));
                         if (mv_cust_debug_code)
                             printk("%s: found udp_src 0x(%04x)\n", __func__, ntohs(udphdrp->source));
                         return 1;
                     }
                 }
                 /* Find configured UDP Dest. Port*/
-                for (i=0; i < sizeof(port_spec_cfg[port].udp_dst)/sizeof(port_spec_cfg[port].udp_dst[0]);i++) {
-                    if ((udphdrp->dest == port_spec_cfg[port].udp_dst[i].udp_port) &&
-                        (port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
-                        memcpy (tx_spec_out, &(port_spec_cfg[port].udp_dst[i].tx_spec), sizeof(struct mv_eth_tx_spec));
+                for (i=0; i < sizeof(udp_port_spec_cfg[port].udp_dst)/sizeof(udp_port_spec_cfg[port].udp_dst[0]);i++) {
+                    if ((udphdrp->dest == udp_port_spec_cfg[port].udp_dst[i].udp_port) &&
+                        (udp_port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
+                        memcpy (tx_spec_out, &(udp_port_spec_cfg[port].udp_dst[i].tx_spec), sizeof(struct mv_eth_tx_spec));
                         if (mv_cust_debug_code)
                             printk("%s: found udp_dst 0x(%04x)\n", __func__, ntohs(udphdrp->dest));
                         return 1;
@@ -626,7 +1016,116 @@
 }
 #endif
 
+
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+void mv_cust_flow_map_print(void)
+{
+    printk("************* Flow Mapping Configuration *****************\n\n");
+    printk("Flow mapping valid = %d\n", mv_cust_flow_map);
+}
+
+static int mv_cust_flow_map_parse(uint8_t *data, uint16_t *vlan, uint8_t *pbits, uint8_t dir)
+{
+    uint16_t ety;
+    uint8_t *fieldp ;
+
+    if (MV_CUST_FLOW_DIR_US == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN;
+    else
+        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
+        fieldp += 2;
+        *vlan  = ntohs(*(uint16_t *)fieldp);
+        *pbits = (*vlan >> 13 ) & 0x7;
+        *vlan  = (*vlan) & 0xfff;
+        return(1);
+    }
+    else {
+        return(0);
+    }
+
+    return(0);
+}
+
+static int mv_cust_flow_map_mod(uint8_t *data, uint16_t vid, uint8_t pbits, uint8_t dir)
+{
+    uint16_t ety  = 0;
+    uint16_t vlan = 0;
+    uint8_t *fieldp;
+
+    if (MV_CUST_FLOW_DIR_US == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN;
+    else
+        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
+
+    /* If not need to modify VID or P-bits */
+    if((vid == MV_CUST_VID_NOT_CARE_VALUE) &&
+       (pbits == MV_CUST_PBITS_NOT_CARE_VALUE))
+        return (1);
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
+        fieldp += 2;
+
+        vlan = ntohs(*(uint16_t *)fieldp);
+
+        if (vid < MV_CUST_VID_NOT_CARE_VALUE)
+            vlan = (vlan & 0xf000) | (vid & 0xfff);
+        if (pbits < MV_CUST_PBITS_NOT_CARE_VALUE)
+            vlan = (vlan & 0x0fff) | ((pbits & 0x7) << 13);
+
+        *(uint16_t *)fieldp = htons(vlan);
+        return(1);
+    }
+    else {
+        return(0);
+    }
+
+    return(0);
+}
+
+static int mv_cust_flow_map_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint16_t vlan        = 0;
+    uint8_t  pbits       = 0;
+    int      btag        = 0;
+    int      ret         = 0;
+    mv_cust_ioctl_flow_map_t cust_flow;
+
+    if (MV_PON_PORT_ID != port)
+        return 0;
+
+    if (mv_cust_flow_map) {
+
+        /* Parse packets to check whether it is tagged or untagged, and get vlan and pbits in tagged mode */
+        btag = mv_cust_flow_map_parse(skb->data, &vlan, &pbits, MV_CUST_FLOW_DIR_DS);
+        //printk(KERN_ERR " %s TX packet 1 btag[%d] vlan[%d]  pbits[%d]\n", __func__, btag, vlan, pbits);
+
+        /* The frame is tagged */
+        if (btag == 1) {
+            cust_flow.vid    = vlan;
+            cust_flow.pbits  = pbits;
+            cust_flow.dir    = MV_CUST_FLOW_DIR_DS;
+
+            ret = mv_cust_tag_map_rule_get(&cust_flow);
+            //printk(KERN_ERR " %s TX packet 2 trg_port[%d] trg_queue[%d]  gem_port[%d]\n", __func__, pkt_fwd.trg_port, pkt_fwd.trg_queue, pkt_fwd.gem_port);
+
+            /* Modify VID and P-bits if needed */
+            if (ret == MV_CUST_OK) {
+
+                /* modify VID and P-bits if needed */
+                ret = mv_cust_flow_map_mod(skb->data, cust_flow.mod_vid, cust_flow.mod_pbits, MV_CUST_FLOW_DIR_DS);
+            }
+        }
+    }
+
+    return 1;
+}
+
 int mv_cust_flow_map_tx(int port, struct net_device *dev, struct sk_buff *skb,
                         struct mv_eth_tx_spec *tx_spec_out)
 {
@@ -647,8 +1146,6 @@
         /* Parse packets to check whether it is tagged or untagged, and get vlan and pbits in tagged mode */
         btag = mv_cust_flow_map_parse(skb->data, &vlan, &pbits, MV_CUST_FLOW_DIR_US);
 
-        //printk(KERN_ERR " %s TX packet 1 btag[%d] vlan[%d]  pbits[%d]\n", __func__, btag, vlan, pbits);
-
         /* The frame is tagged */
         if (btag == 1) {
             cust_flow.vid    = vlan;
@@ -733,368 +1230,44 @@
     }
     return 0;
 }
+
 #endif
 
-void mv_cust_debug_info_set(int val)
+
+
+void mv_cust_print(int type)
 {
-    mv_cust_debug_code = val;
-    return;
-}
-
-void mv_cust_omci_type_set(uint16_t type)
-{
-    mv_cust_xpon_oam_type = htons(type);
-    return;
-}
-EXPORT_SYMBOL(mv_cust_omci_type_set);
-
-void mv_cust_epon_oam_type_set(uint16_t type)
-{
-    mv_cust_xpon_oam_type = htons(type);
-    return;
-}
-EXPORT_SYMBOL(mv_cust_epon_oam_type_set);
-
-
-void mv_cust_xpon_oam_rx_gh_set(int val)
-{
-    mv_cust_xpon_oam_rx_gh = val;
-    return;
-}
-EXPORT_SYMBOL(mv_cust_xpon_oam_rx_gh_set);
-
-
+    switch (type)
+    {
 #ifdef CONFIG_MV_CUST_IGMP_HANDLE
-void mv_cust_igmp_type_set(uint16_t type)
-{
-    mv_cust_igmp_type = htons(type);
+        case MV_CUST_APP_TYPE_IGMP:
+            mv_cust_igmp_print();
+            break;
+#endif
+#ifdef CONFIG_MV_CUST_MLD_HANDLE
+        case MV_CUST_APP_TYPE_MLD:
+            mv_cust_mld_print();
+            break;
+#endif
+#ifdef CONFIG_MV_CUST_LPBK_DETECT_HANDLE
+        case MV_CUST_APP_TYPE_LPBK:
+            mv_cust_loopdet_print();
+            break;
+#endif
+        case MV_CUST_APP_TYPE_OAM:
+            mv_cust_eoam_print();
+            break;
+        case MV_CUST_APP_TYPE_OMCI:
+            mv_cust_omci_print();
+            break;
+        default:
+            break;
+    }
+
     return;
 }
-EXPORT_SYMBOL(mv_cust_igmp_type_set);
-#endif
-
-void mv_cust_loopdet_type_set(uint16_t type)
-{
-    mv_cust_loopdet_type = htons(type);
-    return;
-}
-EXPORT_SYMBOL(mv_cust_loopdet_type_set);
-
-
-void mv_cust_omci_gemport_set(int gemport)
-{
-    mv_cust_omci_gemport = gemport;
-    return;
-}
-EXPORT_SYMBOL(mv_cust_omci_gemport_set);
-
-
-static int mv_cust_omci_gem_parse(uint8_t *data)
-{
-    uint16_t gh;
-
-    gh = ntohs(*(uint16_t *)data);
-
-    if(mv_cust_debug_code)
-        printk("%s:gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
-
-    /* Compare GH for omci_gemport */
-    if ( (gh & MH_GEM_PORT_MASK) != mv_cust_omci_gemport ) {
-        if(mv_cust_debug_code)
-            printk("%s: compare GH for OMCI_gemport failed: gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
-        return(0);
-    }
-
-    return(1);
-}
-
-static int mv_cust_eoam_type_parse(uint8_t *data)
-{
-    uint16_t ety;
-
-    ety = ntohs(*(uint16_t *)(data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN));
-
-    if(mv_cust_debug_code)
-        printk("%s: ety 0x(%04x)\n", __func__, ety);
-
-    /* Compare EPON OAM ether_type */
-    if (ety == MH_EPON_OAM_TYPE)
-        return(1);
-
-    return(0);
-}
-
-
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-static int mv_cust_igmp_parse(uint8_t *data)
-{
-    uint16_t ety;
-    uint8_t  proto;
-    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
-
-    /* Loop through VLAN tags */
-    ety = ntohs(*(uint16_t *)fieldp);
-    while (ety == 0x8100 || ety == 0x88A8) {
-        fieldp+= VLAN_HLEN;
-        ety = ntohs(*(uint16_t *)fieldp);
-    }
-
-    if(mv_cust_debug_code)
-        printk("%s:ety 0x(%04x)\n", __func__, ety);
-
-    if (ety == ETY_IPV4) {
-	    fieldp+= 2;
-        fieldp+= IPV4_PROTO_OFFSET;
-        proto = *fieldp;
-        if (mv_cust_debug_code)
-            printk("%s:proto 0x(%02x)\n", __func__, proto);
-
-        if (proto == IPPROTO_IGMP)
-            return(1);
-    }
-
-    return(0);
-}
-#endif
-
-static int mv_cust_loopdet_parse(uint8_t *data)
-{
-    uint16_t ety;
-    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
-
-    /* Loop through VLAN tags */
-    ety = ntohs(*(uint16_t *)fieldp);
-    while (ety == 0x8100 || ety == 0x88A8) {
-        fieldp+= VLAN_HLEN;
-        ety = ntohs(*(uint16_t *)fieldp);
-    }
-    if(mv_cust_debug_code)
-        printk("%s: ety 0x(%04x)\n", __func__, ety);
-
-    /* Compare EPON OAM ether_type */
-    if (ety == mv_cust_loopdet_type)
-        return(1);
-
-    return(0);
-}
-
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-static int mv_cust_flow_map_parse(uint8_t *data, uint16_t *vlan, uint8_t *pbits, uint8_t dir)
-{
-    uint16_t ety;
-    uint8_t *fieldp;
-
-    if (MV_CUST_FLOW_DIR_US == dir)
-        fieldp = data + ETH_ALEN + ETH_ALEN;
-    else if (MV_CUST_FLOW_DIR_DS == dir)
-        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
-
-    /* Loop through VLAN tags */
-    ety = ntohs(*(uint16_t *)fieldp);
-    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
-        fieldp += 2;
-        *vlan  = ntohs(*(uint16_t *)fieldp);
-        *pbits = (*vlan >> 13 ) & 0x7;
-        *vlan  = (*vlan) & 0xfff;
-        return(1);
-    }
-    else {
-        return(0);
-    }
-
-    return(0);
-}
-
-static int mv_cust_flow_map_mod(uint8_t *data, uint16_t vid, uint8_t pbits, uint8_t dir)
-{
-    uint16_t ety  = 0;
-    uint16_t vlan = 0;
-    uint8_t *fieldp;
-
-    if (MV_CUST_FLOW_DIR_US == dir)
-        fieldp = data + ETH_ALEN + ETH_ALEN;
-    else if (MV_CUST_FLOW_DIR_DS == dir)
-        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
-
-    /* If not need to modify VID or P-bits */
-    if((vid == MV_CUST_VID_NOT_CARE_VALUE) &&
-       (pbits == MV_CUST_PBITS_NOT_CARE_VALUE))
-        return (1);
-
-    /* Loop through VLAN tags */
-    ety = ntohs(*(uint16_t *)fieldp);
-    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
-        fieldp += 2;
-
-        vlan = ntohs(*(uint16_t *)fieldp);
-
-        if (vid < MV_CUST_VID_NOT_CARE_VALUE)
-            vlan = (vlan & 0xf000) | (vid & 0xfff);
-        if (pbits < MV_CUST_PBITS_NOT_CARE_VALUE)
-            vlan = (vlan & 0x0fff) | ((pbits & 0x7) << 13);
-
-        *(uint16_t *)fieldp = htons(vlan);
-        return(1);
-    }
-    else {
-        return(0);
-    }
-
-    return(0);
-}
-
-#endif
-
-void mv_cust_rec_skb(int port, struct sk_buff *skb)
-{
-    uint32_t rx_status;
-    struct eth_port *pp;
-
-    rx_status = netif_receive_skb(skb);
-    pp = mv_eth_port_by_id(port);
-    STAT_DBG(if (rx_status) (pp->stats.rx_drop_sw++));
-}
-
-
-static int mv_cust_omci_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
-{
-    uint32_t rx_bytes;
-
-    if (!mv_cust_omci_gem_parse(skb->data))
-        return 0;
-    if (mv_cust_xpon_oam_rx_gh) {
-        rx_bytes = rx_desc->dataSize;
-    }
-    else {
-        skb->data += MV_ETH_MH_SIZE;
-        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
-    }
-    skb->tail += rx_bytes;
-    skb->len = rx_bytes;
-    skb->protocol = eth_type_trans(skb, dev);
-    skb->protocol = mv_cust_xpon_oam_type;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-    skb->dev = dev;
-#endif
-    mv_cust_rec_skb(port, skb);
-
-    return 1;
-}
-
-static int mv_cust_epon_oam_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
-{
-    uint32_t rx_bytes;
-
-    if (!mv_cust_eoam_type_parse(skb->data))
-        return 0;
-
-    if (mv_cust_xpon_oam_rx_gh) {
-        rx_bytes = rx_desc->dataSize;
-    }
-    else {
-        skb->data += MV_ETH_MH_SIZE;
-        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
-    }
-
-    skb->tail += rx_bytes;
-    skb->len = rx_bytes;
-    skb->protocol = eth_type_trans(skb, dev);
-    skb->protocol = mv_cust_xpon_oam_type;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-    skb->dev = dev;
-#endif
-    mv_cust_rec_skb(port, skb);
-
-    return 1;
-}
-
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-static int mv_cust_igmp_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
-{
-    uint32_t rx_bytes;
-
-    if (!mv_cust_igmp_parse(skb->data))
-        return 0;
-
-    /* To Indicate the source GMAC */
-    skb->data[0] = port;
-
-    rx_bytes = rx_desc->dataSize;
-
-    skb->tail += rx_bytes;
-    skb->len = rx_bytes;
-    skb->protocol = eth_type_trans(skb, dev);
-    skb->protocol = mv_cust_igmp_type;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-    skb->dev = dev;
-#endif
-    mv_cust_rec_skb(port, skb);
-
-    return 1;
-}
-#endif
-
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-static int mv_cust_flow_map_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
-{
-    uint32_t rx_bytes;
-    uint16_t vlan        = 0;
-    uint8_t  pbits       = 0;
-    int      btag        = 0;
-    int      ret         = 0;
-    mv_cust_ioctl_flow_map_t cust_flow;
-
-    if (MV_PON_PORT_ID != port)
-        return 0;
-
-    if (mv_cust_flow_map) {
-
-        /* Parse packets to check whether it is tagged or untagged, and get vlan and pbits in tagged mode */
-        btag = mv_cust_flow_map_parse(skb->data, &vlan, &pbits, MV_CUST_FLOW_DIR_DS);
-        //printk(KERN_ERR " %s TX packet 1 btag[%d] vlan[%d]  pbits[%d]\n", __func__, btag, vlan, pbits);
-
-        /* The frame is tagged */
-        if (btag == 1) {
-            cust_flow.vid    = vlan;
-            cust_flow.pbits  = pbits;
-            cust_flow.dir    = MV_CUST_FLOW_DIR_DS;
-
-            ret = mv_cust_tag_map_rule_get(&cust_flow);
-            //printk(KERN_ERR " %s TX packet 2 trg_port[%d] trg_queue[%d]  gem_port[%d]\n", __func__, pkt_fwd.trg_port, pkt_fwd.trg_queue, pkt_fwd.gem_port);
-
-            /* Modify VID and P-bits if needed */
-            if (ret == MV_CUST_OK) {
-
-                /* modify VID and P-bits if needed */
-                ret = mv_cust_flow_map_mod(skb->data, cust_flow.mod_vid, cust_flow.mod_pbits, MV_CUST_FLOW_DIR_DS);
-            }
-        }
-    }
-
-    return 1;
-}
-#endif
-
-static int mv_cust_loopdet_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
-{
-    uint32_t rx_bytes;
-
-    if (!mv_cust_loopdet_parse(skb->data))
-        return 0;
-
-    rx_bytes = rx_desc->dataSize;
-
-    skb->tail += rx_bytes;
-    skb->len = rx_bytes;
-    skb->protocol = eth_type_trans(skb, dev);
-    skb->protocol = mv_cust_loopdet_type;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-    skb->dev = dev;
-#endif
-    mv_cust_rec_skb(port, skb);
+EXPORT_SYMBOL(mv_cust_print);
 
-    return 1;
-}
 
 void mv_cust_rx_func(int port, int rxq, struct net_device *dev,
                      struct sk_buff *skb, struct neta_rx_desc *rx_desc)
@@ -1112,7 +1285,7 @@
 
     if (rx_desc->pncInfo & NETA_PNC_RX_SPECIAL)
     {
-        if (mv_cust_omci_valid) {
+        if (gCustConfig[MV_CUST_APP_TYPE_OMCI].enable == MV_CUST_APP_ENABLE) {
             if (mv_cust_omci_rx(port, dev, skb, rx_desc)) {
                 if(mv_cust_debug_code)
                     printk("%s omci_packet\n", __func__);
@@ -1120,7 +1293,7 @@
             }
         }
         else{
-            if (mv_cust_eoam_valid) {
+            if (gCustConfig[MV_CUST_APP_TYPE_OAM].enable == MV_CUST_APP_ENABLE) {
                 if (mv_cust_epon_oam_rx(port, dev, skb, rx_desc)) {
                     if (mv_cust_debug_code)
                         printk("%s eoam_packet\n", __func__);
@@ -1130,7 +1303,7 @@
         }
 
 #ifdef CONFIG_MV_CUST_IGMP_HANDLE
-        if (mv_cust_igmp_detect) {
+        if (gCustConfig[MV_CUST_APP_TYPE_IGMP].enable == MV_CUST_APP_ENABLE) {
             if (mv_cust_igmp_rx(port, dev, skb, rx_desc)) {
                 if(mv_cust_debug_code)
                     printk("%s igmp_packet\n", __func__);
@@ -1139,15 +1312,27 @@
         }
 #endif
 
-        if (mv_cust_port_loopback_detect) {
+#ifdef CONFIG_MV_CUST_MLD_HANDLE
+        if (gCustConfig[MV_CUST_APP_TYPE_MLD].enable == MV_CUST_APP_ENABLE) {
+            if (mv_cust_mld_rx(port, dev, skb, rx_desc)) {
+                if(mv_cust_debug_code)
+                    printk("%s mld_packet\n", __func__);
+                return;
+            }
+        }
+#endif
+
+#ifdef CONFIG_MV_CUST_LPBK_DETECT_HANDLE
+        if (gCustConfig[MV_CUST_APP_TYPE_LPBK].enable == MV_CUST_APP_ENABLE) {
             if (mv_cust_loopdet_rx(port, dev, skb, rx_desc)) {
                 if(mv_cust_debug_code)
                     printk("%s loop_det_packet\n", __func__);
                 return;
             }
         }
+#endif
 
-        MVCUST_ERR_PRINT("Special pkt arrived from port(%d), was not handled. \n", port);
+        //MVCUST_ERR_PRINT("Special pkt arrived from port(%d), was not handled. \n", port);
         dev_kfree_skb_any(skb);
         if(mv_cust_debug_code) {
             printk("Input Packet first bytes:\n");
@@ -1175,6 +1360,7 @@
     return;
 }
 
+
 int mv_cust_tx_func(int port, struct net_device *dev, struct sk_buff *skb,
                     struct mv_eth_tx_spec *tx_spec_out)
 {
@@ -1183,14 +1369,24 @@
 
     if (mv_cust_eoam_tx(port, dev, skb, tx_spec_out))
         return 1;
-
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-    if (mv_cust_flow_map_tx(port, dev, skb, tx_spec_out))
+    
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+    if (mv_cust_igmp_tx(port, dev, skb, tx_spec_out))
         return 1;
 #endif
 
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-    if (mv_cust_igmp_tx(port, dev, skb, tx_spec_out))
+#ifdef CONFIG_MV_CUST_MLD_HANDLE
+    if (mv_cust_mld_tx(port, dev, skb, tx_spec_out))
+        return 1;
+#endif
+
+#ifdef CONFIG_MV_CUST_LPBK_DETECT_HANDLE
+    if (mv_cust_loopdet_tx(port, dev, skb, tx_spec_out))
+        return 1;
+#endif
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    if (mv_cust_flow_map_tx(port, dev, skb, tx_spec_out))
         return 1;
 #endif
 
@@ -1204,6 +1400,7 @@
     return 0;
 }
 
+
 int mvcust_netdev_init(void)
 {
     uint32_t port_i;
@@ -1215,16 +1412,16 @@
         mv_eth_ports_num = CONFIG_MV_ETH_PORTS_NUM;
 
     mv_cust_eoam_init();
+    
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+    mv_cust_udp_table_del();
+#endif
 
 /* Initialize flow mapping data structure */
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
     mv_cust_flow_map_init();
 #endif
 
-#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
-    mv_cust_udp_table_del();
-#endif
-
     /* Register special receive check function */
 #ifdef CONFIG_MV_ETH_RX_SPECIAL
     for (port_i=0;port_i< mv_eth_ports_num;port_i++) {
@@ -1240,13 +1437,5 @@
     }
 #endif /* CONFIG_MV_ETH_TX_SPECIAL */
 
-    /* Set global constants */
-    mv_cust_xpon_oam_type = htons(0xBABA);
-
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-    mv_cust_igmp_type     = htons(0xA000);
-#endif
-    mv_cust_loopdet_type  = htons(0xA0A0);
-
     return 0;
 }
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h
index ac34927..4079631 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h
@@ -48,21 +48,45 @@
 
 
 struct mv_udp_port_tx_spec {
-	__be16	udp_port;
-	struct mv_eth_tx_spec tx_spec;
+    __be16    udp_port;
+    struct mv_eth_tx_spec tx_spec;
 };
 
 struct mv_port_tx_spec {
-	struct mv_udp_port_tx_spec udp_src[MV_CUST_MAS_UDP_SRC_PORT];
-	struct mv_udp_port_tx_spec udp_dst[MV_CUST_MAS_UDP_DST_PORT];
+    struct mv_udp_port_tx_spec udp_src[MV_CUST_MAS_UDP_SRC_PORT];
+    struct mv_udp_port_tx_spec udp_dst[MV_CUST_MAS_UDP_DST_PORT];
 };
 
 
 struct mv_eoam_llid_spec {
-	uint8_t llid_mac_address[6];
-	struct  mv_eth_tx_spec tx_spec;
+    uint8_t llid_mac_address[6];
+    struct  mv_eth_tx_spec tx_spec;
 };
 
+typedef enum
+{
+    MV_CUST_APP_TYPE_IGMP = 0, /* For IGMP application               */
+    MV_CUST_APP_TYPE_MLD,      /* For MLD application                */
+    MV_CUST_APP_TYPE_LPBK,     /* For loopback detection application */
+    MV_CUST_APP_TYPE_OAM,      /* For eOAM application               */
+    MV_CUST_APP_TYPE_OMCI,     /* For OMCI application               */
+    MV_CUST_APP_TYPE_MAX       /* Max number of application          */ 
+} mv_cust_app_type_e;
+
+/*  Enum: enable or disable application*/
+typedef enum
+{
+    MV_CUST_APP_DISABLE  = 0,
+    MV_CUST_APP_ENABLE   = 1,
+} mv_cust_app_flag_e;
+
+typedef struct
+{
+    mv_cust_app_type_e app_type; /* Application type, such as IGMP, MLD                */
+    uint16_t           enable;   /* Flag indicates whether to enable application Rx/Tx */         
+    uint16_t           eth_type; /* Application Ethernet type used for socket/skb      */
+    char              *name;     /* The readable name of the application               */
+} mv_cust_app_config_t;
 
 
 /******************************************************
@@ -70,27 +94,19 @@
 *******************************************************/
 void        mv_cust_omci_hw_cmd_set(unsigned int hw_cmd);
 int         mv_cust_omci_tx_set(int tcont, int txq);
-//int         mv_cust_eoam_tx_set(int txp, int txq);
-MV_STATUS   mv_cust_omci_enable(int enable);
-MV_STATUS   mv_cust_eoam_enable(int enable);
-//MV_STATUS   mv_cust_eoam_tx_func_set(void (*tx_func) (uint8_t *data, int size, struct mv_eth_tx_spec *tx_spec));
+
 #ifdef  CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
 MV_STATUS   mv_cust_udp_src_spec_set(int tx_port, uint16_t udp_src_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd);
 MV_STATUS   mv_cust_udp_dest_spec_set(int tx_port, uint16_t udp_dest_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd);
 #endif
-void        mv_cust_omci_type_set(unsigned short int type);
-void        mv_cust_xpon_oam_rx_gh_set(int val);
-void        mv_cust_epon_oam_type_set(unsigned short int type);
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-void        mv_cust_igmp_type_set(unsigned short int type);
-#endif
-void        mv_cust_omci_gemport_set(int gemport);
-void        mv_cust_loopdet_type_set(unsigned short int type);
+
+void        mv_cust_oam_rx_gh_set(int val);
 int         mv_cust_omci_set(int tcont, int txq, int gemport, int keep_rx_mh);
 int         mv_cust_eoam_llid_set(int llid, uint8_t *llid_mac, int txq);
 
-
-
+void        mv_cust_app_flag_set(mv_cust_app_type_e app_type, uint16_t enable);
+void        mv_cust_app_etype_set(mv_cust_app_type_e app_type, uint16_t eth_type);
+void        mv_cust_print(int type);
 
 
 #endif /* __mv_cust_netdev_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c
index 395c59c..3c50c88 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c
@@ -52,34 +52,31 @@
 static ssize_t mv_cust_spec_proc_help(char *buf)
 {
     int off = 0;
-    off += sprintf(buf+off, "cat help                               - show this help\n");
-    off += sprintf(buf+off, "cat omci                               - show OMCI configuration\n");
-    off += sprintf(buf+off, "cat eoam                               - show eoam configuration\n");
-    off += sprintf(buf+off, "cat loopdet                            - show loop detect configuration\n");
-    off += sprintf(buf+off, "cat udp_ports                          - show special udp source and dest. port configuration\n");
-#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
-    off += sprintf(buf+off, "cat flow_map                           - show flow mapping configuration\n");        
-    off += sprintf(buf+off, "cat flow_map_show                      - show flow mapping rules \n");    
-    off += sprintf(buf+off, "cat flow_map_clear                     - clear all flow mapping rules\n");
-    off += sprintf(buf+off, "cat dscp_map_del                       - delete DSCP to P-bits mapping rules\n");    
+    off += sprintf(buf+off, "cat  help                              - show this help\n");
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE    
+    off += sprintf(buf+off, "cat  udp_ports                         - show special udp source and dest. port configuration\n");
 #endif
-    off += sprintf(buf+off, "cat igmp                               - show igmp configuration\n");
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    off += sprintf(buf+off, "cat  flow_map                          - show flow mapping configuration\n");        
+    off += sprintf(buf+off, "cat  flow_map_show                     - show flow mapping rules \n");    
+    off += sprintf(buf+off, "cat  flow_map_clear                    - clear all flow mapping rules\n");
+    off += sprintf(buf+off, "cat  dscp_map_del                      - delete DSCP to P-bits mapping rules\n");    
+#endif
+    off += sprintf(buf+off, "cat  tcont_show                        - Show all T-CONT state\n");
+    off += sprintf(buf+off, "echo tcont state        > tcont_set    - Set T-CONT tatus, tcont(0~7), state(1:enable, 0:disable) \n");
     off += sprintf(buf+off, "echo hex                > debug        - Set Customized module debug information \n");
-    off += sprintf(buf+off, "echo hex                > omci_type    - Set OMCI ethertype\n");
+    off += sprintf(buf+off, "echo app_type           > app_show     - Show application configuration. 0:igmp, 1:mld, 2:lpbk, 3:eoam, 4:omci\n");
+    off += sprintf(buf+off, "echo app_type enable    > app_flag_set - Enable/disable application. 0:igmp, 1:mld, 2:lpbk, 3:eoam, 4:omci, 1:enable, 0:disable\n");
+    off += sprintf(buf+off, "echo app_type hex       > app_etype_set- Set application Eth type. 0:igmp, 1:mld, 2:lpbk, 3:eoam, 4:omci\n");
     off += sprintf(buf+off, "echo tc txq gem keep_mh > omci_set     - set udp source port special Tx behavior\n");
-    off += sprintf(buf+off, "echo hex                > omci_ena     - Disable/Enable OMCI packet detection\n");
-    //off += sprintf(buf+off, "echo txp txq > omci_txq      - set T-CONT and TX queue for outgoing OMCI packet\n");
-    //off += sprintf(buf+off, "echo hex     > omci_cmd      - 4B of tx desc offset 0xc\n");
-    //off += sprintf(buf+off, "echo hex     > omci_gemp     - gemportid to detect OMCI packets\n");
-    off += sprintf(buf+off, "echo hex                > eoam_type    - Set EPON EOAM ethertype\n");
+    off += sprintf(buf+off, "echo keep_mh            > eoam_gh_keep - Keep or not keep GH for eOAM packets, 1:keep, 0:do not keep\n");    
     off += sprintf(buf+off, "echo txq                > eoam_txq     - set TX queue into sw_buffer for EOAM llid command\n");
     off += sprintf(buf+off, "echo mac[0]-mac[5]      > eoam_mac     - set LLID mac into sw_buffer for EOAM llid command\n");
     off += sprintf(buf+off, "echo llid               > eoam_write   - Write EOAM txq and mac address from sw_buffer into LLID\n");
-    off += sprintf(buf+off, "echo hex                > eoam_enable  - Disable/Enable eOAM packet detection\n");
-    //off += sprintf(buf+off, "echo hex                > igmp_type    - Set IGMP ethertype\n");
-    off += sprintf(buf+off, "echo hex                > loopdet_type - Set Port Loopback Detect ethertype\n");
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE    
     off += sprintf(buf+off, "echo p udp_src(dec) txp txq flags hw_cmd  > udp_src - set udp source port special Tx behavior\n");
     off += sprintf(buf+off, "echo p udp_dst(dec) txp txq flags hw_cmd  > udp_dst - set udp dest.  port special Tx behavior\n");
+#endif    
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
     off += sprintf(buf+off, "echo hex                                  > flow_map_debug  - Set flow mapping debug flag, 1:enable, 0:disable \n");    
     off += sprintf(buf+off, "echo vid pbits mod_vid mod_pbits trg_port trg_queue trg_hwf_queue gem_port  > flow_map_us_set - set U/S flow mapping rule\n");
@@ -97,8 +94,10 @@
 static ssize_t mv_cust_spec_proc_show(struct device *dev,
                                       struct device_attribute *attr, char *buf)
 {
-    int off = 0;
-    const char*     name = attr->attr.name;
+    int off   = 0;
+    int index = 0;
+    bool state;
+    const char* name = attr->attr.name;
 
     if (!capable(CAP_NET_ADMIN))
         return -EPERM;
@@ -106,30 +105,11 @@
     if (!strcmp(name, "help") ) {
         off = mv_cust_spec_proc_help(buf);
     }
-    else if (!strcmp(name, "omci")) {
-        mv_cust_omci_print();
-    }
-    else if (!strcmp(name, "eoam")) {
-        mv_cust_eoam_print();
-    }
-    else if (!strcmp(name, "igmp")) {
-#ifdef CONFIG_MV_CUST_IGMP_HANDLE
-        mv_cust_igmp_print();
-#else
-        printk("mv_cust module was not compiled with IGMP Support\n");
-#endif
-
-    }
-    else if (!strcmp(name, "loopdet")) {
-        mv_cust_loopdet_print();
-    }
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE       
     else if (!strcmp(name, "udp_ports")) {
-#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
         mv_cust_udp_spec_print_all();
-#else
-        printk("mv_cust module was not compiled with UDP SAMPLE Config Support\n");
-#endif
     }
+#endif    
 #ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE       
     else if (!strcmp(name, "flow_map")) { 
         mv_cust_flow_map_print();
@@ -143,7 +123,17 @@
     else if (!strcmp(name, "dscp_map_del")) {
         mv_cust_dscp_map_del();
     }     
-#endif    
+#endif
+    else if (!strcmp(name, "tcont_show")) {
+        printk(KERN_INFO "MV_CUST T-CONT state table\n");
+        printk(KERN_INFO "Default invalid Txq:%d \n", CPH_INVALID_TRGT_QUEUE);
+        printk(KERN_INFO "--------------------------\n");
+        for (index = 0; index < CPH_MAX_TCONT_NUM; index++)
+        {
+            state = mv_cust_get_tcont_state(index);
+            printk(KERN_INFO "T-CONT%1.1d: %s\n", index, (state==true)?"enabled":"disabled");
+        }
+    } 
     else
         off = mv_cust_spec_proc_help(buf);
 
@@ -151,7 +141,6 @@
 }
 
 
-
 static ssize_t mv_cust_spec_proc_1_store(struct device *dev,
                                          struct device_attribute *attr,
                                          const char *buf, size_t len)
@@ -167,51 +156,24 @@
     v = 0;
 
     sscanf(buf, "%x", &v);
-
+    
     raw_local_irq_save(flags);
 
     if (!strcmp(name, "debug")) {
         mv_cust_debug_info_set(v);
     }
-    else if (!strcmp(name, "omci_type")) {
-        mv_cust_omci_type_set(v);
+    else if (!strcmp(name, "app_show")) {
+        mv_cust_print(v);
     }
-    else if (!strcmp(name, "eoam_type")) {
-        mv_cust_epon_oam_type_set(v);
-    }
+    else if (!strcmp(name, "eoam_gh_keep")) {
+        mv_cust_oam_rx_gh_set(v);
+    }   
     else if (!strcmp(name, "eoam_txq")) {
         eoam_txq = v;
     }
     else if (!strcmp(name, "eoam_write")) {
         mv_cust_eoam_llid_set((int)v, &eoam_mac[0], eoam_txq);
     }
-    /*
-    else if (!strcmp(name, "omci_cmd")) {
-        mv_cust_omci_hw_cmd_set(v);
-    }
-    */
-    /*
-    else if (!strcmp(name, "omci_gemp")) {
-        mv_cust_omci_gemport_set(v);
-    }
-    */
-    /*
-    else if (!strcmp(name, "omci_gh_keep")) {
-        mv_cust_xpon_oam_rx_gh_set(v);
-    }
-    */
-    else if (!strcmp(name, "eoam_gh_keep")) {
-        mv_cust_xpon_oam_rx_gh_set(v);
-    }
-    else if (!strcmp(name, "loopdet_type")) {
-        mv_cust_loopdet_type_set(v);
-    }
-    else if (!strcmp(name, "omci_enable")) {
-        mv_cust_omci_enable(v);
-    }
-    else if (!strcmp(name, "eoam_enable")) {
-        mv_cust_eoam_enable(v);
-    }
     else
         printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
 
@@ -220,7 +182,7 @@
     return len;
 }
 
-#if 0
+
 static ssize_t mv_cust_spec_proc_2_store(struct device *dev,
                                          struct device_attribute *attr,
                                          const char *buf, size_t len)
@@ -233,20 +195,24 @@
         return -EPERM;
 
     /* Read input */
+    p = 0;
     v = 0;
     sscanf(buf, "%d %x", &p, &v);
 
     raw_local_irq_save(flags);
-    /*
-    if (!strcmp(name, "omci_txq")) {
-        mv_cust_omci_tx_set(p, v);
+
+    if (!strcmp(name, "app_flag_set")) {
+        mv_cust_app_flag_set(p, v);
     }
-    */
-    /*
-    else if (!strcmp(name, "eoam_txq")) {
-        mv_cust_eoam_tx_set(p, v);
+    else if (!strcmp(name, "app_etype_set")) {
+        mv_cust_app_etype_set(p, v);
     }
-    */
+    else if (!strcmp(name, "tcont_set")) {
+        if (v)
+            mv_cust_set_tcont_state(p, true);
+        else
+            mv_cust_set_tcont_state(p, false);
+    }    
     else
         printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
 
@@ -254,7 +220,6 @@
 
     return len;
 }
-#endif
 
 
 static ssize_t mv_cust_spec_proc_6_store(struct device *dev,
@@ -447,61 +412,53 @@
     return len;
 }
 
+static DEVICE_ATTR(help,           S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(debug,          S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-//static DEVICE_ATTR(omci_cmd,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-//static DEVICE_ATTR(omci_gemp,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-static DEVICE_ATTR(omci_type,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-//static DEVICE_ATTR(omci_gh_keep,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-static DEVICE_ATTR(loopdet_type,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-static DEVICE_ATTR(omci_ena,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+
 static DEVICE_ATTR(omci_set,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
-static DEVICE_ATTR(eoam_enable,    S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-static DEVICE_ATTR(eoam_type,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
 static DEVICE_ATTR(eoam_gh_keep,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-//static DEVICE_ATTR(omci_txq,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_2_store);
 static DEVICE_ATTR(eoam_txq,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
-static DEVICE_ATTR(eoam_write,     S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
 static DEVICE_ATTR(eoam_mac,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6h_store);
+static DEVICE_ATTR(eoam_write,     S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+
+static DEVICE_ATTR(tcont_show,     S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(tcont_set,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_2_store);
+
+static DEVICE_ATTR(app_show,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(app_flag_set,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_2_store);
+static DEVICE_ATTR(app_etype_set,  S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_2_store);
+
+static DEVICE_ATTR(udp_ports,      S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(udp_src,        S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
 static DEVICE_ATTR(udp_dst,        S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
-static DEVICE_ATTR(flow_map_debug, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
-static DEVICE_ATTR(flow_map_us_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
-static DEVICE_ATTR(flow_map_ds_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
 
-static DEVICE_ATTR(dscp_map_set,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_64_store);
-static DEVICE_ATTR(flow_map_del,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
-static DEVICE_ATTR(tag_flow_get,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
-static DEVICE_ATTR(untag_flow_get, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
-static DEVICE_ATTR(omci,           S_IRUSR, mv_cust_spec_proc_show, NULL);
-static DEVICE_ATTR(eoam,           S_IRUSR, mv_cust_spec_proc_show, NULL);
-static DEVICE_ATTR(igmp,           S_IRUSR, mv_cust_spec_proc_show, NULL);
-static DEVICE_ATTR(loopdet,        S_IRUSR, mv_cust_spec_proc_show, NULL);
-static DEVICE_ATTR(udp_ports,      S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(flow_map,       S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(flow_map_show,  S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(flow_map_clear, S_IRUSR, mv_cust_spec_proc_show, NULL);
 static DEVICE_ATTR(dscp_map_del,   S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(flow_map_debug, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(flow_map_us_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(flow_map_ds_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(flow_map_del,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(tag_flow_get,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(untag_flow_get, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(dscp_map_set,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_64_store);
 
 
-
-static DEVICE_ATTR(help,         S_IRUSR, mv_cust_spec_proc_show, NULL);
-
 static struct attribute *mv_cust_spec_proc_attrs[] = {
+    &dev_attr_help.attr,    
     &dev_attr_debug.attr,
-    //&dev_attr_omci_cmd.attr,
-    //&dev_attr_omci_gemp.attr,
-    &dev_attr_omci_type.attr,
-    //&dev_attr_omci_gh_keep.attr,
-    //&dev_attr_omci_txq.attr,
-    &dev_attr_omci_ena.attr,
     &dev_attr_omci_set.attr,
-    &dev_attr_eoam_type.attr,
     &dev_attr_eoam_gh_keep.attr,
-    &dev_attr_eoam_enable.attr,
     &dev_attr_eoam_txq.attr,
-    &dev_attr_eoam_write.attr,
     &dev_attr_eoam_mac.attr,
-    &dev_attr_loopdet_type.attr,
+    &dev_attr_eoam_write.attr,
+    &dev_attr_tcont_show.attr,
+    &dev_attr_tcont_set.attr,    
+    &dev_attr_app_show.attr,
+    &dev_attr_app_flag_set.attr,
+    &dev_attr_app_etype_set.attr,   
+    &dev_attr_udp_ports.attr,    
     &dev_attr_udp_src.attr,
     &dev_attr_udp_dst.attr,
     &dev_attr_flow_map_debug.attr,
@@ -510,17 +467,12 @@
     &dev_attr_dscp_map_set.attr,
     &dev_attr_flow_map_del.attr,
     &dev_attr_tag_flow_get.attr,
-    &dev_attr_untag_flow_get.attr,    
-    &dev_attr_omci.attr,
-    &dev_attr_eoam.attr,
-    &dev_attr_igmp.attr,
-    &dev_attr_loopdet.attr,
-    &dev_attr_udp_ports.attr,
+    &dev_attr_untag_flow_get.attr,
     &dev_attr_flow_map.attr,    
     &dev_attr_flow_map_show.attr,     
     &dev_attr_flow_map_clear.attr,   
     &dev_attr_dscp_map_del.attr,       
-    &dev_attr_help.attr,
+
     NULL
 };
 
@@ -571,4 +523,3 @@
 
     printk(KERN_INFO "= CUST Module SYS FS Remove ended successfully =\n");
 }
-
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h
index 9f1d9ac..11ccdc9 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h
@@ -37,6 +37,10 @@
 #define MAC_LEARN_OK 0
 #define MAC_LEARN_FAIL 1
 
+/* CPU rate limit related*/
+#define MAC_LEARN_RATE_LIMIT 128
+#define MAC_LEARN_BUCKET_SIZE 2000
+
 /* Function protype
 ------------------------------------------------------------------------------*/
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c
index b911039..0d1e236 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c
@@ -121,10 +121,11 @@
 	uint32_t i;
 
 	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
-		/*Get spin lock*/
-		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
 		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid &&
 		    MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state) {
+			/*Get spin lock*/
+			spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+
 			memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
 			memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
 			memcpy(del_mac_key.mac.mac_sa, mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
@@ -142,12 +143,15 @@
 
 				return MAC_LEARN_FDB_FAIL;
 			}
-		}
-		/* Release spin lock */
-		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
-		if (mac_learn_db_pncidx_update(0, pnc_idx)) {
-			MVMACLEARN_ERR_PRINT("TPM PNC index update failed(%d)\n", i);
-			return MAC_LEARN_FDB_FAIL;
+
+			/* Release spin lock */
+			spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+
+			/* Update PnC index */
+			if (mac_learn_db_pncidx_update(0, pnc_idx)) {
+				MVMACLEARN_ERR_PRINT("TPM PNC index update failed(%d)\n", i);
+				return MAC_LEARN_FDB_FAIL;
+			}
 		}
 	}
 
@@ -285,8 +289,10 @@
 			if (!memcmp(src_mac_key->mac.mac_sa, mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE)) {
 				if (addr_exist)
 					*addr_exist = 1;
-				if (mac_learn_db_entry)
+				if (mac_learn_db_entry) {
 					memcpy(mac_learn_db_entry, &mac_learn_fdb.mac_learn_db_entry[i], sizeof(mac_learn_db_entry_t));
+					mac_learn_db_entry->fdb_idx = i;
+				}
 				/* Release spin lock */
 				spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
 				break;
@@ -545,6 +551,39 @@
 	printk("+--------------+---------------------+--------------+\n");
 }
 
+/************************************************************************************
+* mac_learn_db_entry_state_update
+* Update entry state of an existing entry
+* input:
+*	fdb_idx: FDB entry index
+*	entry_state: FDB entry state
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_entry_state_update(uint32_t fdb_idx, uint8_t entry_state)
+{
+	/* Para check */
+	if (fdb_idx >= MAC_LEARN_FDB_MAX_COUNT) {
+		MVMACLEARN_ERR_PRINT("MAC learn FDB entry index(%d) invalid\n", fdb_idx);
+		return MAC_LEARN_FDB_FAIL;
+	}
+
+	if ((MAC_LEARN_FDB_STATIC != entry_state) && (MAC_LEARN_FDB_NON_STATIC != entry_state)) {
+		MVMACLEARN_ERR_PRINT("MAC learn FDB entry state(%d) invalid\n", entry_state);
+		return MAC_LEARN_FDB_FAIL;
+	}
+
+	/* Get spin lock */
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	/* Update to expected state */
+	mac_learn_fdb.mac_learn_db_entry[fdb_idx].state = entry_state;
+	/* Release spin lock */
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+
+	return MAC_LEARN_FDB_OK;
+}
+
 /***************************************************************************************************************
 * mac_learn_fdb_init()
 *
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h
index 6f31b92..a650602 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h
@@ -51,6 +51,7 @@
 /* Typedefs
 ------------------------------------------------------------------------------*/
 typedef struct {
+	uint32_t fdb_idx;
 	uint8_t valid;
 	uint8_t state;
 	uint8_t port;
@@ -88,6 +89,7 @@
 void mac_learn_db_nonstatic_count_dec(void);
 int32_t mac_learn_db_nonstatic_count_get(uint32_t *nonstatic_ount);
 void mac_learn_db_valid_print(void);
+int32_t mac_learn_db_entry_state_update(uint32_t fdb_idx, uint8_t entry_state);
 int32_t mac_learn_fdb_init(void);
 
 #endif
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c
index 0685b5a..e86f910 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c
@@ -153,7 +153,7 @@
 	uint32_t i;
 	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
 	uint32_t pnc_idx, read_count,hit_count = 0;
-	uint32_t fdb_valid_count;
+	uint32_t fdb_nonstatic_valid_count;
 	tpm_l2_acl_key_t del_mac_key;
 	mac_learn_db_entry_t mac_learn_db_entry;
 	tpm_db_pnc_range_conf_t range_conf;
@@ -197,9 +197,9 @@
 						} else {
 							/* dec non static entry count */
 							mac_learn_db_nonstatic_count_dec();
-							mac_learn_db_valid_count_get(&fdb_valid_count);
+							mac_learn_db_nonstatic_count_get(&fdb_nonstatic_valid_count);
 							/* start MAC learn again */
-							if ((mac_learn_age->mac_learn_max_count - fdb_valid_count == 1) &&
+							if ((mac_learn_age->mac_learn_max_count - fdb_nonstatic_valid_count == 1) &&
 							    (false == mac_learn_age->mac_learn_overwrite_enable)) {
 								/* Trap packet with new address to CPU again */
 								if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
@@ -257,7 +257,16 @@
 		return;
 	}
 
+	/* Check non-static max count, if 0 just return */
+	if (src_mac->mac_learn_max_count == 0) {
+		/* Read buffer, in order to clear it to avoid bad effection for following MAC learn */
+		mv_mac_learn_queue_read(src_mac_key.mac.mac_sa);
+		return;
+	}
+
 	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		/* Read buffer, in order to clear it to avoid bad effection for following MAC learn */
+		mv_mac_learn_queue_read(src_mac_key.mac.mac_sa);
 		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
 		return;
 	}
@@ -285,11 +294,6 @@
 	/* Check non-static Full or not */
 	if (src_mac->mac_learn_max_count == nonstatic_count) {
 		if (true == src_mac->mac_learn_overwrite_enable) {
-			/* Interval less than 0.2s, overwrite is forbidden*/
-			if (time_after(jiffies, (unsigned long)src_mac->mac_learn_overwrite_time))
-				src_mac->mac_learn_overwrite_time  = jiffies + HZ / 5;/*update overwrite time*/
-			else
-				return;/*return from here, no any operation*/
 			/* Overwrite LU entry */
 			if (!mv_mac_learn_get_lu(&pnc_idx)) {
 				MVMACLEARN_DEBUG_PRINT("PnC index need to be overwritten: %d\n", pnc_idx);
@@ -409,27 +413,43 @@
 	memset(src_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
 	memcpy(src_mac_key.mac.mac_sa, static_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
 
-	/* Check the src mac exist in FDB or not*/
-	if (mac_learn_db_find_mac_addr(&src_mac_key, &fdb_addr_exist, NULL)) {
-		MVMACLEARN_ERR_PRINT("mac_learn_db_find_mac_addr failed\n");
-		return MAC_LEARN_FAIL;
-	}
-	/* If Addr exist in FDB, return OK*/
-	if (fdb_addr_exist == 1) {
-		MVMACLEARN_WARN_PRINT("Entry already exist\n");
-		return MAC_LEARN_OK;
-	}
 	/*Get MAC learn range info*/
 	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
 		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
 		return MAC_LEARN_FAIL;
 	}
-	/*check whether static free entry enough or not*/
+	/* get entry count info */
 	pnc_max_count = range_conf.api_end - range_conf.api_start + 1;
 	if (mac_learn_db_valid_count_get(&valid_count) ||
 	    mac_learn_db_nonstatic_count_get(&non_static_count) ||
 	    mv_mac_learn_op_max_count_get(&non_static_max))
 		return MAC_LEARN_FAIL;
+
+	/* Check the src mac exist in FDB or not*/
+	if (mac_learn_db_find_mac_addr(&src_mac_key, &fdb_addr_exist, &mac_learn_db_entry)) {
+		MVMACLEARN_ERR_PRINT("mac_learn_db_find_mac_addr failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* If Addr exist in FDB, return OK*/
+	if (fdb_addr_exist == 1) {
+		if (MAC_LEARN_FDB_STATIC == mac_learn_db_entry.state) {
+			MVMACLEARN_WARN_PRINT("Entry already exist\n");
+		} else {
+			/*check whether static free entry enough or not*/
+			if ((valid_count - non_static_count) >= (pnc_max_count - non_static_max)) {
+				MVMACLEARN_ERR_PRINT("No free entry for static entry\n");
+				return MAC_LEARN_FAIL;
+			}
+			/* Update original entry state */
+			if (mac_learn_db_entry_state_update(mac_learn_db_entry.fdb_idx, MAC_LEARN_FDB_STATIC)) {
+				MVMACLEARN_ERR_PRINT("MAC learn FDB entry state update failed\n");
+				return MAC_LEARN_FAIL;
+			}
+			mac_learn_db_nonstatic_count_dec();
+		}
+		return MAC_LEARN_OK;
+	}
+	/*check whether static free entry enough or not*/
 	if ((valid_count - non_static_count) >= (pnc_max_count - non_static_max)) {
 		MVMACLEARN_ERR_PRINT("No free entry for static entry\n");
 		return MAC_LEARN_FAIL;
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c
index cd20927..26d4dd7 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c
@@ -237,6 +237,9 @@
 	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
 	tpm_db_pnc_range_conf_t range_conf;
 	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable;
+	tpm_gmacs_enum_t lpk_gmac;
+	uint32_t data_queue, mac_larn_queue;
+	uint32_t lpk_gmac_mh_en;
 
 	/*check original value and new value, if equal, return OK*/
 	if (mac_learn_enable == mc_mac_learn.mac_learn_enable)
@@ -264,6 +267,45 @@
 		else
 			mc_mac_learn.mac_learn_max_count = (range_conf.api_end - range_conf.api_start + 1) / 2;
 		MVMACLEARN_DEBUG_PRINT("non-static entry max count: %d\n",mc_mac_learn.mac_learn_max_count);
+
+		/* set PMT entry for MH modification on GMAC1 */
+		/*check data queue and mac learn queue, if equal, return error*/
+		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+							   &data_queue,
+							   TPM_GMAC1_QUEUE_DATA_TRAFFIC)) {
+			MVMACLEARN_ERR_PRINT("loopback gmac data queue get failed \n");
+			return MAC_LEARN_FAIL;
+		}
+		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+							   &mac_larn_queue,
+							   TPM_GMAC1_QUEUE_MAC_LEARN_TRAFFIC)) {
+			MVMACLEARN_ERR_PRINT("loopback gmac mac learn queue get failed \n");
+			return MAC_LEARN_FAIL;
+		}
+		if (data_queue == mac_larn_queue) {
+			MVMACLEARN_ERR_PRINT("loopback gmac Tx queue %d for data traffix and MAC learn equal\n",
+					     data_queue);
+			return MAC_LEARN_FAIL;
+		}
+		MVMACLEARN_DEBUG_PRINT("lpk gmac %d Tx queue for mac learn: %d\n", lpk_gmac, mac_larn_queue);
+
+		/* limit band width on Tx mac learn queue of lpk gmac */
+		if (mvNetaTxqBurstSet((int)lpk_gmac, 0, mac_larn_queue, MAC_LEARN_BUCKET_SIZE) ||
+		    mvNetaTxqRateSet((int)lpk_gmac, 0, mac_larn_queue, MAC_LEARN_RATE_LIMIT)) {
+			MVMACLEARN_ERR_PRINT("MAC learning CPU rate limit on queue %d failed\n", mac_larn_queue);
+			return MAC_LEARN_FAIL;
+		}
+
+		/* Check MH on lpk gmac */
+		if (tpm_db_gmac_mh_en_conf_get(lpk_gmac, &lpk_gmac_mh_en)) {
+			MVMACLEARN_ERR_PRINT("Marvell Header enable info get failed on GMAC%d\n", lpk_gmac);
+			return MAC_LEARN_FAIL;
+		}
+		if (!lpk_gmac_mh_en) {
+			MVMACLEARN_ERR_PRINT("Marvell Header is not enabled on GMAC%d\n", lpk_gmac);
+			return MAC_LEARN_FAIL;
+		}
+
 		/* Trap packet to CPU */
 		if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
 			MVMACLEARN_ERR_PRINT("TPM default rule action set failed\n");
@@ -392,7 +434,7 @@
 	tpm_db_pnc_range_conf_t range_conf;
 
 	if (true == mc_mac_learn.mac_learn_enable) {
-		MVMACLEARN_DEBUG_PRINT("Old max count: %d, New max count: %d\n", mc_mac_learn.mac_learn_enable, mac_learn_max_count);
+		MVMACLEARN_DEBUG_PRINT("Old max count: %d, New max count: %d\n", mc_mac_learn.mac_learn_max_count, mac_learn_max_count);
 		if (mac_learn_max_count < mc_mac_learn.mac_learn_max_count) {
 			if (!mac_learn_db_nonstatic_count_get(&non_static_count)) {
 				MVMACLEARN_DEBUG_PRINT("Current non-static num: %d\n", non_static_count);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c
index ad69a42..5fb0b31 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c
@@ -97,7 +97,7 @@
 
 	/* Register mac learn parse function */
 	for (port_i=0;port_i< mv_eth_ports_num;port_i++) {
-		if (port_i == 0)
+		if (port_i == 0 || port_i == 1)
 			mv_eth_rx_mac_learn_func(port_i, mv_mac_learn_eth_rx_func);
 		else
 			mv_eth_rx_mac_learn_func(port_i, NULL);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c
index 1e2e584..5831e77 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c
@@ -325,13 +325,20 @@
 	uint32_t max_count;
 	int parsedargs;
 	int numparms;
+	int temp;
 
 	numparms = sys_mac_learn_count_para(buf);
 	if (numparms != mac_learn_max_count_max) {
 		MVMACLEARN_ERR_PRINT("Parameter number not right");
 	} else {
 		/* Get parameters */
-		parsedargs = sscanf(buf, "%d", &max_count);
+		parsedargs = sscanf(buf, "%d", &temp);
+		if (temp < 0) {
+			printk(KERN_INFO "ERROR: Negative Input(%d) can not be accepted\n", temp);
+			return;
+		}
+
+		max_count = temp;
 
 		if (parsedargs != numparms) {
 			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
@@ -362,13 +369,20 @@
 	uint32_t expire_time;
 	int parsedargs;
 	int numparms;
+	int temp;
 
 	numparms = sys_mac_learn_count_para(buf);
 	if (numparms != mac_learn_expire_time_max) {
 		MVMACLEARN_ERR_PRINT("Parameter number not right");
 	} else {
 		/* Get parameters */
-		parsedargs = sscanf(buf, "%d", &expire_time);
+		parsedargs = sscanf(buf, "%d", &temp);
+		if (temp < 0) {
+			printk(KERN_INFO "ERROR: Negative Input(%d) can not be accepted\n", temp);
+			return;
+		}
+
+		expire_time = temp;
 
 		if (parsedargs != numparms) {
 			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
index 6046c62..dfc9301 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
@@ -1024,4 +1024,10 @@
 	---help---
 	If set swap of RX and TX descriptors in BE mode will be done by driver
 
+config MV_ETH_6601_LB_WA
+	bool "WA for 6601 (KW MC) w/ loopback traffic to CPU"
+	default n
+	---help---
+	If set, RX traffic to CPU from GMAC1 is switched to GMAC0 netdev (eth1)
+
 endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c
index d6edeb5..24c3868 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c
@@ -80,6 +80,7 @@
 	off += sprintf(buf+off, "echo p rxq t       > rxq_type      - set RXQ for different packet types. t=0-bpdu, 1-arp, 2-tcp, 3-udp\n");
 	off += sprintf(buf+off, "echo p             > rx_reset      - reset RX part of the port <p>\n");
 	off += sprintf(buf+off, "echo p txp         > txp_reset     - reset TX part of the port <p/txp>\n");
+	off += sprintf(buf+off, "echo p txp txq     > txq_clean     - clean TXQ <p/txp/txq> - invalidate descripotrs and free buffers\n");
 	off += sprintf(buf+off, "echo p txq tos     > txq_tos       - set <txq> for outgoing IP packets with <tos>\n");
 	off += sprintf(buf+off, "echo p txp txq cpu > txq_def       - set default <txp/txq> for packets sent to port <p> by <cpu>\n");
 	off += sprintf(buf+off, "echo p txp {0|1}   > ejp           - enable/disable EJP mode for <port/txp>\n");
@@ -392,6 +393,8 @@
 		mvNetaTxqShow(p, txp, txq, v);
 	} else if (!strcmp(name, "txq_regs")) {
 		mvNetaTxqRegs(p, txp, txq);
+	} else if (!strcmp(name, "txq_clean")) {
+		err = mv_eth_txq_clean(p, txp, txq);
 	} else {
 		err = 1;
 		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
@@ -416,6 +419,7 @@
 static DEVICE_ATTR(txq_wrr,     S_IWUSR, mv_eth_show, mv_eth_4_store);
 static DEVICE_ATTR(txq_rate,    S_IWUSR, mv_eth_show, mv_eth_4_store);
 static DEVICE_ATTR(txq_burst,   S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_clean,   S_IWUSR, mv_eth_show, mv_eth_4_store);
 static DEVICE_ATTR(txp_rate,    S_IWUSR, mv_eth_show, mv_eth_3_store);
 static DEVICE_ATTR(txp_burst,   S_IWUSR, mv_eth_show, mv_eth_3_store);
 static DEVICE_ATTR(txp_reset,   S_IWUSR, mv_eth_show, mv_eth_3_store);
@@ -470,6 +474,7 @@
 	&dev_attr_txq_wrr.attr,
 	&dev_attr_txq_rate.attr,
 	&dev_attr_txq_burst.attr,
+	&dev_attr_txq_clean.attr,
 	&dev_attr_txp_rate.attr,
 	&dev_attr_txp_burst.attr,
 	&dev_attr_txp_reset.attr,
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c
index 6d68843..86d8494 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c
@@ -638,9 +638,15 @@
 	}
 	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
 	if ((txq_ctrl->q) && (txq_ctrl->txq_size != value)) {
+		/* Reset of port/txp is required to change TXQ ring size */
+		if ((mvNetaTxqNextIndexGet(pp->port, txq_ctrl->txp, txq_ctrl->txq) != 0) ||
+			(mvNetaTxqPendDescNumGet(pp->port, txq_ctrl->txp, txq_ctrl->txq) != 0) ||
+			(mvNetaTxqSentDescNumGet(pp->port, txq_ctrl->txp, txq_ctrl->txq) != 0)) {
+			printk(KERN_ERR "%s: port=%d, txp=%d, txq=%d must be in its initial state\n",
+				__func__, port, txq_ctrl->txp, txq_ctrl->txq);
+			return -EINVAL;
+		}
 		mv_eth_txq_delete(pp, txq_ctrl);
-		/* Reset of port/txp is required when TXQ ring size is changed */
-		/* Reset done before as part of stop_internals function */
 	}
 	txq_ctrl->txq_size = value;
 
@@ -654,6 +660,12 @@
 	struct tx_queue *txq_ctrl;
 	struct eth_port *pp = mv_eth_port_by_id(port);
 
+	if (pp == NULL)
+		return -ENODEV;
+
+	if (pp == NULL)
+		return -ENODEV;
+
 	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
 	if (txq_ctrl->cpu_owner) {
 		mode = MV_ETH_TXQ_CPU;
@@ -817,11 +829,12 @@
 							struct sk_buff *skb, struct neta_rx_desc *rx_desc))
 {
 	struct eth_port *pp = mv_eth_port_by_id(port);
-	
+
 	if (pp)
 		pp->rx_special_proc = func;
 }
 #endif /* CONFIG_MV_ETH_RX_SPECIAL */
+
 #ifdef CONFIG_MV_MAC_LEARN
 /* Register mac learn parse function */
 void mv_eth_rx_mac_learn_func(int port, void (*func)(int port, int rxq, struct net_device *dev,
@@ -834,8 +847,7 @@
 }
 #endif /* CONFIG_MV_MAC_LEARN */
 
-static inline u16 mv_eth_select_txq(struct net_device *dev,
-									struct sk_buff *skb)
+static inline u16 mv_eth_select_txq(struct net_device *dev, struct sk_buff *skb)
 {
 	struct eth_port *pp = MV_ETH_PRIV(dev);
 	return mv_eth_tx_policy(pp, skb);
@@ -1232,6 +1244,121 @@
 	return skb;
 }
 
+static inline void mv_eth_txq_buf_free(struct eth_port *pp, u32 shadow)
+{
+	if (!shadow)
+		return;
+
+	if (shadow & MV_ETH_SHADOW_SKB) {
+		shadow &= ~MV_ETH_SHADOW_SKB;
+		dev_kfree_skb_any((struct sk_buff *)shadow);
+		STAT_DBG(pp->stats.tx_skb_free++);
+	} else {
+		if (shadow & MV_ETH_SHADOW_EXT) {
+			shadow &= ~MV_ETH_SHADOW_EXT;
+			mv_eth_extra_pool_put(pp, (void *)shadow);
+		} else {
+			/* packet from NFP without BM */
+			struct eth_pbuf *pkt = (struct eth_pbuf *)shadow;
+			struct bm_pool *pool = &mv_eth_pool[pkt->pool];
+
+			if (mv_eth_pool_bm(pool)) {
+				/* Refill BM pool */
+				STAT_DBG(pool->stats.bm_put++);
+				mvBmPoolPut(pkt->pool, (MV_ULONG) pkt->physAddr);
+			} else {
+				mv_eth_pool_put(pool, pkt);
+			}
+		}
+	}
+}
+
+static inline void mv_eth_txq_cpu_clean(struct eth_port *pp, struct tx_queue *txq_ctrl)
+{
+	int hw_txq_i, last_txq_i, i, count;
+	u32 shadow;
+
+	hw_txq_i = mvNetaTxqNextIndexGet(pp->port, txq_ctrl->txp, txq_ctrl->txq);
+	last_txq_i = txq_ctrl->shadow_txq_put_i;
+
+	i = hw_txq_i;
+	count = 0;
+	while (i != last_txq_i) {
+		shadow = txq_ctrl->shadow_txq[i];
+		mv_eth_txq_buf_free(pp, shadow);
+		txq_ctrl->shadow_txq[i] = (u32)NULL;
+
+		i = MV_NETA_QUEUE_NEXT_DESC(&txq_ctrl->q->queueCtrl, i);
+		count++;
+	}
+	printk(KERN_INFO "\n%s: port=%d, txp=%d, txq=%d, mode=CPU\n",
+			__func__, pp->port, txq_ctrl->txp, txq_ctrl->txq);
+	printk(KERN_INFO "Free %d buffers: from desc=%d to desc=%d, tx_count=%d\n",
+			count, hw_txq_i, last_txq_i, txq_ctrl->txq_count);
+}
+
+static inline void mv_eth_txq_hwf_clean(struct eth_port *pp, struct tx_queue *txq_ctrl, int rx_port)
+{
+	int pool, hw_txq_i, last_txq_i, i, count;
+	struct neta_tx_desc *tx_desc;
+
+	hw_txq_i = mvNetaTxqNextIndexGet(pp->port, txq_ctrl->txp, txq_ctrl->txq);
+
+	if (mvNetaHwfTxqNextIndexGet(rx_port, pp->port, txq_ctrl->txp, txq_ctrl->txq, &last_txq_i) != MV_OK) {
+		printk(KERN_ERR "%s: mvNetaHwfTxqNextIndexGet failed\n", __func__);
+		return;
+	}
+
+	i = hw_txq_i;
+	count = 0;
+	while (i != last_txq_i) {
+		tx_desc = (struct neta_tx_desc *)MV_NETA_QUEUE_DESC_PTR(&txq_ctrl->q->queueCtrl, i);
+		if (mvNetaTxqDescIsValid(tx_desc)) {
+			mvNetaTxqDescInv(tx_desc);
+			mv_eth_tx_desc_flush(tx_desc);
+
+			pool = (tx_desc->command & NETA_TX_BM_POOL_ID_ALL_MASK) >> NETA_TX_BM_POOL_ID_OFFS;
+			mvBmPoolPut(pool, (MV_ULONG)tx_desc->bufPhysAddr);
+			count++;
+		}
+		i = MV_NETA_QUEUE_NEXT_DESC(&txq_ctrl->q->queueCtrl, i);
+	}
+	printk(KERN_DEBUG "\n%s: port=%d, txp=%d, txq=%d, mode=HWF-%d\n",
+			__func__, pp->port, txq_ctrl->txp, txq_ctrl->txq, rx_port);
+	printk(KERN_DEBUG "Free %d buffers to BM pool %d: from desc=%d to desc=%d\n",
+			count, pool, hw_txq_i, last_txq_i);
+}
+
+int mv_eth_txq_clean(int port, int txp, int txq)
+{
+	int mode, rx_port;
+	struct eth_port *pp;
+	struct tx_queue *txq_ctrl;
+
+	if (mvNetaTxpCheck(port, txp))
+		return -EINVAL;
+
+	if (mvNetaMaxCheck(txq, CONFIG_MV_ETH_TXQ))
+		return -EINVAL;
+
+	pp = mv_eth_port_by_id(port);
+	if ((pp == NULL) || (pp->txq_ctrl == NULL))
+		return -ENODEV;
+
+	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+
+	mode = mv_eth_ctrl_txq_mode_get(pp->port, txq_ctrl->txp, txq_ctrl->txq, &rx_port);
+	if (mode == MV_ETH_TXQ_CPU)
+		mv_eth_txq_cpu_clean(pp, txq_ctrl);
+	else if (mode == MV_ETH_TXQ_HWF)
+		mv_eth_txq_hwf_clean(pp, txq_ctrl, rx_port);
+//	else
+// 	printk(KERN_ERR "%s: port=%d, txp=%d, txq=%d is not in use\n",
+// 		__func__, pp->port, txp, txq);
+
+	return 0;
+}
+
 static inline void mv_eth_txq_bufs_free(struct eth_port *pp, struct tx_queue *txq_ctrl, int num)
 {
 	u32 shadow;
@@ -1241,32 +1368,7 @@
 	for (i = 0; i < num; i++) {
 		shadow = txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_get_i];
 		mv_eth_shadow_inc_get(txq_ctrl);
-
-		if (!shadow)
-			continue;
-
-		if (shadow & MV_ETH_SHADOW_SKB) {
-			shadow &= ~MV_ETH_SHADOW_SKB;
-			dev_kfree_skb_any((struct sk_buff *)shadow);
-			STAT_DBG(pp->stats.tx_skb_free++);
-		} else {
-			if (shadow & MV_ETH_SHADOW_EXT) {
-				shadow &= ~MV_ETH_SHADOW_EXT;
-				mv_eth_extra_pool_put(pp, (void *)shadow);
-			} else {
-				/* packet from NFP without BM */
-				struct eth_pbuf *pkt = (struct eth_pbuf *)shadow;
-				struct bm_pool *pool = &mv_eth_pool[pkt->pool];
-
-				if (mv_eth_pool_bm(pool)) {
-					/* Refill BM pool */
-					STAT_DBG(pool->stats.bm_put++);
-					mvBmPoolPut(pkt->pool, (MV_ULONG) pkt->physAddr);
-				} else {
-					mv_eth_pool_put(pool, pkt);
-				}
-			}
-		}
+		mv_eth_txq_buf_free(pp, shadow);
 	}
 }
 
@@ -1481,6 +1583,15 @@
 		dev = pp->dev;
 #endif /* CONFIG_MV_ETH_SWITCH */
 
+#ifdef CONFIG_MV_ETH_6601_LB_WA
+		/* This workaround is for the 6601 w/ loopback.
+		   All RX traffic originating from GMAC1 is treated as if comming from GMAC0 netdev */
+		if (pp->port == 1) {
+			struct eth_port *new_pp = mv_eth_port_by_id(0);
+			dev = new_pp->dev;
+		}
+#endif
+
 		STAT_DBG(pp->stats.rxq[rxq]++);
 		dev->stats.rx_packets++;
 
@@ -1659,6 +1770,9 @@
 		tx_spec.flags = pp->flags;
 	}
 
+	if (tx_spec.txq == MV_ETH_TXQ_INVALID)
+		goto out;
+
 	txq_ctrl = &pp->txq_ctrl[tx_spec.txp * CONFIG_MV_ETH_TXQ + tx_spec.txq];
 	if (txq_ctrl == NULL) {
 		printk(KERN_ERR "%s: invalidate txp/txq (%d/%d)\n", __func__, tx_spec.txp, tx_spec.txq);
@@ -1777,7 +1891,7 @@
 #ifndef CONFIG_MV_ETH_TXDONE_ISR
 	if (txq_ctrl) {
 		if (txq_ctrl->txq_count >= mv_ctrl_txdone) {
-			STAT_DIST(u32 tx_done = )mv_eth_txq_done(pp, txq_ctrl);
+			u32 tx_done = mv_eth_txq_done(pp, txq_ctrl);
 
 			STAT_DIST((tx_done < pp->dist_stats.tx_done_dist_size) ? pp->dist_stats.tx_done_dist[tx_done]++ : 0);
 
@@ -2111,12 +2225,8 @@
 
 	mv_eth_txq_bufs_free(pp, txq_ctrl, tx_done);
 
+	txq_ctrl->txq_count -= tx_done;
 	STAT_DBG(txq_ctrl->stats.txq_txdone += tx_done);
-
-	/* reset txq */
-	txq_ctrl->txq_count = 0;
-	txq_ctrl->shadow_txq_put_i = 0;
-	txq_ctrl->shadow_txq_get_i = 0;
 }
 
 inline u32 mv_eth_tx_done_pon(struct eth_port *pp, int *tx_todo)
@@ -2586,6 +2696,10 @@
 	causeRxTx = MV_REG_READ(NETA_INTR_NEW_CAUSE_REG(pp->port)) &
 	    (MV_ETH_MISC_SUM_INTR_MASK | MV_ETH_TXDONE_INTR_MASK | MV_ETH_RX_INTR_MASK);
 
+	if ((pp->flags & MV_ETH_F_STARTED) == 0) {
+		printk(KERN_ERR "%s: port #%d is not started", __func__, pp->port);
+	}
+
 	if (causeRxTx & MV_ETH_MISC_SUM_INTR_MASK) {
 		MV_U32 causeMisc;
 
@@ -2804,7 +2918,7 @@
 			printk(KERN_ERR "\n  o Warning: GbE port %d is powered off\n\n", port);
 			continue;
 		}
-		if (!MV_PON_PORT(port) && !mvBoardIsGbEPortConnected(port)) {
+		if (!MV_PON_PORT(port) && !mvBoardIsGbEPortConnected(port) && (mvCtrlModelGet()!= MV_6601_DEV_ID)) {
 			printk(KERN_ERR "\n  o Warning: GbE port %d is not connected to PHY/RGMII/Switch, skip initialization\n\n",
 					port);
 			continue;
@@ -2842,8 +2956,8 @@
 			} else if (status == 1) {
 				/* User selected to work without Gateway driver */
 				clear_bit(MV_ETH_F_SWITCH_BIT, &(pp->flags));
-				printk(KERN_ERR "  o Working in External Switch mode\n");
 				ext_switch_port_mask = mv_switch_link_detection_init();
+				printk(KERN_ERR "  o Working in External Switch mode - switch_port_mask = 0x%x\n", ext_switch_port_mask);
 			}
 		}
 
@@ -3760,8 +3874,22 @@
 	for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++) {
 		struct tx_queue *txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + queue];
 
-		if (txq_ctrl->q)
-			mv_eth_txq_done_force(pp, txq_ctrl);
+		if (txq_ctrl->q) {
+			int mode, rx_port;
+
+			mode = mv_eth_ctrl_txq_mode_get(pp->port, txp, queue, &rx_port);
+			if (mode == MV_ETH_TXQ_CPU) {
+				/* Free all buffers in TXQ */
+				mv_eth_txq_done_force(pp, txq_ctrl);
+				/* reset txq */
+				txq_ctrl->shadow_txq_put_i = 0;
+				txq_ctrl->shadow_txq_get_i = 0;
+			} else if (mode == MV_ETH_TXQ_HWF)
+				mv_eth_txq_hwf_clean(pp, txq_ctrl, rx_port);
+			else
+				printk(KERN_ERR "%s: port=%d, txp=%d, txq=%d is not in use\n",
+					__func__, pp->port, txp, queue);
+		}
 	}
 	mvNetaTxpReset(port, txp);
 	return 0;
@@ -4057,7 +4185,7 @@
 int mv_eth_stop_internals(struct eth_port *pp)
 {
 	unsigned long rwflags;
-	int queue;
+	int txp, queue;
 
 	write_lock_irqsave(&pp->rwlock, rwflags);
 
@@ -4080,14 +4208,11 @@
 
 #ifdef CONFIG_MV_ETH_HWF
 	mvNetaHwfEnable(pp->port, 0);
-#else
-	{
-		int txp;
-		/* Reset TX port here. If HWF is supported reset must be called externally */
-		for (txp = 0; txp < pp->txp_num; txp++)
-			mv_eth_txp_reset(pp->port, txp);
-	}
-#endif /* !CONFIG_MV_ETH_HWF */
+#endif /* CONFIG_MV_ETH_HWF */
+
+	for (txp = 0; txp < pp->txp_num; txp++)
+		for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++)
+			mv_eth_txq_clean(pp->port, txp, queue);
 
 	if (mv_eth_ctrl_is_tx_enabled(pp)) {
 		int cpu;
@@ -5357,7 +5482,7 @@
         return mv_eth_switch_change_mtu(mv_net_devs[portNo], mtu);
 	}
 	else
-#endif		
+#endif
 	{
         return mv_eth_change_mtu(mv_net_devs[portNo], mtu);
 	}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h
index 57c0b00..607a4bc 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h
@@ -653,6 +653,7 @@
 
 int         mv_eth_rx_reset(int port);
 int         mv_eth_txp_reset(int port, int txp);
+int			mv_eth_txq_clean(int port, int txp, int txq);
 
 MV_STATUS   mv_eth_rx_ptks_coal_set(int port, int rxq, MV_U32 value);
 MV_STATUS   mv_eth_rx_time_coal_set(int port, int rxq, MV_U32 value);
@@ -677,6 +678,7 @@
 void        mv_eth_status_print(void);
 void        mv_eth_port_status_print(unsigned int port);
 void        mv_eth_port_stats_print(unsigned int port);
+void		mv_eth_pool_status_print(int pool);
 
 void        mv_eth_set_noqueue(struct net_device *dev, int enable);
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
index ff696e2..db660ea 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
@@ -124,4 +124,12 @@
 	Unselect this option only if you have source code of SLIC drivers.
 	If unsure, say "y"
 
+config MV_TDM_EXT_STATS
+	bool "Enable legacy TDM extended statistics"
+	depends on MV_TDM_SUPPORT
+	default n
+	---help---
+	Choosing this option will export extended statistics to procfs.
+	This is relevant only for the legacy TDM unit.
+
 endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h
index d005b4f..f97431e 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h
@@ -56,6 +56,9 @@
 	unsigned int tx_miss;
 	unsigned int rx_over;
 	unsigned int tx_under;
+#ifdef MV_TDM_EXT_STATS
+	MV_TDM_EXTENDED_STATS tdm_ext_stats;
+#endif
 } tal_stats_t;
 
 typedef struct {
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c
index 4ae4bbc..1707719 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c
@@ -98,7 +98,15 @@
                             int buffer_length, int *zero, void *ptr);
 static int proc_tx_under_read(char *buffer, char **buffer_location, off_t offset,
                             int buffer_length, int *zero, void *ptr);
+#ifdef CONFIG_MV_TDM_EXT_STATS
+static int proc_dump_ext_stats(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+#endif
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+/* TDM SW Reset */
+static void tdm_if_stop_channels(unsigned long args);
+#endif
 
 /* Module */
 static int __init tdm_if_module_init(void);
@@ -110,6 +118,9 @@
 static DECLARE_TASKLET(tdm_if_rx_tasklet, tdm_if_pcm_rx_process, 0);
 static DECLARE_TASKLET(tdm_if_tx_tasklet, tdm_if_pcm_tx_process, 0);
 #endif
+#ifdef CONFIG_MV_TDM_SUPPORT
+static DECLARE_TASKLET(tdm_if_stop_tasklet, tdm_if_stop_channels, 0);
+#endif
 static DEFINE_SPINLOCK(tdm_if_lock);
 static unsigned char *rxBuff = NULL, *txBuff = NULL;
 static char irqnr;
@@ -121,6 +132,8 @@
 static int tdm_init = 0;
 static int buff_size = 0;
 static unsigned short test_enable = 0;
+static int pcm_stop_flag;
+static int pcm_stop_status;
 
 #ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
 extern int __must_check
@@ -159,14 +172,49 @@
 	return sprintf(buffer, "%u\n", tx_under);
 }
 
+#ifdef CONFIG_MV_TDM_EXT_STATS
+static int proc_dump_ext_stats(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	char *str;
+	MV_TDM_EXTENDED_STATS tdm_ext_stats;
+
+	if (offset > 0)
+		return 0;
+
+	mvTdmExtStatsGet(&tdm_ext_stats);
+
+	str = buffer;
+	str += sprintf(str, "\nTDM Extended Statistics:\n");
+	str += sprintf(str, "intRxCount  	= %u\n", tdm_ext_stats.intRxCount);
+	str += sprintf(str, "intTxCount  	= %u\n", tdm_ext_stats.intTxCount);
+	str += sprintf(str, "intRx0Count 	= %u\n", tdm_ext_stats.intRx0Count);
+	str += sprintf(str, "intTx0Count 	= %u\n", tdm_ext_stats.intTx0Count);
+	str += sprintf(str, "intRx1Count 	= %u\n", tdm_ext_stats.intRx1Count);
+	str += sprintf(str, "intTx1Count 	= %u\n", tdm_ext_stats.intTx1Count);
+	str += sprintf(str, "intRx0Miss  	= %u\n", tdm_ext_stats.intRx0Miss);
+	str += sprintf(str, "intTx0Miss		= %u\n", tdm_ext_stats.intTx0Miss);
+	str += sprintf(str, "intRx1Miss		= %u\n", tdm_ext_stats.intRx1Miss);
+	str += sprintf(str, "intTx1Miss		= %u\n", tdm_ext_stats.intTx1Miss);
+	str += sprintf(str, "pcmRestartCount	= %u\n", tdm_ext_stats.pcmRestartCount);
+
+	return (int)(str - buffer);
+}
+#endif
+
 MV_STATUS tdm_if_init(tdm_if_register_ops_t* register_ops, tdm_if_params_t* tdm_if_params)
 {
 	MV_TDM_PARAMS tdm_params;
-	
+
+	if (tdm_init) {
+		printk("Marvell Telephony Driver already started...\n");
+		return MV_OK;
+	}
+
 	printk("Loading Marvell Telephony Driver\n");
 
 	/* Check if any SLIC module exists */
-	if(mvBoardTdmDevicesCountGet() == 0) {
+	if (mvBoardTdmDevicesCountGet() == 0) {
 		mvCtrlPwrClckSet(TDM_32CH_UNIT_ID, 0, MV_FALSE);
 		mvCtrlPwrClckSet(TDM_2CH_UNIT_ID, 0, MV_FALSE);
 		printk("%s: Warning, no SLIC module is connected\n",__FUNCTION__);
@@ -180,22 +228,22 @@
 	}
 
 	/* Shut down unused unit */
-	if(mvCtrlTdmUnitTypeGet() == TDM_2CH_UNIT_ID) {
+	if (mvCtrlTdmUnitTypeGet() == TDM_2CH_UNIT_ID) {
 		mvCtrlPwrClckSet(TDM_32CH_UNIT_ID, 0, MV_FALSE);
 	}
 	else { /* TDM_32CH_UNIT_ID */
 		mvCtrlPwrClckSet(TDM_2CH_UNIT_ID, 0, MV_FALSE);
 	}
 
-	if((register_ops == NULL) || (tdm_if_params == NULL)) {
+	if ((register_ops == NULL) || (tdm_if_params == NULL)) {
 		printk("%s: bad parameters\n",__FUNCTION__);
 		return MV_ERROR;
 
 	}
 
 	/* Check callbacks */
-	if(register_ops->tdm_if_pcm_ops.pcm_tx_callback == NULL ||
-	   register_ops->tdm_if_pcm_ops.pcm_rx_callback == NULL ) {
+	if (register_ops->tdm_if_pcm_ops.pcm_tx_callback == NULL ||
+	    register_ops->tdm_if_pcm_ops.pcm_rx_callback == NULL ) {
 		printk("%s: missing parameters\n",__FUNCTION__);
 		return MV_ERROR;
 	}
@@ -209,6 +257,8 @@
 #endif
 	irq_init = 0;
 	tdm_init = 0;
+	pcm_stop_flag = 0;
+	pcm_stop_status = 0;
 
 	/* Extract test enable */
 	test_enable = tdm_if_params->test_enable;
@@ -233,8 +283,13 @@
 	tdm_if_register_ops->tdm_if_ctl_ops.ctl_pcm_start = tdm_if_pcm_start;
 	tdm_if_register_ops->tdm_if_ctl_ops.ctl_pcm_stop = tdm_if_pcm_stop;
 
+	/* Soft reset to PCM I/F */
+#ifdef CONFIG_MV_TDM_SUPPORT
+	mvTdmPcmIfReset();
+#endif
+
 	/* TDM init */
-	if(mvSysTdmInit(&tdm_params) != MV_OK) {
+	if (mvSysTdmInit(&tdm_params) != MV_OK) {
 			printk("%s: Error, TDM initialization failed !!!\n",__FUNCTION__);
 			return MV_ERROR;
 	}
@@ -257,11 +312,16 @@
 
 	/* Create TDM procFS statistics */
 	tdm_stats = proc_mkdir("tdm", NULL);
-	create_proc_read_entry("tdm_init", 0, tdm_stats, proc_tdm_init_read, NULL);
-	create_proc_read_entry("rx_miss", 0, tdm_stats, proc_rx_miss_read, NULL);
-	create_proc_read_entry("tx_miss", 0, tdm_stats, proc_tx_miss_read, NULL);
-	create_proc_read_entry("rx_over", 0, tdm_stats, proc_rx_over_read, NULL);
-	create_proc_read_entry("tx_under", 0, tdm_stats, proc_tx_under_read, NULL);
+	if (tdm_stats != NULL) {
+		create_proc_read_entry("tdm_init", 0, tdm_stats, proc_tdm_init_read, NULL);
+		create_proc_read_entry("rx_miss", 0, tdm_stats, proc_rx_miss_read, NULL);
+		create_proc_read_entry("tx_miss", 0, tdm_stats, proc_tx_miss_read, NULL);
+		create_proc_read_entry("rx_over", 0, tdm_stats, proc_rx_over_read, NULL);
+		create_proc_read_entry("tx_under", 0, tdm_stats, proc_tx_under_read, NULL);
+#ifdef CONFIG_MV_TDM_EXT_STATS
+		create_proc_read_entry("tdm_extended_stats", 0, tdm_stats, proc_dump_ext_stats, NULL);
+#endif
+	}
 
 	TRC_REC("Marvell Telephony Driver Loaded Successfully\n");
 
@@ -278,12 +338,12 @@
 void tdm_if_exit(void)
 {
 	/* Check if already stopped */
-	if(!irq_init && !pcm_enable && !tdm_init)
+	if (!irq_init && !pcm_enable && !tdm_init)
 		return;
 
 	TRC_REC("->%s\n",__FUNCTION__);
 
-	if(irq_init) {
+	if (irq_init) {
 		/* Release interrupt */
 #ifndef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
                 free_irq(irqnr, NULL);
@@ -294,26 +354,29 @@
 	}
 
 	/* Stop PCM data sampling */
-	if(pcm_enable)
+	if (pcm_enable)
 		tdm_if_pcm_stop();
 
-	if(tdm_init) {
+	if (tdm_init) {
 #ifdef CONFIG_MV_TDM_SUPPORT
 		mvTdmRelease();
 #else
 		mvCommUnitRelease();
 #endif
+		/* Remove proc directory & entries */
+		remove_proc_entry("tdm_init", tdm_stats);
+		remove_proc_entry("rx_miss", tdm_stats);
+		remove_proc_entry("tx_miss", tdm_stats);
+		remove_proc_entry("rx_over", tdm_stats);
+		remove_proc_entry("tx_under", tdm_stats);
+#ifdef CONFIG_MV_TDM_EXT_STATS
+		remove_proc_entry("tdm_extended_stats", tdm_stats);
+#endif
+		remove_proc_entry("tdm", NULL);
+
 		tdm_init = 0;
 	}
 
-	/* Remove proc directory & entries */
-	remove_proc_entry("tdm_init", tdm_stats);
-	remove_proc_entry("rx_miss", tdm_stats);
-	remove_proc_entry("tx_miss", tdm_stats);
-	remove_proc_entry("rx_over", tdm_stats);
-	remove_proc_entry("tx_under", tdm_stats);
-	remove_proc_entry("tdm", NULL);
-
 	TRC_REC("<-%s\n",__FUNCTION__);
 
 	/* Dump output and release Marvell trace resources */
@@ -328,8 +391,10 @@
 	TRC_REC("->%s\n",__FUNCTION__);
 
 	spin_lock_irqsave(&tdm_if_lock, flags);
-	if(!pcm_enable) {
+	if (!pcm_enable) {
 		rxBuff = txBuff = NULL;
+		pcm_stop_flag = 0;
+		pcm_stop_status = 0;
 		pcm_enable = 1;
 #ifdef CONFIG_MV_TDM_SUPPORT
 		mvTdmPcmStart();
@@ -350,9 +415,8 @@
 	TRC_REC("->%s\n",__FUNCTION__);
 
 	spin_lock_irqsave(&tdm_if_lock, flags);
-	if(pcm_enable) {
+	if (pcm_enable) {
 		pcm_enable = 0;
-		rxBuff = txBuff = NULL;
 #ifdef CONFIG_MV_TDM_SUPPORT
 		mvTdmPcmStop();
 #else
@@ -369,12 +433,15 @@
 {
 	MV_TDM_INT_INFO tdm_int_info;
 	unsigned int int_type;
+#ifdef CONFIG_MV_TDM_SUPPORT
+	int ret;
+#endif
 
 	TRC_REC("->%s\n",__FUNCTION__);
 
 	/* Extract interrupt information from low level ISR */
 #ifdef CONFIG_MV_TDM_SUPPORT
-	mvTdmIntLow(&tdm_int_info);
+	ret = mvTdmIntLow(&tdm_int_info);
 #else
 	mvCommUnitIntLow(&tdm_int_info);
 #endif
@@ -383,13 +450,34 @@
 	/*device_id = tdm_int_info.cs;*/
 	
 	/* Nothing to do - return */
-	if(int_type == MV_EMPTY_INT)
+	if (int_type == MV_EMPTY_INT)
 		goto out;
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+	if ((ret == -1) && (pcm_stop_status == 0))  {
+		pcm_stop_status = 1;
+
+		/* If Rx/Tx tasklets already scheduled, let them do the work. */
+		if ((!rxBuff) && (!txBuff)) {
+			TRC_REC("Stopping the TDM\n");
+			tdm_if_pcm_stop();
+			pcm_stop_flag = 0;
+			tasklet_hi_schedule(&tdm_if_stop_tasklet);
+		} else {
+			TRC_REC("Some tasklet is running, mark pcm_stop_flag\n");
+			pcm_stop_flag = 1;
+		}
+	}
+
+	/* Restarting PCM, skip Rx/Tx handling */
+	if (pcm_stop_status)
+		goto skip_rx_tx;
+#endif
+
 	/* Support multiple interrupt handling */
 	/* RX interrupt */
-	if(int_type & MV_RX_INT) {
-		if(rxBuff != NULL) {
+	if (int_type & MV_RX_INT) {
+		if (rxBuff != NULL) {
 			rx_miss++;
 			TRC_REC("%s: Warning, missed Rx buffer processing !!!\n",__FUNCTION__);
 		}
@@ -407,8 +495,8 @@
 	}
 
 	/* TX interrupt */
-	if(int_type & MV_TX_INT) {
-		if(txBuff != NULL) {
+	if (int_type & MV_TX_INT) {
+		if (txBuff != NULL) {
 			tx_miss++;
 			TRC_REC("%s: Warning, missed Tx buffer processing !!!\n",__FUNCTION__);
 		}
@@ -425,17 +513,20 @@
 		}
 	}
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+skip_rx_tx:
+#endif
 	/* PHONE interrupt */
-	if(int_type & MV_PHONE_INT) {
+	if (int_type & MV_PHONE_INT) {
 		/* TBD */
 	}
 
 	/* ERROR interrupt */
-	if(int_type & MV_ERROR_INT) {
-		if(int_type & MV_RX_ERROR_INT)
+	if (int_type & MV_ERROR_INT) {
+		if (int_type & MV_RX_ERROR_INT)
 			rx_over++;
 
-		if(int_type & MV_TX_ERROR_INT)
+		if (int_type & MV_TX_ERROR_INT)
 			tx_under++;
 	}
 
@@ -451,8 +542,10 @@
 static void tdm_if_pcm_rx_process(unsigned long arg)
 #endif
 {
+	unsigned long flags;
+
 	TRC_REC("->%s\n",__FUNCTION__);
-	if(pcm_enable) {
+	if (pcm_enable) {
 		if(rxBuff == NULL) {
 			TRC_REC("%s: Error, empty Rx processing\n",__FUNCTION__);
 			return;
@@ -460,10 +553,10 @@
 
 		/* Fill TDM Rx aggregated buffer */
 #ifdef CONFIG_MV_TDM_SUPPORT
-		if(mvTdmRx(rxBuff) == MV_OK)
+		if (mvTdmRx(rxBuff) == MV_OK)
 			tdm_if_register_ops->tdm_if_pcm_ops.pcm_rx_callback(rxBuff, buff_size); /* Dispatch Rx handler */
 #else
-		if(mvCommUnitRx(rxBuff) == MV_OK) {
+		if (mvCommUnitRx(rxBuff) == MV_OK) {
 			tdm_if_register_ops->tdm_if_pcm_ops.pcm_rx_callback(rxBuff, buff_size); /* Dispatch Rx handler */
 			/* Since data buffer is shared among MCDMA and CPU, need to invalidate 	
 				before it accessed by MCDMA	*/
@@ -474,10 +567,22 @@
 			printk("%s: could not fill Rx buffer\n",__FUNCTION__);
 
 	}
-	
+
+	spin_lock_irqsave(&tdm_if_lock, flags);
+
 	/* Clear rxBuff for next iteration */
 	rxBuff = NULL;
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+	if ((pcm_stop_flag == 1) && !txBuff) {
+		TRC_REC("Stopping TDM from Rx tasklet\n");
+		tdm_if_pcm_stop();
+		pcm_stop_flag = 0;
+		tasklet_hi_schedule(&tdm_if_stop_tasklet);
+	}
+#endif
+	spin_unlock_irqrestore(&tdm_if_lock, flags);
+
 	TRC_REC("<-%s\n",__FUNCTION__);
 	return;
 }
@@ -489,10 +594,12 @@
 static void tdm_if_pcm_tx_process(unsigned long arg)
 #endif
 {
+	unsigned long flags;
+
 	TRC_REC("->%s\n",__FUNCTION__);
 
-	if(pcm_enable) {
-		if(txBuff == NULL) {
+	if (pcm_enable) {
+		if (txBuff == NULL) {
 			TRC_REC("%s: Error, empty Tx processing\n",__FUNCTION__);
 			return;
 		}
@@ -500,7 +607,7 @@
 		/* Dispatch Tx handler */
 		tdm_if_register_ops->tdm_if_pcm_ops.pcm_tx_callback(txBuff, buff_size);
 
-		if(test_enable == 0) {
+		if (test_enable == 0) {
 			/* Fill Tx aggregated buffer */
 #ifdef CONFIG_MV_TDM_SUPPORT
 			if(mvTdmTx(txBuff) != MV_OK)
@@ -511,9 +618,21 @@
 		}
 	}
 
+	spin_lock_irqsave(&tdm_if_lock, flags);
+
 	/* Clear txBuff for next iteration */
 	txBuff = NULL;
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+	if ((pcm_stop_flag == 1) && !rxBuff) {
+		TRC_REC("Stopping TDM from Tx tasklet\n");
+		tdm_if_pcm_stop();
+		pcm_stop_flag = 0;
+		tasklet_hi_schedule(&tdm_if_stop_tasklet);
+	}
+#endif
+	spin_unlock_irqrestore(&tdm_if_lock, flags);
+
 	TRC_REC("<-%s\n",__FUNCTION__);
 	return;
 }
@@ -525,10 +644,39 @@
 	tdm_if_stats->tx_miss = tx_miss;
 	tdm_if_stats->rx_over = rx_over;
 	tdm_if_stats->tx_under = tx_under;
-	
+#ifdef CONFIG_MV_TDM_EXT_STATS
+	mvTdmExtStatsGet(&tdm_if_stats->tdm_ext_stats);
+#endif
 	return;
 }
 
+#ifdef CONFIG_MV_TDM_SUPPORT
+static void tdm_if_stop_channels(unsigned long arg)
+{
+	u32 max_poll = 0;
+	unsigned long flags;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	/* Wait for all channels to stop  */
+	while (((MV_REG_READ(CH_ENABLE_REG(0)) & 0x101) || (MV_REG_READ(CH_ENABLE_REG(1)) & 0x101)) && (max_poll < 30)) {
+		mdelay(1);
+		max_poll++;
+	}
+
+	TRC_REC("Finished polling on channels disable\n");
+	if (max_poll >= 30)
+		printk("\n\npolling on channels disabling exceeded 30ms\n\n");
+
+	spin_lock_irqsave(&tdm_if_lock, flags);
+	tdm_if_pcm_start();
+	spin_unlock_irqrestore(&tdm_if_lock, flags);
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+#endif
+
 static int __init tdm_if_module_init(void)
 {
 	/* The real init is done later */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h
index 964cef0..a1f1634 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h
@@ -84,6 +84,9 @@
 	unsigned int tx_miss;
 	unsigned int rx_over;
 	unsigned int tx_under;
+#ifdef CONFIG_MV_TDM_EXT_STATS
+	MV_TDM_EXTENDED_STATS tdm_ext_stats;
+#endif
 } tdm_if_stats_t;
 
 typedef struct {
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c
index 6bcf46b..3fad804 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c
@@ -757,35 +757,82 @@
 **

 **  onuEponLinkIsUp

 **  ____________________________________________________________________________

-** 

+**

 **  DESCRIPTION: The function register Link Status callback function

-**               

+**

 **  PARAMETERS:  None

 **

 **  OUTPUTS:     None

 **

 **  RETURNS:     MV_TRUE or MV_FLASE

-**                   

+**

 *******************************************************************************/

 MV_BOOL onuEponLinkIsUp(void)

 {

-  MV_U32 mode;

+	MV_U32 mode;

 

-  mode = onuEponDbModeGet();

+	mode = onuEponDbModeGet();

 

-  if (onuEponForceTxDownStateGet(0) == MV_TRUE)

-    return(MV_TRUE);

+	if (onuEponForceTxDownStateGet(0) == MV_TRUE)

+	{

+        return (MV_TRUE);

+	}

 

-  if (mode == E_EPON_IOCTL_STD_MODE) 

-  {

-    if (onuEponDbOnuStateGet(0) == ONU_EPON_03_OPERATION) return(MV_TRUE);

-    else                                                  return(MV_FALSE);

-  }

-  else /* P2P */

-  {

-    if (onuEponDbOnuSignalDetectGet() == 1) return(MV_TRUE);

-    else                                    return(MV_FALSE);

-  }

+	if (mode == E_EPON_IOCTL_STD_MODE)

+	{

+        if (onuEponDbOnuStateGet(0) == ONU_EPON_03_OPERATION)

+        {

+            return (MV_TRUE);

+        }

+        else

+        {

+            return (MV_FALSE);

+        }

+	}

+	else /* P2P */

+	{

+        if (onuEponDbOnuSignalDetectGet() == 1)

+        {

+            mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,

+                       "DEBUG: (%s:%d) onuPonLinkIsUp, UP\n", __FILE_DESC__, __LINE__);

+            return (MV_TRUE);

+        }

+        else

+        {

+            mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,

+                       "DEBUG: (%s:%d) onuPonLinkIsUp, DOWN\n", __FILE_DESC__, __LINE__);

+            return (MV_FALSE);

+        }

+	}

+}

+

+MV_STATUS mvEponApi2kSupportedSet(MV_U32 pkt2kSupported)

+{

+    MV_STATUS status;

+    MV_U32    devId;

+

+    devId = mvCtrlModelGet();

+	if (devId != MV_6601_DEV_ID)

+	{

+		return(MV_OK);

+	}

+

+    //status =  mvOnuEponMacPcsRxEnableSet(EPON_PCS_CONFIG_RX_DISABLE);

+

+    if (pkt2kSupported == 1)  /* 2K packet supported */

+    {

+        status |= mvOnuEponMacPcsFrameSizeLimitsSet(EPON_MAC_PCS_FRAME_SIZE_LIMIT_SIZE_2K_SUPP, 

+                                                    EPON_MAC_PCS_FRAME_SIZE_LIMIT_LATENCY_2K_SUPP);

+        status |= mvOnuEponMacRxpDataFifoThresholdSet(EPON_MAC_RXP_DATA_FIFO_THRESHOLD_2K_SUPP);

+    }

+    else if (pkt2kSupported == 0)

+    {

+        status |= mvOnuEponMacPcsFrameSizeLimitsSet(EPON_MAC_PCS_FRAME_SIZE_LIMIT_SIZE_DEF, 

+                                                    EPON_MAC_PCS_FRAME_SIZE_LIMIT_LATENCY_DEF);

+        status |= mvOnuEponMacRxpDataFifoThresholdSet(EPON_MAC_RXP_DATA_FIFO_THRESHOLD_DEF);

+    }

+

+    return (status);

 }

 

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h
index cd4eebd..9e23984 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h
@@ -142,6 +142,9 @@
 MV_STATUS onuEponApiLinkStatusCallbackRegister(void);

 MV_BOOL onuEponLinkIsUp(void);

 

+/* Config API */

+MV_STATUS mvEponApi2kSupportedSet(MV_U32 pkt2kSupported);

+

 /* Macros

 ------------------------------------------------------------------------------*/    

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c
index 040d80b..c5bcf3b 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c
@@ -2009,6 +2009,49 @@
 

 /*******************************************************************************

 **

+**  onuEponDbP2PForceModeSet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function sets EPON P2P Force mode in the database

+**

+**  PARAMETERS:  MV_U32 mode

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponDbP2PForceModeSet(MV_U32  forceMode)

+{

+    if (forceMode >= E_EPON_IOCTL_MAX_MODE_NUM)

+      return(MV_ERROR);

+

+    onuEponDb_s.onuEponGenTbl_s.onuEponP2PForceMode = forceMode;

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbP2PForceModeGet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function returns current EPON P2P Force mode

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode

+**

+*******************************************************************************/

+MV_U32 onuEponDbP2PForceModeGet(void)

+{

+    return(onuEponDb_s.onuEponGenTbl_s.onuEponP2PForceMode);

+}

+

+/*******************************************************************************

+**

 **  onuEponDbPcsCfgSet

 **  ____________________________________________________________________________

 ** 

@@ -2089,10 +2132,10 @@
 

 /*******************************************************************************

 **

-**  onuEponDbXvrPolaritySet

+**  onuEponDbBurstEnablePolaritySet

 **  ____________________________________________________________________________

 ** 

-**  DESCRIPTION: The function sets EPON XVR polarity register value in the database

+**  DESCRIPTION: The function sets EPON XVR burst enable polarity value in the database

 **               

 **  PARAMETERS:  MV_U32 val

 **

@@ -2101,30 +2144,30 @@
 **  RETURNS:     MV_OK or error

 **                   

 *******************************************************************************/

-MV_STATUS onuEponDbXvrPolaritySet(MV_U32   val)

+MV_STATUS onuEponDbBurstEnablePolaritySet(MV_U32 val)

 {

-    onuEponDb_s.onuEponGenTbl_s.onuEponXvrPolarity = val;

+    onuEponDb_s.onuEponGenTbl_s.onuEponXvrBurstEnPolarity = val;

 

     return(MV_OK);

 }

 

 /*******************************************************************************

 **

-**  onuEponDbXvrPolarityGet

+**  onuEponDbBurstEnablePolarityGet

 **  ____________________________________________________________________________

 ** 

-**  DESCRIPTION: The function returns EPON XVR polarity register value

+**  DESCRIPTION: The function gets EPON XVR burst enable polarity value in the database

 **               

 **  PARAMETERS:  None

 **

 **  OUTPUTS:     None

 **

-**  RETURNS:     MV_U32 mode

+**  RETURNS:     polarity

 **                   

 *******************************************************************************/

-MV_U32 onuEponDbXvrPolarityGet(void)

+MV_U32 onuEponDbBurstEnablePolarityGet(void)

 {

-    return(onuEponDb_s.onuEponGenTbl_s.onuEponXvrPolarity);

+    return onuEponDb_s.onuEponGenTbl_s.onuEponXvrBurstEnPolarity;

 }

 

 /*******************************************************************************

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h
index 120be03..df2003e 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h
@@ -353,10 +353,11 @@
   DYINGGASPFUNC    onuDgCallback;

   LINKSTATUSFUNC   onuLinkStatusCallback;

   MV_U32           onuEponMode;

+  MV_U32           onuEponP2PForceMode;

   MV_U32           onuEponPcsCfg;             

   MV_U32           onuEponOverHead;             

   MV_U32           onuEponPhyOutput;             

-  MV_U32           onuEponXvrPolarity;             

+  MV_U32           onuEponXvrBurstEnPolarity;

 }S_OnuEponGenTbl;                                     

 

 /* ONU EPON Data Path tables */

@@ -506,12 +507,14 @@
 

 MV_STATUS   onuEponDbModeSet(MV_U32 mode);

 MV_U32      onuEponDbModeGet(void);

+MV_STATUS   onuEponDbP2PForceModeSet(MV_U32 mode);

+MV_U32      onuEponDbP2PForceModeGet(void);

 MV_STATUS   onuEponDbPcsCfgSet(MV_U32 val);

 MV_U32      onuEponDbPcsCfgGet(void);

 MV_STATUS   onuEponDbOverheadSet(MV_U32 val);

 MV_U32      onuEponDbOverheadGet(void);

-MV_STATUS   onuEponDbXvrPolaritySet(MV_U32 val);

-MV_U32      onuEponDbXvrPolarityGet(void);

+MV_STATUS   onuEponDbBurstEnablePolaritySet(MV_U32 val);

+MV_U32      onuEponDbBurstEnablePolarityGet(void);

 

 /* Macros

 ------------------------------------------------------------------------------*/    

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c
index 9c31f1f..5df06f0 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c
@@ -139,6 +139,7 @@
     return(MV_ERROR);

   }

 

+  ponXvrFunc = EponXvrSDPolarityHighStatus;

   /* init onu database */

   rcode = onuEponDbInit();

   if (rcode != MV_OK)

@@ -416,8 +417,7 @@
 		return(MV_ERROR);

 	}

 

-	onuEponDbXvrPolaritySet(ONU_DEF_DDM_CFG_POLARITY_HIGH);

-	mvOnuPonMacBurstEnablePolarityInit(ONU_DEF_DDM_CFG_POLARITY_HIGH);

+    onuEponDbBurstEnablePolaritySet(ONU_DEF_DDM_CFG_POLARITY_HIGH);

 

 	status = mvOnuEponMacGpmDiscoveryGrantLengthSet(0x26,  /* grantLength */

 							0x06,  /* addOffsetForCalc */

@@ -854,7 +854,6 @@
     return(status);

   }

 

-

   /* Enable MAC */

   status = mvOnuEponMacOnuRxEnableSet(ONU_RX_EN);

   if (status != MV_OK)

@@ -940,7 +939,7 @@
   }

 

   /* re-set DDM polarity */

-  status = mvOnuEponMacDdmTxPolaritySet(ONU_DEF_DDM_CFG_TX_EN_OR, ioctlInit->xvrPolarity);

+  status = mvOnuEponMacDdmTxPolaritySet(ONU_DEF_DDM_CFG_TX_EN_OR, ioctlInit->ponXvrBurstEnPolarity);

   if (status != MV_OK)

   {

     mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

@@ -948,8 +947,9 @@
     return(MV_ERROR);

   }

 

-  onuEponDbXvrPolaritySet(ioctlInit->xvrPolarity);

-  mvOnuPonMacBurstEnablePolarityInit(ioctlInit->xvrPolarity);

+    ponXvrFunc = funcEponXvrSDStatus(ioctlInit->ponXvrPolarity);

+

+    onuP2PDbXvrBurstEnablePolaritySet(ioctlInit->p2pXvrBurstEnPolarity);

 

 #ifndef PON_FPGA

   /* enable onu dying gasp interrupt mask */

@@ -962,6 +962,14 @@
   }

 #endif /* PON_FPGA */

 

+    status = mvEponApi2kSupportedSet(ioctlInit->pkt2kSupported);

+    if (status != MV_OK)

+    {

+        mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+                   "ERROR: (%s:%d) mvEponApi2kSupportedSet\r\n", __FILE_DESC__, __LINE__);

+        return(status);

+    }

+

   return(MV_OK);

 }

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
index ede0df9..11c1a57 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
@@ -165,7 +165,7 @@
 	MV_U32  rxGenFecEn      = 0;
 	MV_U32  interruptEvent  = 0;
 	MV_U32  interruptStatus = 0;
-
+	LINKSTATUSFUNC linkStatusCallback;
 
 #ifdef MV_EPON_HW_INTERRUPT
 	onuEponIsrLowRoutine(&interruptEvent, &interruptStatus);
@@ -178,16 +178,24 @@
 	/* ================= */
 
 	if (interruptEvent & ONU_EPON_XVR_SD_MASK) {
-
+    //TODO(jnewlin): Make sure this is correct for GFLT200 board.
 		if (GFLT200_ID == mvBoardIdGet()) {
 			state = (interruptStatus & ONU_EPON_XVR_SD_MASK) ? MV_TRUE : MV_FALSE;
 		} else {
-			state = (interruptStatus & ONU_EPON_XVR_SD_MASK) ? MV_FALSE : MV_TRUE;
+			state = ponXvrFunc(interruptStatus, ONU_EPON_XVR_SD_MASK);
 		}
 		if (state == MV_FALSE)
+		{
 			onuEponDbOnuSignalDetectSet(1); /* alarm is OFF */
+			mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+				   "DEBUG: (%s:%d) Signal Detect ON\n", __FILE_DESC__, __LINE__);
+		}
 		else if (state == MV_TRUE)
+		{
 			onuEponDbOnuSignalDetectSet(0);/* alarm is ON */
+			mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+				   "DEBUG: (%s:%d) Signal Detect OFF\n", __FILE_DESC__, __LINE__);
+		}
 
 		onuEponPonMngIntrAlarmHandler(ONU_EPON_XVR_SD_MASK, state);
 
@@ -206,13 +214,75 @@
 			mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
 				   "DEBUG: (%s:%d) ResetRandomStateMachine %s\n", __FILE_DESC__, __LINE__);
 			onuEponIsrResetRandomStateMachine();
+			/* Call link status callback function */
+			if (onuEponDbModeGet() == E_EPON_IOCTL_P2P_MODE)
+			{
+				linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+				if (linkStatusCallback != NULL)
+				{
+					linkStatusCallback(MV_TRUE);
+					mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+						   "DEBUG: (%s:%d) Notify link is UP\n", __FILE_DESC__, __LINE__);
+				}
+			}
+		}
+		else if (state == MV_TRUE) /* alarm is ON */
+		{
+			if (onuEponDbP2PForceModeGet())
+			{
+				/* set P2P mode */
+				onuEponDbModeSet(E_EPON_IOCTL_P2P_MODE);
+			}
+			else
+			{
+				/* set EPON mode */
+				onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
+			}
+            
 
+			/* config PCS synchronization configuration  - FEC disabled */
+			mvOnuEponMacPcsDelaySet(0x1C58);
+			/* clear Rx Ctrl message FIFO */
+			onuEponPonMngIntrRxCtrlFifoCleanup();
+
+#if 0
+// TODO(jnewlin): Double check this merge.
+<<<<<<< HEAD
 		} else if (state == MV_TRUE) { /* alarm is ON */
 
 			/* set EPON mode only if it is not P2P */
 			if (E_EPON_IOCTL_P2P_MODE != onuEponDbModeGet()) {
 				onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
 			}
+=======
+			/* Call link status callback function */
+			if (onuEponDbModeGet() == E_EPON_IOCTL_P2P_MODE)
+			{
+				linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+				if (linkStatusCallback != NULL)
+				{
+					linkStatusCallback(MV_TRUE);
+					mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+						   "DEBUG: (%s:%d) Notify link is UP\n", __FILE_DESC__, __LINE__);
+				}
+			}
+		}
+		else if (state == MV_TRUE) /* alarm is ON */
+		{
+			if (onuEponDbP2PForceModeGet())
+			{
+				/* set P2P mode */
+				onuEponDbModeSet(E_EPON_IOCTL_P2P_MODE);
+			}
+			else
+			{
+				/* set EPON mode */
+				onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
+			}
+            
+>>>>>>> remotes/gfiber-internal/vendor_drops
+#endif
+
 			/* config PCS synchronization configuration  - FEC disabled */
 			mvOnuEponMacPcsDelaySet(0x1C58);
 			/* clear Rx Ctrl message FIFO */
@@ -918,8 +988,22 @@
     MV_U32    gpioGroup, gpioMask;
 	MV_U32    interruptMask;
 	MV_U32    polarity;
-
+	MV_U32    interruptStatus;
+    MV_U32    state;
     LINKSTATUSFUNC linkStatusCallback;
+    /* Check for XVR SD interrupt status */
+    mvOnuEponMacPonInterruptGet(&interruptStatus);
+    interruptStatus &= 0xFFFF;
+
+    state = ponXvrFunc(interruptStatus, ONU_EPON_XVR_SD_MASK);
+    if (state == MV_FALSE)
+    {
+        onuEponDbOnuSignalDetectSet(1); /* alarm is OFF */
+    }
+    else if (state == MV_TRUE)
+    {
+        onuEponDbOnuSignalDetectSet(0);/* alarm is ON */
+    }
 
 	if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
 	{
@@ -1114,7 +1198,7 @@
 		return(MV_ERROR);
 	  }
 
-	  polarity = onuEponDbXvrPolarityGet();
+      polarity = onuP2PDbXvrBurstEnablePolarityGet();
 
 	  /* XVR polarity */
 	  /* XVR polarity == 0, Active High, transmit 1 to the line  */
@@ -1129,7 +1213,7 @@
 	  /* XVR polarity == 1, Active Low, write 0 for Force Value */
 
 	  /* PHY control register - force enable value - according to polarity */
-	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, ~polarity, 0);
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, polarity, 0);
 	  if (status != MV_OK)
 	  {
 		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
@@ -1162,7 +1246,9 @@
     linkStatusCallback = onuEponDbLinkStatusCallbackGet();
     if (linkStatusCallback != NULL)
     {
-      linkStatusCallback(MV_TRUE);
+        linkStatusCallback(MV_TRUE);
+        mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+                   "DEBUG: (%s:%d) Notify link is UP\n", __FILE_DESC__, __LINE__);
     }
     /* TODO(kedong): Enable laser when the RX is ready. Need to be cleaned up
      * when wavelength selection code is ready.
@@ -1349,8 +1435,16 @@
 	  }
 	}
 
-    onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
-
+		if (onuEponDbP2PForceModeGet())
+		{
+		  /* set P2P mode */
+          onuEponDbModeSet(E_EPON_IOCTL_P2P_MODE);
+		}
+		else
+		{
+		  /* set EPON mode */
+          onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
+		}
 
 	if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
 	{
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c
index 9327c8f..9d1ec27 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c
@@ -627,7 +627,11 @@
   if (linkStatusCallback != NULL)
   {
     if (onuEponForceTxDownStateGet(0) != MV_TRUE)
-      linkStatusCallback(MV_FALSE);
+	{ 
+	  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE, 
+                 "DEBUG: (%s:%d) Notify link is DOWN\n", __FILE_DESC__, __LINE__); 
+      linkStatusCallback(MV_FALSE); 
+    } 
   }
   /* TODO(kedong): Disable laser when the RX is gone. Need to be cleaned up
    * when wavelength selection code is ready.
@@ -928,6 +932,7 @@
 				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
 						   "ERROR: (%s:%d) Handle Rx Ctrl Frame\n\r", __FILE_DESC__, __LINE__);
 				onuEponPmSwRxCountersAdd(TOTAL_MPCP_RX_ERROR_FRAME_CNT, 0);
+                return;
 			}
 		} while (status == MV_OK);
 
@@ -951,6 +956,7 @@
 
 		mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
 				   "ERROR: (%s:%d) Unsupported Frame\n\r", __FILE_DESC__, __LINE__);
+        return;
 	}
 }
 
@@ -2003,6 +2009,8 @@
   linkStatusCallback = onuEponDbLinkStatusCallbackGet();
   if (linkStatusCallback != NULL)
   {
+  	 mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE, 
+                "DEBUG: (%s:%d) Notify link is UP\n", __FILE_DESC__, __LINE__); 
     linkStatusCallback(MV_TRUE);
   }
 
@@ -3109,3 +3117,37 @@
 	return(status);
 }
 
+/*******************************************************************************
+**
+**  onuEponTimerTxPwrHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function start / stop 1 sec timer that will disable Tx if
+**               expired
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponTimerTxPwrHndl(unsigned long data)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonTxPwrTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  if (onuEponDbOnuStateGet(0) < ONU_EPON_03_OPERATION)
+  {
+     onuPonTxPowerOn(MV_FALSE);
+  }
+
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonTxPwrTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h
index 7db46f0..c5afad8 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h
@@ -131,6 +131,8 @@
 void      onuEponPonMngTimerHwRprtTxModHndl(unsigned long data);
 MV_STATUS onuEponPonMngTimerHwRprtCfg(MV_U32 t0_val, MV_U32 t0_time, MV_U32 t1_val, MV_U32 t1_time);
 
+void 	  onuEponTimerTxPwrHndl(unsigned long data);
+
 /* Macros
 ------------------------------------------------------------------------------*/
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c
index d23c1ac..5442fac 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c
@@ -165,7 +165,7 @@
 **  RETURNS:     MV_TRUE or MV_FALSE
 **
 *******************************************************************************/
-MV_BOOL onuGponAllocIdMacAllocExistCheck(MV_U32 allocId, MV_U32 *entry)
+MV_BOOL onuGponAllocIdMacAllocExistCheck(MV_U32 allocId, MV_U32 *entry, MV_U32 *tcont)
 {
 	MV_U32  iEntry;
 	MV_U32  macAllocId;
@@ -177,6 +177,7 @@
 		status = mvOnuGponMacRxBwMapGet(iEntry,&macAllocId,&valid,&tcontNum);
 		if ((status == MV_OK) && (macAllocId == allocId) && (valid == MV_TRUE)) {
 			*entry = iEntry;
+			*tcont = tcontNum;
 			return (MV_TRUE);
 		}
 	}
@@ -234,14 +235,24 @@
 *******************************************************************************/
 MV_STATUS onuGponAllocIdMacAdd(MV_U32 allocId, MV_U32 tcontId)
 {
-	MV_U32  entry;
-	MV_BOOL exist;
+	MV_STATUS status = MV_OK;
+	MV_U32    entry;
+	MV_BOOL   exist;
 
 	exist = onuGponAllocIdMacAllocFreeEntryGet(&entry);
 	if (exist == MV_FALSE)
 		return (MV_ERROR);
 
-	return (mvOnuGponMacRxBwMapSet(entry, allocId, tcontId, MV_TRUE));
+	status = mvOnuGponMacRxBwMapSet(entry, allocId, tcontId, MV_TRUE);
+	if (status != MV_OK)
+	{
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+			   "ERROR: (%s:%d) onuGponAllocIdMacAdd, failed to add alloc Id(%d) entry(%d)\n",
+			   __FILE_DESC__, __LINE__, allocId, entry);
+		return (status);
+	}
+
+	return (status);
 }
 
 /*******************************************************************************
@@ -264,13 +275,20 @@
 	MV_STATUS status;
 	MV_BOOL   exist;
 	MV_U32    entry;
+	MV_U32    tcont;
 	MV_U32    newIdleTcontEntry;
 	MV_U32    freeTcontEntry;
 	MV_U32    entryAllocId;
 	MV_U32    bwMapEntry;
 
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+              "DEBUG: (%s:%d) AllocIdMacConnect, AllocId(%d), Tcont(%d)\n",
+              __FILE_DESC__, __LINE__, allocId, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
+
 	/* validate that requested alloc-Id is configured in HW and is valid */
-	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry, &tcont);
 	if (exist != MV_TRUE) {
 		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
 					"ERROR: (%s:%d) onuGponAllocIdMacConnect, alloc Id(%d) entry(%d)\n",
@@ -300,7 +318,7 @@
 				onuGponDbBwIdleAllocGet(newIdleTcontEntry, &entryAllocId);
 				if (entryAllocId != PON_ONU_ALLOC_NOT_EXIST) {
 					/* Check if this idle Alloc ID exists in the HW table */
-					exist = onuGponAllocIdMacAllocExistCheck(entryAllocId, &bwMapEntry);
+					exist = onuGponAllocIdMacAllocExistCheck(entryAllocId, &bwMapEntry, &tcont);
 					if (exist == MV_TRUE) {
 						/* re-assign this Alloc ID to the new idle Tcont in HW */
 						status = mvOnuGponMacRxBwMapSet(bwMapEntry, entryAllocId, onuIdleAllocTcont, MV_TRUE);
@@ -323,7 +341,25 @@
 	} /* tcontNum == onuIdleAllocTcont */
 
 	/* update input Alloc-Id and T-Cont in the HW */
-	return (mvOnuGponMacRxBwMapSet(entry, allocId, tcontNum, MV_TRUE));
+	status = mvOnuGponMacRxBwMapSet(entry, allocId, tcontNum, MV_TRUE);
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+              "DEBUG: (%s:%d) AllocIdMacConnect, tpm_active_tcont, Tcont(%d)\n",
+              __FILE_DESC__, __LINE__, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	printk("TCONT (%d) active, Connect\n", tcontNum);
+	status = onuGponWqTcontActivate(tcontNum);
+	if (status != MV_OK)
+	{
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+			   "ERROR: (%s:%d) onuGponAllocIdMacAdd, failed to schedule T-Cont(%d) activate in WQ\n",
+			   __FILE_DESC__, __LINE__, tcontNum);
+		return (status);
+	}
+
+	return (status);
 }
 
 /*******************************************************************************
@@ -334,32 +370,56 @@
 **  DESCRIPTION: The function reconnect alloc-Id to idle tcont
 **
 **  PARAMETERS:  MV_U32 allocId
+**  		 MV_U32 tcontNum
 **
 **  OUTPUTS:     None
 **
 **  RETURNS:     MV_OK or error
 **
 *******************************************************************************/
-MV_STATUS onuGponAllocIdMacReconnect(MV_U32 allocId)
+MV_STATUS onuGponAllocIdMacReconnect(MV_U32 allocId, MV_U32 tcontNum)
 {
 	MV_BOOL   exist;
 	MV_STATUS status = MV_OK;
 	MV_U32    entry;
 	MV_U32    onuId;
-	MV_U32    tcontNum;
+	MV_U32    tcont;
+	MV_U32    tcontFreeNum;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+              "DEBUG: (%s:%d) AllocIdMacReconnect, AllocId(%d), Tcont(%d)\n",
+              __FILE_DESC__, __LINE__, allocId, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
 
 	/* Get free entry */
-	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry, &tcont);
 	if (exist != MV_TRUE)
 		return (MV_ERROR);
 
-	exist = onuGponDbBwTcontFreeGet(allocId, &tcontNum);
+	exist = onuGponDbBwTcontFreeGet(allocId, &tcontFreeNum);
 	if (exist != MV_TRUE)
-		onuIdleAllocTcont = tcontNum;
+		onuIdleAllocTcont = tcontFreeNum;
 
 	/* Check if default Alloc Id */
 	onuId = onuGponDbOnuIdGet();
 	if (allocId != onuId) {
+
+#ifdef MV_GPON_DEBUG_PRINT
+	        mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+                      "DEBUG: (%s:%d) AllocIdMacReconnect, tpm_deactive_tcont, Tcont(%d)\n",
+                      __FILE_DESC__, __LINE__, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	       // printk("TCONT (%d) flush, Reconnect\n", tcontNum);
+	       // status = onuGponWqTcontFlush(tcontNum);
+	       // if (status != MV_OK)
+	       //{
+	       // 	mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+	       // 		   "ERROR: (%s:%d) onuGponAllocIdMacReconnect, failed to schedule T-Cont(%d) flush in WQ\n",
+	       // 		   __FILE_DESC__, __LINE__, tcontNum);
+	       //}
+
 		/* Set Alloc Id to T-Cont in the GMAC hardware */
 		status = mvOnuGponMacRxBwMapSet(entry, allocId, onuIdleAllocTcont, MV_TRUE);
 	}
@@ -385,18 +445,48 @@
 {
 	MV_U32  onuId;
 	MV_U32  entry;
+	MV_U32  tcont;
 	MV_BOOL exist;
 	MV_STATUS status = MV_OK;
 
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+              "DEBUG: (%s:%d) AllocIdMacDisconnect, AllocId(%d)\n",
+              __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
 	/* Check if already exist */
-	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry, &tcont);
 	if (exist == MV_FALSE)
 		return (MV_ERROR);
 
 	/* Check if default Alloc Id */
 	onuId = onuGponDbOnuIdGet();
 	if (allocId != onuId)
+	{
+#ifdef MV_GPON_DEBUG_PRINT
+	        mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+                      "DEBUG: (%s:%d) tpm_deactive_tcont, Tcont(%d)\n",
+                      __FILE_DESC__, __LINE__, tcont);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+		printk("TCONT (%d) flush, Disconnect\n", tcont);
+		status = onuGponWqTcontFlush(tcont);
+		if (status != MV_OK)
+		{
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				   "ERROR: (%s:%d) onuGponAllocIdMacDisconnect, failed to schedule T-Cont(%d) flush in WQ\n",
+				   __FILE_DESC__, __LINE__, tcont);
+		}
+
 		status = mvOnuGponMacRxBwMapSet(entry, 0, 0, MV_FALSE);
+		if (status != MV_OK)
+		{
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				   "ERROR: (%s:%d) onuGponAllocIdMacDisconnect, failed to disconnect  Alloc Id(%d), T-Cont(%d)\n",
+				   __FILE_DESC__, __LINE__, allocId, tcont);
+		}
+	}
 
 	return (status);
 }
@@ -487,6 +577,10 @@
 	/* =============== */
 	/* configured in the T-Cont table and BW MAP */
 	if (allocId == onuId) {
+#ifdef MV_GPON_DEBUG_PRINT
+		mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+			   "DEBUG: (%s:%d) Alloc ID Assign, default alloc Id(%d) set to T-Cont 0(def)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
 		/* Set default Alloc Id to T-Cont table */
 		status = onuGponDbBwTcontAlloc(PON_ONU_DEFAULT_ALLOC_TCONT, allocId);
 		if (status != MV_OK) {
@@ -553,6 +647,7 @@
 	MV_U32    tcontNum;
 	MV_BOOL   allocIdExist;
 	MV_BOOL   valid;
+
 #ifdef MV_GPON_DEBUG_PRINT
 	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
 				"DEBUG: (%s:%d) De-Assign Alloc ID, alloc Id(%d)\n", __FILE_DESC__, __LINE__, allocId);
@@ -605,6 +700,41 @@
 
 /*******************************************************************************
 **
+**  onuGponAllocIdFreeAllBuffers
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function release all buffers assigned to All Alloc IDs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdFreeAllBuffers(void)
+{
+    MV_STATUS status;
+    MV_U32    tcontNum = 0xFF;
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+               "DEBUG: (%s:%d) release All T-Conts buffers, tpm_deactive_tcont\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+    printk("TCONT flush, FreeAllBuffers\n");
+    status = onuGponWqTcontFlush(tcontNum);
+    if (status != MV_OK)
+    {
+            mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+        	       "ERROR: (%s:%d) onuGponAllocIdFreeAllBuffers, failed to schedule All T-Cont flush in WQ\n",
+        	       __FILE_DESC__, __LINE__, tcontNum);
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
 **  onuGponAllocIdDeAssignAll
 **  ____________________________________________________________________________
 **
@@ -620,17 +750,17 @@
 MV_STATUS onuGponAllocIdDeAssignAll(void)
 {
 #ifdef MV_GPON_DEBUG_PRINT
-  mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
-             "DEBUG: (%s:%d) De-Assign All Alloc IDs and T-Conts\n", __FILE_DESC__, __LINE__);
+    mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+               "DEBUG: (%s:%d) De-Assign All Alloc IDs and T-Conts\n", __FILE_DESC__, __LINE__);
 #endif /* MV_GPON_DEBUG_PRINT */
 
-  onuGponDbBwAllocInit();
-  onuGponAllocIdMacInit();
-  onuGponAllocIdInit(0x00FF);
+    onuGponDbBwAllocInit();
+    onuGponAllocIdMacInit();
+    onuGponAllocIdInit(0x00FF);
 
-  sendNotifyToMng = MV_FALSE;
+    sendNotifyToMng = MV_FALSE;
 
-  return (MV_OK);
+    return (MV_OK);
 }
 
 /*******************************************************************************
@@ -788,7 +918,7 @@
 	exist = onuGponDbBwAllocExist(allocId);
 	if (exist == MV_TRUE) {
 		/* Clear T-Cont in hardware in case T-Cont is not connected to default Alloc-Id (== ONU ID) */
-		status = onuGponAllocIdMacReconnect(allocId);
+		status = onuGponAllocIdMacReconnect(allocId, tcontNum);
 		if (status != MV_OK) {
 			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
 						"ERROR: (%s:%d) onuGponAllocIdMacReconnect, alloc Id(%d)\n",
@@ -834,6 +964,7 @@
 	MV_U32  iEntry;
 	MV_BOOL exist;
 	MV_STATUS status;
+	MV_U32    tcontNum = 0xFF;
 
 #ifdef MV_GPON_DEBUG_PRINT
 	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
@@ -847,6 +978,16 @@
 			onuGponAllocIdTcontClear(iEntry);
 	}
 
+	printk("TCONT flush, Clear All\n");
+	status = onuGponWqTcontFlush(tcontNum);
+	if (status != MV_OK)
+	{
+	 	mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+	 		   "ERROR: (%s:%d) onuGponAllocIdTcontClearAll, failed to schedule All T-Cont flush in WQ\n",
+	 		   __FILE_DESC__, __LINE__);
+	}
+
+
 	return (MV_OK);
 }
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h
index 0e5e6e1..14d2f5c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h
@@ -103,6 +103,7 @@
 MV_STATUS onuGponAllocIdTcontSet(MV_U32 allocId, MV_U32 tcontNum);

 MV_STATUS onuGponAllocIdTcontClear(MV_U32 tcontNum);

 MV_STATUS onuGponAllocIdDeAssignAll(void);

+MV_STATUS onuGponAllocIdFreeAllBuffers(void);

 MV_STATUS onuGponAllocIdTcontClearAll(void);

 MV_U32    onuGponIdleAllocIdTcontGet(void);

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c
index c328cfb..e20431d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c
@@ -166,6 +166,9 @@
 
   onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[alarm] = state;
 
+  if (onuGponDbOnuStateGet() == ONU_GPON_06_POPUP)
+	  return (MV_OK);
+
   if (state == ONU_GPON_ALARM_OFF)
   {
     l_onuGponCurrentAlarmState &= ~(1 << alarm);
@@ -371,7 +374,8 @@
 		  linkStatusCallback(MV_FALSE);
 		}
 
-        onuPonTxPowerOn(MV_FALSE);
+ //       onuPonTxPowerOn(MV_FALSE);
+		onuPonTxPowerTimerStateSet(MV_TRUE);
         onuGponSrvcStatusNotify(GPON_ONU_STATUS_DISCONNECTED);
         mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "=========================\n");
         mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "== Downstream sync Off ==\n");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c
index b25a37d..7f54bbc 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c
@@ -120,13 +120,19 @@
 **               MV_U8 *password
 **               MV_BOOL  disabled
 **               MV_U32   sn_src
+**               MV_U32 fecHyst
 **
 **  OUTPUTS:     None
 **
 **  RETURNS:     MV_OK or error
 **
 *******************************************************************************/
-MV_STATUS onuGponApiInit(MV_U8 *serialNumber, MV_U8 *password, MV_BOOL disabled, MV_U32 sn_src)
+MV_STATUS onuGponApiInit(MV_U8 *serialNumber, 
+                         MV_U8 *password, 
+                         MV_BOOL disabled, 
+                         MV_U32 sn_src, 
+                         MV_U32 fecHyst, 
+                         MV_U32 couplingMode)
 {
   MV_STATUS rcode;
   MV_U32    i;
@@ -155,6 +161,22 @@
     return rcode;
   }
 
+    rcode = mvOnuGponMacRxFecHysteresisSet(fecHyst);
+    if (rcode != MV_OK)
+    {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacRxFecHysteresisSet", __FILE_DESC__, __LINE__);
+        return rcode;
+    }
+
+    rcode = onuGponApiCouplingModeSet(couplingMode);
+    if (rcode != MV_OK)
+    {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacCouplingModeSet", __FILE_DESC__, __LINE__);
+        return rcode;
+    }
+
   rcode = onuGponSrvcRangingRandomInit();
   if (rcode != MV_OK)
   {
@@ -1494,9 +1516,6 @@
     return(rcode);
   }
 
-  onuGponDbXvrPolaritySet(burstConfigSet->polarity);
-  mvOnuPonMacBurstEnablePolarityInit(burstConfigSet->polarity);
-
   return(rcode);
 }
 
@@ -2109,7 +2128,47 @@
   return mvOnuGponMacRxFecStatusGet(fecMode);
 }
 
+/*******************************************************************************
+**
+**  mvGponAipCouplingModeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures the coupling mode
+**
+**  PARAMETERS:  MV_U32 couplingMode 0 : DC, 1 : AC
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponApiCouplingModeSet(MV_U32 couplingMode)
+{
+    MV_STATUS status;
+    MV_U32 devId;
+    MV_U32 burstMode = 0;
+    MV_U32 burstTime = 0;
+    MV_U8  dataPattern1 = 0;
+    MV_U8  dataPattern2 = 0;
 
+    devId = mvCtrlModelGet();
+	if (devId != MV_6601_DEV_ID)
+	{
+		return(MV_OK);
+	}
+
+    if (couplingMode == 1)  /* AC coupling mode */
+    {
+        burstMode = GPON_TX_AC_COUPL_BUST_MODE_0;
+        burstTime = GPON_TX_AC_COUPL_PREACT_BURST_TIME;
+        dataPattern1 = GPON_TX_AC_COUPL_DATA_PATTERN_1;
+        dataPattern2 = GPON_TX_AC_COUPL_DATA_PATTERN_2;
+    }
+
+    status = mvOnuGponMacTxConfigAcCouplingSet(burstMode, burstTime, dataPattern1, dataPattern2);
+
+    return (status);
+}
 
 
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h
index 962e2d7..a7b03e1 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h
@@ -169,7 +169,12 @@
 

 /* Init API

 ------------------------------------------------------------------------------*/

-MV_STATUS onuGponApiInit(MV_U8 *serialNumber, MV_U8 *password, MV_BOOL disabled, MV_U32 sn_src);

+MV_STATUS onuGponApiInit(MV_U8 *serialNumber, 

+                         MV_U8 *password, 

+                         MV_BOOL disabled, 

+                         MV_U32 sn_src, 

+                         MV_U32 fecHyst, 

+                         MV_U32 couplingMode);

 

 /* Notify API

 ------------------------------------------------------------------------------*/

@@ -232,6 +237,7 @@
 MV_U32    onuGponApiUponDebugGet(void);

 MV_STATUS onuGponApiAdminStateSet(MV_U32 mode);

 MV_STATUS onuGponApiFecStatusGet(MV_U32 *fecMode);

+MV_STATUS onuGponApiCouplingModeSet(MV_U32 couplingMode);

 

 /* Sn Mask  API

 ------------------------------------------------------------------------------*/

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c
index 8e48a4b..391bc35 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c
@@ -165,8 +165,7 @@
   onuGponDbRateSet(GPON_FRAME_DELINEATION_FR);
 
   /* set gpon xvr polarity to default value */
-  onuGponDbXvrPolaritySet(ONU_PON_XVR_POLARITY_ACT_HIGH);
-
+  
   /* set onu init status to be MV_FALSE */
   onuGponDbInitSet(MV_FALSE);
 
@@ -904,46 +903,6 @@
 
 /*******************************************************************************
 **
-**  onuGponDbXvrPolaritySet
-**  ____________________________________________________________________________
-**
-**  DESCRIPTION: The function set ONU XVR polarity in the database
-**
-**  PARAMETERS:  MV_U32 rate
-**
-**  OUTPUTS:     None
-**
-**  RETURNS:     MV_OK
-**
-*******************************************************************************/
-MV_STATUS onuGponDbXvrPolaritySet(MV_U32 polarity)
-{
-  onuGponDb_s.onuGponGenTbl_s.onuGponXvrPolarity = polarity;
-
-  return(MV_OK);
-}
-
-/*******************************************************************************
-**
-**  onuGponDbXvrPolarityGet
-**  ____________________________________________________________________________
-**
-**  DESCRIPTION: The function return onu polarity
-**
-**  PARAMETERS:  None
-**
-**  OUTPUTS:     None
-**
-**  RETURNS:     onu Rate
-**
-*******************************************************************************/
-MV_U32 onuGponDbXvrPolarityGet(void)
-{
-  return(onuGponDb_s.onuGponGenTbl_s.onuGponXvrPolarity);
-}
-
-/*******************************************************************************
-**
 **  onuGponDbAlarmNotifySet
 **  ____________________________________________________________________________
 **
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h
index 33aafa7..535b6ea 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h
@@ -122,7 +122,7 @@
   MV_U32      onuGponOnuIdOverrideEn;              /* ONU ID Overeide Enable*/
   MV_U32      onuGponOnuIdOverrideVal;             /* ONU ID Overeide value*/
   MV_U32	  onuGponRate;
-  MV_U32	  onuGponXvrPolarity;
+  MV_U32      onuGponP2pXvrBurstEnPolarity;
   GPONFUNCPTR onuGponStateAndEventTbl[ONU_GPON_NUM_OF_EVENTS][ONU_GPON_NUM_OF_STATES];
   MV_BOOL	  onuGponInit;						   /* Is ONU initialized? */
   MV_BOOL     omccValid;
@@ -276,8 +276,6 @@
 MV_STATUS onuGponDbOmccPortOverrideValueSet(MV_U32 omccPort);
 MV_STATUS onuGponDbRateSet(MV_U32 rate);
 MV_U32	  onuGponDbRateGet (void);
-MV_STATUS onuGponDbXvrPolaritySet(MV_U32 rate);
-MV_U32	  onuGponDbXvrPolarityGet (void);
 MV_BOOL   onuGponDbdGaspEnGet(void);
 MV_STATUS onuGponDbdGaspEnSet(MV_BOOL dGaspEn);
 MV_STATUS onuGponDbAlarmNotifySet(ALARMNOTIFYFUNC alarmCallback);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c
index a360076..5fef02d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c
@@ -142,6 +142,7 @@
     return(MV_ERROR);
   }
 
+  ponXvrFunc = GponXvrSDPolarityHighStatus;
   /* init onu database */
   rcode = onuGponDbInit();
   if (rcode != MV_OK)
@@ -514,9 +515,6 @@
     return(rcode);
   }
 
-  onuGponDbXvrPolaritySet(GPON_BURST_EN_P);
-  mvOnuPonMacBurstEnablePolarityInit(GPON_BURST_EN_P);
-
   rcode = mvOnuGponMacTxTxEnableCounterThresholdSet(GPON_BURST_THRESHOLD);
   if (rcode != MV_OK)
   {
@@ -661,6 +659,72 @@
 
 /*******************************************************************************
 **
+**  onuGponAsicUtmBitmapInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init UTM Active TX Bitmap
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicUtmBitmapInit(void)
+{
+	MV_STATUS status;
+
+	status =  mvOnuGponMacUtmActiveTxBitmapSet(GPON_UTM_ACTIVE_TX_BITMAP);
+	if (status == MV_OK) {
+		status =  mvOnuGponMacUtmActiveTxBitmapValidSet(GPON_UTM_ACTIVE_TX_BITMAP_VALID);
+		if (status != MV_OK)
+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) mvOnuGponMacUtmActiveTxBitmapValidSet\n\r", __FILE_DESC__, __LINE__);
+	} else
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) mvOnuGponMacUtmActiveTxBitmapSet\n\r", __FILE_DESC__, __LINE__);
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicGseTransmitThresholdInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init GSE Transmit Threshold
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicGseTransmitThresholdInit(void)
+{
+	MV_STATUS status;
+	MV_U32 threshold;
+
+	threshold = ((GPON_GST_TX_DATA_THRESHOLD << GPON_GST_TX_DATA_SHIFT) |
+						    GPON_GST_TX_IDLE_THRESHOLD);
+
+
+	status =  mvOnuGponMacTxGseTransCounterThresholdSet(threshold);
+	if (status != MV_OK)
+	{
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) mvOnuGponMacUtmActiveTxBitmapValidSet\n\r", __FILE_DESC__, __LINE__);
+		return(status);
+	}
+
+	return(MV_OK);
+
+}
+
+/*******************************************************************************
+**
 **  onuGponAsicInit
 **  ____________________________________________________________________________
 **
@@ -776,7 +840,21 @@
 		return(rcode);
 	}
 
+	rcode = onuGponAsicGseTransmitThresholdInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicGseTransmitThresholdInit\n\r", __FILE_DESC__, __LINE__);
+		return(rcode);
+	}
+
 	if (devId == MV_6601_DEV_ID) {
+		rcode = onuGponAsicUtmBitmapInit();
+		if (rcode != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) onuGponAsicUtmBitmapInit\n", __FILE_DESC__, __LINE__);
+			return(MV_ERROR);
+		}
+
 		/* GPON is always works in legacy mode */
 		MV_REG_WRITE(NETA_LEGACY_DBA_REG(MV_PON_PORT_ID), 0);
 	}
@@ -1036,7 +1114,7 @@
   /* ================ Init App Section ===================== */
   /* ======================================================= */
   onuGponApiSnMaskConfig(MV_FALSE, MV_FALSE);
-  onuGponApiInit(serialNumber, password, disabledSnState,0);
+  onuGponApiInit(serialNumber, password, disabledSnState,0, 1, 0);
 
   /* XVR reset sequence */
   mvOnuGponMacXvrReset(0);
@@ -1127,7 +1205,12 @@
   /* ======================================================= */
   /* ================ Init App Section ===================== */
   /* ======================================================= */
-  onuGponApiInit(onuInit->serialNum, onuInit->password, disabledSnState, onuInit->serialNumSource);
+  onuGponApiInit(onuInit->serialNum,
+                 onuInit->password,
+                 disabledSnState,
+                 onuInit->serialNumSource,
+                 onuInit->fecHyst,
+                 onuInit->couplingMode);
   onuGponDbGemResetSet(onuInit->clearGem == 0 ? MV_FALSE : MV_TRUE);
   onuGponDbTcontResetSet(onuInit->clearTcont  == 0 ? MV_FALSE : MV_TRUE);
   onuGponDbGemRestoreSet(onuInit->restoreGem  == 0 ? MV_FALSE : MV_TRUE);
@@ -1148,7 +1231,7 @@
   /* ======================================================= */
   /* ================ PON XVR polarity Section ============= */
   /* ======================================================= */
-  rcode = mvOnuGponMacTxBurstEnPolaritySet(onuInit->xvrPolarity);
+  rcode = mvOnuGponMacTxBurstEnPolaritySet(onuInit->ponXvrBurstEnPolarity);
   if (rcode != MV_OK)
   {
     mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
@@ -1156,8 +1239,9 @@
     return(rcode);
   }
 
-  onuGponDbXvrPolaritySet(onuInit->xvrPolarity);
-  mvOnuPonMacBurstEnablePolarityInit(onuInit->xvrPolarity);
+    ponXvrFunc = funcGponXvrSDStatus(onuInit->ponXvrPolarity);
+
+    onuP2PDbXvrBurstEnablePolaritySet(onuInit->p2pXvrBurstEnPolarity);
 
 #ifndef PON_FPGA
   /* ========================================================== */
@@ -1209,9 +1293,9 @@
 	if (devId != MV_6601_DEV_ID)
 		return(MV_OK);
 
-	return(mvOnuGponMacTxConfigAcCouplingSet(GPON_TX_AC_COUPL_BUST_MODE_0,
-						 GPON_TX_AC_COUPL_PREACT_BURST_TIME,
-						 GPON_TX_AC_COUPL_DATA_PATTERN_1,
-						 GPON_TX_AC_COUPL_DATA_PATTERN_2));
+	return (mvOnuGponMacTxConfigAcCouplingSet(GPON_TX_AC_COUPL_BUST_MODE_0,
+						                      GPON_TX_AC_COUPL_PREACT_BURST_TIME,
+						                      GPON_TX_AC_COUPL_DATA_PATTERN_1,
+						                      GPON_TX_AC_COUPL_DATA_PATTERN_2));
 }
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c
index 37d9de2..6555274 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c
@@ -147,7 +147,7 @@
 **  onuGponIsrXvrResetTimerHndl

 **  ____________________________________________________________________________

 ** 

-**  DESCRIPTION: The function is called by the GPON Iterrupt handler to execute 

+**  DESCRIPTION: The function is called by the GPON Interrupt handler to execute 

 **               XVR reset sequence in case of a problem with XVR signal detect

 **               

 **  PARAMETERS:  unsigned long data

@@ -256,6 +256,8 @@
   *interruptEvent  = (g_onuGponCurrentInterrupt >> ONU_GPON_EVENT_SHIFT) & ONU_GPON_INTERRUPTS;

   *interruptStatus = (g_onuGponCurrentInterrupt                        ) & ONU_GPON_INTERRUPTS;

 

+  onuGponSyncLog(ONU_GPON_LOG_INTERRUPT, g_onuGponCurrentInterrupt, 0, 0);

+

   g_onuGponCurrentInterrupt = 0;

 

 #ifdef MV_GPON_PERFORMANCE_CHECK

@@ -296,6 +298,41 @@
                __FILE_DESC__, __LINE__, interruptEvent, interruptStatus, timer); 

 #endif

 

+    if (interruptEvent & ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK)

+    {

+        state = ponXvrFunc(interruptStatus, ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK);

+

+	  if (state == MV_TRUE)

+	  {

+		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_FALSE);

+		/* Set signal detect to ON */

+		onuGponDbOnuSignalDetectSet(1);

+

+#ifdef MV_GPON_DEBUG_PRINT

+		mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE,

+			   "DEBUG: (%s:%d) Set signal detect to ON = 1 \n", __FILE_DESC__, __LINE__);

+#endif /* MV_GPON_DEBUG_PRINT */

+#ifndef PON_FPGA

+		onuGponIsrXvrReset();

+		onuGponIsrXvrResetStateSet(MV_TRUE);

+		//onuGponPonMngIntrMessageHandler();

+#endif /* PON_FPGA */

+	  }

+	  else if (state == MV_FALSE)

+	  {

+		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_TRUE);

+		/* Set signal detect to OFF */

+		onuGponDbOnuSignalDetectSet(0);

+

+#ifdef MV_GPON_DEBUG_PRINT

+		mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE,

+			   "DEBUG: (%s:%d) Set signal detect to OFF = 0\n", __FILE_DESC__, __LINE__);

+#endif /* MV_GPON_DEBUG_PRINT */

+	  }

+

+	  onuGponSyncLog(ONU_GPON_LOG_INTERRUPT_XVR_SD, state, 0, 0);

+    }

+    

     if (interruptEvent & ONU_GPON_LOS_ALARM_MASK)

     {

      // state = (interruptStatus & ONU_GPON_LOS_ALARM_MASK) ? MV_TRUE : MV_FALSE;

@@ -307,6 +344,8 @@
       state = (interruptStatus & ONU_GPON_LOF_ALARM_MASK) ? MV_TRUE : MV_FALSE;

       onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOF_ALARM, state);

 

+      onuGponSyncLog(ONU_GPON_LOG_INTERRUPT_LOF, state, 0, 0);

+

 	 // if (state == MV_TRUE) 

 	 // {

   	 //   /* Set DS Sync Ind to OFF */

@@ -380,42 +419,10 @@
     if (interruptEvent & ONU_GPON_PHY_SIGNAL_DETECT_STATUS_MASK)

     {

 #ifdef MV_GPON_DEBUG_PRINT

-      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE,

                  "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

 #endif /* MV_GPON_DEBUG_PRINT */

     }

-

-    if (interruptEvent & ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK)

-    {

-  	  state = (interruptStatus & ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK) ? MV_TRUE : MV_FALSE;

-

-	  if (state == MV_TRUE) 

-	  {

-		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_FALSE);

-  	    /* Set signal detect to ON */

-		onuGponDbOnuSignalDetectSet(1);

-

-#ifdef MV_GPON_DEBUG_PRINT

-        mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

-                   "DEBUG: (%s:%d) Set signal detect to ON = 1 \n", __FILE_DESC__, __LINE__);

-#endif /* MV_GPON_DEBUG_PRINT */

-#ifndef PON_FPGA

-        onuGponIsrXvrReset();

-        onuGponPonMngIntrMessageHandler();

-#endif /* PON_FPGA */

-	  }

-	  else if (state == MV_FALSE)

-	  {

-		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_TRUE);

-	    /* Set signal detect to OFF */

-        onuGponDbOnuSignalDetectSet(0);

-

-#ifdef MV_GPON_DEBUG_PRINT

-        mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

-                   "DEBUG: (%s:%d) Set signal detect to OFF = 0\n", __FILE_DESC__, __LINE__);

-#endif /* MV_GPON_DEBUG_PRINT */

-	  }

-    }

   }

 }

 

@@ -477,12 +484,19 @@
   MV_STATUS status;

   MV_U32    onuState;

   MV_U32    initDone;

+  MV_U32    durationStart = 0;

+  MV_U32    durationEnd   = 0;

+

 

   onuState = onuGponDbOnuStateGet();

   if ((onuState == ONU_GPON_01_INIT) ||

-     ((onuState == ONU_GPON_07_EMERGANCY_STOP) && (onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_ON)) || 

-	 ((onuState == ONU_GPON_06_POPUP)))

+     ((onuState == ONU_GPON_07_EMERGANCY_STOP) && (onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_ON)) ||

+     ((onuState == ONU_GPON_06_POPUP)          && ((onuGponAlarmGet(ONU_GPON_ALARM_LOS) == ONU_GPON_ALARM_OFF) &&

+                                                   (onuGponAlarmGet(ONU_GPON_ALARM_LOF) == ONU_GPON_ALARM_ON))))

   {

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, &durationStart, 0);

+    onuGponSyncLog(ONU_GPON_LOG_INTERRUPT_SERDES_START, 0, 0, 0);

+

     status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);  

     if (status != MV_OK) 

       return(status);

@@ -493,11 +507,17 @@
       if (status != MV_OK) 

         return(status);

 

+      asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, &durationEnd, 0);

+      if (abs((durationEnd - durationStart)) >= 6000)

+	      return (MV_OK);

+

     } while (initDone == 0);

 

     status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);  

     if (status != MV_OK) 

       return(status);

+

+    onuGponSyncLog(ONU_GPON_LOG_INTERRUPT_SERDES_STOP, 0, 0, 0);

   }

   else

   {

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c
index 71f0803..139e964 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c
@@ -364,6 +364,7 @@
   MV_U32          onuState;

   GPONFUNCPTR     ptrFunc;

   S_OnuGponGenTbl *onuGponGenTbl_p = &(onuGponDb_s.onuGponGenTbl_s);

+  MV_U32          *msgData_p = msgData;

 

   /* get onu Id */

   appOnuId = onuGponDbOnuIdGet();

@@ -389,6 +390,9 @@
       {

         (*ptrFunc)(onuId, msgId, msgData);

       }           

+

+      onuGponSyncLog(ONU_GPON_LOG_MSG, onuId, msgId, 0);

+      onuGponSyncLog(ONU_GPON_LOG_MSG_CONTENT, *(msgData_p), *(msgData_p + 1), *(msgData_p + 2));

     }

     /* handle invalid messages */

     else

@@ -536,12 +540,6 @@
 

   onuPonResourceTbl_s.onuPonSwFIFOTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;

 

-  if (onuGponDbOnuStateGet() == ONU_GPON_05_OPERATION)

-  {

-    spin_unlock_irqrestore(&onuPonIrqLock, flags);

-    return;

-  }

-

   /* Call PM handler */

   mvOnuGponFifoAuditTimerExpireHndl();

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h
index 8e54d99..d63cf1d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h
@@ -175,6 +175,7 @@
 void      onuGponPonMngTimerT01ExpireHndl(void);

 void      onuGponPonMngTimerT02ExpireHndl(void);

 void      onuGponPonMngTimerPeeExpireHndl(void);

+void 	  onuGponTimerTxPwrHndl(unsigned long data);

 

 /* Alarm Functions */

 void      onuGponPonMngGenCritAlarm(E_OnuGponAlarmType alarmType_e, MV_U8 dummyVal, MV_U8 *dummyPtr);

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c
index 5248f2b..f645b34 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c
@@ -102,6 +102,7 @@
 ------------------------------------------------------------------------------*/
 MV_STATUS onuGponPonMngrUpdateState(MV_U32 newState);
 MV_STATUS onuGponPonMngClearOnuInfo(void);
+MV_STATUS onuGponPonMngClearOnuBuffers(void);
 MV_STATUS onuGponPonMngClearOnuTconts(void);
 MV_STATUS onuGponPonMngClearOnuPorts(void);
 MV_STATUS onuGponPonMngClearOnuId(void);
@@ -165,13 +166,9 @@
 #endif /* PON_FPGA */
 
     /* stop onu periodic timers */
-    if (g_periodicTimerState != MV_FALSE)
-    {
-      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonPmTimerId));
-      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
-      mvOnuGponMacMessageCleanSwFifo();
-      g_periodicTimerState = MV_FALSE;
-    }
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonPmTimerId));
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
+    mvOnuGponMacMessageCleanSwFifo();
   }
 
   if (newState == ONU_GPON_02_STANDBY)
@@ -182,13 +179,12 @@
 #endif /* PON_FPGA */
 
     /* start onu periodic timers */
-    if (g_periodicTimerState != MV_TRUE)
-    {
-      onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));
-      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
-      mvOnuGponMacMessageCleanSwFifo();
-      g_periodicTimerState = MV_TRUE;
-    }
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
+    mvOnuGponMacMessageCleanSwFifo();
+
+    /* stop onu gpon xvr reset timer */
+    onuGponIsrXvrResetStateSet(MV_FALSE);
   }
 
   rcode = onuGponPonMngPreambleSet(newState);
@@ -224,6 +220,8 @@
     return(rcode);
   }
 
+  onuGponSyncLog(ONU_GPON_LOG_STATE, asicNewState, 0, 0);
+
   /* update database */
   onuGponDbOnuStateSet(newState);
 
@@ -237,6 +235,34 @@
 
 /*******************************************************************************
 **
+**  onuGponPonMngClearOnuBuffers
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset onu buffers to its default state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuBuffers(void)
+{
+   MV_STATUS rcode;
+
+   rcode = onuGponAllocIdFreeAllBuffers();
+   if (rcode != MV_OK)
+   {
+     mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+   	     "ERROR: (%s:%d) onuGponPonMngClearOnuBuffers\n", __FILE_DESC__, __LINE__);
+   }
+
+   return(MV_OK);
+}
+
+/*******************************************************************************
+**
 **  onuGponPonMngClearOnuInfo
 **  ____________________________________________________________________________
 **
@@ -268,6 +294,14 @@
                "ERROR: (%s:%d) onuGponPonMngClearOnuTconts\n", __FILE_DESC__, __LINE__);    return(rcode);
   }
 
+  rcode = onuGponPonMngClearOnuBuffers();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuBuffers\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
   rcode = onuGponPonMngClearOnuId();
   if (rcode != MV_OK)
   {
@@ -1067,6 +1101,9 @@
   finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay);
   equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
 
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+	     "Range Debug Info: (%s:%d), State O4, Message: equalizationDelay(%d:0x%x), finalDelay(%d:0x%x)\n",
+	     __FILE_DESC__, __LINE__, equalizationDelay, equalizationDelay, finalDelay, finalDelay);
 
   /* sync state */
   /* ========== */
@@ -1100,6 +1137,11 @@
     /* update database */
     onuGponDbEqualizationDelaySet(msgDelay);
 
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+	       "Range Debug Info: (%s:%d), State O4, Calc: equalizationDelay(%d:0x%x), finalDelay(%d:0x%x)\n",
+	       __FILE_DESC__, __LINE__, equalizationDelay, equalizationDelay, finalDelay, finalDelay);
+
+
     /* alarm handling */
     /* ============== */
     onuGponAlarmSet(ONU_GPON_ALARM_SUF, ONU_GPON_ALARM_OFF);
@@ -1138,16 +1180,33 @@
     /* get current delay */
     currentDelay = onuGponDbEqualizationDelayGet();
 
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+	       "Range Debug Info: (%s:%d), State O5, Current equalization Delay from DB(%d:0x%x)\n",
+	       __FILE_DESC__, __LINE__, currentDelay, currentDelay);
+
     /* Reduce Equlization delay */
     if (currentDelay > msgDelay)
     {
       changeDelay = currentDelay - msgDelay;
+
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		 "Range Debug Info: (%s:%d), State O5, Current equalization Delay(0x%x) > Message equalization Delay(0x%x), change(0x%x)\n",
+		 __FILE_DESC__, __LINE__, currentDelay, msgDelay, changeDelay);
+
       mvOnuGponMacTxFinalDelayGet(&currFinalDelay);
 
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		 "Range Debug Info: (%s:%d), State O5, Final delay from DB (0x%x)\n",
+		 __FILE_DESC__, __LINE__, currFinalDelay);
+
       /* Check if can change the TX Final Delay only */
       if (changeDelay <= currFinalDelay)
       {
         finalDelay = currFinalDelay - changeDelay;
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		   "Range Debug Info: (%s:%d), State O5, Change delay <= Final delay, updated final delay, finalDelay = currFinalDelay - changeDelay, (0x%x)\n",
+		   __FILE_DESC__, __LINE__, finalDelay);
       }
       else
       {
@@ -1156,6 +1215,10 @@
                    "ERROR: (%s:%d) Change Range delay while O5 - Update EqD\n", __FILE_DESC__, __LINE__);
 #endif /* MV_GPON_DEBUG_PRINT */
 
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		   "Range Debug Info: (%s:%d), State O5, Change > Final delay, updated equalization delay\n",
+		   __FILE_DESC__, __LINE__);
+
         /* calc delay */
         finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay) + (MV_U32)GPON_TX_FINAL_DELAY_FD;
         equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
@@ -1168,6 +1231,10 @@
                      __FILE_DESC__, __LINE__, equalizationDelay);
           return;
         }
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		   "Range Debug Info: (%s:%d), State O5, Updated: equalizationDelay(%d:0x%x), finalDelay(%d:0x%x)\n",
+		   __FILE_DESC__, __LINE__, equalizationDelay, equalizationDelay, finalDelay, finalDelay);
       }
 
       rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
@@ -1184,12 +1251,25 @@
     else if (currentDelay < msgDelay)
     {
       changeDelay = msgDelay - currentDelay;
+
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		 "Range Debug Info: (%s:%d), State O5, Current equalization Delay(0x%x) < Message equalization Delay(0x%x), change(0x%x)\n",
+		 __FILE_DESC__, __LINE__, currentDelay, msgDelay, changeDelay);
+
       mvOnuGponMacTxFinalDelayGet(&currFinalDelay);
 
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		 "Range Debug Info: (%s:%d), State O5, Final delay from DB (0x%x)\n",
+		 __FILE_DESC__, __LINE__, currFinalDelay);
+
       /* Check if can change the TX Final Delay only */
       if (changeDelay + currFinalDelay > GPON_TX_FINAL_DELAY_MAX)
       {
         finalDelay = currFinalDelay + changeDelay;
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		   "Range Debug Info: (%s:%d), State O5, Change delay + current Final delay > MAX Final delay(0x3F), updated final delay, finalDelay = currFinalDelay + changeDelay, (0x%x)\n",
+		   __FILE_DESC__, __LINE__, finalDelay);
       }
       else
       {
@@ -1198,6 +1278,10 @@
                    "DEBUG: (%s:%d) Change Range delay while O5 - Update EqD\n", __FILE_DESC__, __LINE__);
 #endif /* MV_GPON_DEBUG_PRINT */
 
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		   "Range Debug Info: (%s:%d), State O5, Change delay + Final delay < MAX Final delay = 0x3F, updated equalization delay\n",
+		   __FILE_DESC__, __LINE__);
+
         /* calc delay */
         finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay) + (MV_U32)GPON_TX_FINAL_DELAY_FD;
         equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
@@ -1213,6 +1297,11 @@
         }
       }
 
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+		 "Range Debug Info: (%s:%d), State O5, Updated: equalizationDelay(%d:0x%x), finalDelay(%d:0x%x)\n",
+		 __FILE_DESC__, __LINE__, equalizationDelay, equalizationDelay, finalDelay, finalDelay);
+
+
       rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
       if (rcode != MV_OK)
       {
@@ -1375,6 +1464,8 @@
 	if ((disableStatus == GPON_ONU_DISABLE) && (isSnMatch == MV_TRUE) &&
 		(onuState != ONU_GPON_07_EMERGANCY_STOP)) {
 
+        onuPonTxPowerOn(MV_FALSE);
+
 		/* clear onu information */
 		/* ===================== */
 		rcode = onuGponPonMngClearOnuInfo();
@@ -1425,6 +1516,8 @@
 			  ((disableStatus == GPON_ONU_ENABLE_ONU) && (isSnMatch == MV_TRUE))) &&
 			 (onuState == ONU_GPON_07_EMERGANCY_STOP)) {
 
+        onuPonTxPowerOn(MV_TRUE);
+
 		/* alarm handling */
 		/* ============== */
 		onuGponAlarmSet(ONU_GPON_ALARM_DIS, ONU_GPON_ALARM_OFF);
@@ -1634,8 +1727,8 @@
   mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
              "[US PLOAM] PASSWORD, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
              srcOnuId, msgId,
-             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
-             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+             password [0], password [1], password [2], password [3], password [4],
+             password [5], password [6], password [7], password [8], password [9]);
 #endif /* MV_GPON_DEBUG_PRINT */
 
 #ifdef MV_GPON_PERFORMANCE_CHECK
@@ -1849,6 +1942,8 @@
 
   /* stop onu gpon pon mng T02 timer */
   onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT02_TimerId));
+  /* stop onu gpon xvr reset timer */
+  onuGponIsrXvrResetStateSet(MV_FALSE);
 
   if (onuId == ONU_GPON_BROADCAST_ONU_ID) /* Broadcast ONU-ID */
   {
@@ -2766,6 +2861,10 @@
 	else
 	  mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
 	  		     "ERROR: (%s:%d) wrong start to T02\n", __FILE_DESC__, __LINE__);
+#ifndef PON_FPGA
+	/* start xvr reset timer */
+	onuGponIsrXvrResetStateSet(MV_TRUE);
+#endif /* PON_FPGA */
 
 #ifdef MV_GPON_DEBUG_PRINT
     mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "===========\n");
@@ -2827,7 +2926,6 @@
 
   /* alarm handling */
   /* ============== */
-  if (onuGponDbOnuStateGet() != ONU_GPON_06_POPUP)
   onuGponAlarmSet(alarmType_e, ONU_GPON_ALARM_ON);
 }
 
@@ -3044,5 +3142,36 @@
   return(MV_OK);
 }
 
+/*******************************************************************************
+**
+**  onuGponTimerTxPwrHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called by the GPON handler in the case of DS
+**               sync off to start 1 sec timer that will disable Tx if expired
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponTimerTxPwrHndl(unsigned long data)
+{
+  unsigned long flags;
 
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonTxPwrTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  if (onuGponDbOnuStateGet() < ONU_GPON_02_STANDBY)
+  {
+     onuPonTxPowerOn(MV_FALSE);
+  }
+
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonTxPwrTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c
index 654bd6d..044f589 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c
@@ -78,6 +78,7 @@
 /* Include Files

 ------------------------------------------------------------------------------*/

 #include "gponOnuHeader.h"

+#include "tpm_api.h"

 

 /* Local Constant

 ------------------------------------------------------------------------------*/  

@@ -100,7 +101,20 @@
 

 /* Local Variables

 ------------------------------------------------------------------------------*/

-  

+S_OnuGponLogEntry onuGponLogDb[ONU_GPON_LOG_SIZE + 1];

+MV_32             onuGponLogDbEntryIndex = 0;

+MV_32             onuGponLogDbEntryCount = 0;

+MV_BOOL           onuGponLogEnable = MV_FALSE;

+

+MV_32             onuGponTcontFlushState[8] = {TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE,

+                                               TCONT_FLUSH_READY_STATE};

+

 /* Export Functions

 ------------------------------------------------------------------------------*/

 MV_STATUS     onuGponSrvcGenCrcTable(void);

@@ -1076,3 +1090,333 @@
   return(MV_OK);

 }

 

+/*******************************************************************************

+**

+**                            SYNC LOG SECTION

+**

+********************************************************************************/

+

+/*******************************************************************************

+**

+**  onuGponSyncLogEnable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function enable log mechanism to start record events

+**

+**  PARAMETERS:  MV_U32 enable

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+void onuGponSyncLogEnable(MV_U32 enable)

+{

+    if (enable == 0)

+    {

+        onuGponLogEnable = MV_FALSE;

+

+        onuGponLogDbEntryCount = 0;

+        onuGponLogDbEntryIndex = 0;

+    }

+    else

+    {

+        onuGponLogEnable = MV_TRUE;

+    }

+}

+

+/*******************************************************************************

+**

+**  onuGponSyncLog

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function logs records into the cyclic log buffer

+**

+**  PARAMETERS:  MV_U32 event, MV_U32 data1, MV_U32 data2, MV_U32 data3

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+void onuGponSyncLog(MV_U32 event, MV_U32 data1, MV_U32 data2, MV_U32 data3)

+{

+    MV_U32 currentState;

+    MV_U32 timeStamp;

+

+	if (onuGponLogEnable != MV_TRUE)

+    {

+        return;

+	}

+

+    currentState = onuGponDbOnuStateGet();

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, &timeStamp, 0);

+

+    if (onuGponLogDbEntryIndex == ONU_GPON_LOG_SIZE)

+    {

+        onuGponLogDbEntryIndex = 0;

+    }

+

+	/* save log information */

+	onuGponLogDb[onuGponLogDbEntryIndex].event    = event;

+	onuGponLogDb[onuGponLogDbEntryIndex].state    = currentState;

+	onuGponLogDb[onuGponLogDbEntryIndex].time     = timeStamp;

+	onuGponLogDb[onuGponLogDbEntryIndex].dataVal1 = data1;

+	onuGponLogDb[onuGponLogDbEntryIndex].dataVal2 = data2;

+	onuGponLogDb[onuGponLogDbEntryIndex].dataVal3 = data3;

+

+    onuGponLogDbEntryIndex++;

+

+    /* The max number of counter is 512 */

+    if (onuGponLogDbEntryCount < ONU_GPON_LOG_SIZE)

+    {

+        onuGponLogDbEntryCount++;

+    }

+}

+

+/*******************************************************************************

+**

+**  onuGponSyncLogPrint

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function print the records placed in the log

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+void onuGponSyncLogPrint(void)

+{

+    MV_32 index;

+	MV_U32 printEntry;

+    MV_BOOL logEnabled;

+

+    logEnabled = onuGponLogEnable;

+	onuGponLogEnable = MV_FALSE;

+

+	printk("=======GPON LOG has %d items=======\r\n", onuGponLogDbEntryCount);

+

+	for (index = 0; index < onuGponLogDbEntryCount; index++)

+	{

+		if ((onuGponLogDbEntryIndex - index) > 0)

+		{

+			printEntry = onuGponLogDbEntryIndex - index - 1;

+		}

+		else

+		{

+			printEntry = ((MV_U32)ONU_GPON_LOG_SIZE - 1) - (index - onuGponLogDbEntryIndex);

+		}

+

+        switch(onuGponLogDb[printEntry].event)

+        {

+        case ONU_GPON_LOG_MSG:

+            printk("[%03d] PLOAM message, state=%d, time=%08x, onuId=%d, msgId=%d\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time,

+                    onuGponLogDb[printEntry].dataVal1,

+                    onuGponLogDb[printEntry].dataVal2);

+            break;

+

+        case ONU_GPON_LOG_MSG_CONTENT:

+            printk("[%03d] PLOAM message, data=0x%08x%08x%08x\n", printEntry,

+                    onuGponLogDb[printEntry].dataVal1,

+                    onuGponLogDb[printEntry].dataVal2,

+                    onuGponLogDb[printEntry].dataVal3);

+            break;

+

+        case ONU_GPON_LOG_INTERRUPT:

+            printk("[%03d] Interrupt, state=%d, time=%08x, event&status=0x%08x\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time,

+                    onuGponLogDb[printEntry].dataVal1);

+            break;

+

+        case ONU_GPON_LOG_INTERRUPT_XVR_SD:

+            printk("[%03d] LOS Interrupt, state=%d, time=%08x, status=%d\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time,

+                    onuGponLogDb[printEntry].dataVal1);

+            break;

+

+        case ONU_GPON_LOG_INTERRUPT_LOF:

+            printk("[%03d] LOF Interrupt, state=%d, time=%08x, status=%d\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time,

+                    onuGponLogDb[printEntry].dataVal1);

+            break;

+

+        case ONU_GPON_LOG_INTERRUPT_SERDES_START:

+            printk("[%03d] SERDES Start, state=%d, time=%08x\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time);

+            break;

+

+        case ONU_GPON_LOG_INTERRUPT_SERDES_STOP:

+            printk("[%03d] Interrupt, state=%d, time=%08x\n", printEntry,

+                    onuGponLogDb[printEntry].state,

+                    onuGponLogDb[printEntry].time);

+            break;

+

+        case ONU_GPON_LOG_STATE:

+            printk("[%03d] State, state=%d, time=%08x\n", printEntry,

+                    onuGponLogDb[printEntry].dataVal1,

+                    onuGponLogDb[printEntry].time);

+            break;

+

+        default:

+            printk("[%03d] Other\r\n", printEntry);

+            break;

+        }

+    }

+

+    onuGponLogDbEntryCount = 0;

+    onuGponLogDbEntryIndex = 0;

+

+    onuGponLogEnable = logEnabled;

+}

+

+/*******************************************************************************

+**

+**                            T-CONT FLUSH SECTION

+**

+********************************************************************************/

+

+/*******************************************************************************

+**

+**  onuGponWqTcontFlush

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function schedule T-Cont queue flush work to the T-Cont

+**               work queue

+**

+**  PARAMETERS:  MV_U32 tcont

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuGponWqTcontFlush(MV_U32 tcont)

+{

+    MV_STATUS rcode;

+

+    if (tcont != 0xFF)

+	rcode = queue_work(gponTcontFlushWq.ponWq, (struct work_struct *)&gponTcontCleanWork[tcont]);

+    else

+        rcode = queue_work(gponTcontFlushWq.ponWq, (struct work_struct *)&gponTcontCleanAllWork);

+

+    if(rcode == 0)

+	return(MV_ERROR);

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponWqTcontActivate

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function schedule T-Cont queue activate work to the T-Cont

+**               work queue

+**

+**  PARAMETERS:  MV_U32 tcont

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuGponWqTcontActivate(MV_U32 tcont)

+{

+    MV_STATUS rcode;

+

+    rcode = queue_work(gponTcontFlushWq.ponWq, (struct work_struct *)&gponTcontActiveWork[tcont]);

+    if(rcode == 0)

+        return(MV_ERROR);

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponWqTcontFunc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function process incoming work to the T-Cont work queue

+**

+**  PARAMETERS:  struct work_struct *work

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+void onuGponWqTcontFunc(struct work_struct *work)

+{

+    S_onuPonWork *currentWork = (S_onuPonWork *)work;

+    MV_U32 tcont = currentWork->param;

+    MV_U32 index = 0;

+

+    MV_U8 *stateText[] = {"",

+                          "Ready State   ",

+                          "Running State ",

+                          "Blocking State"};

+

+    /* Handle T-Cont Clear */

+    /* =================== */

+    if (currentWork->action == TCONT_CLEAN_EVENT)

+    {

+	if (onuGponTcontFlushState[tcont] == TCONT_FLUSH_RUNNING_STATE)

+	{

+	   onuGponTcontFlushState[tcont] = TCONT_FLUSH_BLOCKING_STATE;

+	   tpm_deactive_tcont(tcont);

+	   printk("TCONT (%d) CLEAN_EVENT\n", tcont);

+	   onuGponTcontFlushState[tcont] = TCONT_FLUSH_READY_STATE;

+	}

+	else

+	{

+	   printk("Received TCONT_CLEAN_EVENT while in T-CONT(%d) state(%s)\n", tcont, stateText[onuGponTcontFlushState[tcont]]);

+	}

+    }

+

+    /* Handle All T-Cont Clear */

+    /* ======================= */

+    else if (currentWork->action == TCONT_CLEAN_ALL_EVENT)

+    {

+	for (tcont = 0; tcont < 8; tcont++)

+	{

+	    if (onuGponTcontFlushState[tcont] == TCONT_FLUSH_RUNNING_STATE)

+	    {

+	       onuGponTcontFlushState[tcont] = TCONT_FLUSH_BLOCKING_STATE;

+	       tpm_deactive_tcont(tcont);

+	       printk("TCONT (%d) CLEAN_EVENT\n", tcont);

+	       onuGponTcontFlushState[tcont] = TCONT_FLUSH_READY_STATE;

+	    }

+	    else

+	    {

+	       printk("Received TCONT_CLEAN_EVENT while in T-CONT(%d) state(%s)\n", tcont, stateText[onuGponTcontFlushState[tcont]]);

+	    }

+	}

+    }

+

+    /* Handle T-Cont Activate */

+    /* ====================== */

+    else if (currentWork->action == TCONT_ACTIVE_EVENT)

+    {

+       if (onuGponTcontFlushState[tcont] == TCONT_FLUSH_READY_STATE)

+       {

+          onuGponTcontFlushState[tcont] = TCONT_FLUSH_RUNNING_STATE;

+          tpm_active_tcont(tcont);

+          printk("TCONT (%d) ACTIVE_EVENT\n", tcont);

+       }

+       else

+       {

+           printk("Received TCONT_ACTIVE_EVENT while in T-CONT state(%s)\n", stateText[onuGponTcontFlushState[tcont]]);

+       }

+    }

+

+    return;

+}

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h
index 839e60c..ed08b2d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h
@@ -80,11 +80,29 @@
 ------------------------------------------------------------------------------*/

  

 /* Definitions

-------------------------------------------------------------------------------*/ 

+------------------------------------------------------------------------------*/

+#define ONU_GPON_LOG_INTERRUPT			(1)

+#define ONU_GPON_LOG_INTERRUPT_XVR_SD		(2)

+#define ONU_GPON_LOG_INTERRUPT_LOF		(3)

+#define ONU_GPON_LOG_INTERRUPT_SERDES_START	(4)

+#define ONU_GPON_LOG_INTERRUPT_SERDES_STOP	(5)

+#define ONU_GPON_LOG_STATE			(6)

+#define ONU_GPON_LOG_MSG			(7)

+#define ONU_GPON_LOG_MSG_CONTENT		(8)

 

-/* Enums                              

-------------------------------------------------------------------------------*/ 

-  

+#define ONU_GPON_LOG_SIZE                       (512)

+

+#define TCONT_CLEAN_EVENT                       (0)

+#define TCONT_CLEAN_ALL_EVENT                   (1)

+#define TCONT_ACTIVE_EVENT                      (2)

+

+#define TCONT_FLUSH_READY_STATE                 (1)

+#define TCONT_FLUSH_RUNNING_STATE               (2)

+#define TCONT_FLUSH_BLOCKING_STATE              (3)

+

+/* Enums

+------------------------------------------------------------------------------*/

+

 /* Typedefs

 ------------------------------------------------------------------------------*/

 typedef struct

@@ -93,8 +111,22 @@
   MV_U32 blockSize;

 }S_DbrBlockSize;

 

+typedef struct

+{

+  MV_U16  event;

+  MV_U16  state;

+  MV_U32  time;

+  MV_U32  dataVal1;

+  MV_U32  dataVal2;

+  MV_U32  dataVal3;

+}S_OnuGponLogEntry;

+

 /* Global variables

 ------------------------------------------------------------------------------*/

+extern S_onuPonWork      gponTcontCleanWork[8];

+extern S_onuPonWork      gponTcontCleanAllWork;

+extern S_onuPonWork      gponTcontActiveWork[8];

+extern S_onuPonWorkQueue gponTcontFlushWq;

 

 /* Global functions

 ------------------------------------------------------------------------------*/

@@ -112,6 +144,14 @@
 MV_STATUS     onuGponSrvcDbrBlockSizeSet(MV_U32 blockSize, MV_U32 *actualBlockSize);

 MV_STATUS     onuGponSrvcRangingRandomInit(void);

 

+void 	      onuGponSyncLog(MV_U32 event, MV_U32 data1, MV_U32 data2, MV_U32 data3);

+void 	      onuGponSyncLogEnable(MV_U32 enable);

+void 	      onuGponSyncLogPrint(void);

+

+extern void onuGponWqTcontFunc(struct work_struct *work);

+extern MV_STATUS onuGponWqTcontFlush(MV_U32 tcont);

+extern MV_STATUS onuGponWqTcontActivate(MV_U32 tcont);

+

 /* Macros

 ------------------------------------------------------------------------------*/    

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c
index d847357..e5baf82 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c
@@ -898,8 +898,14 @@
       }
 
 	  spin_lock_irqsave(&onuPonIrqLock, flags);
-      if (ioctlState) status = mvP2PStart();
-      else            status = mvP2PStop();
+      if (ioctlState)
+      {
+        status = mvP2PStart();
+      }
+      else
+      {
+        status = mvP2PStop();
+      }
 	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
 
       if (status != MV_OK)
@@ -908,6 +914,29 @@
       ret = 0;
       break;
 
+    /* ====== MVEPON_IOCTL_P2P_ FORCE_MODE_SET ==================== */
+    case MVEPON_IOCTL_P2P_FORCE_MODE_SET:
+        if (copy_from_user(&ioctlState, (MV_U32*)arg, sizeof(MV_U32)))
+        {
+            mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                       "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+            goto ioctlErr;
+        }
+
+        spin_lock_irqsave(&onuPonIrqLock, flags);
+        
+        onuEponDbP2PForceModeSet(ioctlState);
+        
+        spin_unlock_irqrestore(&onuPonIrqLock, flags);
+
+        if (status != MV_OK)
+        {
+            goto ioctlErr;
+        }
+
+        ret = 0;
+        break;
+        
     /* ====== MVEPON_IOCTL_TDM_QUE_CFG ==================== */
     case MVEPON_IOCTL_TDM_QUE_CFG:
       if(copy_from_user(&ioctlTdmQueue,  (S_EponIoctlTdmQueue*)arg, sizeof(S_EponIoctlTdmQueue)))
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h
index 0cdb12f..d73b4e3 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h
@@ -94,9 +94,10 @@
 #define MVEPON_IOCTL_HOLDOVER_RPRT _IOW(MVPON_IOCTL_MAGIC, 10, unsigned int)

 #define MVEPON_IOCTL_SILENCE       _IOW(MVPON_IOCTL_MAGIC, 11, unsigned int)

 #define MVEPON_IOCTL_P2P_SET       _IOW(MVPON_IOCTL_MAGIC, 12, unsigned int)

-#define MVEPON_IOCTL_TDM_QUE_CFG   _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

-#define MVEPON_IOCTL_ALARM_GET     _IOR(MVPON_IOCTL_MAGIC, 14, unsigned int)

-#define MVEPON_IOCTL_ROGUE_ONU_SET _IOW(MVPON_IOCTL_MAGIC, 15, unsigned int)
+#define MVEPON_IOCTL_P2P_FORCE_MODE_SET _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

+#define MVEPON_IOCTL_TDM_QUE_CFG   _IOW(MVPON_IOCTL_MAGIC, 14, unsigned int)

+#define MVEPON_IOCTL_ALARM_GET     _IOR(MVPON_IOCTL_MAGIC, 15, unsigned int)

+#define MVEPON_IOCTL_ROGUE_ONU_SET _IOW(MVPON_IOCTL_MAGIC, 16, unsigned int)
 

 #define EPON_MAX_NUM_OF_MAC          (8)

 #define EPON_MAX_NUM_OF_QUEUE        (8)

@@ -224,8 +225,12 @@
 /* Init */

 typedef struct

 {

-  MV_U32 xvrPolarity;

+  MV_U32 ponXvrBurstEnPolarity;

+  MV_U32 ponXvrPolarity;

+  MV_U32 p2pXvrBurstEnPolarity;

+  MV_U32 p2pXvrPolarity;

   MV_U32 dgPolarity;

+  MV_U32 pkt2kSupported;

   MV_U8  macAddr[EPON_MAX_NUM_OF_MAC][EPON_MAC_LEN];

 }S_EponIoctlInit;

 

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c
index e425751..ce98eb1 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c
@@ -894,6 +894,7 @@
 											"limits\n");
 		off += mvOsSPrintf(buf+off, " echo [threshold]     > rxDataFifoThresh - Configure RX Parser Data FIFO "
 											"threshold\n");
+        off += mvOsSPrintf(buf+off, " echo [pkt2kSupported] > pkt2kEn - Configure 2K packet supported\r\n");
 		off += mvOsSPrintf(buf+off, " echo [txMask][txP][serdesP][xvrP][burstEn] > ddmTxPolarity - Configure "
 											" DDM Polarity settings\n");
 	}
@@ -906,6 +907,7 @@
 		off += mvOsSPrintf(buf+off, " cat pcsFrameLimits                     - dump PCS Frame Size Limits\n");
 		off += mvOsSPrintf(buf+off, " cat rxDataFifoThresh                   - dump RX Parser Data FIFO "
 											"threshold\n");
+        off += mvOsSPrintf(buf+off, " cat pkt2kEn                            - dump 2K packet supported registers\r\n");
 	}
 	off += mvOsSPrintf(buf+off, "============================================================================\n");
 
@@ -1408,6 +1410,7 @@
   }
   else
   {
+    onuPonTxPowerOn(MV_TRUE);
     onuPonPatternBurstOn(pattern, (MV_BOOL)burst, period, duration);
   }
 }
@@ -1518,6 +1521,68 @@
 
 /*******************************************************************************
 **
+**  onuEponUiCfgSetPkt2kEnable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures 2K packet supported
+**
+**  PARAMETERS:  MV_U32 enable - 2K packet supported enable or disable
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSetPkt2kEnable(MV_U32 enable)
+{
+    /* Before setting register, needs to disable Rx */
+    mvOnuEponMacPcsRxEnableSet(EPON_PCS_CONFIG_RX_DISABLE); 
+    
+    mvEponApi2kSupportedSet(enable);
+
+    /* After setting register, enable Rx */
+    mvOnuEponMacPcsRxEnableSet(EPON_PCS_CONFIG_RX_ENABLE);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgShowPkt2kEnable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function shows 2K packet supported
+**
+**  PARAMETERS:  char *buf
+**
+**  OUTPUTS:     char *buf
+**
+**  RETURNS:     offset of buf
+**
+*******************************************************************************/
+int onuEponUiCfgShowPkt2kEnable(char* buf)
+{
+    int off = 0;
+	MV_STATUS status;
+	MV_U32 frameSizeLimitSize;
+    MV_U32 frameSizeLimitLatency;
+    MV_U32 dataFifoThreshold;
+
+    status = mvOnuEponMacPcsFrameSizeLimitsGet(&frameSizeLimitSize, &frameSizeLimitLatency);
+	status |= mvOnuEponMacRxpDataFifoThresholdGet(&dataFifoThreshold);
+
+	if (status != MV_OK)
+		off += mvOsSPrintf(buf+off, "Failed to obtain 2K packet support related register value!\r\n");
+	else {
+		off += mvOsSPrintf(buf+off, "\r\n");
+		off += mvOsSPrintf(buf+off, "PcsFrameSizeLimitSize    = %#d\r\n", frameSizeLimitSize);
+        off += mvOsSPrintf(buf+off, "PcsFrameSizeLimitLatency = %#d\r\n", frameSizeLimitLatency);
+        off += mvOsSPrintf(buf+off, "DataFifoThreshold        = %#d\r\n", dataFifoThreshold);
+	}
+
+	return(off);
+}
+
+/*******************************************************************************
+**
 **  onuEponUiCfgSetDdmTxPolarity
 **  ____________________________________________________________________________
 **
@@ -1790,6 +1855,11 @@
 			return(onuEponUiCfgShowPcsFrameLimits(buf));
 		else if (!strcmp(name, "rxDataFifoThresh"))
 			return(onuEponUiCfgShowRxDataFifoThresh(buf));
+        else if (!strcmp(name, "pkt2kEn"))
+        {
+            return onuEponUiCfgShowPkt2kEnable(buf);
+        }
+            
 	}
 
 	return 0;
@@ -1857,6 +1927,10 @@
 			onuEponUiCfgSetPcsFrameLimits((MV_U32)param1, (MV_U32)param2);
 		else if (!strcmp(name, "rxDataFifoThresh"))
 			onuEponUiCfgSetRxDataFifoThresh((MV_U32)param1);
+        else if (!strcmp(name, "pkt2kEn"))
+        {
+            onuEponUiCfgSetPkt2kEnable((MV_U32)param1);
+        }
 		else if (!strcmp(name, "ddmTxPolarity")) /* txEnable, txPol, serdesPol, xvrPol, burstEn */
 			onuEponUiCfgSetDdmTxPolarity((MV_U32)param1,(MV_U32)param2,(MV_U32)param3,
 						     (MV_U32)param4,(MV_U32)param5);
@@ -1895,8 +1969,9 @@
 static DEVICE_ATTR(pcsFrameLimits,          S_IWUSR | S_IRUSR, cfg_show, cfg_store);
 static DEVICE_ATTR(rxDataFifoThresh,        S_IWUSR | S_IRUSR, cfg_show, cfg_store);
 static DEVICE_ATTR(ddmTxPolarity,           S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(pkt2kEn,                 S_IWUSR | S_IRUSR, cfg_show, cfg_store);
 static DEVICE_ATTR(helpCfg,                 S_IRUSR, cfg_show, cfg_store);
-
+ 
 static struct attribute *cfg_attrs[] = {
 	&dev_attr_rxEn.attr,
 	&dev_attr_txEn.attr,
@@ -1918,8 +1993,9 @@
 	&dev_attr_pattern.attr,
 	&dev_attr_printMask.attr,
 	&dev_attr_pcsFrameLimits.attr,
-	&dev_attr_rxDataFifoThresh.attr,
+	&dev_attr_rxDataFifoThresh.attr, 
 	&dev_attr_ddmTxPolarity.attr,
+	&dev_attr_pkt2kEn.attr, 
 	&dev_attr_helpCfg.attr,
 	NULL
 };
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c
index 457c5e7..0b0ac0b 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c
@@ -270,6 +270,25 @@
 

 /*******************************************************************************

 **

+**  onuGponMiClearTcontConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function clears the specifid tcont configuration

+**               

+**  PARAMETERS:  MV_U32 tcont 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiClearTcontConfig(MV_U32 tcont)

+{   

+    return (onuGponApiTcontClear(tcont));

+}

+

+/*******************************************************************************

+**

 **  onuGponMiGem

 **  ____________________________________________________________________________

 ** 

@@ -378,8 +397,7 @@
 	  spin_unlock_irqrestore(&onuPonIrqLock, flags);

       if(status != MV_OK)

         goto ioctlErr;

-	  onuGponDbXvrPolaritySet(ioctlXvr.polarity);

-	  mvOnuPonMacBurstEnablePolarityInit(ioctlXvr.polarity);

+

       ret = 0;

       break;

 

@@ -413,6 +431,27 @@
         ret = 0;

       break;

 

+    /* ====== MVGPON_IOCTL_DATA_TCONT_CLEAR ======== */

+    case MVGPON_IOCTL_DATA_TCONT_CLEAR:

+        if(copy_from_user(&ioctlData, (S_GponIoctlData*)arg, sizeof(S_GponIoctlData)))

+        {

+            mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+            "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+            goto ioctlErr;

+        }

+        

+        spin_lock_irqsave(&onuPonIrqLock, flags);

+        status = onuGponMiClearTcontConfig(ioctlData.tcont);

+        spin_unlock_irqrestore(&onuPonIrqLock, flags);

+        if(status != MV_OK)

+        {

+            goto ioctlErr;

+        }

+        

+        ret = 0;

+

+        break;

+

     /* ====== MVGPON_IOCTL_GEMPORT_STATE_SET ======= */

     case MVGPON_IOCTL_GEMPORT_STATE_SET:

       if(copy_from_user(&ioctlData, (S_GponIoctlData*)arg, sizeof(S_GponIoctlData)))

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h
index d091673..1a9f589 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h
@@ -84,16 +84,17 @@
 #define MVGPON_IOCTL_INIT               _IOW(MVPON_IOCTL_MAGIC, 1,  unsigned int)

 #define MVGPON_IOCTL_BEN_INIT           _IOW(MVPON_IOCTL_MAGIC, 2,  unsigned int)

 #define MVGPON_IOCTL_DATA_TCONT_CONFIG	_IOW(MVPON_IOCTL_MAGIC, 3,  unsigned int)

-#define MVGPON_IOCTL_DATA_TCONT_RESET	 _IO(MVPON_IOCTL_MAGIC, 4)

-#define MVGPON_IOCTL_INFO               _IOR(MVPON_IOCTL_MAGIC, 5,  unsigned int)

-#define MVGPON_IOCTL_ALARM              _IOR(MVPON_IOCTL_MAGIC, 6,  unsigned int)

-#define MVGPON_IOCTL_PM                 _IOR(MVPON_IOCTL_MAGIC, 7,  unsigned int)

-#define MVGPON_IOCTL_GEM                _IOW(MVPON_IOCTL_MAGIC, 8,  unsigned int)

-#define MVGPON_IOCTL_GEMPORT_PM_CONFIG  _IOW(MVPON_IOCTL_MAGIC, 9,  unsigned int)

-#define MVGPON_IOCTL_GEMPORT_PM_GET     _IOR(MVPON_IOCTL_MAGIC, 10, unsigned int)

-#define MVGPON_IOCTL_GEMPORT_PM_RESET   _IOW(MVPON_IOCTL_MAGIC, 11, unsigned int)

-#define MVGPON_IOCTL_GEMPORT_STATE_GET  _IOW(MVPON_IOCTL_MAGIC, 12, unsigned int)

-#define MVGPON_IOCTL_GEMPORT_STATE_SET  _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

+#define MVGPON_IOCTL_DATA_TCONT_CLEAR   _IOR(MVPON_IOCTL_MAGIC, 4,  unsigned int)

+#define MVGPON_IOCTL_DATA_TCONT_RESET	 _IO(MVPON_IOCTL_MAGIC, 5)

+#define MVGPON_IOCTL_INFO               _IOR(MVPON_IOCTL_MAGIC, 6,  unsigned int)

+#define MVGPON_IOCTL_ALARM              _IOR(MVPON_IOCTL_MAGIC, 7,  unsigned int)

+#define MVGPON_IOCTL_PM                 _IOR(MVPON_IOCTL_MAGIC, 8,  unsigned int)

+#define MVGPON_IOCTL_GEM                _IOW(MVPON_IOCTL_MAGIC, 9,  unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_CONFIG  _IOW(MVPON_IOCTL_MAGIC, 10, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_GET     _IOR(MVPON_IOCTL_MAGIC, 11, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_RESET   _IOW(MVPON_IOCTL_MAGIC, 12, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_STATE_GET  _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_STATE_SET  _IOW(MVPON_IOCTL_MAGIC, 14, unsigned int)

 

 #define ONU_GPON_DEBUG_STATE        (0xFF)

 

@@ -227,7 +228,12 @@
   MV_U32 clearTcont;

   MV_U32 restoreGem;

   MV_U32 dgPolarity;

-  MV_U32 xvrPolarity;

+  MV_U32 ponXvrBurstEnPolarity;

+  MV_U32 ponXvrPolarity;

+  MV_U32 p2pXvrBurstEnPolarity;

+  MV_U32 p2pXvrPolarity;

+  MV_U32 fecHyst;

+  MV_U32 couplingMode;    /* AC Coupling Mode */

 }S_GponIoctlInfo;  

                                                                                          

 typedef struct                                                                           

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c
index 7467f76..d3bf5ef 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c
@@ -88,6 +88,7 @@
 
 /* Global Variables
 ------------------------------------------------------------------------------*/
+extern MV_BOOL onuGponLogEnable;
 
 /* Local Variables
 ------------------------------------------------------------------------------*/
@@ -2373,6 +2374,59 @@
 	return(off);
 }
 
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerActiveTxBitmapSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures UTM Active TX Bitmap
+**
+**  PARAMETERS:  MV_U32 bitmap - bitmap
+**               MV_U32 valid  - valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerActiveTxBitmapSet(MV_U32 bitmap, MV_U32 valid)
+{
+	mvOnuGponMacUtmActiveTxBitmapSet(bitmap);
+	mvOnuGponMacUtmActiveTxBitmapValidSet(valid);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerActiveTxBitmapGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints UTM Active TX bitmap
+**
+**  PARAMETERS:  char *buf
+**
+**  OUTPUTS:     char *buf
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+int onuGponUiDebugManagerActiveTxBitmapGet(char *buf)
+{
+
+	int        off = 0;
+	MV_U32     bitmap, valid;
+	MV_STATUS  status;
+
+
+	status  = mvOnuGponMacUtmActiveTxBitmapConfigGet(&bitmap, &valid);
+
+	if (status != MV_OK)
+		off += mvOsSPrintf(buf+off, "Failed to obtain UTM Active TX bitmap!\n");
+	else
+		off += mvOsSPrintf(buf+off, "UTM Active TX bitmap = %#x valid = %d\n", bitmap, valid);
+
+	return(off);
+}
+
 
 /*******************************************************************************
 **
@@ -2607,8 +2661,10 @@
 	off += mvOsSPrintf(buf+off, " echo 0                         > clearFifoCnts - clear all SW FIFO counters\n");
 	off += mvOsSPrintf(buf+off, " echo [enable(1) or disable(0)] > fifoSupport - config US SW FIFO support\n");
 	if (devId == MV_6601_DEV_ID){
-		off += mvOsSPrintf(buf+off, " echo [Mode] [Time] [Pattern1] [Pattern2] > acCoupling - "
-									"configure TX AC Coupling parameters\n");
+		off += mvOsSPrintf(buf+off, " echo [Mode] [Burst_Time] [Pattern1] [Pattern2] > acCoupling - "
+									"configure TX AC Coupling parameters\r\n");
+		off += mvOsSPrintf(buf+off, " echo [Bitmap] [Valid]                    > activeTxBm - "
+									"configure UTM Active TX Bitmap\n");
 	}
 	off += mvOsSPrintf(buf+off, "============================================================================\n");
 	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
@@ -2618,6 +2674,8 @@
 	if (devId == MV_6601_DEV_ID){
 		off += mvOsSPrintf(buf+off, " cat acCoupling                           - "
 									"dump TX AC Coupling parameters\n");
+		off += mvOsSPrintf(buf+off, " cat activeTxBm - "
+									"show UTM Active TX Bitmap\n");
 	}
 	off += mvOsSPrintf(buf+off, "============================================================================\n");
 
@@ -2903,11 +2961,14 @@
 void onuGponUiCfgSetPatternBurst(MV_U32 enable,MV_U32 pattern, MV_U32 burst, MV_U32 duration, MV_U32 period)
 {
 
-    if (enable == 0) {
-        onuPonPatternBurstOff();
+    if (enable == 0)
+    {
+      onuPonPatternBurstOff();
     }
-    else{
-        onuPonPatternBurstOn(pattern, (MV_BOOL)burst, period, duration);
+    else
+    {
+      onuPonTxPowerOn(MV_TRUE);
+      onuPonPatternBurstOn(pattern, (MV_BOOL)burst, period, duration);
     }
 
 }
@@ -3127,6 +3188,43 @@
 
 }
 
+/*******************************************************************************
+**
+**  onuGponUiSyncLogEnable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiSyncLogEnable(MV_U32 enable)
+{
+	onuGponSyncLogEnable(enable);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiSyncLogPrint
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiSyncLogPrint(void)
+{
+	onuGponSyncLogPrint();
+}
 
 /*******************************************************************************
 **
@@ -3184,14 +3282,33 @@
 						"config T01 timer interval in mS\n");
 	off += mvOsSPrintf(buf+off, " echo [T02 Interval]             > t02IntervalCfg  - "
 						"config T02 timer interval in mS\n");
+	off += mvOsSPrintf(buf+off, " echo [0]                        > syncLogEnable  - Enable or Disable record GPON range log\n");
 	off += mvOsSPrintf(buf+off, "============================================================================\n");
 	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
 	off += mvOsSPrintf(buf+off, "============================================================================\n");
 	off += mvOsSPrintf(buf+off, " cat printMask                                     - dump printing options\n");
+    off += mvOsSPrintf(buf+off, " cat syncLogEnable                                 - dump GPON range log enable status\n");
+    off += mvOsSPrintf(buf+off, " cat syncLog                                       - print GPON range log\n");
 
 	return(off);
 }
 
+int onuGponUiSyncLogEnableShow()
+{
+    printk("The Sync Log is ");
+    
+    if (onuGponLogEnable == MV_TRUE)
+    {
+        printk("enabled\r\n");
+    }
+    else
+    {
+        printk("disabled\r\n");
+    }
+    
+    return 0;
+}
+
 /******************************************************************************/
 /******************************************************************************/
 /******************************************************************************/
@@ -3227,6 +3344,10 @@
 		return ponOnuPrintStatus(buf);
 	else if (!strcmp(name, "helpMisc"))
 		return onuGponUiMiscHelpShow(buf);
+	else if (!strcmp(name, "syncLogEnable"))	/* sync log enable or disable */
+		onuGponUiSyncLogEnableShow();
+    else if (!strcmp(name, "syncLog"))	/* sync log stop */
+		onuGponUiSyncLogPrint();
 
 	return 0;
 }
@@ -3287,6 +3408,8 @@
 		onuGponUiT01IntervalConfig((MV_U32)param1);
 	else if (!strcmp(name, "t02IntervalCfg"))	/* T02 interval in mS */
 		onuGponUiT02IntervalConfig((MV_U32)param1);
+	else if (!strcmp(name, "syncLogEnable"))	/* sync log enable or disable */
+		onuGponUiSyncLogEnable((MV_U32)param1);
 	else
 		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
 
@@ -3318,6 +3441,8 @@
 static DEVICE_ATTR(helpMisc,              S_IRUSR, misc_show, misc_store);
 static DEVICE_ATTR(t01IntervalCfg,        S_IWUSR, misc_show, misc_store);
 static DEVICE_ATTR(t02IntervalCfg,        S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(syncLogEnable,         S_IRUSR | S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(syncLog,               S_IRUSR, misc_show, misc_store);
 
 static struct attribute *misc_attrs[] = {
 	&dev_attr_serialNumCfg.attr,
@@ -3340,6 +3465,8 @@
 	&dev_attr_adminCfg.attr,
 	&dev_attr_t01IntervalCfg.attr,
 	&dev_attr_t02IntervalCfg.attr,
+	&dev_attr_syncLogEnable.attr,
+	&dev_attr_syncLog.attr,
 	NULL
 };
 
@@ -3378,6 +3505,8 @@
 	else if (devId == MV_6601_DEV_ID) {
 		if (!strcmp(name, "acCoupling"))
 			return onuGponUiDebugManagerAcCouplingGet(buf);
+		else if (!strcmp(name, "activeTxBm"))
+			return onuGponUiDebugManagerActiveTxBitmapGet(buf);
 	}
 	return 0;
 }
@@ -3435,9 +3564,11 @@
 	else if (!strcmp(name, "fifoSupport"))		/* enable/disable */
 		onuGponUiDebugManagerFifoSupportSet((MV_U32)param1);
 	else if (devId == MV_6601_DEV_ID) {
-		if (!strcmp(name, "acCoupling"))				/* mode, time, pattern1, pattern2 */
-			onuGponUiDebugManagerAcCouplingSet((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
-							   (MV_U32)param4);
+		if (!strcmp(name, "acCoupling"))	
+            /* mode, time, pattern1, pattern2 */
+			onuGponUiDebugManagerAcCouplingSet((MV_U32)param1, (MV_U32)param2, (MV_U32)param3, (MV_U32)param4);
+		else if (!strcmp(name, "activeTxBm"))				/* bitmap, valid */
+			onuGponUiDebugManagerActiveTxBitmapSet((MV_U32)param1, (MV_U32)param2);
 		else
 			printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
 	} else
@@ -3467,6 +3598,8 @@
 static DEVICE_ATTR(ploamBurstCfg,    S_IWUSR, protocol_show, protocol_store);
 static DEVICE_ATTR(clearFifoCnts,    S_IWUSR, protocol_show, protocol_store);
 static DEVICE_ATTR(fifoSupport,      S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(acCoupling,       S_IRUSR | S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(activeTxBm,       S_IRUSR | S_IWUSR, protocol_show, protocol_store);
 static DEVICE_ATTR(helpProto,        S_IRUSR, protocol_show, protocol_store);
 
 static struct attribute *protocol_attrs[] = {
@@ -3486,6 +3619,8 @@
 	&dev_attr_ploamBurstCfg.attr,
 	&dev_attr_clearFifoCnts.attr,
 	&dev_attr_fifoSupport.attr,
+	&dev_attr_acCoupling.attr, 
+	&dev_attr_activeTxBm.attr,
 	&dev_attr_helpProto.attr,
 	NULL
 };
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h
index 620bcb0..9cc5566 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h
@@ -105,7 +105,6 @@
 	int (*cdevIoctl)(struct inode *, struct file *, unsigned int, unsigned long);
 } S_PonFunctions;
 
-
 typedef struct {
 	E_PonDriverMode		drvMode;
 	int					devOpen;
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c
index d1d245f..7d5cd97 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c
@@ -1,479 +1,541 @@
-/*******************************************************************************

-Copyright (C) Marvell International Ltd. and its affiliates

-

-This software file (the "File") is owned and distributed by Marvell 

-International Ltd. and/or its affiliates ("Marvell") under the following

-alternative licensing terms.  Once you have made an election to distribute the

-File under one of the following license alternatives, please (i) delete this

-introductory statement regarding license alternatives, (ii) delete the two

-license alternatives that you have not elected to use and (iii) preserve the

-Marvell copyright notice above.

-

-********************************************************************************

-Marvell Commercial License Option

-

-If you received this File from Marvell and you have entered into a commercial

-license agreement (a "Commercial License") with Marvell, the File is licensed

-to you under the terms of the applicable Commercial License.

-

-********************************************************************************

-Marvell GPL License Option

-

-If you received this File from Marvell, you may opt to use, redistribute and/or 

-modify this File in accordance with the terms and conditions of the General 

-Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

-available along with the File in the license.txt file or by writing to the Free 

-Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

-on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

-

-THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

-WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

-DISCLAIMED.  The GPL License provides additional details about this warranty 

-disclaimer.

-********************************************************************************

-Marvell BSD License Option

-

-If you received this File from Marvell, you may opt to use, redistribute and/or 

-modify this File under the following licensing terms. 

-Redistribution and use in source and binary forms, with or without modification, 

-are permitted provided that the following conditions are met:

-

-    *   Redistributions of source code must retain the above copyright notice,

-	    this list of conditions and the following disclaimer. 

-

-    *   Redistributions in binary form must reproduce the above copyright

-        notice, this list of conditions and the following disclaimer in the

-        documentation and/or other materials provided with the distribution. 

-

-    *   Neither the name of Marvell nor the names of its contributors may be 

-        used to endorse or promote products derived from this software without 

-        specific prior written permission. 

-    

-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-

-******************************************************************************/

-

-/******************************************************************************

-**  FILE        : eponOnuBoard.c                                             **

-**                                                                           **

-**  DESCRIPTION : This file implements ONU Board specific                    **

-*******************************************************************************

-*                                                                             *                              

-*  MODIFICATION HISTORY:                                                      *

-*                                                                             *

-*   29Oct06  Oren Ben Hayun   created                                         *  

-* =========================================================================== *      

-******************************************************************************/

-

-/* Include Files

-------------------------------------------------------------------------------*/

-#include "ponOnuHeader.h"

-

-/* Local Constant

-------------------------------------------------------------------------------*/                                               

-

-/* Global Variables

-------------------------------------------------------------------------------*/

-

-/* Global functions

-------------------------------------------------------------------------------*/

-

-/* Local Variables

-------------------------------------------------------------------------------*/

-

-/* Export Functions

-------------------------------------------------------------------------------*/

-

-/* Local Functions

-------------------------------------------------------------------------------*/

-

-#ifndef PON_FPGA

-/*******************************************************************************

-**

-**  onuEponSerdesPowerUpSeq

-**  ____________________________________________________________________________

-** 

-**  DESCRIPTION: The function set serdes

-**               

-**  PARAMETERS:  None

-**

-**  OUTPUTS:     None    

-**

-**  RETURNS:     MV_OK or error

-**

-*******************************************************************************/

-MV_STATUS onuEponSerdesPowerUpSeq(void)

-{

-  MV_STATUS status;

-  MV_U32    rxReady = 0;

-  MV_U32    txReady = 0;

-  MV_U32    initDone;

-  MV_U32    temp;

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x0, 0);

-  if (status != MV_OK)                                                         

-    return(status);     

-

-  mvOsDelay(10);

-                                                                               

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x0, 0);

-  if (status != MV_OK)                                                         

-    return(status);                                                            

-                                                                              

-  mvOsDelay(10);

-  

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x0, 0);

-  if (status != MV_OK)                                                         

-    return(status);                                                            

-

-  // asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);

-  // temp &= ~(0x7);

-  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 

-  // if (status != MV_OK) 

-  //   return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(40);

-

-  asicOntMiscRegRead(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, &temp, 0);

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, temp | 0x76, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT, 0x3, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x1, 0);

-  // if (status != MV_OK) 

-  //   return(status);

-  // 

-  // mvOsDelay(40);

-  // 

-  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x1, 0); 

-  // if (status != MV_OK) 

-  //   return(status);

-  // 

-  // mvOsDelay(10);

-  // 

-  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x1, 0);  

-  // if (status != MV_OK) 

-  //   return(status);

-

-  asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);

-  temp |= (0x7);

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(20);

-

-  temp = 0;

-  do 

-  {

-	temp++;

-

-	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX, &txReady, 0);  

-    if (status != MV_OK) 

-      return(status);

-

-	mvOsDelay(10);

-

-    status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX, &rxReady, 0);  

-    if (status != MV_OK) 

-      return(status);

-

-	if ((temp % 10) == 0) 

-	{

-	  return (MV_FAIL);

-	}

-

-  } while ((txReady == 0) || (rxReady == 0));

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);  

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  temp = 0;

-  do 

-  {

-	temp++;

-

-	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);  

-    if (status != MV_OK) 

-      return(status);

-

-	if ((temp % 10) == 0) 

-	{

-	  return (MV_FAIL);

-	}

-

-	mvOsDelay(10);

- 

-  } while (initDone == 0);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);  

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  return(MV_OK);

-}

-

-/*******************************************************************************

-**

-**  onuEponSerdesInit

-**  ____________________________________________________________________________

-** 

-**  DESCRIPTION: The function set serdes

-**               

-**  PARAMETERS:  None

-**

-**  OUTPUTS:     None    

-**

-**  RETURNS:     MV_OK or error

-**

-*******************************************************************************/

-MV_STATUS onuEponSerdesInit(void)

-{

-  MV_STATUS status;

-  MV_U32    loop = 0;

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

-  if (status != MV_OK) 

-   return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x0, 0); 

-  if (status != MV_OK) 

-   return(status);

-

-  /* Put PON MAC to Reset */

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Switch to new PON MAC */

-  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0); 

-  if (status != MV_OK) 

-   return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Take PON MAC out of Reset */

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-

-  /*    EPON configuration of XVR SD is done by LSP code (mvBoardEnvSpec.h, mvCtrlEnvLib.c) */

-

-  /*    EPON configuration/SerDes power up and init sequence   */

-  /* ========================================================= */

-

-  do 

-  {

-	loop++;

-

-	status = onuEponSerdesPowerUpSeq();

-	if      (status == MV_ERROR) return(status);

-	else if (status == MV_OK)    break;

-

-  } while (loop < 10);

-

-  if (loop >= 10) 

-  {

-	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");

-    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "========= Serdes Not Sync !!! ========\n");

-	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");

-  }

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT, 0x0, 0);  

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR, 0x0, 0);  

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

-  if (status != MV_OK) 

-      return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  mvOsDelay(10);

-

- // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 

- // if (status != MV_OK) 

- //   return(status);

- //

- // mvOsDelay(10);

-

-  return(MV_OK);

-}

-

-#if 0 /* only for pon mode switch without Reset */

-/*******************************************************************************

-**

-**  onuEponSwitchOver

-**  ____________________________________________________________________________

-** 

-**  DESCRIPTION: The function switch between EPON and GPON

-**               

-**  PARAMETERS:  None

-**

-**  OUTPUTS:     None    

-**

-**  RETURNS:     MV_OK or error

-**

-*******************************************************************************/

-MV_STATUS onuEponSwitchOver(void)

-{

-  MV_STATUS status;

-

-  /* STOP Traffic */

-

-

-  /* Close TX EN */

-  printk("onuPonSwitchOver - Close TX EN\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Put PON MAC to Reset */

-  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

-  if (status != MV_OK) 

-   return(status);

-  

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-  

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Switch to new PON MAC */

-  printk("onuPonSwitchOver - Switch to new PON MAC - EPON\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Take PON MAC out of Reset */

-  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Re-init Serdes */

-  printk("onuPonSwitchOver - Re-init Serdes\n\r");

-

-  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-

-  printk("onuPonSerdeSwitchOverInit - Serdes CLK EN\n\r");

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

-  if (status != MV_OK) 

-      return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  /* Take PON MAC out of Reset */

-  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

-  if (status != MV_OK) 

-	return(status);

-

-  /* Open TX EN */

-  printk("onuPonSwitchOver - Open TX EN\n\r");

-  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 

-  if (status != MV_OK) 

-    return(status);

-

-  return(MV_OK);

-}

-#endif

-#endif /* PON_FPGA */

+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : eponOnuBoard.c                                             **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU Board specific                    **
+*******************************************************************************
+*                                                                             *                              
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *  
+* =========================================================================== *      
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "ponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/                                               
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuEponSerdesPowerUpSeq
+**  ____________________________________________________________________________
+** 
+**  DESCRIPTION: The function set serdes
+**               
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None    
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuEponSerdesPowerUpSeq(void)
+{
+  MV_STATUS status;
+  MV_U32    rxReady = 0;
+  MV_U32    txReady = 0;
+  MV_U32    initDone;
+  MV_U32    temp;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x0, 0);
+  if (status != MV_OK)                                                         
+    return(status);     
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x0, 0);
+  if (status != MV_OK)                                                         
+    return(status);                                                            
+                                                                              
+  mvOsDelay(40);
+  
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x0, 0);
+  if (status != MV_OK)                                                         
+    return(status);                                                            
+
+  // asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);
+  // temp &= ~(0x7);
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 
+  // if (status != MV_OK) 
+  //   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, &temp, 0);
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, temp | 0x76, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT, 0x3, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x1, 0);
+  // if (status != MV_OK) 
+  //   return(status);
+  // 
+  // mvOsDelay(40);
+  // 
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x1, 0); 
+  // if (status != MV_OK) 
+  //   return(status);
+  // 
+  // mvOsDelay(10);
+  // 
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x1, 0);  
+  // if (status != MV_OK) 
+  //   return(status);
+
+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);
+  temp |= (0x7);
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  temp = 0;
+  do 
+  {
+	temp++;
+
+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX, &txReady, 0);  
+    if (status != MV_OK) 
+      return(status);
+
+    mvOsDelay(40);
+
+    status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX, &rxReady, 0);  
+    if (status != MV_OK) 
+      return(status);
+
+	if ((temp % 10) == 0) 
+	{
+	  return (MV_FAIL);
+	}
+
+  } while ((txReady == 0) || (rxReady == 0));
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);  
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  temp = 0;
+  do 
+  {
+	temp++;
+
+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);  
+    if (status != MV_OK) 
+      return(status);
+
+	if ((temp % 10) == 0) 
+	{
+	  return (MV_FAIL);
+	}
+
+   mvOsDelay(40);
+ 
+  } while (initDone == 0);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);  
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponSerdesInit
+**  ____________________________________________________________________________
+** 
+**  DESCRIPTION: The function set serdes
+**               
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None    
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuEponSerdesInit(void)
+{
+  MV_STATUS status;
+  MV_U32    loop = 0;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 
+  if (status != MV_OK) 
+   return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x0, 0); 
+  if (status != MV_OK) 
+   return(status);
+
+  mvOsDelay(40);
+
+  /* PON MAC init to GPON mode */
+  /* ========================= */
+
+  /* Put PON MAC to Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Switch to new PON MAC */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+   return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Take PON MAC out of Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  /* PON MAC init to EPON mode */
+  /* ========================= */
+
+  /* Put PON MAC to Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Switch to new PON MAC */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0); 
+  if (status != MV_OK) 
+   return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Take PON MAC out of Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  /*    EPON configuration of XVR SD is done by LSP code (mvBoardEnvSpec.h, mvCtrlEnvLib.c) */
+
+  /*    EPON configuration/SerDes power up and init sequence   */
+  /* ========================================================= */
+
+  do 
+  {
+	loop++;
+
+	status = onuEponSerdesPowerUpSeq();
+	if      (status == MV_ERROR) return(status);
+	else if (status == MV_OK)    break;
+
+  } while (loop < 10);
+
+  if (loop >= 10) 
+  {
+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "========= Serdes Not Sync !!! ========\n");
+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");
+  }
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT, 0x0, 0);  
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR, 0x0, 0);  
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 
+  if (status != MV_OK) 
+      return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  mvOsDelay(40);
+
+ // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 
+ // if (status != MV_OK) 
+ //   return(status);
+ //
+ // mvOsDelay(10);
+
+  return(MV_OK);
+}
+
+#if 0 /* only for pon mode switch without Reset */
+/*******************************************************************************
+**
+**  onuEponSwitchOver
+**  ____________________________________________________________________________
+** 
+**  DESCRIPTION: The function switch between EPON and GPON
+**               
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None    
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuEponSwitchOver(void)
+{
+  MV_STATUS status;
+
+  /* STOP Traffic */
+
+
+  /* Close TX EN */
+  printk("onuPonSwitchOver - Close TX EN\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  /* Put PON MAC to Reset */
+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 
+  if (status != MV_OK) 
+   return(status);
+  
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+  
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  /* Switch to new PON MAC */
+  printk("onuPonSwitchOver - Switch to new PON MAC - EPON\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  /* Take PON MAC out of Reset */
+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  /* Re-init Serdes */
+  printk("onuPonSwitchOver - Re-init Serdes\n\r");
+
+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+
+  printk("onuPonSerdeSwitchOverInit - Serdes CLK EN\n\r");
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 
+  if (status != MV_OK) 
+      return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  /* Take PON MAC out of Reset */
+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 
+  if (status != MV_OK) 
+	return(status);
+
+  /* Open TX EN */
+  printk("onuPonSwitchOver - Open TX EN\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 
+  if (status != MV_OK) 
+    return(status);
+
+  return(MV_OK);
+}
+#endif
+#endif /* PON_FPGA */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c
index f7bbfcf..af3d3e5 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c
@@ -269,6 +269,19 @@
 	}

   }

 

+  /* onu pon TX Power timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonTxPwrTimerId),   /* timer Id */

+                               "pon_txPwr",                                /* timer description */

+                               (PTIMER_FUNCPTR)onuEponTimerTxPwrHndl,      /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_TX_PWR_INTERVAL,              /* init value */

+                               0);                                         /* periodic value */

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon Tx Power timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

 

   /* Interrupt */

   /* ========= */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c
index b7be4fc..f678ec9 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c
@@ -235,19 +235,19 @@
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x0, 0);
   if (status != MV_OK)
@@ -263,11 +263,12 @@
  if (status != MV_OK)
    return(status);
 
+  mvOsDelay(40);
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x0, 0);
   if (status != MV_OK)
@@ -280,19 +281,19 @@
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x1, 0);
   // if (status != MV_OK)
@@ -316,7 +317,7 @@
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(20);
+  mvOsDelay(40);
 
   temp = 0;
   do
@@ -327,7 +328,7 @@
     if (status != MV_OK)
       return(status);
 
-	mvOsDelay(10);
+    mvOsDelay(40);
 
     status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX, &rxReady, 0);
     if (status != MV_OK)
@@ -340,13 +341,13 @@
 
   } while ((txReady == 0) || (rxReady == 0));
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   temp = 0;
   do
@@ -362,17 +363,17 @@
 	  return (MV_FAIL);
 	}
 
-	mvOsDelay(10);
+   mvOsDelay(40);
 
   } while (initDone == 0);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   return(MV_OK);
 }
@@ -400,37 +401,97 @@
   if (status != MV_OK)
    return(status);
 
+  mvOsDelay(40);
   status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x0, 0);
   if (status != MV_OK)
    return(status);
 
+  mvOsDelay(40);
+
+  /* PON MAC init to EPON mode */
+  /* ========================= */
+
   /* Put PON MAC to Reset */
   status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
+  mvOsDelay(40);
+
   /* Switch to new PON MAC */
-  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 0, 0);
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0);
   if (status != MV_OK)
     return(status);
 
+  mvOsDelay(40);
+
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
+  mvOsDelay(40);
+
   status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0);
   if (status != MV_OK)
    return(status);
 
+  mvOsDelay(40);
+
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
+  mvOsDelay(40);
+
   /* Take PON MAC out of Reset */
   status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
+  mvOsDelay(40);
+
+  /* PON MAC init to GPON mode */
+  /* ========================= */
+
+  /* Put PON MAC to Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Switch to new PON MAC */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+   return(status);
+
+  mvOsDelay(40);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  /* Take PON MAC out of Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
 
   /*    GPON  configuration of XVR SD is done by LSP code (mvBoardEnvSpec.h, mvCtrlEnvLib.c) */
   /* ================================= */
@@ -459,31 +520,31 @@
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR, 0x0, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0);
   if (status != MV_OK)
       return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
   if (status != MV_OK)
     return(status);
 
-  mvOsDelay(10);
+  mvOsDelay(40);
 
  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0);
  // if (status != MV_OK)
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c
index 25f8155..86b921c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c
@@ -88,6 +88,10 @@
 

 /* Global Variables

 ------------------------------------------------------------------------------*/

+S_onuPonWork      gponTcontCleanWork[8];

+S_onuPonWork      gponTcontCleanAllWork;

+S_onuPonWork      gponTcontActiveWork[8];

+S_onuPonWorkQueue gponTcontFlushWq;

 

 /* Global functions

 ------------------------------------------------------------------------------*/

@@ -116,6 +120,50 @@
 

 /*******************************************************************************

 **

+**  onuPonWqInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function allocates GPON work queue and init two work

+**  		 structures for TCONT clean and activate

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuPonWqInit(void)

+{

+  MV_U32 tcontIndex;

+

+  gponTcontFlushWq.ponWq = create_workqueue("gponTcontFlushWQ");

+  if (gponTcontFlushWq.ponWq)

+  {

+    for (tcontIndex = 0; tcontIndex < 8; tcontIndex++)

+    {

+	    INIT_WORK((struct work_struct *) &gponTcontCleanWork[tcontIndex], onuGponWqTcontFunc);

+	    gponTcontCleanWork[tcontIndex].action = TCONT_CLEAN_EVENT;

+	    gponTcontCleanWork[tcontIndex].param  = tcontIndex;

+

+	    INIT_WORK((struct work_struct *) &gponTcontActiveWork[tcontIndex], onuGponWqTcontFunc);

+	    gponTcontActiveWork[tcontIndex].action = TCONT_ACTIVE_EVENT;

+	    gponTcontActiveWork[tcontIndex].param  = tcontIndex;

+    }

+

+    INIT_WORK((struct work_struct *) &gponTcontCleanAllWork, onuGponWqTcontFunc);

+    gponTcontCleanAllWork.action = TCONT_CLEAN_ALL_EVENT;

+

+    printk("STARTING PON WORK QUEUE!!!!!\n");

+

+    return(MV_OK);

+  }

+

+  return(MV_ERROR);

+}

+

+/*******************************************************************************

+**

 **  onuGponRtosResourceInit

 **  ____________________________________________________________________________

 ** 

@@ -235,6 +283,29 @@
     return(MV_ERROR);

   }

 

+  /* onu pon TX Power timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonTxPwrTimerId),   /* timer Id */

+                               "pon_txPwr",                                /* timer description */

+                               (PTIMER_FUNCPTR)onuGponTimerTxPwrHndl,      /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_TX_PWR_INTERVAL,              /* init value */

+                               0);                                         /* periodic value */

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon Tx Power timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* Work Queue */

+  /* ========== */

+  retcode = onuPonWqInit();

+  if (retcode != MV_OK)

+  {

+     mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+                "ERROR: (%s:%d) pon work queue create\n", __FILE_DESC__, __LINE__);

+     return(MV_ERROR);

+  }

 

   /* Interrupt */

   /* ========= */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h
index ca4b7e3..be40786 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h
@@ -89,6 +89,13 @@
 /* Typedefs

 ------------------------------------------------------------------------------*/

 

+/* Global variables

+------------------------------------------------------------------------------*/

+extern S_onuPonWork      gponTcontCleanWork[8];

+extern S_onuPonWork      gponTcontCleanAllWork;

+extern S_onuPonWork      gponTcontActiveWork[8];

+extern S_onuPonWorkQueue gponTcontFlushWq;

+

 /* Global functions

 ------------------------------------------------------------------------------*/

 /* Init API */

@@ -97,9 +104,12 @@
 extern MV_STATUS onuGponRtosResourceRelease(void);

 

 /* Interrupt API */

-extern MV_STATUS onuGponIrqRegister(S_onuPonIrq *irqId); 

+extern MV_STATUS onuGponIrqRegister(S_onuPonIrq *irqId);

 extern MV_STATUS onuGponIrqTaskletInit(S_onuPonIrq *irqId);

 

+/* Work queue API */

+extern void onuGponWqTcontInit(void);

+

 

 /* Macros

 ------------------------------------------------------------------------------*/    

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
index 3e6cc2b..378edbf 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
@@ -83,7 +83,8 @@
 
 /* Global Variables
 ------------------------------------------------------------------------------*/
-MV_U32 ponXvrPolarity;
+S_OnuP2PDb onuP2PDb_s;
+t_ponXvrFuncPtr ponXvrFunc;
 
 /* Global functions
 ------------------------------------------------------------------------------*/
@@ -383,25 +384,48 @@
 	return(status);
 }
 
-/*******************************************************************************
-**
-**  mvOnuPonMacBurstEnablePolarityInit
-**  ____________________________________________________________________________
-**
-**  DESCRIPTION: The function init Burst Enable XVR polarity
-**
-**  PARAMETERS:  MV_U32 polarity
-**
-**  OUTPUTS:     None
-**
-**  RETURNS:     MV_OK or error
-**
-*******************************************************************************/
-MV_STATUS mvOnuPonMacBurstEnablePolarityInit(MV_U32 polarity)
+MV_STATUS EponXvrSDPolarityHighStatus(MV_U32 interruptStatus, MV_U32 statusMask)
 {
-	ponXvrPolarity = polarity;
+    return ((interruptStatus & statusMask) ? MV_FALSE : MV_TRUE);
+}
 
-	return(MV_OK);
+MV_STATUS EponXvrSDPolarityLowStatus(MV_U32 interruptStatus, MV_U32 statusMask)
+{
+    return ((~interruptStatus & statusMask) ? MV_FALSE : MV_TRUE);
+}
+
+MV_STATUS GponXvrSDPolarityHighStatus(MV_U32 interruptStatus, MV_U32 statusMask)
+{
+    return ((interruptStatus & statusMask) ? MV_TRUE : MV_FALSE);
+}
+
+MV_STATUS GponXvrSDPolarityLowStatus(MV_U32 interruptStatus, MV_U32 statusMask)
+{
+    return ((~interruptStatus & statusMask) ? MV_TRUE : MV_FALSE);
+}
+
+t_ponXvrFuncPtr funcEponXvrSDStatus(MV_U32 polarity)
+{
+    if (polarity == 0)
+    {
+        return EponXvrSDPolarityHighStatus;
+    }
+    else
+    {
+        return EponXvrSDPolarityLowStatus;
+    }
+}
+
+t_ponXvrFuncPtr funcGponXvrSDStatus(MV_U32 polarity)
+{
+    if (polarity == 0)
+    {
+        return GponXvrSDPolarityHighStatus;
+    }
+    else
+    {
+        return GponXvrSDPolarityLowStatus;
+    }
 }
 
 /*******************************************************************************
@@ -521,7 +545,7 @@
 			return(MV_ERROR);
 		}
 
-		polarity = ponXvrPolarity;
+        polarity = onuP2PDbXvrBurstEnablePolarityGet();
 
 		/* XVR polarity */
 		/* XVR polarity == 0, Active High, transmit 1 to the line  */
@@ -535,10 +559,8 @@
 		/* XVR polarity == 0, Active High, write 1 for Force Value */
 		/* XVR polarity == 1, Active Low, write 0 for Force Value */
 
-		trans_value = ((on == MV_TRUE) ? (~polarity) : (polarity));
-
 		/* PHY control register - force enable value - according to polarity */
-		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, trans_value, 0);
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, polarity, 0);
 		if (status != MV_OK) {
 			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
 				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl force value %d\n\r",
@@ -772,6 +794,36 @@
 
 /*******************************************************************************
 **
+**  onuPonTxPowerTimerStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable TX power off timer
+**
+**  PARAMETERS:  MV_BOOL mode - MV_TRUE  - start timer
+**                              MV_FALSE - stop timer
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonTxPowerTimerStateSet(MV_BOOL mode)
+{
+  MV_STATUS rcode = MV_OK;
+
+  if (mode == MV_TRUE)
+  {
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonTxPwrTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonTxPwrTimerId));
+  }
+
+  return (rcode);
+}
+
+/*******************************************************************************
+**
 **  onuPonTxPowerOn
 **  ____________________________________________________________________________
 **
@@ -851,7 +903,7 @@
 }
 
 /*******************************************************************************
-**
+**  **  906
 **  onuPonTxLaserOn
 **  ____________________________________________________________________________
 **
@@ -887,4 +939,44 @@
 	return(MV_OK);
 }
 
+/*******************************************************************************
+**
+**  onuP2PDbXvrBurstEnablePolaritySet
+**  ____________________________________________________________________________
+** 
+**  DESCRIPTION: The function sets EPON XVR polarity register value in the database
+**               
+**  PARAMETERS:  MV_U32 val
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**                   
+*******************************************************************************/
+MV_STATUS onuP2PDbXvrBurstEnablePolaritySet(MV_U32 val)
+{
+    onuP2PDb_s.onuP2PGenTbl_s.xvrBurstEnPolarity = val;
+
+    return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuP2PDbXvrBurstEnablePolarityGet
+**  ____________________________________________________________________________
+** 
+**  DESCRIPTION: The function returns EPON XVR polarity register value
+**               
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_U32 mode
+**                   
+*******************************************************************************/
+MV_U32 onuP2PDbXvrBurstEnablePolarityGet(void)
+{
+    return onuP2PDb_s.onuP2PGenTbl_s.xvrBurstEnPolarity;
+}
+
 #endif /* PON_FPGA */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
index ec15f89..6efe4e5 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
@@ -125,11 +125,27 @@
   ACTIVE_LED_ON         = 3
 }E_OnuPonLedActivation;
 
+/* Struct
+------------------------------------------------------------------------------*/
+/* ONU P2P Database */
+typedef struct
+{
+    MV_U32 xvrBurstEnPolarity;
+    MV_U32 xvrPolarity;
+} S_OnuP2PGenTbl;
+
+typedef struct
+{
+  S_OnuP2PGenTbl onuP2PGenTbl_s;
+} S_OnuP2PDb;
+
 /* Typedefs
 ------------------------------------------------------------------------------*/
+typedef MV_STATUS (*t_ponXvrFuncPtr)(MV_U32, MV_U32);
 
 /* Global variables
 ------------------------------------------------------------------------------*/
+extern t_ponXvrFuncPtr ponXvrFunc;
 
 /* Global functions
 ------------------------------------------------------------------------------*/
@@ -147,6 +163,17 @@
 MV_STATUS onuPonTxPowerOn(MV_BOOL txOn);
 MV_STATUS onuPonTxPowerControlInit(void);
 MV_STATUS onuPonTxLaserOn(MV_BOOL txOn);
+MV_STATUS onuPonTxPowerTimerStateSet(MV_BOOL mode);
+
+MV_STATUS EponXvrSDPolarityHighStatus(MV_U32 interruptStatus, MV_U32 statusMask);
+MV_STATUS EponXvrSDPolarityLowStatus(MV_U32 interruptStatus, MV_U32 statusMask);
+MV_STATUS GponXvrSDPolarityHighStatus(MV_U32 interruptStatus, MV_U32 statusMask);
+MV_STATUS GponXvrSDPolarityLowStatus(MV_U32 interruptStatus, MV_U32 statusMask);
+t_ponXvrFuncPtr funcEponXvrSDStatus(MV_U32 polarity);
+t_ponXvrFuncPtr funcGponXvrSDStatus(MV_U32 polarity);
+
+MV_STATUS onuP2PDbXvrBurstEnablePolaritySet(MV_U32 val);
+MV_U32    onuP2PDbXvrBurstEnablePolarityGet(void);
 
 #endif /* PON_FPGA */
 
@@ -154,6 +181,3 @@
 ------------------------------------------------------------------------------*/
 
 #endif /* _ONU_PON_BOARD_H */
-
-
-
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h
index a1e3869..e5b3293 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h
@@ -98,6 +98,7 @@
 #include <linux/cdev.h>

 #include <linux/fs.h>

 #include <linux/ioctl.h>

+#include <linux/workqueue.h>

 

 #include "mvTypes.h"

 #include "mvCommon.h"

@@ -177,7 +178,7 @@
 #define ONU_PON_TIMER_PM_INTERVAL            (1000)  /* 1 sec */

 #define ONU_PON_TIMER_PEE_INTERVAL           (3000)  /* 3 sec */

 #define ONU_PON_TIMER_PON_EVT_CLEAN_INTERVAL (5000)  /* 5 sec */

-#define ONU_PON_TIMER_XVR_RST_INTERVAL       (450)   /* 450 msec */

+#define ONU_PON_TIMER_XVR_RST_INTERVAL       (10)    /* 10 msec */

 #define ONU_PON_TIMER_MPCP_INTERVAL          (1000)  /* 1 sec */

 #define ONU_PON_TIMER_RPRT_INTERVAL          (1)     /* 1 msec */

 #define ONU_PON_TIMER_HW_RPRT_T0_INTERVAL    (2)     /* 2 msec */

@@ -186,6 +187,7 @@
 #define ONU_PON_TIMER_SILENCE_INTERVAL       (60000) /* 60 sec */

 #define ONU_PON_TIMER_TX_MOD_INTERVAL        (1)   /* 1 msec */

 #define ONU_PON_TIMER_EVENT_MISS_INTERVAL    (10)   /* 10 msec */

+#define ONU_PON_TIMER_TX_PWR_INTERVAL        (1000)  /* 1 sec */

 

 #define ONU_PON_TIMER_ACTIVE                 (1)

 #define ONU_PON_TIMER_NOT_ACTIVE             (0)

@@ -221,6 +223,20 @@
   struct tasklet_struct onuPonTasklet;

 }S_onuPonIrq;

 

+

+/* Work queue */

+typedef struct

+{

+  struct work_struct ponWork;

+  int    action;

+  int    param;

+}S_onuPonWork;

+

+typedef struct

+{

+  struct workqueue_struct *ponWq;

+}S_onuPonWorkQueue;

+

 /* ONU GPON resource table */

 typedef struct

 {

@@ -236,7 +252,8 @@
   S_OnuPonTimer onuPonIsrMissTimerId;       /* ONU EPON ISR Miss timer */

   S_OnuPonTimer onuPonHoldoverTimerId;      /* ONU EPON Holdover timer */

   S_OnuPonTimer onuPonSilenceTimerId[8];    /* ONU EPON Silence timer */

-                                            

+

+  S_OnuPonTimer onuPonTxPwrTimerId;         /* ONU PON TX Power timer */

   S_OnuPonTimer onuPonPmTimerId;            /* ONU PON PM timer */

   S_OnuPonTimer onuPonPatternBurstTimerId;  /* ONU PON Pattern Burst timer */

 #ifndef PON_FPGA                            

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c
index 5c27c0d..2f46bee 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c
@@ -46,6 +46,66 @@
 static uint8_t   weight_arr[4] = {0};
 extern GT_QD_DEV *qd_dev;
 
+/*******************************************************************************
+* mv_switch_find_vid_entry_sw
+*
+* DESCRIPTION:
+*       The API find expected VTU entry in sw_vlan_tbl.
+*
+* INPUTS:
+*       vtuEntry      - VTU entry, supply VID
+*
+* OUTPUTS:
+*       vtuEntry      - VTU entry, store entry info if found
+*       found         - find expected entry or not
+*
+* RETURNS:
+*       On success -  GT_OK.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_find_vid_entry_sw(GT_VTU_ENTRY *vtuEntry, GT_BOOL *found)
+{
+    if (vtuEntry == NULL || found == NULL)
+        return GT_BAD_PARAM;
+
+    if (sw_vlan_tbl[vtuEntry->vid].members) {/* if members not 0, this vid entry exist in HW andd SW */
+        memcpy(vtuEntry, &sw_vlan_tbl[vtuEntry->vid].vtu_entry, sizeof(GT_VTU_ENTRY));
+        *found = GT_TRUE;
+    } else {
+        *found = GT_FALSE;
+    }
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* mv_switch_record_vid_entry_sw
+*
+* DESCRIPTION:
+*       The API store expected VTU entry in sw_vlan_tbl.
+*
+* INPUTS:
+*       vtuEntry      - VTU entry
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success -  GT_OK.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_record_vid_entry_sw(GT_VTU_ENTRY *vtuEntry)
+{
+    if (vtuEntry == NULL)
+        return GT_BAD_PARAM;
+    memcpy(&sw_vlan_tbl[vtuEntry->vid].vtu_entry, vtuEntry, sizeof(GT_VTU_ENTRY));
+
+    return GT_OK;
+}
 
 /*******************************************************************************
 * mv_switch_prv_port_add_vid
@@ -54,7 +114,10 @@
 *       The API adds a VID to the list of the allowed VIDs per lport.
 *
 * INPUTS:
-*       vid      - VLAN id.
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       gmac0Idx  - port GMAC0 connects to, if its value is 0xFFFF, do not care GMAC0 port
+*       eMode     - egress mode
 *
 * OUTPUTS:
 *       None.
@@ -69,7 +132,10 @@
 *******************************************************************************/
 int32_t mv_switch_prv_port_add_vid
 (
-    uint16_t vid
+    uint32_t lport,
+    uint16_t vid,
+    uint16_t gmac0Idx,
+    uint8_t  eMode
 )
 {
     GT_STATUS    rc = GT_OK;
@@ -80,17 +146,14 @@
     memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
     tmpVtuEntry.vid   = vid;
 
-    rc = gvtuFindVidEntry(qd_dev, &tmpVtuEntry, &found);
-    if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
-    {
-        printk(KERN_ERR "%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+    rc = mv_switch_find_vid_entry_sw(&tmpVtuEntry, &found);
+    if (rc != GT_OK) {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_find_vid_entry_sw failed rc[0x%x]\r\n",
                __FUNCTION__, __LINE__, rc);
 
         return GT_FAIL;
     }
 
-    printk(KERN_DEBUG "%s: found[%d]\n\r", __FUNCTION__,found);
-
     if (found == GT_FALSE)/* VTU entry does not exist */
     {
         /* Add new VTU entry with VLAN ID vid with lport as members of the Vlan vid. */
@@ -115,7 +178,16 @@
     for (port=0; port < qd_dev->numOfPorts; port++)
     {
         if (sw_vlan_tbl[vid].members & (1 << port)){
-            tmpVtuEntry.vtuData.memberTagP[port] = sw_vlan_tbl[vid].egr_mode[port];
+            if (port == lport)
+                tmpVtuEntry.vtuData.memberTagP[port] = eMode;/* update egress mode only */
+            else
+                tmpVtuEntry.vtuData.memberTagP[port] = sw_vlan_tbl[vid].egr_mode[port];
+        }
+        else if (port == lport) {
+            tmpVtuEntry.vtuData.memberTagP[port] = eMode;
+        }
+        else if (gmac0Idx == port) {/* add GMAC_0 to VLAN if gmac0Idx valid */
+            tmpVtuEntry.vtuData.memberTagP[port] = MEMBER_EGRESS_UNMODIFIED;
         }
         else{
             tmpVtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
@@ -132,6 +204,15 @@
         return GT_FAIL;
     }
 
+    /* Record HW VT entry info to sw_vlan_tbl */
+    rc = mv_switch_record_vid_entry_sw(&tmpVtuEntry);
+    if (rc != GT_OK) {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_record_vid_entry_sw failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
     return rc;
 }
 
@@ -168,21 +249,25 @@
     GT_U8        port_idx;
     uint32_t     isVlanMember = 0;
 
-    memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
-    tmpVtuEntry.vid = vid;
-
-    rc = gvtuFindVidEntry(qd_dev, &tmpVtuEntry, &found);
-    if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
-    {
-        printk(KERN_ERR "%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
-               __FUNCTION__, __LINE__, rc);
-
-        rc = GT_FAIL;
-        goto out_func;
-    }
+    /* Find vid in sw_vlan_tbl first */
+    if (!(sw_vlan_tbl[vid].members & (1 << port)))
+            found = GT_FALSE;
 
     if (found == GT_TRUE) /* VTU entry exist */
     {
+        memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+        tmpVtuEntry.vid = vid;
+        /* Read SW VT to get necessary entry info */
+        rc = mv_switch_find_vid_entry_sw(&tmpVtuEntry, &found);
+        if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
+        {
+            printk(KERN_ERR "%s:%d:==ERROR==mv_switch_find_vid_entry_sw failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            rc = GT_FAIL;
+            goto out_func;
+        }
+
         /* 1. Mark the lport as NOT_A_MEMBER. */
         tmpVtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
 
@@ -210,6 +295,15 @@
                 goto out_func;
             }
 
+            /* Record HW VT entry info to sw_vlan_tbl */
+            rc = mv_switch_record_vid_entry_sw(&tmpVtuEntry);
+            if (rc != GT_OK) {
+                printk(KERN_ERR "%s:%d:==ERROR==mv_switch_record_vid_entry_sw failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                return GT_FAIL;
+            }
+
             sw_vlan_tbl[vid].members &= ~(((uint32_t)0x1) << (port));/* Delete port from VID DB */
         }
         else/* Delete VTU */
@@ -229,7 +323,7 @@
     }
     else /* VTU entry does not exist in search */
     {
-        printk(KERN_ERR "%s:%d:==ERROR== No Such VID\r\n",__FUNCTION__,__LINE__);
+        printk(KERN_ERR "%s:%d:==ERROR== No Such VID in Port(%d) Vlan List\r\n",__FUNCTION__,__LINE__, port);
 
         rc = GT_FAIL;
         goto out_func;
@@ -1249,60 +1343,8 @@
 )
 {
     GT_STATUS rc = GT_OK;
-    uint32_t  port;
-    uint32_t  port_bm;
 
-    /* Verify whether the port is already a member of this VID */
-    port_bm = (uint32_t)(1 << lport);
-    if ( !(sw_vlan_tbl[vid].members & port_bm) )
-    {
-        /* All fallback ports are also added to this VLAN in order
-           to support traffic on this VLAN with all fallback ports */
-        for(port = 0; port < qd_dev->numOfPorts; port++)
-        {
-            if (port == lport)
-            {
-                sw_vlan_tbl[vid].members |= port_bm;
-                sw_vlan_tbl[vid].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
-            }
-            else
-            {
-                #if 0
-                if (sw_ports_tbl[port].port_mode == GT_FALLBACK && \
-                    !(sw_vlan_tbl[vid].members & (1 << port)))
-                {
-                    sw_vlan_tbl[vid].members |= (uint32_t)(1 << port);
-                    sw_vlan_tbl[vid].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
-                }
-                #endif
-            }
-        }
-
-        /*if (sw_ports_tbl[gmac0Idx].port_mode == GT_FALLBACK &&
-            !(sw_vlan_tbl[vid].members & (1 << gmac0Idx)))*/
-        /* Always add GMAC_0 to VLAN */
-        if (!(sw_vlan_tbl[vid].members & (1 << gmac0Idx)))
-        {
-            sw_vlan_tbl[vid].members |= (uint32_t)(1 << gmac0Idx);
-            sw_vlan_tbl[vid].egr_mode[gmac0Idx] = MEMBER_EGRESS_UNMODIFIED;
-        }
-
-        rc = mv_switch_prv_port_add_vid(vid);
-        if (rc != GT_OK)
-        {
-            printk(KERN_ERR "%s:%d:==ERROR== failed rc[0x%x]\r\n",
-                   __FUNCTION__, __LINE__, rc);
-
-            rc = GT_FAIL;
-        }
-    }
-
-    /* Add the specified port to the SW Port table */
-    if (sw_ports_tbl[lport].vlan_blong[vid] == SW_PORT_NOT_BELONG)
-    {
-        sw_ports_tbl[lport].cnt++;
-        sw_ports_tbl[lport].vlan_blong[vid] = SW_PORT_BELONG;
-    }
+    rc = mv_switch_port_add_vid_set_egrs_mode(lport, vid, gmac0Idx, MEMBER_EGRESS_UNMODIFIED);
 
     return rc;
 }
@@ -1410,14 +1452,14 @@
         memset(&vtuEntry, 0, sizeof(GT_VTU_ENTRY));
         vtuEntry.vid = vid;
 
-        rc = gvtuFindVidEntry(qd_dev, &vtuEntry, &found);
+        rc = mv_switch_find_vid_entry_sw(&vtuEntry, &found);
         if (rc != GT_OK && rc != GT_NO_SUCH)
         {
-            printk(KERN_ERR"%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+            printk(KERN_ERR"%s:%d:==ERROR==mv_switch_find_vid_entry_sw failed rc[0x%x]\r\n",
                    __FUNCTION__, __LINE__, rc);
 
             return GT_FAIL;
-    }
+        }
 
         printk(KERN_DEBUG "%s: found[%d]\n\r", __FUNCTION__, found);
 
@@ -1431,6 +1473,15 @@
 
             return GT_FAIL;
         }
+
+        /* Record HW VT entry info to sw_vlan_tbl */
+        rc = mv_switch_record_vid_entry_sw(&vtuEntry);
+        if (rc != GT_OK) {
+            printk(KERN_ERR "%s:%d:==ERROR==mv_switch_record_vid_entry_sw failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            return GT_FAIL;
+        }
     }
     else
     {
@@ -1614,18 +1665,20 @@
         if ( sw_vlan_tbl[vlan_idx].members &&
              !(sw_vlan_tbl[vlan_idx].members & port_bm))
         {
-            sw_vlan_tbl[vlan_idx].members |= port_bm;
-            sw_vlan_tbl[vlan_idx].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
-
             /* Update VTU table */
-            rc |= mv_switch_prv_port_add_vid(vlan_idx);
+            rc |= mv_switch_prv_port_add_vid(port, vlan_idx, 0xFFFF, MEMBER_EGRESS_UNMODIFIED);
 
             if (rc != GT_OK)
             {
                 printk(KERN_ERR
                        "%s:%d:==ERROR== failed to add port [%d] to VLAN [%d]\r\n",
                        __FUNCTION__,__LINE__,port, vlan_idx);
+                return rc;
             }
+
+            sw_vlan_tbl[vlan_idx].members |= port_bm;
+            sw_vlan_tbl[vlan_idx].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
+
         }
     }
 
@@ -4978,6 +5031,7 @@
 		return rc;
 	}
 	memset(sw_vlan_tbl,  0,  sizeof(sw_vlan_tbl));
+
 	for(port = 0; port < qd_dev->numOfPorts; port++)
 	{
 		memset(&(sw_ports_tbl[port].vlan_blong), 0, sizeof(sw_ports_tbl[port].vlan_blong));
@@ -5021,6 +5075,205 @@
 }
 
 /*******************************************************************************
+* mv_switch_set_port_speed_duplex_mode
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed and duplex mode.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*		enable - Enable/Disable full duplex mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_speed_duplex_mode
+(
+IN GT_LPORT port,
+IN GT_PHY_SPEED speed,
+IN GT_BOOL enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPortSpeedDuplexMode(qd_dev, port, speed, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortSpeedDuplexMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_forced_fc_value
+*
+* DESCRIPTION:
+*       This routine will set forced flow control value when forced flow control enabled.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_forced_fc_value
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsSetFCValue(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsSetFCValue failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_forced_flow_control
+*
+* DESCRIPTION:
+*       This routine will enable/disable forced flow control state.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_forced_flow_control
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsSetForcedFC(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsSetForcedFC failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport
+*       and sets the egress mode for the port.
+*
+* INPUTS:
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       gmac0Idx  - port GMAC0 connects to
+*       eMode     - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+int32_t mv_switch_port_add_vid_set_egrs_mode
+(
+    IN uint32_t lport,
+    IN uint16_t vid,
+    IN uint16_t gmac0Idx,
+    IN uint8_t  eMode
+)
+{
+    GT_STATUS rc = GT_OK;
+    uint32_t  port_bm;
+
+    /* Verify whether the port is already a member of this VID */
+    port_bm = (uint32_t)(1 << lport);
+    if (!((sw_vlan_tbl[vid].members & port_bm) && (sw_vlan_tbl[vid].egr_mode[lport] == eMode)))
+    {
+        rc = mv_switch_prv_port_add_vid(lport, vid, gmac0Idx, eMode);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR "%s:%d:==ERROR== failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            return GT_FAIL;
+        }
+
+        /* add port to vid's member bit map and set port egress mode */
+        sw_vlan_tbl[vid].members |= port_bm;
+        sw_vlan_tbl[vid].egr_mode[lport] = eMode;
+
+        /* Always add GMAC_0 to VLAN */
+        if (!(sw_vlan_tbl[vid].members & (1 << gmac0Idx)))
+        {
+            sw_vlan_tbl[vid].members |= (uint32_t)(1 << gmac0Idx);
+            sw_vlan_tbl[vid].egr_mode[gmac0Idx] = MEMBER_EGRESS_UNMODIFIED;
+        }
+    }
+
+    /* Add the specified port to the SW Port table */
+    if (sw_ports_tbl[lport].vlan_blong[vid] == SW_PORT_NOT_BELONG)
+    {
+        sw_ports_tbl[lport].cnt++;
+        sw_ports_tbl[lport].vlan_blong[vid] = SW_PORT_BELONG;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
 * mv_switch_drv_init
 *
 * DESCRIPTION:
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h
index 18c3fb9..a2da3e0 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h
@@ -51,7 +51,6 @@
 #define SW_QOS_NUM_OF_TAG_PRI    (7)
 #define SW_QOS_DSCP_MAX          (64)
 
-
 /* LPort data base*/
 typedef struct _sw_port_info_type_t
 {
@@ -62,8 +61,9 @@
 
 typedef struct _sw_vlan_tbl_type
 {
-    uint32_t members;        /* bitmap of the ports max number of ports 32 */
+    uint32_t members;        /* bitmap of the ports max number of ports 32, if its value is 0, indicates that the VID do not exist in HW */
     uint8_t  egr_mode[SW_MAX_PORTS_NUM]; /* egress mode of each port */
+    GT_VTU_ENTRY vtu_entry; /* Add this member to record HW VT info to SW table, descrease access time for VT table */
 }sw_vlan_tbl_type;
 
 /* auto negotiation type */
@@ -78,13 +78,57 @@
 }sw_autoneg_type_t;
 
 /*******************************************************************************
+* mv_switch_find_vid_entry_sw
+*
+* DESCRIPTION:
+*       The API find expected VTU entry in sw_vlan_tbl.
+*
+* INPUTS:
+*       vtuEntry      - VTU entry, supply VID
+*
+* OUTPUTS:
+*       vtuEntry      - VTU entry, store entry info if found
+*       found         - find expected entry or not
+*
+* RETURNS:
+*       On success -  GT_OK.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_find_vid_entry_sw(GT_VTU_ENTRY *vtuEntry, GT_BOOL *found);
+
+/*******************************************************************************
+* mv_switch_record_vid_entry_sw
+*
+* DESCRIPTION:
+*       The API store expected VTU entry in sw_vlan_tbl.
+*
+* INPUTS:
+*       vtuEntry      - VTU entry
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success -  GT_OK.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_record_vid_entry_sw(GT_VTU_ENTRY *vtuEntry);
+
+/*******************************************************************************
 * mv_switch_prv_port_add_vid
 *
 * DESCRIPTION:
 *       The API adds a VID to the list of the allowed VIDs per lport.
 *
 * INPUTS:
-*       vid      - VLAN id.
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       gmac0Idx  - port GMAC0 connects to, if its value is 0xFFFF, do not care GMAC0 port
+*       eMode     - egress mode
 *
 * OUTPUTS:
 *       None.
@@ -99,7 +143,10 @@
 *******************************************************************************/
 int32_t mv_switch_prv_port_add_vid
 (
-    uint16_t vid
+    uint32_t lport,
+    uint16_t vid,
+    uint16_t gmac0Idx,
+    uint8_t  eMode
 );
 
 /*******************************************************************************
@@ -2842,6 +2889,125 @@
 );
 
 /*******************************************************************************
+* mv_switch_set_port_speed_duplex_mode
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed and duplex mode.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*		enable - Enable/Disable full duplex mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_speed_duplex_mode
+(
+IN GT_LPORT port,
+IN GT_PHY_SPEED speed,
+IN GT_BOOL enable
+);
+
+/*******************************************************************************
+* mv_switch_set_port_forced_fc_value
+*
+* DESCRIPTION:
+*       This routine will set forced flow control value when forced flow control enabled.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_forced_fc_value
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+
+/*******************************************************************************
+* mv_switch_set_port_forced_flow_control
+*
+* DESCRIPTION:
+*       This routine will enable/disable forced flow control state.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_forced_flow_control
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+
+/*******************************************************************************
+* mv_switch_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport
+*       and sets the egress mode for the port.
+*
+* INPUTS:
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       gmac0Idx  - port GMAC0 connects to
+*       eMode     - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+int32_t mv_switch_port_add_vid_set_egrs_mode
+(
+    IN uint32_t lport,
+    IN uint16_t vid,
+    IN uint16_t gmac0Idx,
+    IN uint8_t  eMode
+);
+
+/*******************************************************************************
 * mv_switch_drv_init
 *
 * DESCRIPTION:
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c
index 970597b..a3a5319 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c
@@ -289,8 +289,8 @@
 *                        |TPM_L2_PARSE_PPP_PROT|TPM_L2_PARSE_GEMPORT)
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for L2 API:
-*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_TAG2_MASK|
-*                        TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE
 * l2_key             - Information to create a parsing key for the rule.
 *                      Some pointers may be NULL depending on the parse_rule_bm.
 * pkt_frw            - Information for packet forwarding decision.
@@ -365,8 +365,10 @@
 *                        TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES|TPM_L2_PARSE_PPP_PROT
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for L3 API:
-*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_TAG2_MASK|
-*                        TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE
 * l3_key             - Structure for PPPoE proto or ether type. In order to define a rule for
 *                      any ether type, the ether type value should be set to 0xFFFF
 * action_drop        - If this stage is dropping the packet.
@@ -513,7 +515,10 @@
 *                         |TPM_IPv4_PARSE_PROTO|TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for IPv4 API:
-*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
 * ipv4_key           - Information to create an IPv4 parsing key for the rule.
 *                      Some pointers may be NULL depending on the parse_rule_bm.
 * pkt_frwd           - Information for packet forwarding decision.
@@ -612,7 +617,8 @@
 * rule_num           - Entry index to be added in the current ACL
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for IPv6 NH API:
-*                         TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
 * nh                 - Information to create a NH parsing key for the rule.
 * pkt_frwd           - Information for packet forwarding decision.
 * rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
@@ -702,7 +708,10 @@
 *                      possible values for IPv6 GEN API: 0
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for IPv6 GEN API:
-*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
 * ipv6_gen_key     - Information to create an IPv6 gen parsing key for the rule.
 *                      Some pointers may be NULL depending on the parse_rule_bm.
 * pkt_frwd           - Information for packet forwarding decision.
@@ -810,7 +819,10 @@
 *                      possible values for IPv6 DIP API: TPM_IPv6_PARSE_DIP
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for IPv6 DIP API:
-*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
 * ipv6_dip_key       - Information to create an IPv6 DIP parsing key for the rule.
 *                      Some pointers may be NULL depending on the parse_rule_bm.
 * pkt_frwd           - Information for packet forwarding decision.
@@ -920,7 +932,9 @@
 *                      possible values for L4 API: TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
 * parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
 *                      possible values for L4 API:
-*                         TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_L4_TCP|TPM_PARSE_FLAG_L4_UDP
 * l4_key             - Information to create an L4 parsing key for the rule.
 *                      Some pointers may be NULL depending on the parse_rule_bm.
 * pkt_frwd           - Information for packet forwarding decision.
@@ -1149,6 +1163,83 @@
 EXPORT_SYMBOL(tpm_del_ipv6_l4_ports_5t_rule);
 
 
+/*******************************************************************************
+* tpm_set_active_wan()
+*
+* DESCRIPTION:      Set active WAN port
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* active_wan        - active wan, GMAC0, GMAC1, PON
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_active_wan(uint32_t owner_id,
+				    tpm_gmacs_enum_t active_wan)
+{
+	tpm_error_code_t tpm_ret;
+
+	tpm_ret = tpm_proc_set_active_wan(active_wan);
+	if(TPM_OK != tpm_ret) {
+		TPM_OS_ERROR(TPM_DB_MOD, "set active wan has failed with error code (%d)\n", tpm_ret);
+		return tpm_ret;
+	}
+
+	return (TPM_OK);
+}
+EXPORT_SYMBOL(tpm_set_active_wan);
+/*******************************************************************************
+* tpm_hot_swap_profile()
+*
+* DESCRIPTION:      Swap profile and update all the ACL rules according to
+*                   the new profile
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* profile_id        - the new profile that system is swapping to
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_hot_swap_profile(uint32_t owner_id,
+				    tpm_eth_complex_profile_t profile_id)
+{
+#ifdef CONFIG_MV_ETH_WAN_SWAP
+
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_all_api_busy();
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_hot_swap_profile(owner_id, profile_id);
+
+	busy_ret_code = tpm_proc_all_api_busy_done();
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+#else
+	TPM_OS_ERROR(TPM_DB_MOD, "hot swap profile feature is not supported on this product!\n");
+	return TPM_OK;
+
+#endif /* CONFIG_MV_ETH_WAN_SWAP */
+
+}
+EXPORT_SYMBOL(tpm_hot_swap_profile);
+
 /******************************************************************************/
 /********************************** MC handling APIs **************************/
 /******************************************************************************/
@@ -1198,7 +1289,8 @@
 		return(ret_code);
 
 	ret_code = tpm_proc_add_ipv4_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
-						vid, ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm);
+						vid, ipv4_src_add, ipv4_dst_add, ignore_ipv4_src,
+						TPM_INVALID_QUEUE, dest_port_bm);
 
 	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV4_MC, stream_num);
 
@@ -1207,6 +1299,62 @@
 EXPORT_SYMBOL(tpm_add_ipv4_mc_stream);
 
 /*******************************************************************************
+* tpm_add_ipv4_mc_stream_set_queue()
+*
+* DESCRIPTION:      Creates a new IPv4 MC stream with dest Queue.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv4_src_add       - IPv4 source IP address in network order.
+* ipv4_src_add       - IPv4 destination IP address in network order.
+* ignore_ipv4_src    - when set to 1 - the IP source is not part of the key.
+* dest_queue          - destination queue number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_mc_stream_set_queue(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv4_src_add[4],
+					uint8_t ipv4_dst_add[4],
+					uint8_t ignore_ipv4_src,
+					uint16_t dest_queue,
+					tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV4_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv4_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
+						vid, ipv4_src_add, ipv4_dst_add, ignore_ipv4_src,
+						dest_queue, dest_port_bm);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV4_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv4_mc_stream_set_queue);
+
+/*******************************************************************************
 * tpm_updt_ipv4_mc_stream()
 *
 * DESCRIPTION:      Updates an existing IPv4 MC stream.
@@ -1319,7 +1467,8 @@
 		return(ret_code);
 
 	ret_code = tpm_proc_add_ipv6_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
-						vid, ipv6_src_add, ipv6_dst_add, ignore_ipv6_src, dest_port_bm);
+						vid, ipv6_src_add, ipv6_dst_add, ignore_ipv6_src,
+						TPM_INVALID_QUEUE, dest_port_bm);
 
 
 	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_MC, stream_num);
@@ -1330,6 +1479,64 @@
 EXPORT_SYMBOL(tpm_add_ipv6_mc_stream);
 
 /*******************************************************************************
+* tpm_add_ipv6_mc_stream_set_queue()
+*
+* DESCRIPTION:      Creates a new ipv6 MC stream with specified destination queue number.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv6_src_add       - ipv6 source IP address in network order.
+* ipv6_dst_add       - ipv6 destination IP address in network order.
+* ignore_ipv6_src    - when set to 1 - the IP source is not part of the key.
+* dest_queue          - destination queue number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_mc_stream_set_queue(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv6_src_add[16],
+					uint8_t ipv6_dst_add[16],
+					uint8_t ignore_ipv6_src,
+					uint16_t dest_queue,
+					tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
+						vid, ipv6_src_add, ipv6_dst_add, ignore_ipv6_src,
+						dest_queue, dest_port_bm);
+
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+
+}
+EXPORT_SYMBOL(tpm_add_ipv6_mc_stream_set_queue);
+
+/*******************************************************************************
 * tpm_updt_ipv6_mc_stream()
 *
 * DESCRIPTION:      Updates an existing ipv6 MC stream.
@@ -1515,16 +1722,43 @@
 * COMMENTS:
 *
 *******************************************************************************/
-tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id)
+tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id, tpm_ether_type_key_t ety)
 {
 	tpm_error_code_t ret_code;
 
-	ret_code = tpm_proc_loop_detect_add_channel(owner_id);
+	ret_code = tpm_proc_loop_detect_add_channel(owner_id, ety);
 	return ret_code;
 }
 EXPORT_SYMBOL(tpm_loop_detect_add_channel);
 
 /*******************************************************************************
+* tpm_loop_detect_del_channel()
+*
+* DESCRIPTION:      remove a communication channel for loop detection management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_loop_detect_del_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_loop_detect_del_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_loop_detect_del_channel);
+
+/*******************************************************************************
 * tpm_oam_loopback_add_channel()
 *
 * DESCRIPTION:      Establishes a communication channel for the OAM remote loopback.
@@ -2939,7 +3173,7 @@
 * according to the case - see tpm_error_code_t.
 *
 * COMMENTS:
-* 
+*
 *
 *******************************************************************************/
 tpm_error_code_t tpm_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num)
@@ -3170,3 +3404,207 @@
 }
 EXPORT_SYMBOL(tpm_mac_learn_entry_num_get);
 
+/*******************************************************************************
+* tpm_set_gmac_loopback()
+*
+* DESCRIPTION: The API enable/disable loopback mode of gmac.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* gmac                 -
+* enable               - 1 for enable, 0 for disable
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_gmac_loopback (uint32_t	  owner_id,
+						tpm_gmacs_enum_t  gmac,
+						uint8_t		  enable)
+{
+	tpm_error_code_t ret_code = TPM_RC_OK;
+
+	ret_code = tpm_init_gmac_loopback(gmac, enable);
+
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_set_gmac_loopback);
+
+/*******************************************************************************
+* tpm_add_ds_load_balance_rule()
+*
+* DESCRIPTION: The API adds DS load balance PnC rules to set target port to GMAC0 or GMAC1
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L2 API:
+*                        TPM_L2_PARSE_MAC_DA|TPM_L2_PARSE_MAC_SA|TPM_L2_PARSE_ONE_VLAN_TAG
+*                        |TPM_L2_PARSE_TWO_VLAN_TAG|TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES
+*                        |TPM_L2_PARSE_PPP_PROT|TPM_L2_PARSE_GEMPORT)
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L2 API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE
+* l2_key             - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* tgrt_port          - target Port: GMAC0, GMAC1 or CPU
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ds_load_balance_rule(uint32_t owner_id,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_l2_acl_key_t *l2_key,
+						tpm_ds_load_balance_tgrt_t tgrt_port)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_section Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_DS_LOAD_BALANCE, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ds_load_balance_acl_rule(owner_id, rule_num, rule_idx,
+		parse_rule_bm, parse_flags_bm, l2_key, tgrt_port);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_DS_LOAD_BALANCE, rule_num);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ds_load_balance_rule);
+
+/*******************************************************************************
+* tpm_del_ds_load_balance_rule()
+*
+* DESCRIPTION: The API delete CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ds_load_balance_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	ret_code = tpm_proc_del_ds_load_balance_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_del_ds_load_balance_rule);
+
+/*******************************************************************************
+* tpm_xlate_uni_2_switch_port()
+*
+* DESCRIPTION: The API translates TPM logic UNI port into Switch port.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* uni_port           - TPM logic port that need to be translated.
+*
+* OUTPUTS:
+* switch_port      - switch port.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_xlate_uni_2_switch_port (uint32_t		  owner_id,
+						     tpm_src_port_type_t  uni_port,
+						     uint32_t		 *switch_port)
+{
+	tpm_error_code_t ret_code = TPM_RC_OK;
+
+	*switch_port = tpm_db_eth_port_switch_port_get(uni_port);
+	if (TPM_DB_ERR_PORT_NUM == *switch_port)
+		ret_code = ERR_SRC_PORT_INVALID;
+
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_xlate_uni_2_switch_port);
+/*******************************************************************************
+* tpm_active_tcont()
+*
+* DESCRIPTION:    Function used to enable hwf to certain tcont.
+*
+* INPUTS:
+* tcont_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_active_tcont(uint32_t tcont_num)
+{
+	tpm_error_code_t ret_code;
+
+	/* active tcont hwf */
+	ret_code = tpm_proc_hwf_admin_set(TPM_ENUM_PMAC, tcont_num, true);
+
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_active_tcont);
+/*******************************************************************************
+* tpm_deactive_tcont()
+*
+* DESCRIPTION:    Function used to disable hwf to certain tcont.
+*
+* INPUTS:
+* tcont_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_deactive_tcont(uint32_t tcont_num)
+{
+	tpm_error_code_t ret_code;
+	/* deactive tcont hwf */
+	ret_code = tpm_proc_hwf_admin_set(TPM_ENUM_PMAC, tcont_num, false);
+
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_deactive_tcont);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h
index ffa8aa3..11fdd2d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h
@@ -777,6 +777,45 @@
 					tpm_trg_port_type_t 	dest_port_bm);
 
 /*******************************************************************************
+* tpm_add_ipv4_mc_stream_set_queue()
+*
+* DESCRIPTION:      Creates a new IPv4 MC stream with dest Queue.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv4_src_add       - IPv4 source IP address in network order.
+* ipv4_src_add       - IPv4 destination IP address in network order.
+* ignore_ipv4_src    - when set to 1 - the IP source is not part of the key.
+* dest_queue          - destination queue number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_mc_stream_set_queue(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv4_src_add[4],
+					uint8_t ipv4_dst_add[4],
+					uint8_t ignore_ipv4_src,
+					uint16_t dest_queue,
+					tpm_trg_port_type_t dest_port_bm);
+
+/*******************************************************************************
 * tpm_updt_ipv4_mc_stream()
 *
 * DESCRIPTION:      Updates an existing IPv4 MC stream.
@@ -860,6 +899,45 @@
 					tpm_trg_port_type_t dest_port_bm);
 
 /*******************************************************************************
+* tpm_add_ipv6_mc_stream_set_queue()
+*
+* DESCRIPTION:      Creates a new ipv6 MC stream with dest Queue.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv6_src_add       - ipv6 source IP address in network order.
+* ipv6_dst_add       - ipv6 destination IP address in network order.
+* ignore_ipv6_src    - when set to 1 - the IP source is not part of the key.
+* dest_queue          - destination queue number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_mc_stream_set_queue(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv6_src_add[16],
+					uint8_t ipv6_dst_add[16],
+					uint8_t ignore_ipv6_src,
+					uint16_t dest_queue,
+					tpm_trg_port_type_t dest_port_bm);
+
+/*******************************************************************************
 * tpm_updt_ipv6_mc_stream()
 *
 * DESCRIPTION:      Updates an existing ipv6 MC stream.
@@ -1155,7 +1233,27 @@
 * COMMENTS:
 *
 *******************************************************************************/
-tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id);
+tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id, tpm_ether_type_key_t ety);
+
+/*******************************************************************************
+* tpm_loop_detect_del_channel()
+*
+* DESCRIPTION:      remove a communication channel for loop detection management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_loop_detect_del_channel(uint32_t owner_id);
 
 /******************************************************************************/
 /********************************** Configuration retrieval APIs **************/
@@ -1928,6 +2026,62 @@
 					uint32_t dport,
 					tpm_sw_mirror_type_t mode,
 					bool enable);
+/*******************************************************************************
+* tpm_sw_set_trunk_ports
+*
+* DESCRIPTION:
+*       This function creates trunk ports and trunk id on switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       trunk_id    - valid from 0x0 to 0xf
+*       ports_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_trunk_ports
+(
+    uint32_t owner_id,
+    uint32_t trunk_id,
+    uint32_t ports_mask
+);
+/*******************************************************************************
+* tpm_sw_set_trunk_mask
+*
+* DESCRIPTION:
+*       This function sets trunk mask on switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       mask_num    - trunk mask number, valid from 0 to 7.
+*       trunk_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_trunk_mask
+(
+    uint32_t owner_id,
+    uint32_t mask_num,
+    uint32_t trunk_mask
+);
 
 /*******************************************************************************
 * tpm_sw_get_port_mirror
@@ -2061,7 +2215,7 @@
 * INPUTS:
 *       owner_id     - APP owner id should be used for all API calls.
 *       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       allow_tagged - set to 1 = discard tagged packets per lport
+*       drop_tagged - set to 1 = drop tagged packets per lport
 *                      set to 0 = allow tagged packets per lport.
 *
 * OUTPUTS:
@@ -2077,7 +2231,7 @@
 *******************************************************************************/
 tpm_error_code_t tpm_sw_set_port_tagged(uint32_t owner_id,
 					tpm_src_port_type_t src_port,
-					uint8_t allow_tagged);
+					uint8_t drop_tagged);
 
 /*******************************************************************************
 * tpm_sw_get_port_tagged
@@ -2113,7 +2267,7 @@
 * INPUTS:
 *       owner_id       - APP owner id should be used for all API calls.
 *       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       allow_untagged - set to 1 = discard untagged packets per lport
+*       drop_untagged - set to 1 = drop untagged packets per lport
 *                        set to 0 = alow untagged packets per lport.
 *
 * OUTPUTS:
@@ -2129,7 +2283,7 @@
 *******************************************************************************/
 tpm_error_code_t tpm_sw_set_port_untagged(uint32_t owner_id,
 					  tpm_src_port_type_t src_port,
-					  uint8_t allow_untagged);
+					  uint8_t drop_untagged);
 
 /*******************************************************************************
 * tpm_sw_get_port_untagged
@@ -3528,7 +3682,7 @@
 * INPUTS:
 *      owner_id          - APP owner id  should be used for all API calls.
 *       port              - The logical port number
-*      tpm_swport_pm_3   - Holds PM data
+*      tpm_swport_pm_3_all_t   - Holds PM data
 *
 * OUTPUTS:
 * PM data is supplied structure.
@@ -3540,7 +3694,7 @@
 *******************************************************************************/
 tpm_error_code_t tpm_sw_pm_3_read(uint32_t owner_id,
 				  tpm_src_port_type_t port,
-				  tpm_swport_pm_3_t *tpm_swport_pm_3);
+				  tpm_swport_pm_3_all_t *tpm_swport_pm_3);
 
 /*******************************************************************************
 * tpm_sw_clear_port_counter
@@ -3574,7 +3728,7 @@
 * owner_id           - APP owner id  should be used for all API calls.
 * src_port           - The packet originating source port, could be any UNI port:
 * precedence         - precedence of this CnM rule, from 0 to 7
-* l2_parse_rule_bm   
+* l2_parse_rule_bm
 * ipv4_parse_rule_bm
 *                    - Bitmap containing the significant flags for parsing fields of the packet.
 * l2_key
@@ -3805,6 +3959,228 @@
 *******************************************************************************/
 tpm_error_code_t tpm_mac_learn_entry_num_get(uint32_t *entry_num);
 
+/*******************************************************************************
+* tpm_add_ds_load_balance_rule()
+*
+* DESCRIPTION: The API adds DS load balance PnC rules to set target port to GMAC0 or GMAC1
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L2 API:
+*                        TPM_L2_PARSE_MAC_DA|TPM_L2_PARSE_MAC_SA|TPM_L2_PARSE_ONE_VLAN_TAG
+*                        |TPM_L2_PARSE_TWO_VLAN_TAG|TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES
+*                        |TPM_L2_PARSE_PPP_PROT|TPM_L2_PARSE_GEMPORT)
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L2 API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE
+* l2_key             - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* tgrt_port          - target Port: GMAC0, GMAC1 or CPU
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ds_load_balance_rule(uint32_t owner_id,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_l2_acl_key_t *l2_key,
+						tpm_ds_load_balance_tgrt_t tgrt_port);
+
+/*******************************************************************************
+* tpm_del_ds_load_balance_rule()
+*
+* DESCRIPTION: The API delete CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ds_load_balance_rule(uint32_t owner_id, uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_set_active_wan()
+*
+* DESCRIPTION:      Set active WAN port
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* active_wan        - active wan, GMAC0, GMAC1, PON
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_active_wan(uint32_t owner_id,
+				    tpm_gmacs_enum_t active_wan);
+/*******************************************************************************
+* tpm_hot_swap_profile()
+*
+* DESCRIPTION:      Swap profile and update all the ACL rules according to
+*                   the new profile
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* profile_id        - the new profile that system is swapping to
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_hot_swap_profile(uint32_t owner_id,
+				    tpm_eth_complex_profile_t profile_id);
+
+/*******************************************************************************
+* tpm_xlate_uni_2_switch_port()
+*
+* DESCRIPTION: The API translates TPM logic UNI port into Switch port.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* uni_port           - TPM logic port that need to be translated.
+*
+* OUTPUTS:
+* switch_port      - switch port.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_xlate_uni_2_switch_port (uint32_t		  owner_id,
+					     tpm_src_port_type_t  uni_port,
+					     uint32_t		 *switch_port);
+
+/*******************************************************************************
+* tpm_set_gmac_loopback()
+*
+* DESCRIPTION: The API enable/disable loopback mode of gmac.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* gmac                 -
+* enable               - 1 for enable, 0 for disable
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_gmac_loopback (uint32_t	  owner_id,
+						tpm_gmacs_enum_t  gmac,
+						uint8_t		  enable);
+
+/*******************************************************************************
+* tpm_sw_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per UNI port,
+*       and sets the egress mode for the port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - vlan id
+*       eMode      - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid_set_egrs_mode (uint32_t            owner_id,
+                                                    tpm_src_port_type_t port,
+                                                    uint16_t            vid,
+                                                    uint8_t             eMode);
+/*******************************************************************************
+* tpm_active_tcont()
+*
+* DESCRIPTION:    Function used to enable hwf to certain tcont.
+*
+* INPUTS:
+* tcont_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_active_tcont(uint32_t tcont_num);
+/*******************************************************************************
+* tpm_deactive_tcont()
+*
+* DESCRIPTION:    Function used to disable hwf to certain tcont.
+*
+* INPUTS:
+* tcont_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_deactive_tcont(uint32_t tcont_num);
+
 /* OLD API functions */
 #define tpm_add_l2_prim_acl_rule                            tpm_add_l2_rule
 #define tpm_add_l3_type_acl_rule                            tpm_add_l3_type_rule
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c
index 8aed74f..05e468a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c
@@ -507,28 +507,9 @@
 	tpm_pnc_ranges_t l_range_id;
 	int32_t ret_code = TPM_RC_OK;
 
-	/* Check whether the API group is supported, currently only support three types */
-	if ((api_type != TPM_API_L2_PRIM) && (api_type != TPM_API_L3_TYPE)
-	    && (api_type != TPM_API_IPV4)) {
-		TPM_OS_ERROR(TPM_PNCL_MOD, "api_type[%d] is not supported \n", api_type);
-		return ERR_GENERAL;
-	}
-
 	/* Convert to API section ID */
-	switch (api_type) {
-	case TPM_API_L2_PRIM:
-		l_api_section = TPM_L2_PRIM_ACL;
-		break;
-	case TPM_API_L3_TYPE:
-		l_api_section = TPM_L3_TYPE_ACL;
-		break;
-	case TPM_API_IPV4:
-		l_api_section = TPM_IPV4_ACL;
-		break;
-	default:
-		l_api_section = TPM_IPV4_ACL;
-		break;
-	}
+	ret_code = tpm_db_api_section_get_from_api_type(api_type, &l_api_section);
+	IF_ERROR(ret_code);
 
 	/* Get PnC range ID */
 	ret_code = tpm_db_api_section_main_pnc_get(l_api_section, &l_range_id);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c
index 1075e6b..568c868 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c
@@ -84,9 +84,14 @@
 #include "tpm_common.h"
 #include "tpm_header.h"
 #include "tpm_cpu_port_fc.h"
+#include "dbg-trace.h"
 
 static tpm_fc_info_t fc_info;
 
+extern int mv_enable_fc_events(void*, unsigned long);
+extern void mv_disable_fc_events(void);
+void tpm_fc_hr_timer_handler(void);
+
 /*******************************************************************************
 **
 **  tpm_fc_rate_limit
@@ -194,7 +199,7 @@
 void tpm_fc_set_config(tpm_fc_cfg_t *cfg)
 {
 	tpm_init_fc_params_t db_fc_conf;
-	
+
 	fc_info.cfg.thresh_high = cfg->thresh_high;
 	fc_info.cfg.thresh_low  = cfg->thresh_low;
 	fc_info.cfg.port        = cfg->port;
@@ -209,12 +214,12 @@
 
 	/* update DB with new settings */
 	tpm_db_fc_conf_get(&db_fc_conf);
-	
+
 	db_fc_conf.port		= cfg->tx_port;
 	db_fc_conf.tgt_port 	= cfg->tgt_port;
 	db_fc_conf.thresh_high 	= cfg->thresh_high;
 	db_fc_conf.thresh_low 	= cfg->thresh_low;
-	db_fc_conf.tx_port	= cfg->tx_port; 
+	db_fc_conf.tx_port	= cfg->tx_port;
 	db_fc_conf.tx_queue	= cfg->tx_queue;
 
 	tpm_db_fc_conf_set(&db_fc_conf);
@@ -238,7 +243,7 @@
 {
 	MV_U32 ns_period = us_period * 1000;
 	tpm_init_fc_params_t db_fc_conf;
-	
+
 	if (ns_period < us_period)
 		return (MV_ERROR);
 
@@ -248,6 +253,7 @@
 	tpm_db_fc_conf_set(&db_fc_conf);
 
 	fc_info.cfg.hrt_hit_time = ktime_set(0, ns_period);
+	mv_enable_fc_events(&tpm_fc_hr_timer_handler, ns_period);
 
 	return (MV_OK);
 }
@@ -289,9 +295,16 @@
 **  RETURNS:     hr_timer_RESTART
 **
 *******************************************************************************/
+#if 0
 static enum hrtimer_restart tpm_fc_hr_timer_handler(struct hrtimer *timer)
 {
 	ktime_t current_time    = timer->base->get_time();
+#else
+void tpm_fc_hr_timer_handler(void)
+{
+	ktime_t current_time    = ktime_get_real();
+#endif
+
 	s64     current_time_ns = ktime_to_ns(current_time);
 	s64     last_hit_ns     = ktime_to_ns(fc_info.hrt_last_hit);
 	s64     time_slip_ns;
@@ -299,13 +312,16 @@
 
 #ifdef TPM_FC_DEBUG
 	fc_info.stat.hrt_hits_num++;
+	if (fc_info.stat.hrt_hits_num < 100)
+		TRC_REC("Hit %ld\n", fc_info.stat.hrt_hits_num);
+
 	if ((fc_info.cfg.oneshot_count != 0) && (fc_info.oneshot_stat.hrt_hits_num < fc_info.cfg.oneshot_count))
 		fc_info.oneshot_stat.hrt_hits_num++;
 #endif
-
+#if 0
 	/* Update timer for the next hit at the beginning for better precision */
 	hrtimer_forward(timer, current_time, fc_info.cfg.hrt_hit_time);
-
+#endif
 	/* First compute the real timer period */
 	time_slip_ns = current_time_ns - last_hit_ns;
 
@@ -327,8 +343,11 @@
 
 		/* Flow Control the port */
 		tpm_fc_rate_limit();
-		
+#if 0
 		return (HRTIMER_RESTART);
+#else
+		return;
+#endif
 	}
 #endif
 
@@ -364,7 +383,7 @@
 
 			if (time_slip_ns > fc_info.oneshot_stat.hrt_lost_max_ns)
 				fc_info.oneshot_stat.hrt_lost_max_ns = time_slip_ns;
-			
+
 			if (time_slip_ns >= (hit_time_ns << 1))
 				fc_info.oneshot_stat.hrt_lost_200_up++;
 			else if (time_slip_ns >= (hit_time_ns + (hit_time_ns >> 1)))
@@ -383,8 +402,9 @@
 
 	/* Flow Control the port */
 	tpm_fc_rate_limit();
-
+#if 0
 	return (HRTIMER_RESTART);
+#endif
 }
 
 
@@ -414,9 +434,12 @@
 		if (true == fc_is_running) {
 			MV_U32  phy_addr = mvBoardPhyAddrGet(fc_info.cfg.tgt_port);
 			MV_U32	reg_val;
-			
+
+#if 0
 			hrtimer_cancel(&fc_info.hr_timer);
-			
+#else
+			mv_disable_fc_events();
+#endif
 			reg_val  = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(fc_info.cfg.tgt_port));
 			reg_val |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
 			reg_val &= ~NETA_SET_FLOW_CONTROL_MASK;
@@ -429,10 +452,11 @@
 			fc_info.magic = 0;
 			config_change = true;
 		}
-		
+
 #ifdef TPM_FC_DEBUG
 		fc_info.cfg.oneshot_count = 0;
 #endif
+		TRC_RELEASE();
 	}
 	else
 	{
@@ -448,13 +472,17 @@
 
 			/* set FC running indication */
 			fc_info.magic = TPM_FC_MAGIC_NUMBER;
-			
+
 			/* save the current time in the last hit */
 			fc_info.hrt_last_hit = ktime_get_real();
+#if 0
 			hrtimer_init(&fc_info.hr_timer, CLOCK_REALTIME, HRTIMER_MODE_REL);
 			fc_info.hr_timer.function = &tpm_fc_hr_timer_handler;
 			hrtimer_start(&fc_info.hr_timer, fc_info.cfg.hrt_hit_time, HRTIMER_MODE_REL);
-
+#else
+			//TRC_INIT();
+			mv_enable_fc_events(&tpm_fc_hr_timer_handler, ktime_to_ns(fc_info.cfg.hrt_hit_time));
+#endif
 			config_change = true;
 		}
 	}
@@ -523,9 +551,9 @@
 		TPM_OS_DEBUG(TPM_MTU_MOD, "SW port FC disabled!\n");
 		tpm_fc_enable(MV_FALSE);
 	}
-	
+
 	memset(&fc_info, 0, sizeof(tpm_fc_info_t));
-	
+
 	ns_q_sample_freq = db_fc_conf.queue_sample_freq * 1000;
 
 	if (ns_q_sample_freq < db_fc_conf.queue_sample_freq)
@@ -534,7 +562,7 @@
 	fc_info.cfg.hrt_hit_time	= ktime_set(0, ns_q_sample_freq);
 	fc_info.cfg.thresh_high		= db_fc_conf.thresh_high;
 	fc_info.cfg.thresh_low		= db_fc_conf.thresh_low;
-	fc_info.cfg.port		= db_fc_conf.port;
+	fc_info.cfg.port		    = db_fc_conf.port;
 	fc_info.cfg.tgt_port		= db_fc_conf.tgt_port;
 	fc_info.cfg.tgt_port_changed	= MV_TRUE;
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c
index e87c85f..44b119a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c
@@ -124,7 +124,8 @@
 
 	if (l2_parse_rule_bm)
 		ret_code = tpm_proc_add_l2_cnm_rule(owner_id, src_port, precedence, l2_parse_rule_bm, l2_key,
-						    ipv4_key_idx, pkt_frwd, pkt_act, pbits, rule_index);
+						    ipv4_parse_rule_bm, ipv4_key, ipv4_key_idx, pkt_frwd,
+						    pkt_act, pbits, rule_index);
 	else if (ipv4_parse_rule_bm)
 		ret_code = tpm_proc_add_ipv4_cnm_rule(owner_id, src_port, precedence, ipv4_parse_rule_bm,
 						      ipv4_key, pkt_frwd, pkt_act, pbits, rule_index);
@@ -235,7 +236,7 @@
 	}
 
 	if (l2_parse_rule_bm & ~(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG |
-				 TPM_L2_PARSE_ETYPE)) {
+				 TPM_L2_PARSE_TWO_VLAN_TAG | TPM_L2_PARSE_ETYPE)) {
 		TPM_OS_ERROR(TPM_CTC_CM_MOD, "l2_parse_rule_bm (%d) is invalid!\n", l2_parse_rule_bm);
 		return(ERR_PARSE_MAP_INVALID);
 	}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c
index ffa53d0..426528a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c
@@ -109,6 +109,7 @@
 
 /* TODO - change to static variable after updating print functions */
 tpm_db_t tpm_db;
+tpm_db_hot_swap_bak_db_t hot_swap_bak_db;
 
 static uint32_t mem_alloc_start_ind;
 
@@ -155,6 +156,8 @@
 uint8_t tpm_db_mc_igmp_proxy_sa_mac[6];
 uint8_t tpm_db_mc_igmp_proxy_sa_mac_valid;
 
+static uint32_t tpm_db_global_rule_idx = 1000;
+
 /* Function Declarations */
 int32_t tpm_db_api_freeentry_get(tpm_api_sections_t api_section, int32_t *index);
 int32_t tpm_db_api_entry_ind_get(tpm_api_sections_t api_section, uint32_t rule_num, int32_t *index);
@@ -277,6 +280,19 @@
 	}
 	return (TPM_DB_ERR_PORT_NUM);
 }
+uint32_t tpm_db_rule_index_get(void)
+{
+	return tpm_db_global_rule_idx;
+}
+int32_t tpm_db_rule_index_set(uint32_t rule_index)
+{
+	tpm_db_global_rule_idx = rule_index;
+	return TPM_DB_OK;
+}
+void tpm_db_rule_index_incrs(void)
+{
+	tpm_db_global_rule_idx++;
+}
 bool tpm_db_gmac1_lpbk_en_get(void)
 {
 	return tpm_db.func_profile.gmac1_loopback_en;
@@ -293,6 +309,22 @@
 {
 	tpm_db.func_profile.cpu_wan_loopback_en = en;
 }
+bool tpm_db_ds_load_bal_en_get(void)
+{
+	return tpm_db.func_profile.ds_load_bal_en;
+}
+void tpm_db_ds_load_bal_en_set(bool en)
+{
+	tpm_db.func_profile.ds_load_bal_en = en;
+}
+bool tpm_db_switch_active_wan_en_get(void)
+{
+	return tpm_db.func_profile.switch_active_wan_en;
+}
+void tpm_db_switch_active_wan_en_set(bool en)
+{
+	tpm_db.func_profile.switch_active_wan_en = en;
+}
 
 int32_t tpm_db_get_valid_uni_ports_num(uint32_t *num_ports)
 {
@@ -406,6 +438,7 @@
 			   gmac0 = 0,
 			   gmac1 = 0;
 	int32_t ret_code;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	switch(tpm_db.eth_cmplx_profile)
 	{
@@ -456,7 +489,7 @@
 		break;
 
 	case TPM_PON_G1_WAN_G0_INT_SWITCH:
-       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+       		if (TPM_ENUM_GMAC_1 == tpm_db.init_misc.active_wan) {
 			pon = TPM_GMAC_FUNC_NONE;
 			gmac1 = TPM_GMAC_FUNC_WAN;
 		}else{
@@ -467,7 +500,7 @@
 		break;
 
 	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
-       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+       		if (TPM_ENUM_GMAC_1 == tpm_db.init_misc.active_wan) {
 			pon = TPM_GMAC_FUNC_NONE;
 			gmac1 = TPM_GMAC_FUNC_WAN;
 		}else{
@@ -478,7 +511,7 @@
 		break;
 
 	case TPM_PON_G0_WAN_G1_INT_SWITCH:
-       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+       		if (TPM_ENUM_GMAC_0 == tpm_db.init_misc.active_wan) {
 			pon = TPM_GMAC_FUNC_NONE;
 			gmac0 = TPM_GMAC_FUNC_WAN;
 		}else{
@@ -489,7 +522,7 @@
 		break;
 
 	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
-		if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+		if (TPM_ENUM_GMAC_0 == tpm_db.init_misc.active_wan) {
 			pon = TPM_GMAC_FUNC_NONE;
 			gmac0 = TPM_GMAC_FUNC_WAN;
 		}else{
@@ -508,11 +541,21 @@
 
 	case TPM_PON_WAN_G0_G1_LPBK:
 		pon = TPM_GMAC_FUNC_WAN;
-		gmac0 = TPM_GMAC_FUNC_LAN_UNI;
+		gmac0 = TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI;
 		gmac1 = TPM_GMAC_FUNC_LAN;
 		break;
+	case TPM_PON_WAN_G0_G1_DUAL_LAN:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN_UNI;
+		gmac1 = TPM_GMAC_FUNC_LAN_UNI;
+		break;
 	}
 
+	/* when ds load balance on G0 and G1 is enabled, G0/1 are both LAN */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	if (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable)
+		gmac1 = TPM_GMAC_FUNC_LAN;
+
 	ret_code = tpm_db_gmac_func_set(TPM_ENUM_PMAC, pon);
 	IF_ERROR(ret_code);
 	ret_code = tpm_db_gmac_func_set(TPM_ENUM_GMAC_0, gmac0);
@@ -549,6 +592,7 @@
 
 	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
 	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+	case TPM_PON_WAN_G0_G1_DUAL_LAN:
 		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_1;
        	break;
 
@@ -585,8 +629,8 @@
 	uint32_t dst_port, trg_port_uni_any_bmp = 0;
 	tpm_src_port_type_t src_port;
 
-	for (dst_port = TPM_TRG_UNI_0, src_port = TPM_SRC_PORT_UNI_0; 
-	     dst_port <= TPM_TRG_UNI_7; 
+	for (dst_port = TPM_TRG_UNI_0, src_port = TPM_SRC_PORT_UNI_0;
+	     dst_port <= TPM_TRG_UNI_7;
 	     dst_port = (dst_port << 1), src_port += 1) {
 
 		/* if port is valid */
@@ -609,6 +653,21 @@
 	return false;
 }
 
+int32_t tpm_db_target_to_gmac(tpm_pnc_trg_t pnc_target, tpm_gmacs_enum_t *gmac)
+{
+	if (TPM_PNC_TRG_GMAC0 == pnc_target)
+		*gmac = TPM_ENUM_GMAC_0;
+	else if (TPM_PNC_TRG_GMAC1 == pnc_target)
+		*gmac = TPM_ENUM_GMAC_1;
+	else if (TPM_PNC_TRG_CPU == pnc_target) {
+		TPM_OS_ERROR(TPM_DB_MOD, "target to CPU, no GMAC valid\n");
+		return TPM_DB_ERR_INV_INPUT;
+	} else
+		*gmac = TPM_ENUM_PMAC;
+
+	return TPM_DB_OK;
+}
+
 /*******************************************************************************
 * tpm_db_to_lan_gmac_get()
 *
@@ -646,8 +705,10 @@
 					continue;
 			if (!tpm_db_gmac1_lpbk_en_get()) {
 				if (TPM_GMAC_FUNC_LAN == tpm_db.gmac_func[i]      ||
-				    TPM_GMAC_FUNC_LAN_UNI == tpm_db.gmac_func[i])
+				    TPM_GMAC_FUNC_LAN_UNI == tpm_db.gmac_func[i]) {
 					gmac_vec |= (TPM_ENUM_GMAC_0 == i) ? TPM_PNC_TRG_GMAC0 : TPM_PNC_TRG_GMAC1;
+					break;/* target only one, no others */
+				}
 			} else {
 				gmac_vec |= TPM_PNC_TRG_GMAC0;
 				break;
@@ -955,6 +1016,31 @@
 }
 
 /*******************************************************************************
+* tpm_db_gmac_conn_conf_get()
+*
+* DESCRIPTION:      Function to get GMAC connection information from DB
+*
+* INPUTS:
+* gmac                   - GMAC port
+*
+* OUTPUTS:
+* gmac_port_conf         - connection info
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK.
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_conn_conf_get(tpm_gmacs_enum_t gmac, tpm_init_gmac_conn_conf_t *gmac_port_conf)
+{
+	if (NULL == gmac_port_conf)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memcpy(gmac_port_conf, &tpm_db.gmac_port_conf[gmac], sizeof(tpm_init_gmac_conn_conf_t));
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
 * tpm_db_gmac_tcont_llid_set()
 *
 * DESCRIPTION:      Function to set the GMAC connection and T-CONTs  in the DB
@@ -1299,7 +1385,7 @@
 {
 	if ((gmac >= TPM_MAX_NUM_GMACS) || (queue_num >= TPM_MAX_NUM_RX_QUEUE))
 		return (TPM_DB_ERR_INV_INPUT);
-		
+
 	tpm_db.gmac_rx[gmac].rx_queue[queue_num].queue_size = queue_size;
 	tpm_db.gmac_rx[gmac].rx_queue[queue_num].valid = TPM_DB_VALID;
 
@@ -1456,10 +1542,10 @@
 /*******************************************************************************
 * tpm_db_gmac_lpk_queue_get()
 *
-* DESCRIPTION:      Function to get the queue id used to do gmac loopback on MC
-*
+* DESCRIPTION:      Function to get the queue id used to do gmac loopback on MC, min queue id for data traffic,
+*                   max queue id for MAC learning
 * INPUTS:
-*	None
+* queue_type     - queue type for GMAC1 loopback, for data traffic or for MAC learning
 * OUTPUTS:
 * gmac           - gmac on which loopback is done
 * queue_idx      - queue index which do loopback
@@ -1467,12 +1553,15 @@
 * On success, the function returns TPM_DB_OK. On error different types are returned
 * according to the case - see tpm_db_err_t.
 *******************************************************************************/
-uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac, uint32_t *queue_idx)
+uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac,
+				   uint32_t *queue_idx,
+				   tpm_db_gmac1_lpk_queue_type_t queue_type)
 {
 	uint32_t queue_id, q_valid, gmac_id;
 	tpm_db_txq_owner_t queue_owner, lpk_queue_owner = TPM_Q_OWNER_GMAC0;
 	tpm_db_gmac_func_t lpk_gmac_func;
 	tpm_db_tx_mod_t tx_mod;
+	uint32_t q_expected = TPM_MAX_NUM_TX_QUEUE;
 
 	/*check input parameters*/
 	if (NULL == gmac || NULL == queue_idx) {
@@ -1509,21 +1598,25 @@
 		if (TPM_DB_OK != tpm_db_gmac_tx_q_conf_get(tx_mod, queue_id, &q_valid, NULL,
 							   &queue_owner, NULL, NULL, NULL))
 			continue;
-		if (q_valid == TPM_TRUE && queue_owner == lpk_queue_owner)
-					break;
+		if (q_valid == TPM_TRUE && queue_owner == lpk_queue_owner) {
+			q_expected = queue_id;
+			if (TPM_GMAC1_QUEUE_DATA_TRAFFIC == queue_type)
+				break;
+			else if (TPM_GMAC1_QUEUE_MAC_LEARN_TRAFFIC == queue_type)
+				continue;
+		}
 	}
-	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
-		TPM_OS_ERROR(TPM_DB_MOD, "Invalid Tx queue %d of GMAC1 assigned to GMAC0 \n", queue_id);
+	if (q_expected >= TPM_MAX_NUM_TX_QUEUE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid Tx queue %d of GMAC1 assigned to GMAC0 \n", q_expected);
 		return ERR_SW_TM_QUEUE_INVALID;
 	}
 
 	*gmac = gmac_id;
-	*queue_idx = queue_id;
+	*queue_idx = q_expected;
 
 	return (TPM_DB_OK);
 }
 
-
 /*******************************************************************************
 * tpm_db_pnc_rng_create()
 *
@@ -1849,6 +1942,9 @@
 	case TPM_API_CPU_LOOPBACK:
 		*api_section = TPM_CPU_LOOPBACK_ACL;
 		break;
+	case TPM_API_DS_LOAD_BALANCE:
+		*api_section = TPM_DS_LOAD_BALANCE_ACL;
+		break;
 	case TPM_API_L2_PRIM:
 		*api_section = TPM_L2_PRIM_ACL;
 		break;
@@ -1900,6 +1996,9 @@
 	case TPM_CPU_LOOPBACK_ACL:
 		*api_type = TPM_API_CPU_LOOPBACK;
 		break;
+	case TPM_DS_LOAD_BALANCE_ACL:
+		*api_type = TPM_API_DS_LOAD_BALANCE;
+		break;
 	case TPM_L2_PRIM_ACL:
 		*api_type = TPM_API_L2_PRIM;
 		break;
@@ -2477,6 +2576,53 @@
 	return (TPM_DB_OK);
 }
 
+
+/*******************************************************************************
+* tpm_db_igmp_set_snoop_enable()
+*
+* DESCRIPTION:      Set IGMP snoop enable
+*
+* INPUTS:
+* igmp_snoop_enable       - IGMP snoop enable
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_set_snoop_enable(uint32_t igmp_snoop_enable)
+{
+	tpm_db.igmp_def.igmp_snoop_enable = igmp_snoop_enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_igmp_get_snoop_enable()
+*
+* DESCRIPTION:      Get IGMP snoop enable
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop_enable       - IGMP snoop enable
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_get_snoop_enable(uint32_t *igmp_snoop_enable)
+{
+	*igmp_snoop_enable = tpm_db.igmp_def.igmp_snoop_enable;
+	return (TPM_DB_OK);
+}
+
 /*******************************************************************************
 * tpm_db_omci_type_set()
 *
@@ -2897,7 +3043,7 @@
 }
 
 /*******************************************************************************
-* tpm_db_backup_wan_set()
+* tpm_db_active_wan_set()
 *
 * DESCRIPTION:      Set WAN technology
 *
@@ -2912,14 +3058,14 @@
 * COMMENTS:
 *
 *******************************************************************************/
-int32_t tpm_db_backup_wan_set(tpm_gmacs_enum_t backup_wan)
+int32_t tpm_db_active_wan_set(tpm_gmacs_enum_t active_wan)
 {
-	tpm_db.init_misc.backup_wan = backup_wan;
+	tpm_db.init_misc.active_wan = active_wan;
 	return (TPM_DB_OK);
 }
 
 /*******************************************************************************
-* tpm_db_backup_wan_get()
+* tpm_db_active_wan_get()
 *
 * DESCRIPTION:      Set WAN technology
 *
@@ -2934,36 +3080,9 @@
 * COMMENTS:
 *
 *******************************************************************************/
-int32_t tpm_db_backup_wan_get(tpm_gmacs_enum_t *backup_wan)
-{
-	*backup_wan = tpm_db.init_misc.backup_wan;
-	return (TPM_DB_OK);
-}
-
 tpm_gmacs_enum_t tpm_db_active_wan_get()
 {
-	switch (tpm_db.eth_cmplx_profile) {
-	case TPM_PON_G1_WAN_G0_INT_SWITCH:
-		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_1 : TPM_ENUM_PMAC;
-
-	case TPM_PON_G0_WAN_G1_INT_SWITCH:
-		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_0 : TPM_ENUM_PMAC;
-
-	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
-		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_0 : TPM_ENUM_PMAC;
-
-	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
-		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_1 : TPM_ENUM_PMAC;
-
-	case TPM_G0_WAN_G1_INT_SWITCH:
-		return TPM_ENUM_GMAC_0;
-
-	case TPM_G1_WAN_G0_INT_SWITCH:
-		return TPM_ENUM_GMAC_1;
-
-	default:
-		return TPM_ENUM_PMAC;
-	}
+	return tpm_db.init_misc.active_wan;
 }
 
 /*******************************************************************************
@@ -4214,10 +4333,10 @@
 			     tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con, uint32_t *rule_idx)
 {
 	int32_t ind;
-	static uint32_t l_rule_idx = 1000;
 	tpm_pnc_ranges_t range_id = 0;
 	tpm_db_pnc_range_conf_t rangConf;
 	int32_t ret_code;
+	uint32_t l_rule_idx;
 
 	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), - rule_num(%d)\n", api_section, rule_num);
 
@@ -4240,6 +4359,7 @@
 	memcpy(&(API_ENT_I(api_section, ind).pnc_tbl_conn), pnc_con, sizeof(tpm_db_pnc_conn_t));
 
 	API_ENT_I(api_section, ind).bi_dir = bi_dir;
+	l_rule_idx = tpm_db_rule_index_get();
 	if (TPM_RANGE_TYPE_ACL == rangConf.range_type)
 		API_ENT_I(api_section, ind).rule_idx = l_rule_idx;
 	else
@@ -4262,7 +4382,7 @@
 
 	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
 		*rule_idx = l_rule_idx;
-		l_rule_idx++;
+		tpm_db_rule_index_incrs();
 	} else
 		*rule_idx = rule_num;
 
@@ -4675,6 +4795,34 @@
 	return (TPM_DB_OK);
 }
 
+int32_t tpm_db_api_entry_update_rule_idx(tpm_api_sections_t api_section,
+			     			uint32_t rule_idx_pre,
+			     			uint32_t rule_idx_new)
+{
+	int32_t ind;
+	int32_t ret_code;
+	uint32_t rule_num = 0;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), - rule_num(%d)\n", api_section, rule_num);
+
+	/* Get the rule_num */
+	ret_code = tpm_db_api_rulenum_get(api_section, rule_idx_pre, &rule_num);
+	if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+		TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+		return ERR_RULE_IDX_INVALID;
+	}
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+
+	tpm_db_api_entry_ind_get(api_section, rule_num, &ind);
+	if (ind == -1)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	/* update rule_index */
+	API_ENT_I(api_section, ind).rule_idx = rule_idx_new;
+
+	return (TPM_DB_OK);
+}
+
 /*******************************************************************************
 * tpm_db_api_rulenum_get()
 *
@@ -5514,7 +5662,7 @@
 {
 	uint32_t entry_id, first_free = TPM_MC_MAX_MAC_NUM;
 	uint32_t port_nr;
-	
+
 	for (entry_id = 0; entry_id < TPM_MC_MAX_MAC_NUM; entry_id++) {
 		if (tpm_db_mc_mac_table[entry_id] != NULL) {
 			if (!memcmp(tpm_db_mc_mac_table[entry_id]->mac_addr, mac_addr, 6 * sizeof(uint8_t)))
@@ -5616,12 +5764,12 @@
 	default:
 		return 0;
 	}
-	
+
 	if (TRG_UNI(uni_port)) {
 		if (port_nr < TPM_MAX_NUM_UNI_PORTS)
 			return tpm_db_mc_mac_table[entry_id]->user_num[port_nr];
 	}
-	
+
 	return 0;
 }
 
@@ -5910,7 +6058,7 @@
 
 	/* reset IPv6 MC rule */
 	memset(tpm_db.ipv6_mc_stream, 0, sizeof(tpm_db.ipv6_mc_stream));
-	
+
 }
 int32_t tpm_db_mc_vlan_get_ai_bit_by_vid(uint32_t mc_vlan, uint32_t *ai_bit)
 {
@@ -6550,7 +6698,7 @@
 	if (tpm_db_mod2_jump_split_mod_all_entry_bm[gmac_port][i] & mask) {
 		/* this is a split mod pmt entry */
 		tpm_db_mod2_jump_split_mod_occupied_entry_bm[gmac_port][i] &= ~mask;
-	} 
+	}
 	else {
 		tpm_db_mod2_jump_occupied_entry_bm[gmac_port][i] &= ~mask;
 	}
@@ -7257,7 +7405,7 @@
 
 	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
 		if (tpm_db.split_mod_conf.gmac_vlan_conf[gmac_port].split_mod_vlan[i].valid)
-			vlan_num++; 
+			vlan_num++;
 	}
 
 	return vlan_num;
@@ -7289,7 +7437,7 @@
 		vlan_out = &mod_data->vlan_mod.vlan2_out;
 	else
 		vlan_out = &mod_data->vlan_mod.vlan1_out;
-	
+
 	if (0 == vlan_out->pbit_mask)
 		/* pbit AS_IS */
 		pbit_index = 0;
@@ -7298,9 +7446,9 @@
 		if (next_free != 1)
 			pbit_index++;
 	}
-	
+
 	next_free += pbit_index;
-	
+
 	if (next_free != TPM_MOD2_NULL_ENT_IDX) {
 		tpm_db_mod2_jump_pmt_info[gmac_port][next_free].status = TPM_MOD_ENTRY_BOOKED;
 
@@ -7325,17 +7473,17 @@
 		TPM_OS_ERROR(TPM_DB_MOD, "already has %d num_vlans\n", vlan_num - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM);
 		return TPM_DB_ERR_DB_TBL_FULL;
 	}
-	
+
 	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
-		if (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid) 
+		if (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid)
 			continue;
 
 		//here finds a spot
 		tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid = 1;
-		
+
 		if (mod_data->vlan_mod.vlan1_out.vid_mask)
 			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_1 = mod_data->vlan_mod.vlan1_out.vid;
-		
+
 		if (mod_data->vlan_mod.vlan2_out.vid_mask)
 			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_2 = mod_data->vlan_mod.vlan2_out.vid;
 
@@ -7356,11 +7504,11 @@
 int32_t tpm_db_mod2_split_mod_get_vlan_index(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, uint32_t *index)
 {
 	uint32_t i;
-	//printk("input: port: %d, vlan_op: %d, vlan1: %d(%d), vlan2: %d(%d)\n", 
+	//printk("input: port: %d, vlan_op: %d, vlan1: %d(%d), vlan2: %d(%d)\n",
 		//port, mod_data->vlan_mod.vlan_op, mod_data->vlan_mod.vlan1_out.vid, mod_data->vlan_mod.vlan1_out.vid_mask,
 		//mod_data->vlan_mod.vlan2_out.vid, mod_data->vlan_mod.vlan2_out.vid_mask);
 	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
-		//printk("output: port: %d, vlan_op: %d, vlan1: %d, vlan2: %d\n", 
+		//printk("output: port: %d, vlan_op: %d, vlan1: %d, vlan2: %d\n",
 			//tpm_db.split_mod_conf.gmac_vlan_conf[i].gmac_port, tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_op,
 			//tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_1, tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_2);
 		if (!tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid)
@@ -7424,7 +7572,7 @@
 	return TPM_DB_OK;
 }
 
-int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port, 
+int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port,
 						     uint32_t       vlan_index,
 						     uint32_t      *user_num)
 {
@@ -7432,12 +7580,12 @@
 		TPM_OS_ERROR(TPM_DB_MOD, "Invalid port: %d\n", port);
 		return TPM_DB_ERR_INV_INPUT;
 	}
-	
+
 	if (vlan_index >= TPM_DB_SPLIT_MOD_NUM_VLANS_MAX) {
 		TPM_OS_ERROR(TPM_DB_MOD, "Invalid vlan_index: %d\n", vlan_index);
 		return TPM_DB_ERR_INV_INPUT;
 	}
-	
+
 	if (!tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index].valid) {
 		TPM_OS_ERROR(TPM_DB_MOD, "Invalid vlan entry: %d\n", vlan_index);
 		return TPM_DB_ERR_INV_INPUT;
@@ -7755,7 +7903,7 @@
 		split_jump_entries = 16 * 2/*init added*/ +
 					(split_vlan_num - 1) * 16/*internal VLAN*/ +
 					split_pbit_num + 1/*last VLAN*/;
-		split_jump_free_entries = 2 * (15 - split_pbit_num)/*init occupy*/ + 
+		split_jump_free_entries = 2 * (15 - split_pbit_num)/*init occupy*/ +
 					(split_vlan_num - 1) * (16 - split_pbit_num - 1)/*internal VLAN*/;
 	}
 
@@ -7955,7 +8103,7 @@
 		}
 		memset(tpm_db_mod2_jump_occupied_entry_bm[port], 0, bm_size);
 		tpm_db_mod2_jump_occupied_entry_bm[port][0] |= 0x1;
-		
+
 		if (tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] != NULL) {
 			vfree(tpm_db_mod2_jump_split_mod_occupied_entry_bm[port]);
 			tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] = NULL;
@@ -7986,11 +8134,11 @@
 		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED\n");
 		return(TPM_OK);
 	}
-	
+
 	vlan_nums = tpm_db_split_mod_get_num_vlans();
 	p_bits_nums = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
 
-	
+
 	tpm_db_mod2_jump_area_cfg.next_free[port] = p_bits_nums + 1;
 	//tpm_db_mod2_jump_area_cfg.next_split[port] = 16;
 
@@ -9156,7 +9304,7 @@
 	if (key_array[key_id].valid == TPM_FALSE)
 		return TPM_DB_ERR_REC_STATUS_ERR;
 
-	user_num = tpm_db_get_ipv6_gen_key_user_num(key_id);
+	user_num = tpm_db_get_ipv6_dip_key_user_num(key_id);
 
 	if (user_num == 0)
 		memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_dip_key_t));
@@ -10262,9 +10410,41 @@
 }
 
 int32_t tpm_db_set_gmac_rate_limit(tpm_db_tx_mod_t gmac_i,
+				   uint32_t bucket_size,
+				   uint32_t rate_limit,
+				   uint32_t prio)
+{
+	/*check param*/
+	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	tpm_db.gmac_tx[gmac_i].bucket_size = bucket_size;
+	tpm_db.gmac_tx[gmac_i].rate_limit = rate_limit;
+	tpm_db.gmac_tx[gmac_i].prio = prio;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+				   uint32_t *bucket_size,
+				   uint32_t *rate_limit,
+				   uint32_t *prio)
+{
+	/*check param*/
+	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	*bucket_size = tpm_db.gmac_tx[gmac_i].bucket_size;
+	*rate_limit = tpm_db.gmac_tx[gmac_i].rate_limit;
+	*prio = tpm_db.gmac_tx[gmac_i].prio;
+
+	return TPM_DB_OK;
+}
+int32_t tpm_db_set_gmac_q_rate_limit(tpm_db_tx_mod_t gmac_i,
 				   uint32_t queue,
 				   uint32_t bucket_size,
-				   uint32_t rate_limit)
+				   uint32_t rate_limit,
+				   uint32_t wrr)
 {
 	/*check param*/
 	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
@@ -10275,14 +10455,16 @@
 
 	tpm_db.gmac_tx[gmac_i].tx_queue[queue].bucket_size = bucket_size;
 	tpm_db.gmac_tx[gmac_i].tx_queue[queue].rate_limit = rate_limit;
+	tpm_db.gmac_tx[gmac_i].tx_queue[queue].wrr = wrr;
 
 	return TPM_DB_OK;
 }
 
-int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+int32_t tpm_db_get_gmac_q_rate_limit(tpm_gmacs_enum_t gmac_i,
 				   uint32_t queue,
 				   uint32_t *bucket_size,
-				   uint32_t *rate_limit)
+				   uint32_t *rate_limit,
+				   uint32_t *wrr)
 {
 	/*check param*/
 	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
@@ -10293,6 +10475,7 @@
 
 	*bucket_size = tpm_db.gmac_tx[gmac_i].tx_queue[queue].bucket_size;
 	*rate_limit = tpm_db.gmac_tx[gmac_i].tx_queue[queue].rate_limit;
+	*wrr = tpm_db.gmac_tx[gmac_i].tx_queue[queue].wrr;
 
 	return TPM_DB_OK;
 }
@@ -10312,9 +10495,9 @@
 	return TPM_DB_OK;
 }
 
-int32_t tpm_db_get_ipv4_pre_filter_key(tpm_src_port_type_t src_port, 
-				       uint32_t key_idx, 
-				       tpm_parse_fields_t *parse_rule_bm, 
+int32_t tpm_db_get_ipv4_pre_filter_key(tpm_src_port_type_t src_port,
+				       uint32_t key_idx,
+				       tpm_parse_fields_t *parse_rule_bm,
 				       tpm_ipv4_acl_key_t *ipv4_key)
 {
 	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
@@ -10466,6 +10649,354 @@
 	return TPM_DB_OK;
 }
 
+
+/*******************************************************************************
+* tpm_db_mac_learn_mod_idx_set()
+*
+* DESCRIPTION: Set mac leanring pmt mod index, just for mac learning
+*
+* INPUTS:
+* mod_idx
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mac_learn_mod_idx_set(uint32_t mod_idx)
+{
+	tpm_db.mac_learn_mod_idx = mod_idx;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mac_learn_mod_idx_get()
+*
+* DESCRIPTION: Get mac leanring pmt mod index, just for mac learning
+*
+* INPUTS:
+* mod_idx
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mac_learn_mod_idx_get(uint32_t *mod_idx)
+{
+	*mod_idx = tpm_db.mac_learn_mod_idx;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_ds_mac_based_trunk_enable_set()
+*
+* DESCRIPTION: Set ds_mac_based_trunk_enable
+*
+* INPUTS:
+* enable       -   ds_mac_based_trunk_enable
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ds_mac_based_trunk_enable_set(tpm_db_ds_mac_based_trunk_enable_t enable)
+{
+	tpm_db.ds_mac_based_trunk_enable = enable;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_ds_mac_based_trunk_enable_get()
+*
+* DESCRIPTION: Get ds_mac_based_trunk_enable
+*
+* INPUTS:
+*
+* OUTPUTS:
+* enable       -   ds_mac_based_trunk_enable
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ds_mac_based_trunk_enable_get(tpm_db_ds_mac_based_trunk_enable_t *enable)
+{
+	*enable = tpm_db.ds_mac_based_trunk_enable;
+
+	return (TPM_DB_OK);
+}
+int32_t tpm_db_api_data_backup(void)
+{
+	memcpy(hot_swap_bak_db.api_ent_mem_area_bak, tpm_db.api_ent_mem_area, sizeof(tpm_db.api_ent_mem_area));
+	memcpy(hot_swap_bak_db.api_section_bak, tpm_db.api_section, sizeof(tpm_db.api_section));
+	memcpy(hot_swap_bak_db.mc_vid_port_cfg_bak, tpm_db.mc_vid_port_cfg, sizeof(tpm_db.mc_vid_port_cfg));
+	memcpy(hot_swap_bak_db.gmac_tx_bak, tpm_db.gmac_tx, sizeof(tpm_db.gmac_tx));
+	memcpy(hot_swap_bak_db.igmp_proxy_sa_mac, tpm_db_mc_igmp_proxy_sa_mac, 6);
+	hot_swap_bak_db.igmp_proxy_sa_mac_valid = tpm_db_mc_igmp_proxy_sa_mac_valid;
+	hot_swap_bak_db.switch_init = tpm_db.func_profile.switch_init;
+
+	return (TPM_DB_OK);
+}
+int32_t tpm_db_api_data_rcvr(void)
+{
+	memcpy(tpm_db.mc_vid_port_cfg, hot_swap_bak_db.mc_vid_port_cfg_bak, sizeof(tpm_db.mc_vid_port_cfg));
+	memcpy(tpm_db.gmac_tx, hot_swap_bak_db.gmac_tx_bak, sizeof(tpm_db.gmac_tx));
+	memcpy(tpm_db_mc_igmp_proxy_sa_mac, hot_swap_bak_db.igmp_proxy_sa_mac, 6);
+	tpm_db_mc_igmp_proxy_sa_mac_valid = hot_swap_bak_db.igmp_proxy_sa_mac_valid;
+	tpm_db.func_profile.switch_init = hot_swap_bak_db.switch_init;
+
+	return (TPM_DB_OK);
+}
+void tpm_db_exchange_value(uint32_t *v1, uint32_t *v2)
+{
+	uint32_t tmp;
+
+	tmp = *v1;
+	*v1 = *v2;
+	*v2 = tmp;
+
+	return;
+}
+int32_t tpm_db_wan_lan_rate_limit_exchange_db(tpm_db_gmac_tx_t *gmac_tx)
+{
+	int32_t queue;
+
+	for (queue = 0; queue < TPM_MAX_NUM_TX_QUEUE; queue++) {
+		tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].tx_queue[queue].bucket_size),
+					&(gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[queue].bucket_size));
+		tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].tx_queue[queue].rate_limit),
+					&(gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[queue].rate_limit));
+		tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].tx_queue[queue].wrr),
+					&(gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[queue].wrr));
+	}
+
+	tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].bucket_size),
+				&(gmac_tx[TPM_TX_MOD_GMAC1].bucket_size));
+	tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].rate_limit),
+				&(gmac_tx[TPM_TX_MOD_GMAC1].rate_limit));
+	tpm_db_exchange_value(&(gmac_tx[TPM_TX_MOD_GMAC0].prio),
+				&(gmac_tx[TPM_TX_MOD_GMAC1].prio));
+
+	return (TPM_DB_OK);
+}
+int32_t tpm_db_wan_lan_rate_limit_exchange(void)
+{
+	tpm_db_wan_lan_rate_limit_exchange_db(tpm_db.gmac_tx);
+	tpm_db_wan_lan_rate_limit_exchange_db(hot_swap_bak_db.gmac_tx_bak);
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_api_section_bak_num_entries_get(tpm_api_sections_t api_section, uint32_t *num_entries)
+{
+	if (hot_swap_bak_db.api_section_bak[api_section].valid == TPM_DB_INVALID) {
+		printk("api_section: %d is not valid\n", api_section);
+		*num_entries = 0;
+	} else
+		*num_entries = hot_swap_bak_db.api_section_bak[api_section].num_valid_entries;
+
+	printk("api_section: %d, number_valid: %d\n", api_section, *num_entries);
+	return (TPM_DB_OK);
+}
+int32_t tpm_db_api_section_bak_ent_tbl_get(tpm_api_sections_t api_sec, tpm_db_api_entry_t *api_ent_mem_area, uint32_t index)
+{
+	if (ILLEGAL_API_SEC(api_sec))
+		IF_ERROR_I(TPM_DB_ERR_REC_NOT_EXIST, api_sec);
+
+	if (NULL == api_ent_mem_area)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memcpy(api_ent_mem_area,
+		&hot_swap_bak_db.api_ent_mem_area_bak[(hot_swap_bak_db.api_section_bak[api_sec].table_start) + index],
+		sizeof(tpm_db_api_entry_t));
+
+	return (TPM_DB_OK);
+}
+int32_t tpm_db_api_entry_bak_get_next(tpm_api_sections_t api_section,
+				      int32_t cur_rule,
+				      int32_t *next_rule)
+{
+	int32_t ind = -1;
+	int32_t i;
+	uint32_t min_rule, l_next_rule = ~0;
+	tpm_db_api_entry_t *api_tbl;
+
+	api_tbl = &(hot_swap_bak_db.api_ent_mem_area_bak[hot_swap_bak_db.api_section_bak[api_section].table_start]);
+
+	if (cur_rule <= -1)
+		min_rule = 0;
+	else
+		min_rule = cur_rule + 1;
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "min_rule(%d) \n", min_rule); */
+
+	for (i = 0; i <= hot_swap_bak_db.api_section_bak[api_section].last_valid_index; i++) {
+		if (((api_tbl + i)->valid == TPM_DB_VALID) &&
+		    ((api_tbl + i)->rule_num >= min_rule) && ((api_tbl + i)->rule_num < l_next_rule)) {
+			l_next_rule = (api_tbl + i)->rule_num;
+			ind = i;
+			TPM_OS_INFO(TPM_DB_MOD, "rule_num(%d), rule_idx(%d) update\n", (api_tbl + i)->rule_num, (api_tbl + i)->rule_idx);
+		} else
+			TPM_OS_INFO(TPM_DB_MOD, "rule_num(%d), rule_idx(%d) \n", (api_tbl + i)->rule_num, (api_tbl + i)->rule_idx);
+	}
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "l_next_rule(%d) ind(%d) \n", l_next_rule, ind); */
+
+	if ((l_next_rule < (uint32_t) (~0)) && (ind != -1)) {
+		*next_rule = ind;
+	} else		/* Not found */
+		*next_rule = -1;
+
+	TPM_OS_INFO(TPM_DB_MOD, "next_rule(%d) \n", *next_rule);
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_max_uni_port_nr_get()
+*
+* DESCRIPTION: Get max UNI port number
+*
+* INPUTS:
+*
+* OUTPUTS:
+* max_uni_port_nr       -   max UNI port number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_max_uni_port_nr_get(uint32_t *max_uni_port_nr)
+{
+	*max_uni_port_nr = tpm_db.max_uni_port_nr + 1;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_uni_egr_rate_limit_set()
+*
+* DESCRIPTION: Set GMAC UNI egress rate limit
+*
+* INPUTS:
+*        port - GMAC UNI port to do rate limit
+*        rate_limit - rate limit value
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_uni_egr_rate_limit_set(tpm_src_port_type_t port, uint32_t rate_limit)
+{
+	tpm_db.gmac_uni_egr_rate_limit[port] = rate_limit;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_uni_egr_rate_limit_get()
+*
+* DESCRIPTION: Get GMAC UNI egress rate limit
+*
+* INPUTS:
+*        port - GMAC UNI port to do rate limit
+* OUTPUTS:
+*        rate_limit - rate limit value, if value got is 0, means no rate limit set
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_uni_egr_rate_limit_get(tpm_src_port_type_t port, uint32_t *rate_limit)
+{
+	if (NULL == rate_limit)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	*rate_limit = tpm_db.gmac_uni_egr_rate_limit[port];
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_lpk_uni_ingr_rate_limit_set()
+*
+* DESCRIPTION: Set GMAC UNI ingress rate limit only with loopback mode
+*
+* INPUTS:
+*        port - GMAC UNI port to do rate limit
+*        rate_limit - rate limit value
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_lpk_uni_ingr_rate_limit_set(tpm_src_port_type_t port, tpm_db_gmac_lpk_uni_ingr_rate_limit_t rate_limit)
+{
+	tpm_db.gmac_lpk_uni_ingr_rate_limit[port].count_mode = rate_limit.count_mode;
+	tpm_db.gmac_lpk_uni_ingr_rate_limit[port].cir = rate_limit.cir;
+	tpm_db.gmac_lpk_uni_ingr_rate_limit[port].cbs = rate_limit.cbs;
+	tpm_db.gmac_lpk_uni_ingr_rate_limit[port].ebs = rate_limit.ebs;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_lpk_uni_ingr_rate_limit_get()
+*
+* DESCRIPTION: Get GMAC UNI ingress rate limit with loopback mode
+*
+* INPUTS:
+*        port - GMAC UNI port to do rate limit
+* OUTPUTS:
+*        rate_limit - rate limit value, if value got is 0, means no rate limit set
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_lpk_uni_ingr_rate_limit_get(tpm_src_port_type_t port, tpm_db_gmac_lpk_uni_ingr_rate_limit_t *rate_limit)
+{
+	if (NULL == rate_limit)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memcpy(rate_limit,
+	       &tpm_db.gmac_lpk_uni_ingr_rate_limit[port],
+	       sizeof(tpm_db_gmac_lpk_uni_ingr_rate_limit_t));
+
+	return (TPM_DB_OK);
+}
+
 /*******************************************************************************
 * tpm_db_init()
 *
@@ -10514,6 +11045,7 @@
 	for (i = TPM_SRC_PORT_UNI_0; i <= TPM_SRC_PORT_UNI_7; i++)
 		 tpm_db.igmp_def.frwd_mode[i] = TPM_IGMP_FRWD_MODE_DROP;
 	tpm_db.igmp_def.cpu_queue = 0;
+	tpm_db.igmp_def.igmp_snoop_enable = TPM_FALSE;
 
 	tpm_db.igmp_def.mc_lpbk_enable[TPM_IP_VER_4] = TPM_FALSE;
 	tpm_db.igmp_def.mc_lpbk_enable[TPM_IP_VER_6] = TPM_FALSE;
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h
index 0ada80e..a526cfd 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h
@@ -113,7 +113,8 @@
 	TPM_GMAC_FUNC_WAN,
 	TPM_GMAC_FUNC_LAN_AND_WAN,
 	TPM_GMAC_FUNC_VIRT_UNI,
-	TPM_GMAC_FUNC_LAN_UNI
+	TPM_GMAC_FUNC_LAN_UNI,
+	TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI /* For Media Convert Loopback mode */
 } tpm_db_gmac_func_t;
 
 typedef enum {
@@ -131,6 +132,11 @@
 	TPM_PNC_RNG_LAST_INIT_TRAP	/* Last entry in PnC range is hardcoded to TRAP to CPU */
 } tpm_db_pnc_rng_last_ent_t;
 
+typedef enum {
+	TPM_GMAC1_QUEUE_DATA_TRAFFIC,
+	TPM_GMAC1_QUEUE_MAC_LEARN_TRAFFIC,
+}tpm_db_gmac1_lpk_queue_type_t;
+
 typedef tpm_init_sched_t tpm_db_sched_t;
 typedef tpm_init_port_admin_t tpm_db_port_admin_t;
 typedef tpm_init_port_speed_t tpm_db_port_speed_t;
@@ -155,6 +161,7 @@
 typedef tpm_init_ctc_cm_enable_t    tpm_db_ctc_cm_enable_t;
 typedef tpm_init_split_mod_mode_t    tpm_db_split_mod_mode_t;
 typedef tpm_ctc_cm_ipv6_parse_win_t tpm_db_ctc_cm_ipv6_parse_win_t;
+typedef tpm_init_ds_mac_based_trunk_enable_t tpm_db_ds_mac_based_trunk_enable_t;
 
 /*************************************************************/
 /*               DEFINITIONS                                 */
@@ -452,7 +459,7 @@
 	uint32_t pnc_init_debug_port;
 	uint32_t oam_loopback_channel_configured;
 	tpm_db_pon_type_t pon_type;
-	tpm_gmacs_enum_t backup_wan;
+	tpm_gmacs_enum_t active_wan;
 
 	tpm_db_mh_src_t ds_mh_set_conf;
 
@@ -475,6 +482,7 @@
 
 /* Structure holds the IGMP/MLD settings */
 typedef struct {
+	uint32_t igmp_snoop_enable;
 	uint32_t frwd_mode[TPM_MAX_NUM_PORTS];
 	uint32_t cpu_queue;
 	tpm_mc_filter_mode_t filter_mode;
@@ -511,11 +519,15 @@
 	uint32_t queue_weight;
 	uint32_t bucket_size;
 	uint32_t rate_limit;
+	uint32_t wrr;
 } tpm_db_gmac_txq_t;
 
 /*Structure defines the details of a Packet Processor Tx component  */
 typedef struct {
 	uint32_t valid;						/* Defines if the Tx component is used */
+	uint32_t bucket_size;
+	uint32_t rate_limit;
+	uint32_t prio;
 	tpm_db_gmac_txq_t tx_queue[TPM_MAX_NUM_TX_QUEUE];	/* Config. of each of the 8 Tx queue of this Tx component */
 } tpm_db_gmac_tx_t;
 
@@ -635,6 +647,7 @@
 	uint8_t group_addr[16];
 	uint8_t src_addr[16];
 	uint8_t ignore_src_addr;
+	uint16_t dest_queue;
 	uint32_t dest_port_bm;
 	uint32_t u4_entry;
 } tpm_db_ipv6_mc_stream_entry_t;
@@ -702,6 +715,23 @@
 } tpm_db_cnm_ipv4_pre_filter_t;
 
 typedef struct {
+	/* api_ent_mem_area backup used for hot swap profile feature */
+	tpm_db_api_entry_t api_ent_mem_area_bak[TPM_DB_API_ENTRIES_TBL_SIZE];
+
+	/* API section backup used for hot swap profile feature */
+	tpm_db_api_section_t api_section_bak[TPM_MAX_NUM_API_SECTIONS];
+
+	/* MC VID setting backup */
+	tpm_mc_vid_cfg_t mc_vid_port_cfg_bak[TPM_MC_VID_NUM_MAX];
+	tpm_db_gmac_tx_t gmac_tx_bak[TPM_MAX_NUM_TX_PORTS];
+
+	uint32_t igmp_proxy_sa_mac[6];
+	uint32_t igmp_proxy_sa_mac_valid;
+
+	bool     switch_init;
+}tpm_db_hot_swap_bak_db_t;
+
+typedef struct {
 	tpm_db_ctc_cm_enable_t enable;
 	tpm_db_ctc_cm_ipv6_parse_win_t ipv6_parse_win;
 	/* init value from XML */
@@ -717,12 +747,21 @@
 	bool switch_init;
 	bool gmac1_loopback_en;
 	bool cpu_wan_loopback_en;
+	bool ds_load_bal_en;
+	bool switch_active_wan_en;
 	tpm_db_ety_dsa_enable_t  ety_dsa_enable;
 	tpm_init_virt_uni_t virt_uni_info;
 
 } tpm_db_func_profile_t;
 
 typedef struct {
+	tpm_limit_mode_t count_mode;
+	uint32_t cir;
+	uint32_t cbs;
+	uint32_t ebs;
+} tpm_db_gmac_lpk_uni_ingr_rate_limit_t;
+
+typedef struct {
 	/* Physical chip config */
 	tpm_eth_complex_profile_t eth_cmplx_profile;
 	tpm_src_port_type_t max_uni_port_nr;
@@ -798,7 +837,6 @@
 	tpm_db_ipv6_mc_stream_entry_t  ipv6_mc_stream[TPM_MC_MAX_STREAM_NUM];
 	tpm_db_split_mod_t   split_mod_conf;
 
-	
 	/* Array indicates which API's are currently called for synch purposes.
 	   When API is not in called, invalid=-1 When API is called, it will set it's rule_num */
 	int32_t tpm_busy_apis[TPM_MAX_API_TYPES][TPM_MAX_PARALLEL_API_CALLS];
@@ -807,6 +845,15 @@
 	/* func profile, based on chip type and board profile */
 	tpm_db_func_profile_t    func_profile;
 
+	/* MC MAC learning pmt mod index */
+	uint32_t mac_learn_mod_idx;
+
+	tpm_db_ds_mac_based_trunk_enable_t  ds_mac_based_trunk_enable;
+
+	/* To record GMAC UNI egress rate limit */
+	uint32_t gmac_uni_egr_rate_limit[TPM_MAX_NUM_UNI_PORTS];
+	/* To record GMAC LPK UNI ingress rate limit */
+	tpm_db_gmac_lpk_uni_ingr_rate_limit_t gmac_lpk_uni_ingr_rate_limit[TPM_MAX_NUM_UNI_PORTS];
 } tpm_db_t;
 
 typedef struct {
@@ -816,6 +863,7 @@
 	uint16_t vid;
 	uint8_t group_addr[4];
 	uint8_t src_addr[4];
+	uint16_t dest_queue;
 	uint32_t dest_port_bm;
 	uint32_t u4_entry;
 } tpm_db_mc_stream_entry_t;
@@ -866,12 +914,14 @@
 int32_t tpm_db_trg_port_switch_port_get(tpm_trg_port_type_t ext_port);
 int32_t tpm_db_eth_port_conf_set(tpm_init_eth_port_conf_t *eth_port_conf);
 int32_t tpm_db_gmac_conn_conf_set(tpm_init_gmac_conn_conf_t *gmac_port_conf, uint32_t arr_size);
+int32_t tpm_db_gmac_conn_conf_get(tpm_gmacs_enum_t gmac, tpm_init_gmac_conn_conf_t *gmac_port_conf);
 
 /* GMAC Config */
 int32_t tpm_db_gmac_tcont_llid_set(uint32_t num_tcont_llid);
 int32_t tpm_db_gmac_conn_get(tpm_gmacs_enum_t gmac, tpm_db_gmac_conn_t *gmac_con);
 int32_t tpm_db_gmac_mh_en_conf_set(tpm_gmacs_enum_t gmac, uint32_t mh_en);
 int32_t tpm_db_gmac_mh_en_conf_get(tpm_gmacs_enum_t gmac, uint32_t *mh_en);
+int32_t tpm_db_target_to_gmac(tpm_pnc_trg_t pnc_target, tpm_gmacs_enum_t *gmac);
 int32_t tpm_db_gmac_bm_bufs_conf_set(tpm_gmacs_enum_t gmac, uint32_t large_pkt_buffers,
 					uint32_t small_pkt_buffers);
 int32_t tpm_db_gmac_bm_bufs_conf_get(tpm_gmacs_enum_t gmac, uint32_t *valid, uint32_t *large_pkt_buffers,
@@ -897,7 +947,9 @@
 
 int32_t tpm_db_gmac_tx_val_set(tpm_db_tx_mod_t tx_mod);
 uint32_t tpm_db_gmac_tx_val_get(tpm_db_tx_mod_t tx_mod);
-uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac, uint32_t *queue_idx);
+uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac,
+				   uint32_t *queue_idx,
+				   tpm_db_gmac1_lpk_queue_type_t queue_type);
 
 /* RX queues Config */
 int32_t tpm_db_gmac_rx_val_set(tpm_gmacs_enum_t gmac);
@@ -930,6 +982,8 @@
 int32_t tpm_db_igmp_get_port_frwd_mode(uint32_t port, uint32_t *mode);
 int32_t tpm_db_igmp_set_cpu_queue(uint32_t queue);
 int32_t tpm_db_igmp_get_cpu_queue(uint32_t *queue);
+int32_t tpm_db_igmp_get_snoop_enable(uint32_t *igmp_snoop_enable);
+int32_t tpm_db_igmp_set_snoop_enable(uint32_t igmp_snoop_enable);
 
 /* MISC */
 int32_t tpm_db_omci_type_set(uint32_t omci_etype);
@@ -953,8 +1007,7 @@
 int32_t tpm_db_ds_mh_set_conf_set(tpm_db_mh_src_t ds_mh_set_conf);
 int32_t tpm_db_ds_mh_get_conf_set(tpm_db_mh_src_t *ds_mh_set_conf);
 
-int32_t tpm_db_backup_wan_set(tpm_gmacs_enum_t backup_wan);
-int32_t tpm_db_backup_wan_get(tpm_gmacs_enum_t *backup_wan);
+int32_t tpm_db_active_wan_set(tpm_gmacs_enum_t active_wan);
 tpm_gmacs_enum_t tpm_db_active_wan_get(void);
 
 #if 0				/*Keep to be added in future version */
@@ -1032,6 +1085,9 @@
 				tpm_db_pnc_conn_t *pnc_con);
 
 int32_t tpm_db_api_tcam_num_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *tcam_num);
+int32_t tpm_db_api_entry_update_rule_idx(tpm_api_sections_t api_section,
+			     			uint32_t rule_idx_pre,
+			     			uint32_t rule_idx_new);
 int32_t tpm_db_api_rulenum_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *rule_num);
 int32_t tpm_db_api_rulenum_get_from_l2_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
 						tpm_l2_acl_key_t *l2_key, uint32_t *rule_num);
@@ -1045,6 +1101,7 @@
 int32_t tpm_db_api_entry_val_get_next(tpm_api_sections_t api_section, int32_t cur_rule, int32_t *next_rule,
 					uint32_t *rule_idx, uint32_t *bi_dir, tpm_rule_entry_t *api_data,
 					tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con);
+int32_t tpm_db_rule_index_set(uint32_t rule_index);
 int32_t tpm_db_api_entry_invalidate(tpm_api_sections_t api_section, uint32_t rule_num);
 int32_t tpm_db_api_entry_ind_get(tpm_api_sections_t api_section, uint32_t rule_num, int32_t *index);
 int32_t tpm_db_api_tcam_rule_idx_get(tpm_api_sections_t api_section, uint32_t tcam_num, uint32_t *rule_idx);
@@ -1116,13 +1173,15 @@
 int32_t tpm_db_mod2_get_chain_id_by_pmt_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
 						tpm_chain_type_t *chain_type, uint16_t *chain_id);
 uint16_t tpm_db_mod2_get_next_free_jump_entry(tpm_gmacs_enum_t gmac_port);
+uint8_t tpm_db_mod2_rollback_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					 uint16_t chain_id, uint8_t on_failure);
 
 uint16_t tpm_db_mod2_get_next_split_mod_free_jump_entry(tpm_gmacs_enum_t gmac_port, tpm_pkt_mod_t *mod_data);
 //void tpm_db_mod2_update_split_mod_next_free_jump_entry(tpm_gmacs_enum_t gmac_port);
 int32_t tpm_db_mod2_split_mod_insert_vlan(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data);
 int32_t tpm_db_mod2_split_mod_get_vlan_index(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, uint32_t *index);
 int32_t tpm_db_mod2_split_mod_increase_vlan_user_num(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data);
-int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port, 
+int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port,
 													 uint32_t       vlan_index,
 													 uint32_t      *user_num);
 void tpm_db_mod2_set_multicast_mh_state(uint8_t enable);
@@ -1334,13 +1393,23 @@
 int32_t tpm_db_dec_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx);
 int32_t tpm_db_get_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t *num_users);
 int32_t tpm_db_set_gmac_rate_limit(tpm_db_tx_mod_t gmac_i,
+				   uint32_t bucket_size,
+				   uint32_t rate_limit,
+				   uint32_t prio);
+int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+				   uint32_t *bucket_size,
+				   uint32_t *rate_limit,
+				   uint32_t *prio);
+int32_t tpm_db_set_gmac_q_rate_limit(tpm_db_tx_mod_t gmac_i,
 				   uint32_t queue,
 				   uint32_t bucket_size,
-				   uint32_t rate_limit);
-int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+				   uint32_t rate_limit,
+				   uint32_t wrr);
+int32_t tpm_db_get_gmac_q_rate_limit(tpm_gmacs_enum_t gmac_i,
 				   uint32_t queue,
 				   uint32_t *bucket_size,
-				   uint32_t *rate_limit);
+				   uint32_t *rate_limit,
+				   uint32_t *wrr);
 int32_t tpm_db_fc_conf_set(tpm_init_fc_params_t *port_fc_conf);
 int32_t tpm_db_fc_conf_get(tpm_init_fc_params_t *port_fc_conf);
 /* switch_init */
@@ -1353,6 +1422,30 @@
 void tpm_db_gmac1_lpbk_en_set(bool en);
 bool tpm_db_cpu_wan_lpbk_en_get(void);
 void tpm_db_cpu_wan_lpbk_en_set(bool en);
+bool tpm_db_ds_load_bal_en_get(void);
+void tpm_db_ds_load_bal_en_set(bool en);
+bool tpm_db_switch_active_wan_en_get(void);
+void tpm_db_switch_active_wan_en_set(bool en);
+int32_t tpm_db_api_data_backup(void);
+int32_t tpm_db_api_data_rcvr(void);
+int32_t tpm_db_api_section_bak_num_entries_get(tpm_api_sections_t api_section, uint32_t *num_entries);
+int32_t tpm_db_api_section_bak_ent_tbl_get(tpm_api_sections_t api_sec, tpm_db_api_entry_t *api_ent_mem_area, uint32_t index);
+int32_t tpm_db_api_entry_bak_get_next(tpm_api_sections_t api_section,
+				      int32_t cur_rule,
+				      int32_t *next_rule);
+int32_t tpm_db_wan_lan_rate_limit_exchange(void);
+
+int32_t tpm_db_mac_learn_mod_idx_set(uint32_t mod_idx);
+int32_t tpm_db_mac_learn_mod_idx_get(uint32_t *mod_idx);
+int32_t tpm_db_ds_mac_based_trunk_enable_set(tpm_db_ds_mac_based_trunk_enable_t enable);
+int32_t tpm_db_ds_mac_based_trunk_enable_get(tpm_db_ds_mac_based_trunk_enable_t *enable);
+
+int32_t tpm_db_max_uni_port_nr_get(uint32_t *max_uni_port_nr);
+
+int32_t tpm_db_gmac_uni_egr_rate_limit_set(tpm_src_port_type_t port, uint32_t rate_limit);
+int32_t tpm_db_gmac_uni_egr_rate_limit_get(tpm_src_port_type_t port, uint32_t *rate_limit);
+int32_t tpm_db_gmac_lpk_uni_ingr_rate_limit_set(tpm_src_port_type_t port, tpm_db_gmac_lpk_uni_ingr_rate_limit_t rate_limit);
+int32_t tpm_db_gmac_lpk_uni_ingr_rate_limit_get(tpm_src_port_type_t port, tpm_db_gmac_lpk_uni_ingr_rate_limit_t *rate_limit);
 
 #ifdef __cplusplus
 }
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c
index 7c586ab..006dd73 100644
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c
@@ -140,7 +140,8 @@
 			"PON_G0_WAN_G1_INT_SWITCH",		"PON_WAN_DUAL_MAC_EXT_SWITCH",
 		    	"PON_WAN_G1_MNG_EXT_SWITCH",		"PON_WAN_G0_SINGLE_PORT",
 			"PON_WAN_G1_SINGLE_PORT",		"PON_G1_WAN_G0_SINGLE_PORT",
-			"PON_G0_WAN_G1_SINGLE_PORT",		"PON_WAN_G0_G1_LPBK"};
+			"PON_G0_WAN_G1_SINGLE_PORT",		"PON_WAN_G0_G1_LPBK",
+			"TPM_PON_WAN_G0_G1_DUAL_LAN"};
 
 static tpm_pnc_range_lookup_map_t pnc_range_lookup_tbl[TPM_MAX_NUM_RANGES] = {
 /*  Range_num             lu_id  last_range  valid */
@@ -148,6 +149,7 @@
 	{TPM_PNC_MAC_LEARN, 0, 1, 1},
 	{TPM_PNC_CPU_WAN_LPBK_US, 0, 0, 1},
 	{TPM_PNC_NUM_VLAN_TAGS, 0, 0, 1},
+	{TPM_PNC_DS_LOAD_BALANCE, 0, 0, 1},
 	{TPM_PNC_MULTI_LPBK, 0, 0, 1},
 	{TPM_PNC_VIRT_UNI, 0, 0, 1},
 	{TPM_PNC_LOOP_DET_US, 0, 0, 1},
@@ -156,13 +158,14 @@
 	{TPM_PNC_IGMP, 2, 0, 1},
 	{TPM_PNC_IPV4_MC_DS, 2, 0, 1},
 	{TPM_PNC_IPV4_MAIN, 2, 1, 1},
-	{TPM_PNC_TCP_FLAG, 3, 1, 1},
+	{TPM_PNC_IPV4_TCP_FLAG, 3, 1, 1},
 	{TPM_PNC_TTL, 4, 1, 1},
 	{TPM_PNC_IPV4_PROTO, 5, 0, 1},
 	{TPM_PNC_IPV4_FRAG, 5, 0, 1},
 	{TPM_PNC_IPV4_LEN, 5, 1, 1},
 	{TPM_PNC_IPV6_NH, 6, 1, 1},
 	{TPM_PNC_IPV6_L4_MC_DS, 7, 1, 1},
+	{TPM_PNC_IPV6_TCP_FLAG, 7, 1, 1},
 	{TPM_PNC_IPV6_L4, 7, 1, 1},
 	{TPM_PNC_IPV6_HOPL, 8, 1, 1},
 	{TPM_PNC_IPV6_MC_SIP, 8, 1, 1},
@@ -179,6 +182,15 @@
 
 };
 
+bool tpm_init_check_gmac_init(tpm_gmacs_enum_t gmac_i)
+{
+	/* Check Port Available or not */
+	if (mvNetaPortCheck(gmac_i) || (NULL == mvNetaPortHndlGet(gmac_i))) {
+		return false;
+	}
+	return true;
+}
+
 bool tpm_init_gmac_in_gateway_mode(tpm_gmacs_enum_t gmac_i)
 {
 	struct eth_port *pp = NULL;
@@ -275,9 +287,10 @@
 	tpm_init.eth_cmplx_profile = tpm_init_params->eth_cmplx_profile;
 	memcpy(&(tpm_init.gmac_port_conf), &(tpm_init_params->gmac_port_conf),
 		sizeof(tpm_init.gmac_port_conf));
-	tpm_init.backup_wan = tpm_init_params->backup_wan;
+	tpm_init.active_wan = tpm_init_params->active_wan;
 	memcpy(&(tpm_init.split_mod_config), &(tpm_init_params->split_mod_config), sizeof(tpm_init_split_mod_params_t));
 	tpm_init.switch_init = tpm_init_params->switch_init;
+	tpm_init.ds_mac_based_trunk_enable = tpm_init_params->ds_mac_based_trunk_enable;
 }
 
 void tpm_init_pon_type_get(void)
@@ -557,12 +570,18 @@
 		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G1_SINGLE_PORT
 		    || tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_SINGLE_PORT
 		    || tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_SINGLE_PORT
-		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK
+		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_DUAL_LAN)
 			tpm_init.switch_init = 0;
 		else
 			tpm_init.switch_init = 1;
 	}
 }
+void tpm_init_ds_mac_based_trunk_enable_get(void)
+{
+	if (tpm_init.ds_mac_based_trunk_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ds_mac_based_trunk_enable = TPM_DS_MAC_BASED_TRUNK_DISABLED;
+}
 
 void tpm_init_ipv6_5t_enable_get(void)
 {
@@ -577,7 +596,7 @@
 {
 	uint32_t i,j, off = 0;
 	char buff[1024];
-	uint32_t profile[8]= {0};
+	uint32_t profile[7]= {0};
 
 	off += sprintf(buff+off, "\nSelected Eth Complex Profile: %s", prof_str_tlb[tpm_init.eth_cmplx_profile]);
 	off += sprintf(buff+off, "\nHW enabled options:\n\t");
@@ -596,33 +615,33 @@
 		break;
 
 	case TPM_PON_WAN_G0_INT_SWITCH:
-		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY | ESC_OPT_GEPHY_SW_P0;
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
 		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII;
 		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
-		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY | ESC_OPT_RGMIIA_SW_P6;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
 		break;
 
 	case TPM_PON_WAN_G1_LAN_G0_INT_SWITCH:
-		profile[0] = ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
-		profile[1] = ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII;
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII;
 		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
-		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY | ESC_OPT_RGMIIA_SW_P6;
 		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
+		profile[5] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
 		break;
 
 	case TPM_G0_WAN_G1_INT_SWITCH:
 		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
-		profile[1] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII;
+		profile[1] = ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII;
 		break;
 
 	case TPM_G1_WAN_G0_INT_SWITCH:
 		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
-        profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_FE3PHY;
-		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII;
-		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
-		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
-		profile[5] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
-		profile[6] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
+		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
+		profile[5] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
 		break;
 
 	case TPM_PON_G1_WAN_G0_INT_SWITCH:
@@ -657,11 +676,9 @@
 		break;
 
 	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
-		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
-		break;
-
 	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
 		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		profile[1] = ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_MAC0;
 		break;
 
 	case TPM_PON_WAN_G0_G1_LPBK:
@@ -673,6 +690,9 @@
 			|| (GFLT200_ID == mvBoardIdGet()) || (GFLT110_ID == mvBoardIdGet()))
 			profile[0] = ESC_OPT_GEPHY_MAC0;
 		break;
+	case TPM_PON_WAN_G0_G1_DUAL_LAN:
+		profile[0] = ESC_OPT_GEPHY_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		break;
 	}
 
 	off += sprintf(buff+off, "\nProfile supported options:\n");
@@ -693,7 +713,6 @@
 		TPM_OS_ERROR(TPM_INIT_MOD, "%s", buff);
 }
 
-
 static uint32_t tpm_init_eth_cmplx_update_conf(void)
 {
 	uint32_t i;
@@ -702,9 +721,12 @@
 	if (hwEthCmplx & (ESC_OPT_AUTO | ESC_OPT_ILLEGAL))
 	{
 		TPM_OS_ERROR(TPM_INIT_MOD, "\n Illegal values in mvBoardEthComplexConfigGet 0x%x\n", hwEthCmplx);
-       	return TPM_FAIL;
+		return TPM_FAIL;
 	}
 
+	/* do not check SATA */
+	hwEthCmplx &= (~ESC_OPT_SATA);
+
 	if (tpm_init.eth_cmplx_profile == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
 		if (TPM_VALID_ENABLED == tpm_init.validation_en){
 			TPM_OS_ERROR(TPM_INIT_MOD, "\n ETH COMPLEX PROFILE - missing initialization\n");
@@ -712,6 +734,9 @@
 		}
 	}
 
+	if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.active_wan)
+		tpm_init.active_wan = TPM_ENUM_PMAC;
+
 	/* set default values for all ports and GMACs */
 	switch (tpm_init.eth_cmplx_profile)
 	{
@@ -719,7 +744,7 @@
 		if (!VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
 		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx) &&
 		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6), hwEthCmplx) &&
-		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5| ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx))
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx))
 			goto setup_err;
 
 		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
@@ -891,7 +916,7 @@
 			goto virt_uni_err;
 
 		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
-		    !VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx))
+		    !VALID_ONLY((ESC_OPT_RGMIIA_SW_P6 |ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx))
 			goto setup_err;
 
 		tpm_init.pon_type = TPM_NONE;
@@ -908,13 +933,13 @@
 		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
 
 		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
-       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+			if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
 				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
 
 				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
 				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
 				    (tpm_init.eth_port_conf[i].switch_port <= 3))
-       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
 				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
 					 (tpm_init.eth_port_conf[i].switch_port == 0))
 					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
@@ -988,7 +1013,6 @@
 			}
 
 		if (VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) ||
-               VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY), hwEthCmplx) ||
 		    VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII), hwEthCmplx)){
 			for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
 				if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
@@ -1020,9 +1044,6 @@
 		break;
 
 	case TPM_PON_G1_WAN_G0_INT_SWITCH:
-		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
-			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
-
 		if (1 == tpm_init.virt_uni_info.enabled)
 			goto virt_uni_err;
 
@@ -1092,9 +1113,6 @@
 		break;
 
 	case TPM_PON_G0_WAN_G1_INT_SWITCH:
-		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
-			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
-
 		if (1 == tpm_init.virt_uni_info.enabled)
 			goto virt_uni_err;
 
@@ -1115,13 +1133,13 @@
 
 
 		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
-       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+			if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
 				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
 
 				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
 				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
 				    (tpm_init.eth_port_conf[i].switch_port <= 3))
-       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
 				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
 					 (tpm_init.eth_port_conf[i].switch_port == 0))
 					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
@@ -1270,20 +1288,10 @@
 		if (1 == tpm_init.virt_uni_info.enabled)
 			goto virt_uni_err;
 
-		if ((TPM_ENUM_GMAC_0 != tpm_init.backup_wan) && (TPM_ENUM_GMAC_1 != tpm_init.backup_wan) &&
-		    (TPM_ENUM_PMAC   != tpm_init.backup_wan)) {
-			TPM_OS_ERROR(TPM_INIT_MOD, "\n tpm_init.backup_wan (%x) is not set\n",
-					tpm_init.backup_wan);
-			goto setup_err;
-		}
-
 		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx) &&
 		    !VALID_ONLY((ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_MAC0), hwEthCmplx))
 			goto setup_err;
 
-		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
-			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
-
 		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
 		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_UNI_0;
 
@@ -1322,19 +1330,10 @@
 		if (1 == tpm_init.virt_uni_info.enabled)
 			goto virt_uni_err;
 
-		if ((TPM_ENUM_GMAC_0 != tpm_init.backup_wan) && (TPM_ENUM_GMAC_1 != tpm_init.backup_wan) &&
-		    (TPM_ENUM_PMAC   != tpm_init.backup_wan)) {
-			TPM_OS_ERROR(TPM_INIT_MOD, "\n tpm_init.backup_wan (%x) is not set\n",
-					tpm_init.backup_wan);
-			goto setup_err;
-		}
 		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx) &&
 		    !VALID_ONLY((ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_MAC0), hwEthCmplx))
 			goto setup_err;
 
-		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
-			tpm_init.backup_wan = TPM_ENUM_GMAC_0;
-
 		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
 		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_WAN;
 
@@ -1391,12 +1390,45 @@
 		i = 0;
 		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
 		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
-		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
 		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
 		i++;
 		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
 			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
 		break;
+	case TPM_PON_WAN_G0_G1_DUAL_LAN:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		/* FIXME - Add correct condition, after answers from lsp team. */
+		/*if (!VALID_ONLY((ESC_OPT_GEPHY_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx))
+			goto setup_err;*/
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_GE_PHY;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_UNI_1;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+		i++;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_1;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+		i++;
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
 	}
 
 	return TPM_OK;
@@ -1503,6 +1535,7 @@
 	tpm_init_ety_dsa_enable_get();
 	tpm_init_split_mod_get();
 	tpm_init_switch_init_get();
+	tpm_init_ds_mac_based_trunk_enable_get();
 
 	return (TPM_OK);
 }
@@ -1520,116 +1553,118 @@
 	uint32_t cpu_owner = 0;
 
 	/********************************************************************/
-	if (tpm_init.validation_en == TPM_VALID_ENABLED) {
-	/******************** EPON/GPON system - check num of LLID / TCONT : legal values: 1..8 *********************/
-		if ((tpm_init.pon_type == TPM_EPON) || (tpm_init.pon_type == TPM_GPON)) {
-			if ((tpm_init.num_tcont_llid <= 0) || (tpm_init.num_tcont_llid > 8)) {
-				TPM_OS_FATAL(TPM_INIT_MOD, "\n TCONT/LLID: illegal value(%d) => legal values <1-8>.\n",
-					tpm_init.num_tcont_llid);
-				return (TPM_FAIL);
-			}
-		}
-	/***** EPON case: validate vs .config value for EPON *****/
-		if (tpm_init.pon_type == TPM_EPON) {
-			min_tcont_llid = min(TPM_GPON_MAX_NUM_OF_T_CONTS, TPM_EPON_MAX_MAC_NUM);
-			if (tpm_init.num_tcont_llid > min_tcont_llid) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n LLID: illegal value(%d) => max legal value defined in kernel is %d.\n",
-					tpm_init.num_tcont_llid, TPM_EPON_MAX_MAC_NUM);
-				return (TPM_FAIL);
-			}
-		}
-	/***** GPON case: validate vs .config value for GPON *****/
-		if (tpm_init.pon_type == TPM_GPON) {
-			if (tpm_init.num_tcont_llid > TPM_GPON_MAX_NUM_OF_T_CONTS) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n TCONT: illegal value(%d) => max legal value defined in kernel is %d.\n",
-					tpm_init.num_tcont_llid, TPM_GPON_MAX_NUM_OF_T_CONTS);
-				return (TPM_FAIL);
-			}
-		}
-#if 0				/*Keep to be added in future version */
-	/******************** Debug port setting - validation **********************************/
-		if ((tpm_init.deb_port_valid != 0) && (tpm_init.deb_port_valid != 1)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n Debug port valid is wrong => legal values <0=invalid/1=valid>. \n");
-			return (TPM_FAIL);
-		}
-		if ((tpm_init.deb_port_valid == 1) &&
-		    ((tpm_init.deb_port < TPM_SRC_PORT_UNI_0) || (tpm_init.deb_port > TPM_SRC_PORT_UNI_3))) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n Bad debug port => legal values <TPM_SRC_PORT_UNI_0-TPM_SRC_PORT_UNI_3>. \n");
-			return (TPM_FAIL);
-		}
-#endif
-		/********************* pon type validation *********************************************/
-		/* for FPGA systems - the WAN tech is defined as TPM_NONE */
-		if (tpm_init.pon_type > TPM_NONE) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n pon type: wrong init value(%d) => legal values "
-				"<%d=TPM_EPON/%d=TPM_GPON/%d=TPM_P2P/%d=TPM_NONE>. \n",
-				tpm_init.pon_type, TPM_EPON, TPM_GPON, TPM_P2P, TPM_NONE);
-			return (TPM_FAIL);
-		}
+	if (tpm_init.validation_en != TPM_VALID_ENABLED)
+		return TPM_OK;
 
-		/********************* CFG PNC PARSE validation *******************************************/
-		if ((tpm_init.cfg_pnc_parse < TPM_CFG_PNC_PARSE_DISABLED)
-		    || (tpm_init.cfg_pnc_parse > TPM_CFG_PNC_PARSE_ENABLED)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n CFG PNC parse: wrong init value(%d) => legal values <0=DISABLED/1=ENABLED. \n",
-				tpm_init.cfg_pnc_parse);
+	/******************** EPON/GPON system - check num of LLID / TCONT : legal values: 1..8 *********************/
+	if ((tpm_init.pon_type == TPM_EPON) || (tpm_init.pon_type == TPM_GPON)) {
+		if ((tpm_init.num_tcont_llid <= 0) || (tpm_init.num_tcont_llid > 8)) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n TCONT/LLID: illegal value(%d) => legal values <1-8>.\n",
+				tpm_init.num_tcont_llid);
 			return (TPM_FAIL);
 		}
-		/* get the config_pnc_parser value */
-		config_pnc_parser_val = mv_eth_ctrl_pnc_get();
+	}
+	/***** EPON case: validate vs .config value for EPON *****/
+	if (tpm_init.pon_type == TPM_EPON) {
+		min_tcont_llid = min(TPM_GPON_MAX_NUM_OF_T_CONTS, TPM_EPON_MAX_MAC_NUM);
+		if (tpm_init.num_tcont_llid > min_tcont_llid) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n LLID: illegal value(%d) => max legal value defined in kernel is %d.\n",
+				tpm_init.num_tcont_llid, TPM_EPON_MAX_MAC_NUM);
+			return (TPM_FAIL);
+		}
+	}
+	/***** GPON case: validate vs .config value for GPON *****/
+	if (tpm_init.pon_type == TPM_GPON) {
+		if (tpm_init.num_tcont_llid > TPM_GPON_MAX_NUM_OF_T_CONTS) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n TCONT: illegal value(%d) => max legal value defined in kernel is %d.\n",
+				tpm_init.num_tcont_llid, TPM_GPON_MAX_NUM_OF_T_CONTS);
+			return (TPM_FAIL);
+		}
+	}
+#if 0				/*Keep to be added in future version */
+/******************** Debug port setting - validation **********************************/
+	if ((tpm_init.deb_port_valid != 0) && (tpm_init.deb_port_valid != 1)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n Debug port valid is wrong => legal values <0=invalid/1=valid>. \n");
+		return (TPM_FAIL);
+	}
+	if ((tpm_init.deb_port_valid == 1) &&
+	    ((tpm_init.deb_port < TPM_SRC_PORT_UNI_0) || (tpm_init.deb_port > TPM_SRC_PORT_UNI_3))) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n Bad debug port => legal values <TPM_SRC_PORT_UNI_0-TPM_SRC_PORT_UNI_3>. \n");
+		return (TPM_FAIL);
+	}
+#endif
+	/********************* pon type validation *********************************************/
+	/* for FPGA systems - the WAN tech is defined as TPM_NONE */
+	if (tpm_init.pon_type > TPM_NONE) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n pon type: wrong init value(%d) => legal values "
+			"<%d=TPM_EPON/%d=TPM_GPON/%d=TPM_P2P/%d=TPM_NONE>. \n",
+			tpm_init.pon_type, TPM_EPON, TPM_GPON, TPM_P2P, TPM_NONE);
+		return (TPM_FAIL);
+	}
+
+	/********************* CFG PNC PARSE validation *******************************************/
+	if ((tpm_init.cfg_pnc_parse < TPM_CFG_PNC_PARSE_DISABLED)
+	    || (tpm_init.cfg_pnc_parse > TPM_CFG_PNC_PARSE_ENABLED)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n CFG PNC parse: wrong init value(%d) => legal values <0=DISABLED/1=ENABLED. \n",
+			tpm_init.cfg_pnc_parse);
+		return (TPM_FAIL);
+	}
+	/* get the config_pnc_parser value */
+	config_pnc_parser_val = mv_eth_ctrl_pnc_get();
 
         /* logical validation */
 
 #ifdef CONFIG_MV_ETH_PNC
-		if (tpm_init.cfg_pnc_parse == 0) {
-			if (config_pnc_parser_val == 0) {
-				/* the intention is to give the control to mv neta PNC configuration
-				   do not permit moving from 0 to 1 */
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n CFG PNC bad value: PNC in LSP cannot move from 0 to 1 \n");
-				return (TPM_FAIL);
-			} else {
-				/* config_pnc_parser == 1 */
-				/* nothing to do - the control is in LSP config */
-			}
-		}
-		if (tpm_init.cfg_pnc_parse == 1) {
-			if (config_pnc_parser_val == 0) {
-				/* nothing to do - the control is in TPM */
-			} else {	/* config_pnc_parser == 1 */
-				/* set the config_pnc_parser to 0 - control is set to TPM */
-				rc = mv_eth_ctrl_pnc(0);
-				if (rc != 0) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n Failed to SET the config PNC parse parameter. \n");
-					return (TPM_FAIL);
-				}
-			}
-		}
-#else
-		/* if compilation flag is turned off - there are no relevant functions for PNC_PARSER
-		   therefore do not permit the flag to be 0 - meaning the LSP is taking the responsibility */
-		if (tpm_init.cfg_pnc_parse == 0) {
-			TPM_OS_FATAL(TPM_INIT_MOD, "\n CFG PNC bad value: PNC in LSP does not support PNC PARSER \n");
+	if (tpm_init.cfg_pnc_parse == 0) {
+		if (config_pnc_parser_val == 0) {
+			/* the intention is to give the control to mv neta PNC configuration
+			   do not permit moving from 0 to 1 */
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CFG PNC bad value: PNC in LSP cannot move from 0 to 1 \n");
 			return (TPM_FAIL);
 		} else {
-			if (config_pnc_parser_val == 0) {
-				/*do nothing */
-			} else {
-				/* set the config_pnc_parser to 0 - control is set to TPM */
-				rc = mv_eth_ctrl_pnc(0);
-				if (rc != 0) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n Failed to SET the config PNC parse parameter. \n");
-					return (TPM_FAIL);
-				}
+			/* config_pnc_parser == 1 */
+			/* nothing to do - the control is in LSP config */
+		}
+	}
+	if (tpm_init.cfg_pnc_parse == 1) {
+		if (config_pnc_parser_val == 0) {
+			/* nothing to do - the control is in TPM */
+		} else {	/* config_pnc_parser == 1 */
+			/* set the config_pnc_parser to 0 - control is set to TPM */
+			rc = mv_eth_ctrl_pnc(0);
+			if (rc != 0) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n Failed to SET the config PNC parse parameter. \n");
+				return (TPM_FAIL);
 			}
 		}
+	}
+#else
+	/* if compilation flag is turned off - there are no relevant functions for PNC_PARSER
+	   therefore do not permit the flag to be 0 - meaning the LSP is taking the responsibility */
+	if (tpm_init.cfg_pnc_parse == 0) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "\n CFG PNC bad value: PNC in LSP does not support PNC PARSER \n");
+		return (TPM_FAIL);
+	} else {
+		if (config_pnc_parser_val == 0) {
+			/*do nothing */
+		} else {
+			/* set the config_pnc_parser to 0 - control is set to TPM */
+			rc = mv_eth_ctrl_pnc(0);
+			if (rc != 0) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n Failed to SET the config PNC parse parameter. \n");
+				return (TPM_FAIL);
+			}
+		}
+	}
 #endif
 
 	/********************* CPU loopback type validation  ********************************************/
@@ -1640,451 +1675,485 @@
 				tpm_init.cpu_loopback);
 			return (TPM_FAIL);
 		}
+		if (tpm_init.cpu_loopback == TPM_CPU_LOOPBACK_ENABLED) {
+			if (tpm_init.gmac_port_conf[1].valid == TPM_TRUE &&
+			    tpm_init.gmac_port_conf[1].port_src != TPM_SRC_PORT_ILLEGAL) {
+				TPM_OS_FATAL(TPM_INIT_MOD, "\n CPU loopback not supported for GMAC function \n");
+				return (TPM_FAIL);
+			}
+		}
 
 	/********************* TRACE DEBUG INFO validation *******************************************/
-		if (tpm_init.trace_debug_info == 0) {
-			TPM_OS_WARN(TPM_INIT_MOD,
-				"\n TRACE DEBUG info: init value is %d - no ERRORs will be displayed. \n ",
-				tpm_init.trace_debug_info);
-		}
+	if (tpm_init.trace_debug_info == 0) {
+		TPM_OS_WARN(TPM_INIT_MOD,
+			"\n TRACE DEBUG info: init value is %d - no ERRORs will be displayed. \n ",
+			tpm_init.trace_debug_info);
+	}
 
 	/********************* IGMP snooping validation *********************************************/
-		if ((tpm_init.igmp_snoop != 0) && (tpm_init.igmp_snoop != 1)) {
+	if ((tpm_init.igmp_snoop != 0) && (tpm_init.igmp_snoop != 1)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n IGMP snooping: wrong init value(%d) => legal values <0=disabled/1=enabled>. \n",
+			     tpm_init.igmp_snoop);
+		return (TPM_FAIL);
+	}
+	if (tpm_init.igmp_snoop == 1) {
+		if (tpm_init.igmp_cpu_queue > 7) {
 			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n IGMP snooping: wrong init value(%d) => legal values <0=disabled/1=enabled>. \n",
-				     tpm_init.igmp_snoop);
+				     "\n IGMP snooping: wrong CPU queue(%d) => legal values <0-7>. \n",
+				     tpm_init.igmp_cpu_queue);
 			return (TPM_FAIL);
 		}
-		if (tpm_init.igmp_snoop == 1) {
-			if (tpm_init.igmp_cpu_queue > 7) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					     "\n IGMP snooping: wrong CPU queue(%d) => legal values <0-7>. \n",
-					     tpm_init.igmp_cpu_queue);
-				return (TPM_FAIL);
-			}
-		}
+	}
 
 	/********************* Multicast validation *********************************************/
-		if (tpm_init.mc_setting.per_uni_vlan_xlat) {
-			if (tpm_init.mc_setting.filter_mode != TPM_MC_COMBINED_IP_MAC_FILTER) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					     "\n multicast per uni vlan translation is not supported in filter_mode (%d). \n",
-					     tpm_init.mc_setting.filter_mode);
-				return (TPM_FAIL);
-			}
+	if (tpm_init.mc_setting.per_uni_vlan_xlat) {
+		if (tpm_init.mc_setting.filter_mode != TPM_MC_COMBINED_IP_MAC_FILTER) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n multicast per uni vlan translation is not supported in filter_mode (%d). \n",
+				     tpm_init.mc_setting.filter_mode);
+			return (TPM_FAIL);
+		}
 #if 0
-			if (tpm_init.mc_setting.igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_init.mc_setting.mc_pppoe_enable) {
-			   TPM_OS_FATAL(TPM_INIT_MOD, "\n multicast per uni vlan translation is not supported "
-						"in igmp snooping over pppoe. \n");
-			   return(TPM_FAIL);
-			}
+		if (tpm_init.mc_setting.igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_init.mc_setting.mc_pppoe_enable) {
+		   TPM_OS_FATAL(TPM_INIT_MOD, "\n multicast per uni vlan translation is not supported "
+					"in igmp snooping over pppoe. \n");
+		   return(TPM_FAIL);
+		}
 #endif
-		}
+	}
 
-		/* check that igmp_cpu_queue is CPU's reserved queue */
-		/* oct*>>> to do - if per system Q6 is the IGMP CPU - check in all GMACs that Q6 is of CPU ownership */
+	/* check that igmp_cpu_queue is CPU's reserved queue */
+	/* oct*>>> to do - if per system Q6 is the IGMP CPU - check in all GMACs that Q6 is of CPU ownership */
 
-		if (tpm_init.mc_setting.mc_hwf_queue > 7) {
-			TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC HWF queue(%d) => legal values <0-7>. \n",
-				     tpm_init.mc_setting.mc_hwf_queue);
-			return (TPM_FAIL);
-		}
+	if (tpm_init.mc_setting.mc_hwf_queue > 7) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC HWF queue(%d) => legal values <0-7>. \n",
+			     tpm_init.mc_setting.mc_hwf_queue);
+		return (TPM_FAIL);
+	}
 
-		if (tpm_init.mc_setting.mc_cpu_queue > 7) {
-			TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC CPU queue(%d) => legal values <0-7>. \n",
-				     tpm_init.mc_setting.mc_cpu_queue);
-			return (TPM_FAIL);
-		}
+	if (tpm_init.mc_setting.mc_cpu_queue > 7) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC CPU queue(%d) => legal values <0-7>. \n",
+			     tpm_init.mc_setting.mc_cpu_queue);
+		return (TPM_FAIL);
+	}
 
 	/********************** GMAC_0 connectivity validation *************************************/
-		if ((tpm_init.gmac_port_conf[0].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[0].conn > TPM_GMAC_CON_GE_PHY)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_0 connectivity: wrong init value(%d) => legal values <0-7> \n",
-				     tpm_init.gmac_port_conf[0].conn);
-			return (TPM_FAIL);
-		}
+	if ((tpm_init.gmac_port_conf[0].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[0].conn > TPM_GMAC_CON_GE_PHY)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_0 connectivity: wrong init value(%d) => legal values <0-7> \n",
+			     tpm_init.gmac_port_conf[0].conn);
+		return (TPM_FAIL);
+	}
 	/********************** GMAC_1 connectivity validation *************************************/
-		if ((tpm_init.gmac_port_conf[1].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[1].conn > TPM_GMAC_CON_GE_PHY)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_1 connectivity: wrong init value(%d) => legal values <0-7> \n",
-				     tpm_init.gmac_port_conf[1].conn);
-			return (TPM_FAIL);
-		}
+	if ((tpm_init.gmac_port_conf[1].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[1].conn > TPM_GMAC_CON_GE_PHY)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_1 connectivity: wrong init value(%d) => legal values <0-7> \n",
+			     tpm_init.gmac_port_conf[1].conn);
+		return (TPM_FAIL);
+	}
 	/********************** GMAC_0 MH enable validation   *************************************/
-		if ((tpm_init.gmac0_mh_en != 0) && (tpm_init.gmac0_mh_en != 1)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_0 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
-				     tpm_init.gmac0_mh_en);
-			return (TPM_FAIL);
-		}
-		rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_0, tpm_init.gmac0_mh_en);
-		if (rc != TPM_OK) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_0 is in GateWay mode, MH can not be disabled\n");
-			return (TPM_FAIL);
-		}
+	if ((tpm_init.gmac0_mh_en != 0) && (tpm_init.gmac0_mh_en != 1)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_0 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
+			     tpm_init.gmac0_mh_en);
+		return (TPM_FAIL);
+	}
+	rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_0, tpm_init.gmac0_mh_en);
+	if (rc != TPM_OK) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_0 is in GateWay mode, MH can not be disabled\n");
+		return (TPM_FAIL);
+	}
 	/********************** GMAC_1 MH enable validation   *************************************/
-		if ((tpm_init.gmac1_mh_en != 0) && (tpm_init.gmac1_mh_en != 1)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_1 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
-				     tpm_init.gmac1_mh_en);
-			return (TPM_FAIL);
-		}
-		rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_1, tpm_init.gmac1_mh_en);
-		if (rc != TPM_OK) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n GMAC_1 is in GateWay mode, MH can not be disabled\n");
-			return (TPM_FAIL);
-		}
+	if ((tpm_init.gmac1_mh_en != 0) && (tpm_init.gmac1_mh_en != 1)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_1 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
+			     tpm_init.gmac1_mh_en);
+		return (TPM_FAIL);
+	}
+	rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_1, tpm_init.gmac1_mh_en);
+	if (rc != TPM_OK) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n GMAC_1 is in GateWay mode, MH can not be disabled\n");
+		return (TPM_FAIL);
+	}
 	/********************** GMAC_ Buffer Mngmt Pool_sizes validation ***********************************/
-		for (i = 0; i < sizeof(tpm_init.gmac_bp_bufs) / sizeof(tpm_init_gmac_bufs_t); i++) {
-			if (tpm_init.gmac_bp_bufs[i].valid) {
-				if (((tpm_init.gmac_bp_bufs[i].large_pkt_buffers != 0) &&
-				     (tpm_init.gmac_bp_bufs[i].large_pkt_buffers < MV_BM_POOL_CAP_MIN)) ||
-				    ((tpm_init.gmac_bp_bufs[i].small_pkt_buffers != 0) &&
-				     (tpm_init.gmac_bp_bufs[i].small_pkt_buffers < MV_BM_POOL_CAP_MIN))) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n GMAC%d BM Pool has too small buffer assigment "
-						"large_buf %d, small_buf %d\n",
-						i, tpm_init.gmac_bp_bufs[i].large_pkt_buffers,
-						tpm_init.gmac_bp_bufs[i].small_pkt_buffers);
-					return (TPM_FAIL);
-				}
+	for (i = 0; i < sizeof(tpm_init.gmac_bp_bufs) / sizeof(tpm_init_gmac_bufs_t); i++) {
+		if (tpm_init.gmac_bp_bufs[i].valid) {
+			if (((tpm_init.gmac_bp_bufs[i].large_pkt_buffers != 0) &&
+			     (tpm_init.gmac_bp_bufs[i].large_pkt_buffers < MV_BM_POOL_CAP_MIN)) ||
+			    ((tpm_init.gmac_bp_bufs[i].small_pkt_buffers != 0) &&
+			     (tpm_init.gmac_bp_bufs[i].small_pkt_buffers < MV_BM_POOL_CAP_MIN))) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n GMAC%d BM Pool has too small buffer assigment "
+					"large_buf %d, small_buf %d\n",
+					i, tpm_init.gmac_bp_bufs[i].large_pkt_buffers,
+					tpm_init.gmac_bp_bufs[i].small_pkt_buffers);
+				return (TPM_FAIL);
 			}
 		}
+	}
 	/********************** PNC MH enabled allow for DS   *************************************/
-		if ((tpm_init.ds_mh_set_conf != 0) && (tpm_init.ds_mh_set_conf != 1)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n PNC - DS MH allow: wrong init value(%d) => "
-				"legal values <0=MH not allowed/DS,1=MH allowed/DS> \n",
-				tpm_init.ds_mh_set_conf);
+	if ((tpm_init.ds_mh_set_conf != 0) && (tpm_init.ds_mh_set_conf != 1)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n PNC - DS MH allow: wrong init value(%d) => "
+			"legal values <0=MH not allowed/DS,1=MH allowed/DS> \n",
+			tpm_init.ds_mh_set_conf);
+		return (TPM_FAIL);
+	}
+
+	if (tpm_init.port_fc_conf.enabled) {
+		MV_U32 device_id = mvCtrlModelGet();
+
+		if (device_id != MV_6601_DEV_ID) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n port SW Flow-Control is not supported by this device");
 			return (TPM_FAIL);
 		}
 
-		if (tpm_init.port_fc_conf.enabled) {
-			MV_U32 device_id = mvCtrlModelGet();
-
-			if (device_id != MV_6601_DEV_ID) {
-				TPM_OS_FATAL(TPM_INIT_MOD, "\n port SW Flow-Control is not supported by this device");
-				return (TPM_FAIL);
-			}
-
-			if ((tpm_init.port_fc_conf.port > TPM_MAX_GMAC) 	||
-			    (tpm_init.port_fc_conf.tgt_port > TPM_MAX_GMAC)	||
-			    (tpm_init.port_fc_conf.tx_port > TPM_MAX_GMAC)){
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n port SW Flow-Control invalid port number:"
-					"port=%d tgt_port=%d tx_port=%d\n",
-					tpm_init.port_fc_conf.port,
-					tpm_init.port_fc_conf.tgt_port,
-					tpm_init.port_fc_conf.tx_port);
-				return (TPM_FAIL);
-			}
-
-			if (tpm_init.port_fc_conf.tx_queue >= TPM_MAX_NUM_TX_QUEUE){
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n port SW Flow-Control invalid port number: tx_queue=%d",
-					tpm_init.port_fc_conf.tx_queue);
-				return (TPM_FAIL);
-			}
+		if ((tpm_init.port_fc_conf.port > TPM_MAX_GMAC) 	||
+		    (tpm_init.port_fc_conf.tgt_port > TPM_MAX_GMAC)	||
+		    (tpm_init.port_fc_conf.tx_port > TPM_MAX_GMAC)){
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n port SW Flow-Control invalid port number:"
+				"port=%d tgt_port=%d tx_port=%d\n",
+				tpm_init.port_fc_conf.port,
+				tpm_init.port_fc_conf.tgt_port,
+				tpm_init.port_fc_conf.tx_port);
+			return (TPM_FAIL);
 		}
+
+		if (tpm_init.port_fc_conf.tx_queue >= TPM_MAX_NUM_TX_QUEUE){
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n port SW Flow-Control invalid port number: tx_queue=%d",
+				tpm_init.port_fc_conf.tx_queue);
+			return (TPM_FAIL);
+		}
+	}
 	/********************** ethernet ports validation ******************************************/
-		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
-			if (tpm_init.eth_port_conf[i].valid == TPM_TRUE) {
-				if ((tpm_init.eth_port_conf[i].chip_connect < TPM_CONN_DISC) ||
-						(tpm_init.eth_port_conf[i].chip_connect > TPM_CONN_RGMII2)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n ETH_port[(%d)]: chip_connect - wrong init value(%d)"
-						" => legal values <0-5> \n",
-						i, tpm_init.eth_port_conf[i].chip_connect);
-					return (TPM_FAIL);
-				}
-				if ((tpm_init.eth_port_conf[i].int_connect < TPM_INTCON_GMAC0) ||
-						(tpm_init.eth_port_conf[i].int_connect > TPM_INTCON_SWITCH)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n ETH_port[(%d)]: chip_connect - wrong init "
-						"value(%d) => legal values <0-2> \n",
-						i, tpm_init.eth_port_conf[i].int_connect);
-					return (TPM_FAIL);
-				}
-				if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
-						(tpm_init.eth_port_conf[i].switch_port > 6)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"\n ETH_port[(%d)]: switch_port - wrong init "
-						"value(%d) => legal values <0-6> \n",
-						i, tpm_init.eth_port_conf[i].switch_port);
-					return (TPM_FAIL);
-				}
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (tpm_init.eth_port_conf[i].valid == TPM_TRUE) {
+			if ((tpm_init.eth_port_conf[i].chip_connect < TPM_CONN_DISC) ||
+					(tpm_init.eth_port_conf[i].chip_connect > TPM_CONN_RGMII2)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n ETH_port[(%d)]: chip_connect - wrong init value(%d)"
+					" => legal values <0-5> \n",
+					i, tpm_init.eth_port_conf[i].chip_connect);
+				return (TPM_FAIL);
+			}
+			if ((tpm_init.eth_port_conf[i].int_connect < TPM_INTCON_GMAC0) ||
+					(tpm_init.eth_port_conf[i].int_connect > TPM_INTCON_SWITCH)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n ETH_port[(%d)]: chip_connect - wrong init "
+					"value(%d) => legal values <0-2> \n",
+					i, tpm_init.eth_port_conf[i].int_connect);
+				return (TPM_FAIL);
+			}
+			if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
+					(tpm_init.eth_port_conf[i].switch_port > 6)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n ETH_port[(%d)]: switch_port - wrong init "
+					"value(%d) => legal values <0-6> \n",
+					i, tpm_init.eth_port_conf[i].switch_port);
+				return (TPM_FAIL);
+			}
 
-				if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
-					 (tpm_init.eth_port_conf[i].switch_port <= 6)) {
-					num_uni_ports++;
-				}
+			if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
+				 (tpm_init.eth_port_conf[i].switch_port <= 6)) {
+				num_uni_ports++;
 			}
 		}
+	}
 	/********************* Virtual UNI validation *************************************/
 
-		if ((tpm_init.virt_uni_info.enabled < TPM_VIRT_UNI_DISABLED) ||
-				(tpm_init.virt_uni_info.enabled > TPM_VIRT_UNI_ENABLED)) {
-			TPM_OS_FATAL(TPM_INIT_MOD,
-				"\n Virtual UNI: wrong init value(%d) => legal "
-				"values <0=TPM_WIFI_VIRT_UNI_DISABLED/1=TPM_VIRT_UNI_ENABLED. \n",
-				tpm_init.virt_uni_info.enabled);
-			return (TPM_FAIL);
-		}
-		if (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED) {
-		/*oct* - open this validation in next LSP - meantime it works only on RD */
+	if ((tpm_init.virt_uni_info.enabled < TPM_VIRT_UNI_DISABLED) ||
+			(tpm_init.virt_uni_info.enabled > TPM_VIRT_UNI_ENABLED)) {
+		TPM_OS_FATAL(TPM_INIT_MOD,
+			"\n Virtual UNI: wrong init value(%d) => legal "
+			"values <0=TPM_WIFI_VIRT_UNI_DISABLED/1=TPM_VIRT_UNI_ENABLED. \n",
+			tpm_init.virt_uni_info.enabled);
+		return (TPM_FAIL);
+	}
+	if (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED) {
+	/*oct* - open this validation in next LSP - meantime it works only on RD */
 #if 0
-			/* check that GMAC1 is connected to internal switch port #5 */
-			rc = mvBoardIsInternalSwitchConnected(1);
-			if (rc == 0) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n WiFi virtual UNI: feature ENABLED - GMAC1 "
-					"is NOT HW-connected to Switch  port #5. \n");
-				return (TPM_FAIL);
-			}
-#endif
-			/* fail eth complex other than dual MAC */
-			if (TPM_PON_WAN_DUAL_MAC_INT_SWITCH != tpm_init.eth_cmplx_profile)
-			{
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n Virtual UNI suppoerted only by ethernet Complex %x (used %x) \n",
-					TPM_PON_WAN_DUAL_MAC_INT_SWITCH, tpm_init.eth_cmplx_profile);
-				return (TPM_FAIL);
-			}
-
-			/* currently support only UNI_VIRT port for WIFI virtual UNI port */
-			if (tpm_init.virt_uni_info.uni_port != TPM_SRC_PORT_UNI_VIRT) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n Virtual UNI: wrong port value(%d) => "
-					"legal values <0-%d> - default value<%d. \n",
-					tpm_init.virt_uni_info.uni_port, TPM_SRC_PORT_UNI_VIRT ,TPM_SRC_PORT_UNI_VIRT);
-				return (TPM_FAIL);
-			}
-
-			num_uni_ports++;
-
-			/* if feature enabled and missing PNC range in the xml - return ERROR */
-			for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
-				if (tpm_init.pnc_range[i].range_num == TPM_PNC_VIRT_UNI) {
-					if (tpm_init.pnc_range[i].valid != TPM_TRUE) {
-						TPM_OS_FATAL(TPM_INIT_MOD,
-							"\n Virtual UNI: feature ENABLED - missing "
-							"PNC range <TPM_PNC_VIRT_UNI> in XML config file. \n");
-						return (TPM_FAIL);
-					}
-				}
-			}	/* for */
-			/* TODO: check all GMAC1 TX queues are owned by CPU */
-
-		}
-
-		/*if wifi feature enabled - end validation */
-	/********************* PNC validations *****************************************************/
-		found_ipv4_pre = found_cnm_main = TPM_FALSE;
-		ipv4_pre_size = cnm_main_size = 0;
-
-		/* Validate total number of Pnc Entries */
-		for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
-			if (tpm_init.pnc_range[i].valid == TPM_TRUE) {
-				j += tpm_init.pnc_range[i].range_size;
-				if (tpm_init.pnc_range[i].range_num >= TPM_MAX_NUM_RANGES) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"PNC range[%d]: range_num - wrong init value(%d) => "
-						"legal values <0-%d>\n",
-						i, tpm_init.pnc_range[i].range_num, TPM_MAX_RANGE);
-					return (TPM_FAIL);
-				}
-				if (tpm_init.pnc_range[i].range_type > TPM_RANGE_TYPE_TABLE) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"PNC range[%d]: range_type - wrong init value(%d) => "
-						"legal values <0=TYPE_ACL,1=TYPE_TABLE>\n",
-						i, tpm_init.pnc_range[i].range_type);
-					return (TPM_FAIL);
-				}
-				if ((tpm_init.pnc_range[i].cntr_grp < 0) || (tpm_init.pnc_range[i].cntr_grp > 3)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						     "PNC range[%d] cntr_grp - wrong init value(%d) => legal values <0-3>\n",
-						     i, tpm_init.pnc_range[i].cntr_grp);
-					return (TPM_FAIL);
-				}
-				if ((tpm_init.pnc_range[i].lu_mask < 0) || (tpm_init.pnc_range[i].lu_mask > 1)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						     "PNC range[%d] lu_mask - wrong init value(%d) => legal values <0-1>\n",
-						     i, tpm_init.pnc_range[i].lu_mask);
-					return (TPM_FAIL);
-				}
-				if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_IPV4_PRE) {
-					found_ipv4_pre = TPM_TRUE;
-					ipv4_pre_size = tpm_init.pnc_range[i].range_size;
-				} else if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_MAIN) {
-					found_cnm_main = TPM_TRUE;
-					cnm_main_size = tpm_init.pnc_range[i].range_size;
-				}
-			}
-		}
-		if (j > TPM_PNC_SIZE) {
-			TPM_OS_FATAL(TPM_INIT_MOD, "Sum of Pnc ranges(%d) is bigger than PnC size(%d)\n", j,
-				     TPM_PNC_SIZE);
+		/* check that GMAC1 is connected to internal switch port #5 */
+		rc = mvBoardIsInternalSwitchConnected(1);
+		if (rc == 0) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n WiFi virtual UNI: feature ENABLED - GMAC1 "
+				"is NOT HW-connected to Switch  port #5. \n");
 			return (TPM_FAIL);
 		}
+#endif
+		/* fail eth complex other than dual MAC */
+		if (TPM_PON_WAN_DUAL_MAC_INT_SWITCH != tpm_init.eth_cmplx_profile)
+		{
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n Virtual UNI suppoerted only by ethernet Complex %x (used %x) \n",
+				TPM_PON_WAN_DUAL_MAC_INT_SWITCH, tpm_init.eth_cmplx_profile);
+			return (TPM_FAIL);
+		}
+
+		/* currently support only UNI_VIRT port for WIFI virtual UNI port */
+		if (tpm_init.virt_uni_info.uni_port != TPM_SRC_PORT_UNI_VIRT) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n Virtual UNI: wrong port value(%d) => "
+				"legal values <0-%d> - default value<%d. \n",
+				tpm_init.virt_uni_info.uni_port, TPM_SRC_PORT_UNI_VIRT ,TPM_SRC_PORT_UNI_VIRT);
+			return (TPM_FAIL);
+		}
+
+		num_uni_ports++;
+
+		/* if feature enabled and missing PNC range in the xml - return ERROR */
+		for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+			if (tpm_init.pnc_range[i].range_num == TPM_PNC_VIRT_UNI) {
+				if (tpm_init.pnc_range[i].valid != TPM_TRUE) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n Virtual UNI: feature ENABLED - missing "
+						"PNC range <TPM_PNC_VIRT_UNI> in XML config file. \n");
+					return (TPM_FAIL);
+				}
+			}
+		}	/* for */
+		/* TODO: check all GMAC1 TX queues are owned by CPU */
+
+	}
+
+	/*if wifi feature enabled - end validation */
+	/********************* PNC validations *****************************************************/
+	found_ipv4_pre = found_cnm_main = TPM_FALSE;
+	ipv4_pre_size = cnm_main_size = 0;
+
+	/* Validate total number of Pnc Entries */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_init.pnc_range[i].valid == TPM_TRUE) {
+			j += tpm_init.pnc_range[i].range_size;
+			if (tpm_init.pnc_range[i].range_num >= TPM_MAX_NUM_RANGES) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"PNC range[%d]: range_num - wrong init value(%d) => "
+					"legal values <0-%d>\n",
+					i, tpm_init.pnc_range[i].range_num, TPM_MAX_RANGE);
+				return (TPM_FAIL);
+			}
+			if (tpm_init.pnc_range[i].range_type > TPM_RANGE_TYPE_TABLE) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"PNC range[%d]: range_type - wrong init value(%d) => "
+					"legal values <0=TYPE_ACL,1=TYPE_TABLE>\n",
+					i, tpm_init.pnc_range[i].range_type);
+				return (TPM_FAIL);
+			}
+			if ((tpm_init.pnc_range[i].cntr_grp < 0) || (tpm_init.pnc_range[i].cntr_grp > 3)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					     "PNC range[%d] cntr_grp - wrong init value(%d) => legal values <0-3>\n",
+					     i, tpm_init.pnc_range[i].cntr_grp);
+				return (TPM_FAIL);
+			}
+			if ((tpm_init.pnc_range[i].lu_mask < 0) || (tpm_init.pnc_range[i].lu_mask > 1)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					     "PNC range[%d] lu_mask - wrong init value(%d) => legal values <0-1>\n",
+					     i, tpm_init.pnc_range[i].lu_mask);
+				return (TPM_FAIL);
+			}
+			if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_IPV4_PRE) {
+				found_ipv4_pre = TPM_TRUE;
+				ipv4_pre_size = tpm_init.pnc_range[i].range_size;
+			} else if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_MAIN) {
+				found_cnm_main = TPM_TRUE;
+				cnm_main_size = tpm_init.pnc_range[i].range_size;
+			}
+		}
+	}
+	if (j > TPM_PNC_SIZE) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "Sum of Pnc ranges(%d) is bigger than PnC size(%d)\n", j,
+			     TPM_PNC_SIZE);
+		return (TPM_FAIL);
+	}
 
 	/********************* MOD validations *****************************************************/
-		/* Validate TPM reserved modification entries */
+	/* Validate TPM reserved modification entries */
 	/********************* TX module validations *****************************************************/
 
-		for (tx_mod = TPM_TX_MOD_GMAC0; tx_mod < TPM_MAX_NUM_TX_PORTS; (tx_mod)++) {
-			/* validate gmac_tx - according to tpm_init.num_tcont_llid */
-			if (tx_mod >= TPM_TX_MOD_PMAC_0) {
-				if (((tx_mod - TPM_TX_MOD_GMAC1) > tpm_init.num_tcont_llid) &&
-				    (tpm_init.gmac_tx[tx_mod].valid == 1)) {
-					tpm_init.gmac_tx[tx_mod].valid = 0;
-					TPM_OS_WARN(TPM_INIT_MOD,
-						    " Illegal TCONT/LLID %d configuration - max legal value is %d.\n ",
-						    tx_mod, tpm_init.num_tcont_llid);
-				}
-			}
-			for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
-				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].valid != 1)
-					continue;
-
-				if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner < TPM_Q_OWNER_CPU) ||
-				    (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner >= TPM_Q_OWNER_MAX)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"TX module queue [%d]: queue_owner - wrong init value(%d)"
-						" => legal values <%d-%d>\n",
-						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner,
-						TPM_Q_OWNER_CPU, TPM_Q_OWNER_PMAC);
-					return (TPM_FAIL);
-				}
-				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num >= TPM_MAX_NUM_TX_QUEUE) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"TX module queue [%d]: owner_queue_num - wrong init value(%d) "
-						"is bigger than maximum queue number (%d)\n",
-						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
-						TPM_MAX_NUM_TX_QUEUE - 1);
-					return (TPM_FAIL);
-				}
-				if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method < TPM_SCHED_SP) ||
-				    (tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method > TPM_SCHED_WRR)) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"TX module queue [%d]: sched_method  - wrong init value(%d) => "
-						"legal values <%d-%d>\n\n",
-						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
-						TPM_SCHED_SP, TPM_SCHED_WRR);
-					return (TPM_FAIL);
-				}
-				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight > TPM_MAX_WRR_WEIGHT) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-						"TX module queue [%d]: queue_weight  - wrong init value(%d) "
-						"=> legal values <0-%d>\n\n",
-						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight,
-						TPM_MAX_WRR_WEIGHT);
-					return (TPM_FAIL);
-				}
-			}
-		}
-
-		/********* per GMAC - validate that default TCONT & Queue - are not set as HWF in xml *****/
-		for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
-			rc = mv_eth_get_txq_cpu_def(gmac_i, &txp, &txq, 0);
-			if (rc != 0) {
-				TPM_OS_WARN(TPM_INIT_MOD, "\n Failed to GET the default queue per GMAC%d - rc= %d. \n",
-					    gmac_i, rc);
-       			continue;
-			}
-			if (gmac_i >= TPM_TX_MOD_PMAC_0) {
-				if (tpm_init.gmac_tx[gmac_i + txp].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
-					TPM_OS_WARN(TPM_INIT_MOD,
-						" Default TX queue(%d) per GMAC (%d) must not be set in "
-						"hardware forwarding mode in config params.\n\n", txq, gmac_i);
-				}
-			} else {
-				if (tpm_init.gmac_tx[gmac_i].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
-					TPM_OS_WARN(TPM_INIT_MOD,
-						" Default TX queue(%d) per GMAC (%d) must not be set in "
-						"hardware forwarding mode in config params.\n\n", txq, gmac_i);
-				}
-			}
-		}
-
-		/*****split mod setting validation******/
-		if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_ENABLED) {
-			if(tpm_init.split_mod_config.vlan_num > (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM)) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-				     "\n Split Mod VLAN num %d, it should not larger than %d \n",
-				     tpm_init.split_mod_config.vlan_num, (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM));
-				return (TPM_FAIL);
-			}
-			if (tpm_init.split_mod_config.p_bit_num > TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX || tpm_init.split_mod_config.p_bit_num == TPM_DB_SPLIT_MOD_P_BIT_NO_SET) {
-				TPM_OS_FATAL(TPM_INIT_MOD, "\n Split Mod P_bit number out of range.\n");
-				return (TPM_FAIL);
-			}
-			for (i = 0; i < tpm_init.split_mod_config.p_bit_num; i++) {
-				if(tpm_init.split_mod_config.p_bit[i] > TPM_DB_SPLIT_MOD_P_BIT_MAX) {
-					TPM_OS_FATAL(TPM_INIT_MOD,
-				     		"\n Split Mod P_bit %d No Valid\n",
-						tpm_init.split_mod_config.p_bit[i]);
-					return (TPM_FAIL);
-				}
-				for (j = i + 1; j < tpm_init.split_mod_config.p_bit_num; j++) {
-					if(tpm_init.split_mod_config.p_bit[i] == tpm_init.split_mod_config.p_bit[j]) {
-						TPM_OS_FATAL(TPM_INIT_MOD,
-				     			"\n Split Mod P_bit %d Repeat\n",
-							tpm_init.split_mod_config.p_bit[i]);
-						return (TPM_FAIL);
-					}
-				}
-			}
-		}
-
-		/********************* CTC CNM validation *************************************/
-		if (tpm_init.ctc_cm_enable != TPM_CTC_CM_DISABLED) {
-			if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_DISABLED) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n CTC CM: CTC CnM is enabled while split modification is disabled! \n");
-				return (TPM_FAIL);
-			}
-
-			if (!found_ipv4_pre) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n CTC CM: CTC CnM is enabled while CNM_IPV4_PRE range size is Zero! \n");
-				return (TPM_FAIL);
-			} else {
-				exp_range_size = num_uni_ports * TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_PORT + 1;
-				if (exp_range_size > ipv4_pre_size) {
-					TPM_OS_WARN(TPM_INIT_MOD,
-						"\n CTC CM: CNM IPV4 PRE FILTER is not enough for "
-						"L2 & IPV4 combo rules (%d/%d) of %d UNI ports! \n",
-						exp_range_size, ipv4_pre_size, num_uni_ports);
-				}
-			}
-
-			if (!found_cnm_main) {
-				TPM_OS_FATAL(TPM_INIT_MOD,
-					"\n CTC CM: CTC CnM is enabled while CNM_MAIN range size is Zero! \n");
-				return (TPM_FAIL);
-			} else {
-				exp_range_size = num_uni_ports * TPM_MAX_NUM_CTC_PRECEDENCE + 2;
-				if (exp_range_size > cnm_main_size) {
-					TPM_OS_WARN(TPM_INIT_MOD,
-						"\n CTC CM: CNM MAIN is not enough for "
-						"8 precedence rules (%d/%d) of %d UNI ports! \n",
-						exp_range_size, cnm_main_size, num_uni_ports);
-				}
-			}
-		} else {
-			if (found_ipv4_pre) {
+	for (tx_mod = TPM_TX_MOD_GMAC0; tx_mod < TPM_MAX_NUM_TX_PORTS; (tx_mod)++) {
+		/* validate gmac_tx - according to tpm_init.num_tcont_llid */
+		if (tx_mod >= TPM_TX_MOD_PMAC_0) {
+			if (((tx_mod - TPM_TX_MOD_GMAC1) > tpm_init.num_tcont_llid) &&
+			    (tpm_init.gmac_tx[tx_mod].valid == 1)) {
+				tpm_init.gmac_tx[tx_mod].valid = 0;
 				TPM_OS_WARN(TPM_INIT_MOD,
-					"\n CTC CM: Since CTC CnM is disabled, CNM_IPV4_PRE range size should be Zero! \n");
+					    " Illegal TCONT/LLID %d configuration - max legal value is %d.\n ",
+					    tx_mod, tpm_init.num_tcont_llid);
 			}
-			if (found_cnm_main) {
-				TPM_OS_WARN(TPM_INIT_MOD,
-					"\n CTC CM: Since CTC CnM is disabled, CNM_MAIN range size should be Zero! \n");
+		}
+		for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+			if (tpm_init.gmac_tx[tx_mod].tx_queue[i].valid != 1)
+				continue;
+
+			if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner < TPM_Q_OWNER_CPU) ||
+			    (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner >= TPM_Q_OWNER_MAX)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"TX module queue [%d]: queue_owner - wrong init value(%d)"
+					" => legal values <%d-%d>\n",
+					tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner,
+					TPM_Q_OWNER_CPU, TPM_Q_OWNER_PMAC);
+				return (TPM_FAIL);
+			}
+			if (tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num >= TPM_MAX_NUM_TX_QUEUE) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"TX module queue [%d]: owner_queue_num - wrong init value(%d) "
+					"is bigger than maximum queue number (%d)\n",
+					tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
+					TPM_MAX_NUM_TX_QUEUE - 1);
+				return (TPM_FAIL);
+			}
+			if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method < TPM_SCHED_SP) ||
+			    (tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method > TPM_SCHED_WRR)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"TX module queue [%d]: sched_method  - wrong init value(%d) => "
+					"legal values <%d-%d>\n\n",
+					tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
+					TPM_SCHED_SP, TPM_SCHED_WRR);
+				return (TPM_FAIL);
+			}
+			if (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight > TPM_MAX_WRR_WEIGHT) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"TX module queue [%d]: queue_weight  - wrong init value(%d) "
+					"=> legal values <0-%d>\n\n",
+					tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight,
+					TPM_MAX_WRR_WEIGHT);
+				return (TPM_FAIL);
 			}
 		}
 	}
 
+	/********* per GMAC - validate that default TCONT & Queue - are not set as HWF in xml *****/
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		rc = mv_eth_get_txq_cpu_def(gmac_i, &txp, &txq, 0);
+		if (rc != 0) {
+			TPM_OS_WARN(TPM_INIT_MOD, "\n Failed to GET the default queue per GMAC%d - rc= %d. \n",
+				    gmac_i, rc);
+			continue;
+		}
+		if (gmac_i >= TPM_TX_MOD_PMAC_0) {
+			if (tpm_init.gmac_tx[gmac_i + txp].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					" Default TX queue(%d) per GMAC (%d) must not be set in "
+					"hardware forwarding mode in config params.\n\n", txq, gmac_i);
+			}
+		} else {
+			if (tpm_init.gmac_tx[gmac_i].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					" Default TX queue(%d) per GMAC (%d) must not be set in "
+					"hardware forwarding mode in config params.\n\n", txq, gmac_i);
+			}
+		}
+	}
+
+	/*****split mod setting validation******/
+	if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_ENABLED) {
+		if(tpm_init.split_mod_config.vlan_num > (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+			     "\n Split Mod VLAN num %d, it should not larger than %d \n",
+			     tpm_init.split_mod_config.vlan_num, (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM));
+			return (TPM_FAIL);
+		}
+		if (tpm_init.split_mod_config.p_bit_num > TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX || tpm_init.split_mod_config.p_bit_num == TPM_DB_SPLIT_MOD_P_BIT_NO_SET) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n Split Mod P_bit number out of range.\n");
+			return (TPM_FAIL);
+		}
+		for (i = 0; i < tpm_init.split_mod_config.p_bit_num; i++) {
+			if(tpm_init.split_mod_config.p_bit[i] > TPM_DB_SPLIT_MOD_P_BIT_MAX) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+			     		"\n Split Mod P_bit %d No Valid\n",
+					tpm_init.split_mod_config.p_bit[i]);
+				return (TPM_FAIL);
+			}
+			for (j = i + 1; j < tpm_init.split_mod_config.p_bit_num; j++) {
+				if(tpm_init.split_mod_config.p_bit[i] == tpm_init.split_mod_config.p_bit[j]) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+			     			"\n Split Mod P_bit %d Repeat\n",
+						tpm_init.split_mod_config.p_bit[i]);
+					return (TPM_FAIL);
+				}
+			}
+		}
+	}
+
+	/********************* CTC CNM validation *************************************/
+	if (tpm_init.ctc_cm_enable != TPM_CTC_CM_DISABLED) {
+		if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_DISABLED) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CTC CM: CTC CnM is enabled while split modification is disabled! \n");
+			return (TPM_FAIL);
+		}
+
+		if (!found_ipv4_pre) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CTC CM: CTC CnM is enabled while CNM_IPV4_PRE range size is Zero! \n");
+			return (TPM_FAIL);
+		} else {
+			exp_range_size = num_uni_ports * TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_PORT + 1;
+			if (exp_range_size > ipv4_pre_size) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					"\n CTC CM: CNM IPV4 PRE FILTER is not enough for "
+					"L2 & IPV4 combo rules (%d/%d) of %d UNI ports! \n",
+					exp_range_size, ipv4_pre_size, num_uni_ports);
+			}
+		}
+
+		if (!found_cnm_main) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CTC CM: CTC CnM is enabled while CNM_MAIN range size is Zero! \n");
+			return (TPM_FAIL);
+		} else {
+			exp_range_size = num_uni_ports * TPM_MAX_NUM_CTC_PRECEDENCE + 2;
+			if (exp_range_size > cnm_main_size) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					"\n CTC CM: CNM MAIN is not enough for "
+					"8 precedence rules (%d/%d) of %d UNI ports! \n",
+					exp_range_size, cnm_main_size, num_uni_ports);
+			}
+		}
+	} else {
+		if (found_ipv4_pre) {
+			TPM_OS_WARN(TPM_INIT_MOD,
+				"\n CTC CM: Since CTC CnM is disabled, CNM_IPV4_PRE range size should be Zero! \n");
+		}
+		if (found_cnm_main) {
+			TPM_OS_WARN(TPM_INIT_MOD,
+				"\n CTC CM: Since CTC CnM is disabled, CNM_MAIN range size should be Zero! \n");
+		}
+	}
+
+	/********************* ds_mac_based_trunking validation *************************************/
+	if (tpm_init.ds_mac_based_trunk_enable == TPM_DS_MAC_BASED_TRUNK_ENABLED) {
+		if (    (tpm_init.cpu_loopback == TPM_CPU_LOOPBACK_ENABLED)
+		     || (tpm_init.mc_setting.per_uni_vlan_xlat)
+		     || (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n when ds_mac_based_trunk is enabled, cpu_loopback, per_uni_vlan_xlat"
+				" and virt_uni can not be enabled! \n");
+			return (TPM_FAIL);
+		}
+
+		if (    (tpm_init.gmac0_mh_en == 0)
+		     || (tpm_init.gmac1_mh_en == 0)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n when ds_mac_based_trunk is enabled, MH on GMAC0/1 must be enabled\n");
+			return (TPM_FAIL);
+		}
+
+		if (    (tpm_init.eth_cmplx_profile != TPM_PON_WAN_DUAL_MAC_INT_SWITCH)
+		     && (tpm_init.eth_cmplx_profile != TPM_PON_WAN_DUAL_MAC_EXT_SWITCH)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n when ds_mac_based_trunk is enabled, eth_cmplx_profile must be "
+				"TPM_PON_WAN_DUAL_MAC_INT_SWITCH"
+				" or TPM_PON_WAN_DUAL_MAC_EXT_SWITCH! \n");
+			return (TPM_FAIL);
+		}
+
+	}
 	/********************* No switch init(MC) validation *************************************/
 	if (tpm_init.switch_init == 0) {
 		if (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED) {
@@ -2117,7 +2186,8 @@
 			return (TPM_FAIL);
 		}
 
-		if (tpm_init.pnc_range[TPM_PNC_MAC_LEARN].range_size == 0) {
+		if (tpm_init.pnc_range[TPM_PNC_MAC_LEARN].range_size == 0 &&
+		    tpm_init.pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_ENABLED) {
 			TPM_OS_FATAL(TPM_INIT_MOD,
 					"\n No Switch Init: PNC range[%d] size is 0! \n", TPM_PNC_MAC_LEARN);
 			return (TPM_FAIL);
@@ -2134,11 +2204,28 @@
 			TPM_OS_WARN(TPM_INIT_MOD,
 					"\n No Switch Init: MAC learn enabled, PNC range[%d] size is too small! \n", TPM_PNC_MAC_LEARN);
 		}
+
+		if (tpm_init.pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_ENABLED &&
+		    tpm_init.eth_cmplx_profile != TPM_PON_WAN_G0_G1_LPBK) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n PNC MAC learning not supported with profile (%d) \n",
+					tpm_init.eth_cmplx_profile);
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.ipv6_5t_enable == TPM_IPV6_5T_ENABLED &&
+		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_DUAL_LAN) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n IPV6 5-tuple supported with profile (%d) \n",
+					tpm_init.eth_cmplx_profile);
+			return (TPM_FAIL);
+		}
 	} else if ((tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_SINGLE_PORT ||
 		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G1_SINGLE_PORT ||
 		    tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_SINGLE_PORT ||
 		    tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_SINGLE_PORT ||
-		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK ||
+		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_DUAL_LAN)
 		 && tpm_init.switch_init == 1) {
 			TPM_OS_FATAL(TPM_INIT_MOD,
 					"\n Switch can not be Init at this profile: [%d]! \n", tpm_init.eth_cmplx_profile);
@@ -2191,6 +2278,26 @@
 		}
 	}
 
+	/* check all the loopback features */
+	if (tpm_init.mc_setting.per_uni_vlan_xlat) {
+		if (tpm_init.virt_uni_info.enabled != TPM_VIRT_UNI_ENABLED) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n per_uni_vlan_xlat can not be supported when virt_uni is disabled\n");
+			return (TPM_FAIL);
+		}
+	}
+	if (tpm_init.cpu_loopback == TPM_CPU_LOOPBACK_ENABLED) {
+		if (tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+			;/* OK */
+		else if (    (tpm_init.gmac_port_conf[TPM_ENUM_GMAC_1].conn == TPM_GMAC_CON_SWITCH_5)
+		          && (tpm_init.eth_cmplx_profile != TPM_G0_WAN_G1_INT_SWITCH)
+		          && (tpm_init.eth_cmplx_profile != TPM_PON_G0_WAN_G1_INT_SWITCH))
+			;/* OK */
+		else {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n cpu_wan_loopback can not be supported on this profile\n");
+			return (TPM_FAIL);
+		}
+	}
+
 	return (TPM_OK);
 }
 
@@ -2241,7 +2348,7 @@
 {
 	uint32_t i;
 
-	for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+	for (i = 0; i < TPM_MAX_NUM_RX_QUEUE; i++) {
 		if (tpm_init.gmac_rx[gmac].rx_queue[i].valid == TPM_TRUE)
 			tpm_db_gmac_rx_q_conf_set(gmac, i, tpm_init.gmac_rx[gmac].rx_queue[i].queue_size);
 	}
@@ -2425,6 +2532,9 @@
 	ret_code = tpm_init_api_rng_init(TPM_PNC_CNM_MAIN, TPM_CNM_MAIN_ACL, TPM_DIR_DS);
 	IF_ERROR(ret_code);
 
+	ret_code = tpm_init_api_rng_init(TPM_PNC_DS_LOAD_BALANCE, TPM_DS_LOAD_BALANCE_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
 	return (TPM_OK);
 }
 
@@ -2527,7 +2637,7 @@
 	IF_ERROR(ret_code);
 	ret_code = tpm_db_pon_type_set(tpm_init.pon_type);
 	IF_ERROR(ret_code);
-	ret_code = tpm_db_backup_wan_set(tpm_init.backup_wan);
+	ret_code = tpm_db_active_wan_set(tpm_init.active_wan);
 	IF_ERROR(ret_code);
 	ret_code = tpm_db_ds_mh_set_conf_set(tpm_init.ds_mh_set_conf);
 	IF_ERROR(ret_code);
@@ -2559,6 +2669,8 @@
 	IF_ERROR(ret_code);
 	ret_code = tpm_db_fc_conf_set(&tpm_init.port_fc_conf);
 	IF_ERROR(ret_code);
+	ret_code = tpm_db_ds_mac_based_trunk_enable_set(tpm_init.ds_mac_based_trunk_enable);
+	IF_ERROR(ret_code);
 
 	/* Set GMAC Logical Functions */
 
@@ -2587,6 +2699,7 @@
 		printk(KERN_INFO "TPM_SRC_PORT: %d, value: %d\n", src_port, tpm_init.igmp_pkt_frwd_mod[src_port]);
 	}
 	tpm_db_igmp_set_cpu_queue(tpm_init.igmp_cpu_queue);
+	tpm_db_igmp_set_snoop_enable(tpm_init.igmp_snoop);
 	/*printk("TPM_SRC_PORT_WAN: %d, TPM_SRC_PORT_UNI_0: %d, TPM_SRC_PORT_UNI_1: %d, TPM_SRC_PORT_UNI_2: %d, "
 	   "TPM_SRC_PORT_UNI_3: %d, igmp_cpu_queue: %d\n",
 	   tpm_init.igmp_pkt_frwd_mod[4],tpm_init.igmp_pkt_frwd_mod[0],tpm_init.igmp_pkt_frwd_mod[1],
@@ -2661,7 +2774,9 @@
 		tpm_init_gmac_rxq_set(TPM_ENUM_GMAC_1);
 	}
 	/* PMAC Rx */
-	if (tpm_init.pon_type == TPM_GPON || tpm_init.pon_type == TPM_EPON) {
+	if (    tpm_init.pon_type == TPM_GPON
+	     || tpm_init.pon_type == TPM_EPON
+	     || tpm_init.pon_type == TPM_P2P) {
 		tpm_db_gmac_rx_val_set(TPM_ENUM_PMAC);
 		tpm_init_gmac_rxq_set(TPM_ENUM_PMAC);
 	}
@@ -2755,13 +2870,24 @@
 		tpm_db_gmac1_lpbk_en_set(false);
 
 	/* set CPU WAN loopback en */
-	if (    (tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
-	     || (tpm_init.gmac_port_conf[TPM_ENUM_GMAC_0].conn == TPM_GMAC_CON_SWITCH_5))
-		tpm_db_cpu_wan_lpbk_en_set(true);
-	else
-		tpm_db_cpu_wan_lpbk_en_set(false);
+	tpm_db_cpu_wan_lpbk_en_set(tpm_init.cpu_loopback);
 
 	tpm_db_switch_init_set(tpm_init.switch_init);
+	if (	(tpm_init.eth_cmplx_profile == TPM_PON_WAN_DUAL_MAC_INT_SWITCH)
+	     || (tpm_init.eth_cmplx_profile == TPM_PON_WAN_DUAL_MAC_EXT_SWITCH))
+		tpm_db_ds_load_bal_en_set(true);
+	else
+		tpm_db_ds_load_bal_en_set(false);
+
+
+	/* set switch active WAN en */
+	if (    (tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_INT_SWITCH)
+	     || (tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_INT_SWITCH)
+	     || (tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_SINGLE_PORT)
+	     || (tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_SINGLE_PORT))
+		tpm_db_switch_active_wan_en_set(true);
+	else
+		tpm_db_switch_active_wan_en_set(false);
 
 	return (TPM_OK);
 }
@@ -2803,6 +2929,14 @@
 						     "GMAC = %d TCONT = %d Q = %d HWF: owner_rx %d\n",
 						     dest_port, dest_port_txp, q_num, owner_rx_port);
 				}
+				else
+				{
+					if (mv_eth_ctrl_txq_cpu_own(dest_port, dest_port_txp, q_num, 1)){
+						TPM_OS_ERROR(TPM_INIT_MOD,
+						"mv_eth_ctrl_txq_cpu_own err GMAC = %d TCONT = %d Q = %d SWF: owner_rx %d\n",
+						     dest_port, dest_port_txp, q_num, owner_rx_port);
+					}
+				}
 			} else {
 				if (mv_eth_ctrl_txq_hwf_own(dest_port, dest_port_txp, q_num, -1)){
 						TPM_OS_DEBUG(TPM_INIT_MOD,
@@ -2899,7 +3033,7 @@
 	}			/* All GMACs */
 }
 
-int32_t tpm_init_mh_select(void)
+int32_t tpm_init_mh_select(tpm_init_mh_src_t ds_mh_set_conf)
 {
 	tpm_gmacs_enum_t gmac_i;
 	tpm_db_gmac_func_t gmac_func;
@@ -2912,7 +3046,7 @@
 		tpm_db_gmac_func_get(gmac_i, &gmac_func);
 
 		if ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_WAN)) {
-			switch (tpm_init.ds_mh_set_conf) {
+			switch (ds_mh_set_conf) {
 			case TPM_MH_SRC_RX_CTRL:
 				mvNetaHwfMhSrcSet(gmac_i, MV_NETA_HWF_MH_REG);
 				mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_REPLACE_MH_REG(0));
@@ -2923,10 +3057,10 @@
 				mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_DONT_CHANGE);
 				break;
 			default:
-				TPM_OS_ERROR(TPM_INIT_MOD, " Unknown d/s MH source (%d)\n", tpm_init.ds_mh_set_conf);
+				TPM_OS_ERROR(TPM_INIT_MOD, " Unknown d/s MH source (%d)\n", ds_mh_set_conf);
 				return (TPM_FAIL);
 			}
-		} else if ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN)) {
+		} else if ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN) || (gmac_func == TPM_GMAC_FUNC_LAN_UNI)) {
 			mvNetaHwfMhSrcSet(gmac_i, MV_NETA_HWF_MH_REG);
 			mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_REPLACE_GPON_HDR);
 		}
@@ -2985,6 +3119,34 @@
 	return ret_code;
 }
 
+/*******************************************************************************
+* tpm_init_gmac_PHY_poll()
+*
+* DESCRIPTION:      Initialize the GMAC PHY polling state accordint to it connect to PHY or not
+*
+* INPUTS:
+*	port -- GMAC port
+*	state -- true: enable PHY polling; false: disable PHY polling
+* OUTPUTS:None
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_gmac_PHY_poll(int port, bool state)
+{
+	unsigned int regData;
+
+	regData = MV_REG_READ(ETH_UNIT_CONTROL_REG(port));
+	if (state)
+		regData |= ETH_PHY_POLLING_ENABLE_MASK;
+	else
+		regData &= (~ETH_PHY_POLLING_ENABLE_MASK);
+
+	MV_REG_WRITE(ETH_UNIT_CONTROL_REG(port), regData);
+
+	return TPM_OK;
+}
+
 int32_t tpm_init_switch(void)
 {
 	uint32_t i;
@@ -3002,6 +3164,7 @@
 	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
 	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
 	case TPM_PON_WAN_G0_G1_LPBK:
+	case TPM_PON_WAN_G0_G1_DUAL_LAN:
 		return (TPM_OK);
        default:
        	break;
@@ -3160,10 +3323,20 @@
 	if (mv_switch_mac_addr_set(gq_da, 0, sw_port_bmp, 1))
 		TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_mac_addr_set err. sw_port_bmp 0X%x\n", sw_port_bmp);
 
+	/* If Switch port MAC no connected to PHY, disable GMAC PHY polling */
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (TPM_FALSE == tpm_init.gmac_port_conf[gmac_i].valid)
+			continue;
+
+		if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn ||
+		    TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn)
+			tpm_init_gmac_PHY_poll(gmac_i, false);
+	}
+
 	return (TPM_OK);
 }
 
-int32_t tpm_init_mh_conf_set(void)
+int32_t tpm_init_mh_conf_set(uint32_t gmac0_mh_en, uint32_t gmac1_mh_en, tpm_init_gmac_conn_conf_t *gmac_port_conf)
 {
 	tpm_gmacs_enum_t gmac_i;
 	uint32_t amber_port_num, mh_en;
@@ -3181,13 +3354,13 @@
 
 		switch (gmac_i) {
 		case TPM_ENUM_GMAC_0:
-			mh_en = tpm_init.gmac0_mh_en;
-			if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn)
+			mh_en = gmac0_mh_en;
+			if (TPM_GMAC_CON_SWITCH_4 == gmac_port_conf[gmac_i].conn)
 				amber_port_num = TPM_GMAC0_AMBER_PORT_NUM;
 			break;
 		case TPM_ENUM_GMAC_1:
-			mh_en = tpm_init.gmac1_mh_en;
-			if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn)
+			mh_en = gmac1_mh_en;
+			if (TPM_GMAC_CON_SWITCH_5 == gmac_port_conf[gmac_i].conn)
 				amber_port_num = TPM_GMAC1_AMBER_PORT_NUM;
 			break;
 		case TPM_ENUM_PMAC:
@@ -3223,7 +3396,7 @@
 	return (TPM_OK);
 }
 
-int32_t tpm_init_mh_reg_set(void)
+int32_t tpm_init_mh_reg_set(tpm_init_mh_src_t ds_mh_set_conf)
 {
 	tpm_gmacs_enum_t gmac_i;
 	uint32_t pp_port_num;
@@ -3249,7 +3422,7 @@
 		}
 		pp_port_num = TPM_GMAC_TO_PP_PORT(gmac_i);
 
-		if (((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN)) &&
+		if (((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN) || (gmac_func == TPM_GMAC_FUNC_LAN_UNI)) &&
 		    gmac_mh_en && (tpm_init.ds_mh_set_conf == TPM_MH_SRC_PNC_RI)) {
 			/* Set MH Tx registers to full table */
 			for (tx_reg_i = 0; tx_reg_i < TPM_TX_MAX_MH_REGS; tx_reg_i++) {
@@ -3276,9 +3449,9 @@
 				/*                   VLANTable field is  (re)set to 'all_other_switch_ports' */
 
 				if (gmac_i == TPM_ENUM_GMAC_0)
-					regVal = 0x3f & (~(1 << TPM_GMAC0_AMBER_PORT_NUM));
+					regVal = 0x7f & (~(1 << TPM_GMAC0_AMBER_PORT_NUM));
 				else
-					regVal = 0x3f & (~(1 << TPM_GMAC1_AMBER_PORT_NUM));
+					regVal = 0x7f & (~(1 << TPM_GMAC1_AMBER_PORT_NUM));
 			} else {
 				if (tpm_db_num_tcont_llid_get(&num_txp) != TPM_OK) {
 					TPM_OS_ERROR(TPM_INIT_MOD,
@@ -3308,8 +3481,8 @@
 {
 	tpm_db_tx_mod_t tx_mod_i;
 	tpm_gmacs_enum_t gmac_i;
-	uint32_t txp_i = 0;
-	uint32_t size = 0, queue = 0, rate = 0;
+	uint32_t txp_i = 0, prio = 0;
+	uint32_t size = 0, queue = 0, rate = 0, wrr = 0;
 
 	for (tx_mod_i = 0; tx_mod_i < TPM_MAX_NUM_TX_PORTS; tx_mod_i++) {
 		if (TPM_FALSE == tpm_db_gmac_tx_val_get(tx_mod_i)) {
@@ -3323,19 +3496,34 @@
 			gmac_i = TPM_ENUM_PMAC;
 			txp_i = tx_mod_i - TPM_TX_MOD_PMAC_0;
 		}
+
 		/* get Tx queue bucket size */
 		for (queue = 0; queue < TPM_MAX_NUM_TX_QUEUE; queue++) {
 #ifdef MV_ETH_WRR_NEW
 			size = MV_REG_READ(NETA_TXQ_TOKEN_SIZE_REG(gmac_i, txp_i, queue));
 			rate = MV_REG_READ(NETA_TXQ_REFILL_REG(gmac_i, txp_i, queue));
+			wrr = MV_REG_READ(NETA_TXQ_WRR_ARBITER_REG(gmac_i, txp_i, queue));
 #else /* Old WRR/EJP module */
 			/* token size and rate are in the same reg */
 			rate = MV_REG_READ(ETH_TXQ_TOKEN_CFG_REG(gmac_i, txp_i, queue));
 #endif /* MV_ETH_WRR_NEW */
 			TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), queue (%d), size (%d), rate (%d)\n",
 				gmac_i, txp_i, queue, size, rate);
-			tpm_db_set_gmac_rate_limit(tx_mod_i, queue, size, rate);
+			tpm_db_set_gmac_q_rate_limit(tx_mod_i, queue, size, rate, wrr);
 		}
+
+		/* get TX bucket and rate */
+#ifdef MV_ETH_WRR_NEW
+		size = MV_REG_READ(NETA_TXP_TOKEN_SIZE_REG(gmac_i, txp_i));
+		rate = MV_REG_READ(NETA_TXP_REFILL_REG(gmac_i, txp_i));
+		prio = MV_REG_READ(NETA_TX_FIXED_PRIO_CFG_REG(gmac_i, txp_i));
+#else /* Old WRR/EJP module */
+		rate = MV_REG_READ(ETH_TXP_TOKEN_RATE_CFG_REG(gmac_i, txp_i));
+		size = MV_REG_READ(ETH_TXP_TOKEN_SIZE_REG(gmac_i, txp_i));
+#endif /* MV_ETH_WRR_NEW */
+		TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), queue (%d), size (%d), rate (%d)\n",
+			gmac_i, txp_i, queue, size, rate);
+		tpm_db_set_gmac_rate_limit(tx_mod_i, size, rate, prio);
 	}
 	return (TPM_OK);
 }
@@ -3345,6 +3533,10 @@
 	tpm_gmacs_enum_t gmac_i;
 	uint32_t txp_i = 0;
 	uint32_t size = 0, queue = 0, rate = 0;
+	uint32_t wrr = 0, prio = 0, regVal = 0;
+
+	/* keep the compiler quiet */
+	regVal = 0;
 
 	for (tx_mod_i = 0; tx_mod_i < TPM_MAX_NUM_TX_PORTS; tx_mod_i++) {
 		if (TPM_FALSE == tpm_db_gmac_tx_val_get(tx_mod_i))
@@ -3356,18 +3548,39 @@
 			gmac_i = TPM_ENUM_PMAC;
 			txp_i = tx_mod_i - TPM_TX_MOD_PMAC_0;
 		}
-		/* get Tx queue bucket size */
+
+		/* set Tx queue bucket size */
 		for (queue = 0; queue < TPM_MAX_NUM_TX_QUEUE; queue++) {
-			tpm_db_get_gmac_rate_limit(tx_mod_i, queue, &size, &rate);
+			tpm_db_get_gmac_q_rate_limit(tx_mod_i, queue, &size, &rate, &wrr);
 			TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), queue (%d), size (%d), rate (%d)\n",
 				gmac_i, txp_i, queue, size, rate);
 #ifdef MV_ETH_WRR_NEW
 			MV_REG_WRITE(NETA_TXQ_REFILL_REG(gmac_i, txp_i, queue), rate);
 			MV_REG_WRITE(NETA_TXQ_TOKEN_SIZE_REG(gmac_i, txp_i, queue), size);
+			MV_REG_WRITE(NETA_TXQ_WRR_ARBITER_REG(gmac_i, txp_i, queue), wrr);
 #else /* Old WRR/EJP module */
 			MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(gmac_i, txp_i, queue), rate);
 #endif /* MV_ETH_WRR_NEW */
 		}
+
+		tpm_db_get_gmac_rate_limit(tx_mod_i, &size, &rate, &prio);
+		TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), size (%d), rate (%d)\n",
+			gmac_i, txp_i, size, rate);
+		/* set TX bucket and rate */
+#ifdef MV_ETH_WRR_NEW
+		MV_REG_WRITE(NETA_TXP_TOKEN_SIZE_REG(gmac_i, txp_i), size);
+		MV_REG_WRITE(NETA_TXP_REFILL_REG(gmac_i, txp_i), rate);
+		MV_REG_WRITE(NETA_TX_FIXED_PRIO_CFG_REG(gmac_i, txp_i), prio);
+#else /* Old WRR/EJP module */
+		regVal = MV_REG_READ(ETH_TXP_TOKEN_RATE_CFG_REG(gmac_i, txp_i));
+		regVal &= ~ETH_TXP_TOKEN_RATE_ALL_MASK;
+		regVal |= ETH_TXP_TOKEN_RATE_MASK(rate);
+		MV_REG_WRITE(ETH_TXP_TOKEN_RATE_CFG_REG(gmac_i, txp_i), regVal);
+		regVal = MV_REG_READ(ETH_TXP_TOKEN_SIZE_REG(gmac_i, txp_i));
+		regVal &= ~ETH_TXP_TOKEN_SIZE_ALL_MASK;
+		regVal |= ETH_TXP_TOKEN_SIZE_MASK(size);
+		MV_REG_WRITE(ETH_TXP_TOKEN_SIZE_REG(gmac_i, txp_i), regVal);
+#endif /* MV_ETH_WRR_NEW */
 	}
 	return (TPM_OK);
 }
@@ -3397,17 +3610,20 @@
 	return (TPM_OK);
 }
 
-int32_t tpm_init_mh(void)
+int32_t tpm_init_mh(tpm_init_mh_src_t ds_mh_set_conf,
+			uint32_t gmac0_mh_en,
+			uint32_t gmac1_mh_en,
+			tpm_init_gmac_conn_conf_t *gmac_port_conf)
 {
-	if (tpm_init_mh_select() != TPM_OK) {
+	if (tpm_init_mh_select(ds_mh_set_conf) != TPM_OK) {
 		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_select err\n");
 		return (TPM_FAIL);
 	}
-	if (tpm_init_mh_conf_set() != TPM_OK) {
+	if (tpm_init_mh_conf_set(gmac0_mh_en, gmac1_mh_en, gmac_port_conf) != TPM_OK) {
 		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_conf_set err\n");
 		return (TPM_FAIL);
 	}
-	if (tpm_init_mh_reg_set() != TPM_OK) {
+	if (tpm_init_mh_reg_set(ds_mh_set_conf) != TPM_OK) {
 		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_reg_set err\n");
 		return (TPM_FAIL);
 	}
@@ -3452,7 +3668,7 @@
 	return (TPM_OK);
 }
 
-int32_t tpm_init_ipg(void)
+int32_t tpm_init_ipg(int32_t mod_value)
 {
 	int status;
 	tpm_gmacs_enum_t gmac_i;
@@ -3461,7 +3677,14 @@
 	tpm_db_gmac_func_t gmac_func;
 	tpm_db_gmac_conn_t gmac_con;
 	MV_BOOL link_is_up;
+	tpm_db_error_t db_ret_code;
+	uint32_t gmac0_mh_en = 0;
+	uint32_t gmac1_mh_en = 0;
 
+	db_ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_0, &gmac0_mh_en);
+	IF_ERROR(db_ret_code);
+	db_ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_1, &gmac1_mh_en);
+	IF_ERROR(db_ret_code);
 
 	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
 		if (!INIT_GMAC_VALID(gmac_i))
@@ -3472,12 +3695,13 @@
 
 		if (gmac_func != TPM_GMAC_FUNC_NONE) {
 
-			if ((gmac_i == 0 && tpm_init.gmac0_mh_en != TPM_FALSE && gmac_con == TPM_GMAC_CON_SWITCH_4) ||
-			    (gmac_i == 1 && tpm_init.gmac1_mh_en != TPM_FALSE && gmac_con == TPM_GMAC_CON_SWITCH_5)) {
+			if ((gmac_i == 0 && gmac0_mh_en != TPM_FALSE && gmac_con == TPM_GMAC_CON_SWITCH_4) ||
+			    (gmac_i == 1 && gmac1_mh_en != TPM_FALSE && (gmac_con == TPM_GMAC_CON_SWITCH_5 ||
+			     tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK))) {
 				mvNetaPortDisable(gmac_i);
 				mvNetaHwfEnable(gmac_i, 0);
 				ipg_val = mvNetaPortIpgGet(gmac_i);
-				ipg_val -= TPM_MH_LEN;
+				ipg_val += mod_value;
 				mvNetaPortIpgSet(gmac_i, ipg_val);
 				mvNetaHwfEnable(gmac_i, 1);
 				status = mvNetaPortEnable(gmac_i);
@@ -3488,23 +3712,25 @@
 						mvNetaPortUp(gmac_i);
 				}
 
-				if (gmac_i == 0)
-					port = TPM_GMAC0_AMBER_PORT_NUM;
-				else
-					port = TPM_GMAC1_AMBER_PORT_NUM;
+				if ((gmac_con == TPM_GMAC_CON_SWITCH_4) || (gmac_con == TPM_GMAC_CON_SWITCH_5)) {
+					if (gmac_i == 0)
+						port = TPM_GMAC0_AMBER_PORT_NUM;
+					else
+						port = TPM_GMAC1_AMBER_PORT_NUM;
 
-				/* TODO: Need to check if switch is attached to GMAC */
-				status = mv_switch_get_port_preamble(port, &preamble);
-				if (status) {
-					TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get port(%d) preamble_len\n", port);
-					return (TPM_FAIL);
-				}
-				preamble -= TPM_MH_LEN;
-				status = mv_switch_set_port_preamble(port, preamble);
-				if (status) {
-					TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set port(%d) preamble_len(%d)\n"
-						     , port, preamble);
-					return (TPM_FAIL);
+					/* TODO: Need to check if switch is attached to GMAC */
+					status = mv_switch_get_port_preamble(port, &preamble);
+					if (status) {
+						TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get port(%d) preamble_len\n", port);
+						return (TPM_FAIL);
+					}
+					preamble += mod_value;
+					status = mv_switch_set_port_preamble(port, preamble);
+					if (status) {
+						TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set port(%d) preamble_len(%d)\n"
+							     , port, preamble);
+						return (TPM_FAIL);
+					}
 				}
 			}
 		}
@@ -3596,20 +3822,57 @@
 * RETURNS:
 *
 *******************************************************************************/
-int32_t tpm_init_gmac_loopback(int port)
+int32_t tpm_init_gmac_loopback(tpm_gmacs_enum_t port, uint8_t enable)
 {
 	uint32_t regVal;
 
-	mvNetaPortDisable(port);
-	mvNetaHwfEnable(port, 0);
+	if (port > TPM_MAX_GMAC) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "GMAC port(%d) is invalid\n", port);
+		return TPM_FAIL;
+	}
 
-	mvNetaForceLinkModeSet(port, 1, 0);/*for link up*/
-	mvNetaSpeedDuplexSet(port, MV_ETH_SPEED_1000, MV_ETH_DUPLEX_FULL);/*set 1G*/
+	/* Check Port Available or not */
+	if (!tpm_init_check_gmac_init(port)) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "GMAC port(%d) is not available\n", port);
+		return TPM_FAIL;
+	}
 
-	mvNetaHwfEnable(port, 1);
-	mvNetaPortEnable(port);
+	if (mvNetaPortDisable(port)) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to disable GMAC port(%d)\n", port);
+		return (TPM_FAIL);
+	}
+	if (mvNetaHwfEnable(port, 0)) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to disable GMAC port(%d) HWF\n", port);
+		return (TPM_FAIL);
+	}
 
-	MV_REG_WRITE(NETA_GMAC_CTRL_1_REG(port), 0x31); /* set gmac to loopback mode */
+	if (mvNetaForceLinkModeSet(port, 1, 0)) {/*for link up*/
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set GMAC port(%d) force link\n", port);
+		return (TPM_FAIL);
+	}
+	if (mvNetaSpeedDuplexSet(port, MV_ETH_SPEED_1000, MV_ETH_DUPLEX_FULL)) {/*set 1G*/
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set GMAC port(%d) speed and duplex\n", port);
+		return (TPM_FAIL);
+	}
+
+	if (mvNetaHwfEnable(port, 1)) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to enable GMAC port(%d) HWF\n", port);
+		return (TPM_FAIL);
+	}
+	if (mvNetaPortEnable(port)) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to enable GMAC port(%d)\n", port);
+		return (TPM_FAIL);
+	}
+
+	/* set GMAC_CTRL_2_REG */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	regVal &= ~NETA_GMAC_PSC_ENABLE_MASK;
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+
+	if (enable)
+		MV_REG_WRITE(NETA_GMAC_CTRL_1_REG(port), 0x31); /* set gmac to loopback mode */
+	else
+		MV_REG_WRITE(NETA_GMAC_CTRL_1_REG(port), 0x11); /* set gmac to no-loopback mode */
 
 	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(port));
 	regVal |=  NETA_FORCE_LINK_FAIL_MASK;  			/* enable Force Link Pass 	*/
@@ -3642,12 +3905,15 @@
 	tpm_pnc_ranges_t cur_range = TPM_INVALID_RANGE, next_range = 0;
 	tpm_db_pnc_range_t next_range_data;
 	tpm_db_pnc_range_conf_t range_conf;
+	tpm_db_pnc_range_conf_t range_conf_tcp_flag;
 	uint32_t switch_init;
-	int32_t ret_code;
+	int32_t ret_code, ret_code_tcp_flag;
 	tpm_db_ttl_illegal_action_t ttl_illegal_action;
 	tpm_db_tcp_flag_check_t tcp_flag_check;
 	tpm_gmacs_enum_t gmac_i;
 	tpm_db_gmac_func_t gfunc;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
+	uint32_t snoop_enable;
 
 	TPM_OS_DEBUG(TPM_INIT_MOD, "\n");
 
@@ -3667,23 +3933,26 @@
 		ret_code = tpm_mod2_split_mod_init(gmac_i);
 		IF_ERROR(ret_code);
 	}
-	/* Init Tx queue rate limit */
-	ret_code = tpm_init_reset_gmac_queue_rate_limit();
-	IF_ERROR(ret_code);
 
 	/* Init Amber Switch */
 	tpm_db_switch_init_get(&switch_init);
 	if (switch_init)
 		tpm_init_switch();
-#if 0 /* No GMAC1 on MC RD board */
-		else
-		/* Init GMAC1 in loopback mod if no switch*/
-		tpm_init_gmac_loopback(TPM_ENUM_GMAC_1);
-#endif
+	else {
+		if (tpm_db_gmac1_lpbk_en_get()) {
+			/* Init GMAC1 in loopback mod if GMAC loopback is enabled */
+			ret_code = tpm_init_gmac_loopback(TPM_ENUM_GMAC_1, 1);
+			IF_ERROR(ret_code);
+		}
+	}
 	/*Init TX scheduling */
 	ret_code = tpm_init_tx_queue_sched();
 	IF_ERROR(ret_code);
 
+	/* Init Tx queue rate limit */
+	ret_code = tpm_init_reset_gmac_queue_rate_limit();
+	IF_ERROR(ret_code);
+
 	/* Initialize (wipe out) the PNC ranges in PnC HW */
 	tpm_db_pnc_rng_val_get_next(cur_range, &next_range, &next_range_data);
 	TPM_OS_DEBUG(TPM_INIT_MOD, "next_range(%d)\n", next_range);
@@ -3707,6 +3976,25 @@
 	} else
 		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_NUM_VLAN_TAGS);
 
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_DS_LOAD_BALANCE, &range_conf);
+	if (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable) {
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "PNC range TPM_PNC_DS_LOAD_BALANCE is not created "
+				"when ds_mac_based_trunk is enabled\n");
+			return ERR_GENERAL;
+		} else if (range_conf.range_size < 3) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "PNC range TPM_PNC_DS_LOAD_BALANCE size should be at least "
+				"3 when ds_mac_based_trunk is enabled\n");
+			return ERR_GENERAL;
+		}
+	} else {
+		if ((ret_code == TPM_DB_OK) && (range_conf.range_size != 0)) {
+			TPM_OS_WARN(TPM_INIT_MOD, "do not perform ds_mac_based_trunk, "
+				"no need to create TPM_PNC_DS_LOAD_BALANCE range\n");
+		}
+	}
+
 	tpm_db_get_ttl_illegal_action(&ttl_illegal_action);
 	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
 	if (TPM_TTL_ZERO_ACTION_NOTHING == ttl_illegal_action) {
@@ -3763,11 +4051,21 @@
 		}
 	}
 	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IGMP, &range_conf);
-	if (ret_code == TPM_DB_OK) {
-		ret_code = tpm_proc_ipv4_igmp_init();
-		IF_ERROR(ret_code);
-	} else
-		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IGMP);
+	tpm_db_igmp_get_snoop_enable(&snoop_enable);
+	if (TPM_TRUE == snoop_enable) {
+		if (ret_code == TPM_DB_OK) {
+			ret_code = tpm_proc_ipv4_igmp_init();
+			IF_ERROR(ret_code);
+		} else {
+			TPM_OS_ERROR(TPM_INIT_MOD, "PNC range(TPM_PNC_IGMP) not initialized with IGMP snoop enabled\n");
+			return ERR_GENERAL;
+		}
+	} else if (ret_code == TPM_DB_OK) {
+		if (range_conf.range_size != 0) {
+			/* igmp snoop is disabled, no need to create TPM_PNC_IGMP range */
+			TPM_OS_WARN(TPM_INIT_MOD, "igmp snoop is disabled, no need to create TPM_PNC_IGMP range\n");
+		}
+	}
 
 	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
 	if (ret_code == TPM_DB_OK) {
@@ -3791,16 +4089,20 @@
 		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_CATCH_ALL);
 
 	tpm_db_get_tcp_flag_check(&tcp_flag_check);
-	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TCP_FLAG, &range_conf);
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_TCP_FLAG, &range_conf);
+	ret_code_tcp_flag = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_TCP_FLAG, &range_conf_tcp_flag);
 	if (TPM_TCP_FLAG_NOT_CHECK == tcp_flag_check) {
-		if (ret_code == TPM_DB_OK) {
+		if (ret_code == TPM_DB_OK || ret_code_tcp_flag == TPM_DB_OK) {
 			/* do not check tcp flag, no need to create tcp flag range */
-			TPM_OS_WARN(TPM_INIT_MOD, "do not check tcp flag, no need to create tcp flag range\n");
+			TPM_OS_WARN(TPM_INIT_MOD, "do not check tcp flag, no need to create IPv4/6 tcp flag range\n");
 		}
 	} else {
-		if ((ret_code != TPM_DB_OK) || (range_conf.range_size < 4)) {
+		if ((ret_code != TPM_DB_OK) || (range_conf.range_size < 3)) {
 			/* check tcp flag, need to create tcp flag range */
-			TPM_OS_WARN(TPM_INIT_MOD, "check tcp flag, need to create tcp flag range with size of 4\n");
+			TPM_OS_WARN(TPM_INIT_MOD, "check tcp flag, need to create IPv4 tcp flag range with size of 3\n");
+		} else if ((ret_code_tcp_flag != TPM_DB_OK) || (range_conf_tcp_flag.range_size < 2)) {
+			/* check tcp flag, need to create tcp flag range */
+			TPM_OS_WARN(TPM_INIT_MOD, "check tcp flag, need to create IPv6 tcp flag range with size of 2\n");
 		} else {
 			ret_code = tpm_proc_tcp_flag_init();
 			IF_ERROR(ret_code);
@@ -3909,6 +4211,20 @@
 
 	TPM_OS_DEBUG(TPM_INIT_MOD, "\n");
 
+	/* check PON and GMAC state */
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gfunc);
+
+		if (gfunc == TPM_GMAC_FUNC_NONE)
+			continue;
+		if (!tpm_init_check_gmac_init(gmac_i)) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "GMAC port(%d) is not init, system is not fully functional!\n", gmac_i);
+			return TPM_FAIL;
+		}
+	}
 	/* Init Vlan Ethertype Registers */
 	ret_code = tpm_init_vlan_etype_set();
 	IF_ERROR(ret_code);
@@ -3949,14 +4265,17 @@
 	tpm_init_rxq_size_set();
 
 	/* Init marvell header configuration */
-	ret_code = tpm_init_mh();
+	ret_code = tpm_init_mh(tpm_init.ds_mh_set_conf,
+				tpm_init.gmac0_mh_en,
+				tpm_init.gmac1_mh_en,
+				tpm_init.gmac_port_conf);
 	IF_ERROR(ret_code);
 
 	/* Init Buffer Mngmt Pool configuration */
 	tpm_init_bm_pool();
 
 	/* Init IPG */
-	tpm_init_ipg();
+	tpm_init_ipg((-TPM_MH_LEN));
 
 	ret_code = tpm_init_system_mib_reset(reset_type);
 	IF_ERROR(ret_code);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h
index 311a5be..009d272 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h
@@ -102,5 +102,12 @@
 int32_t tpm_module_init(void);
 int32_t tpm_module_start(tpm_init_t *tpm_init);
 void tpm_init_params_get(tpm_init_t *tpm_init_params);
+int32_t tpm_init_get_gmac_queue_rate_limit(void);
+int32_t tpm_init_mh(tpm_init_mh_src_t ds_mh_set_conf,
+			uint32_t gmac0_mh_en,
+			uint32_t gmac1_mh_en,
+			tpm_init_gmac_conn_conf_t *gmac_port_conf);
+int32_t tpm_init_ipg(int32_t mod_value);
+int32_t tpm_init_gmac_loopback(tpm_gmacs_enum_t port, uint8_t enable);
 
 #endif /* _TPM_INIT_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h
index 947432a..7f8344e 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h
@@ -95,8 +95,6 @@
 
 #define TPM_CHAIN_NUM_UNLIMITED		(0x1000)
 
-#define FROM_SPEC_UNI(src)		(src >= TPM_SRC_PORT_UNI_0 && src <= TPM_SRC_PORT_UNI_VIRT)
-
 /* PNC Target TXP, in exact numbering scheme, do not change !! */
 typedef enum {
 	TPM_INVALID_PNC_TRG = -1,
@@ -114,22 +112,13 @@
 } tpm_pnc_trg_t;
 
 typedef enum {
-	TPM_INVALID_GMAC = -1,
-	TPM_ENUM_GMAC_0,
-	TPM_ENUM_GMAC_1,
-	TPM_ENUM_PMAC,
-	TPM_MAX_GMAC = TPM_ENUM_PMAC,
-	TPM_MAX_NUM_GMACS
-} tpm_gmacs_enum_t;
-
-typedef enum {
 	TPM_INT_CALL = 0,
 	TPM_EXT_CALL
 } tpm_caller_t;
 
 
 #define TPM_MAX_VID			(4096)	/* legal VLAN ID = 0-4095 */
-#define TPM_MAX_NUM_CTC_PRECEDENCE		(8)	
+#define TPM_MAX_NUM_CTC_PRECEDENCE		(8)
 
 #define PON_PORT			(2)
 #define SW_GMAC_0			(0)
@@ -165,20 +154,22 @@
 
 #define TPM_INTERNAL_OWNER_ID		(0xABBACDDC)
 
+#define TPM_INVALID_QUEUE		(0xFFFF)
 
 typedef enum {
 	TPM_INVALID_SECTION = -1,
 	TPM_PNC_MAC_LEARN_ACL,
+	TPM_DS_LOAD_BALANCE_ACL,
 	TPM_CPU_LOOPBACK_ACL,
 	TPM_L2_PRIM_ACL,
 	TPM_L3_TYPE_ACL,
 	TPM_IPV4_ACL,
 	TPM_IPV4_MC,
+	TPM_IPV6_NH_ACL,
+	TPM_L4_ACL,
 	TPM_IPV6_GEN_ACL,
 	TPM_IPV6_DIP_ACL,
 	TPM_IPV6_MC_ACL,
-	TPM_IPV6_NH_ACL,
-	TPM_L4_ACL,
 	TPM_CNM_MAIN_ACL,
 	TPM_MAX_NUM_API_SECTIONS	/* Equals to number of entries in enum */
 } tpm_api_sections_t;
@@ -224,6 +215,9 @@
 #define TPM_PARSE_FLAG_CNM_IPV4_MASK	(TPM_PARSE_FLAG_CNM_IPV4_TRUE | TPM_PARSE_FLAG_CNM_IPV4_FALSE)
 #define TPM_PARSE_FLAG_SPLIT_MOD_MASK	(TPM_PARSE_FLGA_SPLIT_MOD_TRUE | TPM_PARSE_FLGA_SPLIT_MOD_FALSE)
 
+#define TPM_DS_LOAD_BALNC_PARSE_BM_MASK		\
+		(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_TWO_VLAN_TAG |\
+		TPM_L2_PARSE_ETYPE | TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT | TPM_L2_PARSE_GEMPORT)
 #define TPM_L2_PARSE_BM_MASK		\
 		(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_TWO_VLAN_TAG |\
 		TPM_L2_PARSE_ETYPE | TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT | TPM_L2_PARSE_GEMPORT)
@@ -262,6 +256,7 @@
 #define TPM_PARSE_FLAG_IPV4_PRE_KEY_PARSE   (0x00020000LL)
 #define TPM_PARSE_FLAG_CNM_PREC_PARSE       (0x00040000LL)
 #define TPM_PARSE_FLAG_IPV6_MC_SIP_PARSE    (0x00080000LL)
+#define TPM_PARSE_FLAG_DNRT_DS_TRUNK        (0x00100000LL)	/* Set DNRT_DS_TRUNK bit */
 
 /* Following additional TPM_ACTIONs for internal use, they must co-exist (not overlap)
    with existing TPM_ACTIONs in types.h */
@@ -290,6 +285,7 @@
 #define TPM_ACTION_UNSET_IPV4_PRE_KEY   (0x00400000LL)
 #define TPM_ACTION_SET_CNM_PREC         (0x00800000LL)
 #define TPM_ACTION_UNSET_CNM_PREC       (0x01000000LL)
+#define TPM_ACTION_UNSET_DNRT_DS_TRUNK  (0x02000000LL)	/* Unset DNRT_DS_TRUNK bit */
 
 #define     TPM_MAX_WRR_WEIGHT             (255)
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c
index 99f1d34..7f8b193 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c
@@ -259,10 +259,10 @@
 		return NULL;
 
 	hdr = (tpm_common_mpool_hdr_t *) ((uint8_t *) ptr - sizeof(tpm_common_mpool_hdr_t));
-	
+
 	if (!hdr)
 		return NULL;
-		
+
 	ftr = (tpm_common_mpool_ftr_t *) ((uint8_t *) ptr + hdr->pool->data_size);
 
 	if (hdr->magic != TPM_COMMON_MPOOL_HDR_MAGIC) {
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c
index 75e6b8c..a911319 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c
@@ -109,7 +109,7 @@
 		pnc_range_id = TPM_PNC_IPV4_LEN;
 		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg);
 	} else {
-		/*pnc_range_id = TPM_PNC_IPV6_LEN; 
+		/*pnc_range_id = TPM_PNC_IPV6_LEN;
 		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg.pncIndex_cfg);*/
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "there is no length check for IPv6\n");
 		return ERR_GENERAL;
@@ -169,7 +169,7 @@
 	} else {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "there is no length check for IPv6\n");
 		return ERR_GENERAL;
-		/*pnc_range_id = TPM_PNC_IPV6_LEN; 
+		/*pnc_range_id = TPM_PNC_IPV6_LEN;
 		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg.pncIndex_cfg);*/
 	}
 
@@ -295,7 +295,7 @@
 
 	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
 
-	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TCP_FLAG, &nextphase_range_data);
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_TCP_FLAG, &nextphase_range_data);
 	IF_ERROR(int_ret_code);
 	ipv6_frag_type_lu = nextphase_range_data.pnc_range_conf.base_lu_id;
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c
index ea0a0a0..3098a69 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c
@@ -85,6 +85,7 @@
 #include "tpm_header.h"
 
 /* Local definitions */
+extern MV_STATUS mv_cust_set_tcont_state(uint32_t tcont, bool state);
 
 typedef tpm_error_code_t (*tpm_proc_common_int_del_func_t) (uint32_t, uint32_t);
 
@@ -143,12 +144,31 @@
 /* Bitmap of PNC port_ids */
 static uint32_t gmac_pnc_bm[3] = { TPM_BM_GMAC_0, TPM_BM_GMAC_1, TPM_BM_PMAC};
 
+tpm_hot_swap_acl_recovery_t tpm_hot_swap_acl_recovery[] = {
+	{TPM_API_MAC_LEARN,        tpm_acl_rcvr_func_mac_learn},
+	{TPM_API_DS_LOAD_BALANCE,  tpm_acl_rcvr_func_ds_load_balance},
+	{TPM_API_CPU_LOOPBACK,     tpm_acl_rcvr_func_cpu_loopback},
+	{TPM_API_L2_PRIM,          tpm_acl_rcvr_func_l2_prim},
+	{TPM_API_L3_TYPE,          tpm_acl_rcvr_func_l3_type},
+	{TPM_API_IPV4,             tpm_acl_rcvr_func_ipv4},
+	{TPM_API_IPV4_MC,          tpm_acl_rcvr_func_ipv4_mc},
+	{TPM_API_IPV6_GEN,         tpm_acl_rcvr_func_ipv6_gen},
+	{TPM_API_IPV6_DIP,         tpm_acl_rcvr_func_ipv6_dip},
+	{TPM_API_IPV6_MC,          tpm_acl_rcvr_func_ipv6_mc},
+	{TPM_API_IPV6_NH,          tpm_acl_rcvr_func_ipv6_nh},
+	{TPM_API_IPV6_L4,          tpm_acl_rcvr_func_ipv6_l4},
+	{TPM_API_CNM,              tpm_acl_rcvr_func_cnm},
+
+};
 
 
 static tpm_api_sup_param_val_t api_sup_param_val[] = {
 	/* tpm_pnc_api_num		Supported parse field bits
 		Supported parse flag bits
 		Forbidden actions */
+	{TPM_ADD_DS_LOAD_BALANCE_RULE,	TPM_DS_LOAD_BALNC_PARSE_BM_MASK,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_TAG2_MASK),
+		(0)},
 	{TPM_ADD_L2_PRIM_ACL_RULE,      TPM_L2_PARSE_BM_MASK,
 		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_TAG2_MASK),
 		(0)},
@@ -338,6 +358,7 @@
 	tpm_gmacs_enum_t gmac_i;
 	tpm_gmac_bm_t l_gmac_bm = 0;
 	tpm_db_gmac_func_t gmac_func;
+	tpm_init_gmac_conn_conf_t gmac_port_conf;
 
 	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
 		if (!tpm_db_gmac_valid(gmac_i))
@@ -351,22 +372,27 @@
 
 		/* LAN possiblilties  (Note: can be from both WAN or LAN) */
 
-		/* From UNI_$, but not Virtual_Port */
-		if (src_port == TPM_SRC_PORT_UNI_VIRT) {
-			if (GMAC_IS_UNI_LAN(gmac_func)) {
-				l_gmac_bm = gmac_pnc_bm[gmac_i];
-				break;
-			}
-
-			if (GMAC_IS_LAN(gmac_func))
-				l_gmac_bm = gmac_pnc_bm[gmac_i];
-		/* Any other UNI */
-		} else if (FROM_SPEC_UNI(src_port) && GMAC_IS_LAN(gmac_func)) {
-			l_gmac_bm = gmac_pnc_bm[gmac_i];
-			break;
-		/* Any remaining LAN option (UNI_ANY or WAN_OR_LAN) */
-		} else if (FROM_LAN(src_port) && (GMAC_IS_UNI_LAN(gmac_func) || GMAC_IS_LAN(gmac_func)))
+		/* From UNI_$, include UNI_virt Port */
+		if (FROM_SPEC_UNI(src_port) && GMAC_IS_LAN(gmac_func)) {
 			l_gmac_bm |= gmac_pnc_bm[gmac_i];
+			//break;
+		/* Any remaining LAN option (UNI_ANY or WAN_OR_LAN) */
+		} else if (FROM_LAN(src_port) && (GMAC_IS_UNI_LAN(gmac_func) || GMAC_IS_LAN(gmac_func))) {
+			if (GMAC_IS_UNI_LAN(gmac_func)) {
+				if (tpm_db_gmac_conn_conf_get(gmac_i, &gmac_port_conf)) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "gmac(%d) connection info get fail\n", gmac_i);
+					return(TPM_FAIL);
+				}
+				if (src_port == gmac_port_conf.port_src) {
+					l_gmac_bm |= gmac_pnc_bm[gmac_i];
+					break;
+				} else if (src_port == TPM_SRC_PORT_UNI_ANY) {
+					l_gmac_bm |= gmac_pnc_bm[gmac_i];
+				}
+			} else {
+				l_gmac_bm |= gmac_pnc_bm[gmac_i];
+			}
+		}
 	}
 
 	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "gmac_bm(0x%x)\n", l_gmac_bm);
@@ -520,25 +546,37 @@
 {
 	tpm_gmacs_enum_t gmac_i;
 	tpm_db_gmac_func_t gmac_func;
-	tpm_eth_complex_profile_t profile;
+	tpm_init_gmac_conn_conf_t gmac_port_conf;
 
 	if (gmac_port == NULL) {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid pointer-NULL \n");
 		return(ERR_GENERAL);
 	}
 
-	/* get board profile */
-	profile = tpm_db_eth_cmplx_profile_get();
-
 	(*gmac_port) = -1;
 	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
 		if (!tpm_db_gmac_valid(gmac_i))
 			continue;
 
 		tpm_db_gmac_func_get(gmac_i, &gmac_func);
-
-		if (((TRG_WAN(trg_port)) && GMAC_IS_WAN(gmac_func))
-		    || ((TRG_UNI(trg_port)) && ((!tpm_db_gmac1_lpbk_en_get()) ? GMAC_IS_LAN(gmac_func) : GMAC_IS_UNI_LAN(gmac_func)))) {
+		if (tpm_db_gmac_conn_conf_get(gmac_i, &gmac_port_conf)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "gmac(%d) connection info get fail\n", gmac_i);
+			return(TPM_FAIL);
+		}
+		/* TRG WAN */
+		if ((TRG_WAN(trg_port)) && GMAC_IS_WAN(gmac_func)) {
+			(*gmac_port) = gmac_i;
+			break;
+		/* TRG GMAC_UNI, such as MC lpk, dual gmac uni */
+		} else if (TRG_UNI(trg_port) && (GMAC_IS_UNI_LAN(gmac_func) || GMAC_IS_DS_UNI_LAN(gmac_func))) {
+			if ((gmac_port_conf.port_src != TPM_SRC_PORT_ILLEGAL) &&
+			    ((trg_port == (1 << (gmac_port_conf.port_src + TPM_TRG_UNI_OFFSET))) ||
+			     (trg_port == TPM_TRG_PORT_UNI_ANY))) {
+				(*gmac_port) = gmac_i;
+				break;
+			}
+		/* TRG UNI, such as KW2 */
+		} else if (TRG_UNI(trg_port) && GMAC_IS_LAN(gmac_func)) {
 			(*gmac_port) = gmac_i;
 			break;
 		}
@@ -590,23 +628,78 @@
 	return(l_gmac_bm);
 }
 
+int32_t tpm_proc_delete_mod(tpm_mod_owner_t owner, tpm_gmacs_enum_t gmac_port, uint32_t mod_entry)
+{
+	tpm_gmacs_enum_t  duplicate_gmac;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
+	int32_t ret_code;
+
+	ret_code = tpm_mod2_entry_del(owner, gmac_port, mod_entry);
+	IF_ERROR(ret_code);
+
+	/* when ds load balance on G0 and G1 is enabled, need to duplicate DS PMT on G0/1 */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	if (	(TPM_DS_MAC_BASED_TRUNK_DISABLED == ds_mac_based_trunk_enable)
+	     || ((gmac_port != TPM_ENUM_GMAC_0) && (gmac_port != TPM_ENUM_GMAC_1))) {
+		/* if this is US or DS_MAC_BASED_TRUNK is DISABLED, do nothing */
+		return(TPM_OK);
+	}
+
+	if (gmac_port == TPM_ENUM_GMAC_0)
+		duplicate_gmac = TPM_ENUM_GMAC_1;
+	else
+		duplicate_gmac = TPM_ENUM_GMAC_0;
+
+	ret_code = tpm_mod2_entry_del(owner, duplicate_gmac, mod_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
 int32_t tpm_proc_create_mod(tpm_pkt_action_t pkt_act, tpm_trg_port_type_t trg_port, tpm_pkt_mod_t *pkt_mod,
 			    tpm_pkt_mod_bm_t pkt_mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm, uint32_t *mod_entry,
 			    uint32_t *trg_gmac)
 {
 	int32_t ret_code;
+	tpm_gmacs_enum_t  duplicate_gmac;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	if (SET_MOD(pkt_act)) {
 		/* Currently supporting Vlan operation only */
 		/* Get dest. gmac */
-		tpm_proc_trg_port_gmac_map(trg_port, trg_gmac);
-		if (*trg_gmac == -1) {
-			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "pkt modification not possible on this target gmac(%d) \n",
-				     *trg_gmac);
-			return(ERR_ACTION_INVALID);
+		if (TPM_TRG_LOAD_BAL & trg_port) {
+			/* DS load balance, set trg port to G1 */
+			*trg_gmac = TPM_ENUM_GMAC_1;
+		} else {
+			tpm_proc_trg_port_gmac_map(trg_port, trg_gmac);
+			if (*trg_gmac == -1) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "pkt modification not possible on this target gmac(%d) \n",
+					     *trg_gmac);
+				return(ERR_ACTION_INVALID);
+			}
+		}
+		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, *trg_gmac, pkt_mod_bm, int_mod_bm, pkt_mod, mod_entry);
+		IF_ERROR(ret_code);
+
+		/* when ds load balance on G0 and G1 is enabled, need to duplicate DS PMT on G0/1 */
+		tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+		if (    (TPM_DS_MAC_BASED_TRUNK_DISABLED == ds_mac_based_trunk_enable)
+		     || (TRG_WAN(trg_port))) {
+		     /* if this is US or DS_MAC_BASED_TRUNK is DISABLED, do nothing */
+			return(TPM_OK);
 		}
 
-		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, *trg_gmac, pkt_mod_bm, int_mod_bm, pkt_mod, mod_entry);
+		if (*trg_gmac == TPM_ENUM_GMAC_0)
+			duplicate_gmac = TPM_ENUM_GMAC_1;
+		else if (*trg_gmac == TPM_ENUM_GMAC_1)
+			duplicate_gmac = TPM_ENUM_GMAC_0;
+		else {
+			TPM_OS_INFO(TPM_TPM_LOG_MOD, "target gmac(%d) invalid\n", *trg_gmac);
+			return(TPM_OK);
+		}
+
+		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, duplicate_gmac,
+						pkt_mod_bm, int_mod_bm, pkt_mod, mod_entry);
 		IF_ERROR(ret_code);
 	}
 	return(TPM_OK);
@@ -660,13 +753,21 @@
 
 int32_t tpm_proc_check_valid_target(tpm_dir_t dir,
 				    tpm_db_pon_type_t pon_type,
+				    tpm_src_port_type_t src_port,
 				    tpm_trg_port_type_t trg_port,
 				    uint8_t trg_queue,
-				    tpm_pkt_action_t pkt_act)
+				    tpm_pkt_action_t pkt_act,
+				    uint8_t ds_load_bal_valid)
 {
 
 	tpm_init_virt_uni_t virt_uni_info;
 	int32_t ret_code;
+	uint32_t rx_queue_valid, rx_queue_size;
+	tpm_gmac_bm_t gmac_bm;
+	tpm_gmacs_enum_t gmac;
+	uint32_t tx_queue_valid, tx_queue_size;
+	tpm_db_txq_owner_t tx_owner;
+	tpm_db_tx_mod_t tx_port;
 	tpm_gmacs_enum_t act_wan= tpm_db_active_wan_get();
 
 	/* Check Valid Target */
@@ -678,6 +779,20 @@
 			/* check target uni port valid or not */
 			ret_code = tpm_proc_check_dst_uni_port(trg_port);
 			IF_ERROR(ret_code);
+
+			/* check ds load balance trg */
+			if (trg_port & TPM_TRG_LOAD_BAL) {
+				if (!ds_load_bal_valid) {
+					/* TPM_TRG_LOAD_BAL should not be set */
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "TPM_TRG_LOAD_BAL should not be set\n");
+					return(ERR_FRWD_INVALID);
+				}
+				if (!tpm_db_ds_load_bal_en_get()) {
+					/* profile dose not support TPM_TRG_LOAD_BAL */
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "profile dose not support TPM_TRG_LOAD_BAL\n");
+					return(ERR_FRWD_INVALID);
+				}
+			}
 		} else {
 			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "* dir=%d, trg_port=%d, pon_type=%d *\r\n", dir, trg_port,
 				     pon_type);
@@ -704,11 +819,101 @@
 	}
 
 	/* Check Valid Queue */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
 	/* TODO - Check Queue depending on actual queues in target or in Rx */
 	if (SET_TARGET_QUEUE(pkt_act) && (trg_queue >= TPM_MAX_NUM_TX_QUEUE)) {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Out of Range\n");
 		return(ERR_FRWD_INVALID);
 	}
+	/* Check Rx queue valid */
+	if (SET_TARGET_PORT(pkt_act) && TO_CPU(trg_port) && SET_TARGET_QUEUE(pkt_act)) {
+		for (gmac = TPM_ENUM_GMAC_0; gmac < TPM_MAX_NUM_GMACS; gmac++) {
+			if (((gmac_bm & TPM_BM_GMAC_0) && (gmac == TPM_ENUM_GMAC_0)) ||
+			    ((gmac_bm & TPM_BM_GMAC_1) && (gmac == TPM_ENUM_GMAC_1)) ||
+			    ((gmac_bm & TPM_BM_PMAC) && (gmac == TPM_ENUM_PMAC))) {
+				/* Get Rx queue info */
+				ret_code = tpm_db_gmac_rx_q_conf_get(gmac, trg_queue, &rx_queue_valid, &rx_queue_size);
+				if (ret_code != TPM_DB_OK) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, " rx queue recvd ret_code(%d)\n", ret_code);
+					return(ERR_FRWD_INVALID);
+				}
+
+				/* Check queue valid state */
+				if (TPM_FALSE == rx_queue_valid) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Invalid\n");
+					return(ERR_FRWD_INVALID);
+				}
+
+				/* Check queue size */
+				if (0 == rx_queue_size) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Size is Zero\n");
+					return(ERR_FRWD_INVALID);
+				}
+			}
+		}
+	}
+
+	/* Check Tx queue valid */
+	if (SET_TARGET_PORT(pkt_act) && (!TO_CPU(trg_port)) && SET_TARGET_QUEUE(pkt_act)) {
+		tpm_proc_trg_port_gmac_map(trg_port, &gmac);
+		for (tx_port = TPM_TX_MOD_GMAC0; tx_port < TPM_MAX_NUM_TX_PORTS; tx_port++) {
+			if (((trg_port & TPM_TRG_TCONT_0) && (act_wan == TPM_ENUM_PMAC) && (tx_port == TPM_TX_MOD_PMAC_0)) ||
+			    ((trg_port & TPM_TRG_TCONT_0) && (act_wan == TPM_ENUM_GMAC_0) && (tx_port == TPM_TX_MOD_GMAC0)) ||
+			    ((trg_port & TPM_TRG_TCONT_0) && (act_wan == TPM_ENUM_GMAC_1) && (tx_port == TPM_TX_MOD_GMAC1)) ||
+			    ((trg_port & TPM_TRG_TCONT_1) && (tx_port == TPM_TX_MOD_PMAC_1)) ||
+			    ((trg_port & TPM_TRG_TCONT_2) && (tx_port == TPM_TX_MOD_PMAC_2)) ||
+			    ((trg_port & TPM_TRG_TCONT_3) && (tx_port == TPM_TX_MOD_PMAC_3)) ||
+			    ((trg_port & TPM_TRG_TCONT_4) && (tx_port == TPM_TX_MOD_PMAC_4)) ||
+			    ((trg_port & TPM_TRG_TCONT_5) && (tx_port == TPM_TX_MOD_PMAC_5)) ||
+			    ((trg_port & TPM_TRG_TCONT_6) && (tx_port == TPM_TX_MOD_PMAC_6)) ||
+			    ((trg_port & TPM_TRG_TCONT_7) && (tx_port == TPM_TX_MOD_PMAC_7)) ||
+			    ((trg_port & (TPM_TRG_UNI_0 |
+			    		  TPM_TRG_UNI_1 |
+			    		  TPM_TRG_UNI_2 |
+			    		  TPM_TRG_UNI_3 |
+			    		  TPM_TRG_UNI_4 |
+			    		  TPM_TRG_UNI_5 |
+			    		  TPM_TRG_UNI_6 |
+			    		  TPM_TRG_UNI_7 |
+			    		  TPM_TRG_UNI_VIRT |
+			    		  TPM_TRG_PORT_UNI_ANY)) && (tx_port == (tpm_db_tx_mod_t)gmac))) {
+				/* Get Tx queue info */
+				ret_code = tpm_db_gmac_tx_q_conf_get(tx_port,
+								     trg_queue,
+								     &tx_queue_valid,
+								     NULL,
+								     &tx_owner,
+								     NULL,
+								     &tx_queue_size,
+								     NULL);
+				if (ret_code != TPM_DB_OK) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, " tx queue recvd ret_code(%d)\n", ret_code);
+					return(ERR_FRWD_INVALID);
+				}
+
+				/* Check queue valid state */
+				if (TPM_FALSE == tx_queue_valid) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Invalid\n");
+					return(ERR_FRWD_INVALID);
+				}
+
+				/* Check queue owner */
+				if (((gmac_bm & TPM_BM_GMAC_0) && (tx_owner != TPM_Q_OWNER_GMAC0)) ||
+				    ((gmac_bm & TPM_BM_GMAC_1) && (tx_owner != TPM_Q_OWNER_GMAC1)) ||
+				    ((gmac_bm & TPM_BM_PMAC) && (tx_owner != TPM_Q_OWNER_PMAC))) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Owner Invalid, gmac_bm: [%d], tx_owner: [%d]\n",
+									gmac_bm, tx_owner);
+					return(ERR_FRWD_INVALID);
+				}
+
+				/* check queue size */
+				if (0 == tx_queue_size) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Size is Zero\n");
+					return(ERR_FRWD_INVALID);
+				}
+			}
+		}
+	}
 
 	return(TPM_OK);
 }
@@ -779,6 +984,47 @@
 	return(TPM_OK);
 }
 
+/* Get GMAC Lan UNI number and UNI port number */
+/*******************************************************************************
+* tpm_proc_gmaclanuni_uninum_get()
+*
+* DESCRIPTION:    The function Get GMAC Lan UNI number and UNI port number.
+*
+* INPUTS:
+* src_port         - None
+*
+* OUTPUTS:
+* gmac_is_uni_num  - number of GMAC which is LAN UNI
+* max_uni_port_num - number os UNI ports
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_gmaclanuni_uninum_get(uint32_t *gmac_is_uni_num, uint32_t *max_uni_port_num)
+{
+	tpm_db_gmac_func_t gmac_func;
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t temp1 = 0, temp2 = 0;
+
+	/* Cal number of GMAC LAN UNI */
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+		if (GMAC_IS_UNI_LAN(gmac_func))
+			temp1++;
+	}
+	/* Get Max UNI port number */
+	tpm_db_max_uni_port_nr_get(&temp2);
+
+	*gmac_is_uni_num = temp1;
+	*max_uni_port_num = temp2;
+
+	return (TPM_OK);
+}
+
 /*******************************************************************************
 * tpm_proc_src_port_check()
 *
@@ -804,6 +1050,7 @@
 	tpm_db_int_conn_t dummy_int_conn;
 	uint32_t dummy_switch_port;
 	tpm_init_virt_uni_t virt_uni_info;
+	uint32_t gmac_is_uni_num = 0, max_uni_port_num = 0;
 
 	/* Check Port exists */
 	if (src_port == TPM_SRC_PORT_WAN) {
@@ -824,9 +1071,17 @@
 			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Source UNI Port (%d) is not valid port \n", src_port);
 			return(TPM_FAIL);
 		}
-	} else if (src_port == TPM_SRC_PORT_UNI_ANY)
+	} else if (src_port == TPM_SRC_PORT_UNI_ANY) {
+		/* Check UNI_ANY is supported or not */
+		/* Get GMAC LAN_UNI and UNI ports number */
+		tpm_proc_gmaclanuni_uninum_get(&gmac_is_uni_num, &max_uni_port_num);
+		if (gmac_is_uni_num > TPM_SRC_PORT_UNI_1 ||
+		    (gmac_is_uni_num == TPM_SRC_PORT_UNI_1 && max_uni_port_num > TPM_SRC_PORT_UNI_1)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Src port UNI_ANY is not supported\n");
+			return(ERR_SRC_PORT_INVALID);
+		}
 		return(TPM_OK);
-	else if (src_port == TPM_SRC_PORT_UNI_VIRT) {
+	} else if (src_port == TPM_SRC_PORT_UNI_VIRT) {
 		tpm_db_virt_info_get(&virt_uni_info);
 		if (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled) {
 			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "UNI_VIRT is not enabled\n");
@@ -972,6 +1227,7 @@
 				tpm_pncl_sram_data_t *sram_data)
 {
 	uint32_t i;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	if (SET_TARGET_PORT(rule_action->pkt_act)) {
 		tpm_gmacs_enum_t act_wan= tpm_db_active_wan_get();
@@ -999,13 +1255,22 @@
 				return(TPM_FAIL);
 			}
 		} else if (TO_LAN(dir, pkt_frwd->trg_port)) {
-			tpm_trg_port_type_t pnc_target;
+			tpm_pnc_trg_t pnc_target;
 
-			if (tpm_db_to_lan_gmac_get(pkt_frwd->trg_port, &pnc_target) != TPM_DB_OK){
+			/* when ds load balance on G0 and G1 is enabled, trgt port can only
+			 * be set in the first range TPM_DS_MAC_BASED_TRUNKING.
+			 */
+			tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+			if (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable) {
+				sram_data->sram_updt_bm &= (~TPM_PNCL_SET_TXP);
+ 			} else if (TPM_TRG_LOAD_BAL & pkt_frwd->trg_port) {
+				/* DS load balance, set trg port to G1 */
+				pnc_target = TPM_PNC_TRG_GMAC1;
+			} else if (tpm_db_to_lan_gmac_get(pkt_frwd->trg_port, &pnc_target) != TPM_DB_OK){
 				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_db_to_lan_gmac_get failed trg_port 0x%x\n",
 					     pkt_frwd->trg_port);
 				return(TPM_FAIL);
-       		}
+       			}
 			sram_data->flow_id_sub.pnc_target = pnc_target;
 		} else if (TO_CPU(pkt_frwd->trg_port)) {
 			sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
@@ -1135,6 +1400,41 @@
 	return(rc_code);
 }
 
+int32_t tpm_proc_check_all_api_busy(void)
+{
+	uint32_t  db_ret_code;
+	int32_t rc_code = TPM_RC_OK;
+	int32_t rule_num;
+	int32_t rule_num_max;
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_api_type_t api_type;
+
+	for (api_type = TPM_API_MAC_LEARN; api_type < TPM_MAX_API_TYPES; api_type++) {
+
+		/* Get api_section, range_Id, range configuration, to get range type */
+		db_ret_code = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+		IF_ERROR(db_ret_code);
+		db_ret_code = tpm_db_api_section_main_pnc_get(api_section, &range_id);
+		if (TPM_DB_OK != db_ret_code)
+			continue;
+		db_ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+		IF_ERROR(db_ret_code);
+
+		if (rangConf.range_type == TPM_RANGE_TYPE_ACL)
+			rule_num_max = 1;
+		else
+			rule_num_max = TPM_MAX_PARALLEL_API_CALLS;
+
+		for (rule_num = 0; rule_num < rule_num_max; rule_num++) {
+			rc_code = tpm_proc_check_api_busy(api_type, rule_num);
+				IF_ERROR(rc_code);
+		}
+	}
+
+	return(TPM_OK);
+}
 
 int32_t tpm_proc_api_busy_done(tpm_api_type_t api_type, uint32_t rule_num)
 {
@@ -1151,6 +1451,42 @@
 	return(rc_code);
 }
 
+int32_t tpm_proc_all_api_busy_done(void)
+{
+	uint32_t  db_ret_code;
+	int32_t rc_code = TPM_RC_OK;
+	int32_t rule_num;
+	int32_t rule_num_max;
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_api_type_t api_type;
+
+	for (api_type = TPM_API_MAC_LEARN; api_type < TPM_MAX_API_TYPES; api_type++) {
+
+		/* Get api_section, range_Id, range configuration, to get range type */
+		db_ret_code = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+		IF_ERROR(db_ret_code);
+		db_ret_code = tpm_db_api_section_main_pnc_get(api_section, &range_id);
+		if (TPM_DB_OK != db_ret_code)
+			continue;
+		db_ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+		IF_ERROR(db_ret_code);
+
+		if (rangConf.range_type == TPM_RANGE_TYPE_ACL)
+			rule_num_max = 1;
+		else
+			rule_num_max = TPM_MAX_PARALLEL_API_CALLS;
+
+		for (rule_num = 0; rule_num < rule_num_max; rule_num++) {
+			rc_code = tpm_proc_api_busy_done(api_type, rule_num);
+			IF_ERROR(rc_code);
+		}
+	}
+
+	return(TPM_OK);
+}
+
 
 
 int32_t tpm_proc_parse_flag_ai_tcam_build(tpm_ai_vectors_t *ai_fields,
@@ -1281,6 +1617,11 @@
 		*ai_mask |= TPM_AI_SPLIT_MOD_MASK;
 	}
 
+	if (parse_int_flags & TPM_PARSE_FLAG_DNRT_DS_TRUNK) {
+		*ai_data &= ~(TPM_AI_DNRT_DS_TRUNK_MASK);
+		*ai_mask |= TPM_AI_DNRT_DS_TRUNK_MASK;
+	}
+
 	/*BIT_4 */
 	if (parse_int_flags & TPM_PARSE_FLAG_UNI_PORT_PARSE) {
 		if (ai_fields == NULL) {
@@ -1360,6 +1701,10 @@
 		*ai_data &= ~(TPM_AI_DNRT_MASK);
 		*ai_mask |= TPM_AI_DNRT_MASK;
 	}
+	if (int_pkt_action & TPM_ACTION_UNSET_DNRT_DS_TRUNK) {
+		*ai_data &= ~(TPM_AI_DNRT_DS_TRUNK_MASK);
+		*ai_mask |= TPM_AI_DNRT_DS_TRUNK_MASK;
+	}
 
 	if (int_pkt_action & TPM_ACTION_UNSET_UNI_PORT) {
 		*ai_data &= ~(TPM_AI_UNI_MASK);
@@ -1556,6 +1901,8 @@
 *******************************************************************************/
 int32_t tpm_proc_virt_uni_trg_port_validation(tpm_trg_port_type_t trg_port)
 {
+	/* unset TPM_TRG_LOAD_BAL first, since it can be mixed with UNI port */
+	trg_port &= (~TPM_TRG_LOAD_BAL);
 
 	if ((trg_port == TPM_TRG_UNI_0) ||
 	    (trg_port == TPM_TRG_UNI_1) ||
@@ -1779,7 +2126,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_bm */
@@ -1927,6 +2275,105 @@
 
 	return(TPM_RC_OK);
 }
+/*******************************************************************************
+* tpm_proc_add_ds_load_balance_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_ds_load_balance_acl_rule params.
+*
+* INPUTS:
+* owner_id         - See tpm_proc_add_ds_load_balance_acl_rule
+* rule_num         - See tpm_proc_add_ds_load_balance_acl_rule
+* parse_rule_bm    - See tpm_proc_add_ds_load_balance_acl_rule
+* l2_key           - See tpm_proc_add_ds_load_balance_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ds_load_balance_check(uint32_t owner_id,
+						uint32_t rule_num,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_l2_acl_key_t *l2_key)
+{
+	int32_t ret_code;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pnc_range_conf_t rangConf;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Get Range_Id, rang configuration, to get range type */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_DS_LOAD_BALANCE_ACL, &range_id);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Check necessary pointers are valid */
+	if ((l2_key == NULL) && (parse_rule_bm != 0)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parsing requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+	IF_ERROR(ret_code);
+
+	/* Check parse_rule_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_DS_LOAD_BALANCE_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flag_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_DS_LOAD_BALANCE_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm(0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check Vlan Tag TPID mask */
+	if (parse_rule_bm & (TPM_L2_PARSE_TWO_VLAN_TAG | TPM_L2_PARSE_ONE_VLAN_TAG)) {
+		if ((l2_key->vlan1.tpid_mask != 0) && (l2_key->vlan1.tpid_mask != 0xffff)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid vlan1 tpid mask(0x%x) \n", l2_key->vlan1.tpid_mask);
+			return(ERR_L2_KEY_INVALID);
+		}
+
+		if (parse_rule_bm & TPM_L2_PARSE_ONE_VLAN_TAG) {
+			if ((l2_key->vlan2.tpid_mask != 0) && (l2_key->vlan2.tpid_mask != 0xffff)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid vlan2 tpid mask(0x%x) \n", l2_key->vlan2.tpid_mask);
+				return(ERR_L2_KEY_INVALID);
+			}
+		}
+	}
+
+	/* Cannot do Double Vlan Tag with looking into PPPoE (up to 24Bytes) with MH */
+	if ((parse_rule_bm & TPM_L2_PARSE_TWO_VLAN_TAG) &&
+	    ((parse_rule_bm & TPM_L2_PARSE_PPP_PROT) || (parse_rule_bm & TPM_L2_PARSE_PPPOE_SES))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parse map of Double Vlan Tag + PPPoE not supported\n");
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Cannot do Single or Double Vlan Tag with checking   PPP protocol (up to 24Bytes) with MH */
+	if (((parse_rule_bm & TPM_L2_PARSE_TWO_VLAN_TAG) || (parse_rule_bm & TPM_L2_PARSE_ONE_VLAN_TAG))
+	    && (parse_rule_bm & TPM_L2_PARSE_PPP_PROT)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parse map of Single Vlan Tag + PPPoE proto not supported\n");
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_DS_LOAD_BALANCE, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_DS_LOAD_BALANCE_ACL, rangConf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	return(TPM_RC_OK);
+}
+
 
 tpm_error_code_t tpm_proc_add_ipv6_gen_check(uint32_t owner_id,
 					       tpm_src_port_type_t src_port,
@@ -1971,7 +2418,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_bm */
@@ -2074,7 +2522,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_rule_bm */
@@ -2117,7 +2566,7 @@
 	}
 
 	/* Check forwarding rule, currently only support STAGE_DONE */
-	if (rule_action->next_phase != STAGE_IPv6_NH && rule_action->next_phase != STAGE_DONE) {
+	if (rule_action->next_phase != STAGE_DONE) {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
 		return(ERR_NEXT_PHASE_INVALID);
 	}
@@ -2176,7 +2625,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_rule_bm */
@@ -2254,6 +2704,7 @@
 	tpm_db_pnc_range_t range_data;
 	tpm_pkt_mod_t pkt_mod;
 	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	/* Check TPM was successfully initialized */
 	if (!tpm_db_init_done_get())
@@ -2345,6 +2796,15 @@
 		return(ERR_ACTION_INVALID);
 	}
 
+	/* when ds load balance on G0 and G1 is enabled, no 2 NH rule can be added */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	if (	(TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable)
+	     && (NH_ITER_1 == nh_iter)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "when ds load balance on G0 and G1 is enabled, "
+			"no 2 NH rule can be added\n");
+		return(ERR_FEAT_UNSUPPORT);
+	}
+
 	return(TPM_RC_OK);
 }
 
@@ -2407,7 +2867,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_TRUE);
 	IF_ERROR(ret_code);
 
 	/* Check Packet Modification */
@@ -2565,7 +3026,8 @@
 	*lu_id = range_conf.base_lu_id;
 	start_offset->range_id = range_id;
 
-	if (range_id == TPM_PNC_L2_MAIN || range_id == TPM_PNC_MAC_LEARN) {
+	if (    range_id == TPM_PNC_L2_MAIN || range_id == TPM_PNC_MAC_LEARN
+	     || range_id == TPM_PNC_DS_LOAD_BALANCE) {
 		start_offset->offset_base = TPM_PNCL_ZERO_OFFSET;
 		start_offset->offset_sub.subf = TPM_L2_PARSE_MH;
 	} else if (range_id == TPM_PNC_ETH_TYPE) {
@@ -2683,6 +3145,9 @@
 	if (rule_action->pkt_act & TPM_ACTION_SPEC_MC_VID)
 		return false;
 
+	if (!SET_MOD(rule_action->pkt_act))
+		return false;
+
 	if (STAGE_DONE == rule_action->next_phase)
 		return false;
 
@@ -2842,7 +3307,7 @@
 	}
 
 	/* Unset DNRT bit (Do not Repeat Tags Phase), the bit is leftover from previous hardcoded Vlan_tags phase */
-	int_pkt_act |= TPM_ACTION_UNSET_DNRT;
+	int_pkt_act |= (TPM_ACTION_UNSET_DNRT | TPM_ACTION_UNSET_DNRT_DS_TRUNK);
 
 	/* Set UNI Port */
 	if (FROM_SPEC_UNI(src_port)) {
@@ -2917,6 +3382,136 @@
 }
 
 /*******************************************************************************
+* tpm_proc_ds_load_balance_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* rule_num          - API rule number
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+*
+* OUTPUTS:
+* tcam_data         - Logical TCAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ds_load_balance_tcam_build(uint32_t rule_num,
+				       tpm_l2_acl_key_t *l2_key,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_parse_flags_t parse_flags_bm,
+				       tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	int32_t ret_code;
+	long long parse_int_flags = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) parse_rule_bm(%x)  \n", rule_num, parse_rule_bm);
+
+	/* L2 Parsing, according to bm in param */
+	tcam_data->l2_parse_bm = parse_rule_bm;
+
+	/* do not repeat this section again */
+	parse_int_flags |= TPM_PARSE_FLAG_DNRT_DS_TRUNK;
+
+	tpm_proc_parse_flag_ai_tcam_build(NULL, parse_flags_bm, parse_int_flags,
+				&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/*Parse MH for specific src_port or for gemport_parse request */
+	if (parse_rule_bm & TPM_L2_PARSE_GEMPORT)
+		tcam_data->l2_parse_bm |= TPM_L2_PARSE_MH;
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = TPM_SRC_PORT_WAN;
+	if (l2_key)
+		memcpy(&(tcam_data->pkt_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_DS_LOAD_BALANCE, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ds_load_balance_sram_build()
+*
+* DESCRIPTION:     Function builds a logical SRAM entry from the API data
+*
+* INPUTS:
+* rule_num          - API rule number
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+*
+* OUTPUTS:
+* sram_data         - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ds_load_balance_sram_build(uint32_t rule_num,
+				       tpm_pncl_sram_data_t *sram_data,
+				       tpm_l2_acl_key_t *l2_key,
+				       tpm_ds_load_balance_tgrt_t tgrt_port)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t cpu_rx_queue = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) \n", rule_num);
+
+	sram_data->add_info_data |= (1 << TPM_AI_DNRT_DS_TRUNK_BIT_OFF);
+	sram_data->add_info_mask |= TPM_AI_DNRT_DS_TRUNK_MASK;
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_L2_MAIN, &range_conf);
+	IF_ERROR(ret_code);
+
+	sram_data->next_lu_id = range_conf.base_lu_id;
+	sram_data->next_lu_off_reg = TPM_PNC_LU_REG0;
+
+	/* For Target set PNC TXP, GemPort */
+	sram_data->sram_updt_bm = TPM_PNCL_SET_TXP;
+	sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	if (TPM_DS_TGRT_G0 == tgrt_port)
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC0;
+	else if (TPM_DS_TGRT_G1 == tgrt_port)
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC1;
+	else {
+		/* Set lookup done and target */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+		sram_data->pnc_queue = cpu_rx_queue;
+
+		/* Set L3, L4 to OTHER */
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+		sram_data->l3_type = TPM_PNCL_L3_OTHER;
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
 * tpm_proc_ipv4_tcam_build()
 *
 * DESCRIPTION:     Function builds a logical TCAM entry from the API data
@@ -3169,7 +3764,7 @@
 		l4_parse = ((ipv4_parse_bm & TPM_PARSE_L4_SRC) || (ipv4_parse_bm & TPM_PARSE_L4_DST));
 		if (l4_parse && (sram_data->l4_type == TPM_PNCL_L4_TCP)) {
 			sram_data->next_lu_off_reg = TPM_PNC_LU_REG1;
-			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TCP_FLAG, &range_conf);
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_TCP_FLAG, &range_conf);
 			IF_ERROR(ret_code);
 		}
 		/* For any other NAPT/ROUTE, check TTL */
@@ -4313,7 +4908,7 @@
 
 	/* Check whether CPU loopback entry number exceed the Max value */
 	lpbk_num = tpm_proc_get_cpu_lpbk_entry_num();
-	if (lpbk_num > TPM_MAX_CPU_LOOPBACK_ENTRY) {
+	if (lpbk_num >= TPM_MAX_CPU_LOOPBACK_ENTRY) {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]:(%d) Exceed MAX entry number\r\n", __func__, __LINE__,
 			     lpbk_num);
 		return ERR_GENERAL;
@@ -4490,9 +5085,9 @@
 {
 	tpm_error_code_t ret_code;
 	int32_t int_ret_code;
-	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t pnc_entry = 0, mod_entry = 0, mod_entry_tmp = 0, api_rng_entries = 0;
 	uint32_t l_rule_idx = 0, bi_dir = 0, update_sram_only = 0;
-	tpm_gmacs_enum_t trg_gmac;
+	tpm_gmacs_enum_t trg_gmac, duplicate_gmac;
 	tpm_dir_t dir = 0;
 	tpm_pnc_ranges_t range_id = 0;
 	tpm_db_pon_type_t pon_type = 0;
@@ -4505,6 +5100,7 @@
 	tpm_db_pnc_range_t range_data;
 	tpm_db_pnc_range_conf_t rangConf;
 	tpm_api_lu_conf_t lu_conf;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	/* Set Structs to zero */
 	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
@@ -4570,15 +5166,15 @@
 		}
 	}
 
-	if (!update_sram_only) {
-		if (SET_MOD(rule_action->pkt_act)) {
-			if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
-				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
-				return(ERR_MOD_INVALID);
-			} else if (trg_gmac == TPM_INVALID_GMAC) {
-				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
-				return(ERR_MOD_INVALID);
-			}
+	if (    (!update_sram_only)
+	     && (SET_MOD(rule_action->pkt_act))) {
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
 		}
 
 		/* if split mod is enable, add split rule if possible*/
@@ -4592,13 +5188,13 @@
 				TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to add pmt split mod stage-1\n");
 				return(TPM_FAIL);
 			}
-			int_ret_code = tpm_db_mod2_split_mod_get_vlan_index(trg_gmac, pkt_mod, &mod_entry);
+			int_ret_code = tpm_db_mod2_split_mod_get_vlan_index(trg_gmac, pkt_mod, &mod_entry_tmp);
 			if (TPM_DB_OK != int_ret_code) {
 				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-1, failed to get pmt entry\n");
 				return ERR_MOD_INVALID;
 			}
 
-			mod_entry *= 16;
+			mod_entry = mod_entry_tmp * 16;
 
 			/* VLANOP_EXT_TAG_MOD_INS mod insert VLAN p_bit*/
 			if (VLANOP_EXT_TAG_MOD_INS == pkt_mod->vlan_mod.vlan_op) {
@@ -4610,6 +5206,28 @@
 			}
 
 			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+
+			/* when ds load balance on G0 and G1 is enabled, need to duplicate DS PMT on G0/1 */
+			tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+			if (    (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable)
+			     && (TPM_ENUM_GMAC_0 == trg_gmac || TPM_ENUM_GMAC_1 == trg_gmac)) {
+
+				/* if this is DS and DS_MAC_BASED_TRUNK is ENABLED */
+				if (trg_gmac == TPM_ENUM_GMAC_0)
+					duplicate_gmac = TPM_ENUM_GMAC_1;
+				else
+					duplicate_gmac = TPM_ENUM_GMAC_0;
+
+				ret_code = tpm_mod2_split_mod_create_l2_pmts(duplicate_gmac, pkt_mod, false);
+				if (TPM_RC_OK != ret_code)
+				{
+					TPM_OS_ERROR(TPM_MODZ2_HM_MOD,
+						"failed to add pmt split mod stage-1 for duplicate GMAC\n");
+					tpm_mod2_split_mod_try_pmt_entry_del(TPM_L2_PRIM_ACL, trg_gmac, mod_entry_tmp);
+					return(TPM_FAIL);
+				}
+
+			}
 		} else if((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
 							(TPM_VLAN_MOD == pkt_mod_bm) &&
 							(VLANOP_NOOP == pkt_mod->vlan_mod.vlan_op) &&
@@ -4729,6 +5347,171 @@
 	return(TPM_RC_OK);
 }
 
+
+/*******************************************************************************
+* tpm_proc_add_ds_load_balance_acl_rule()
+*
+* DESCRIPTION:    Main function for adding DS load balance API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ds_load_balance_acl_rule(uint32_t owner_id,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l2_acl_key_t *l2_key,
+					       tpm_ds_load_balance_tgrt_t tgrt_port)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	uint32_t bi_dir;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_api_lu_conf_t lu_conf;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d), rule_num(%d)\n", owner_id, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ds_load_balance_check(owner_id, rule_num, parse_rule_bm, parse_flags_bm, l2_key);
+	IF_ERROR(ret_code);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_DS_LOAD_BALANCE_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Only do it in table mode */
+	if (TPM_RANGE_TYPE_TABLE == rangConf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_DS_LOAD_BALANCE_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) , rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ds_load_balance_acl_rule(owner_id, rule_num, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		} else {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) , rule_num(%d) is a new entry\n", owner_id, rule_num);
+		}
+	}
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ds_load_balance_tcam_build(rule_num, l2_key,
+				parse_rule_bm, parse_flags_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ds_load_balance_sram_build(rule_num, &(pnc_data.pncl_sram), l2_key, tgrt_port);
+	IF_ERROR(int_ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_DS_LOAD_BALANCE_ACL, rule_num, &pnc_data,
+					&pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+	/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_DS_LOAD_BALANCE_ACL, rule_num, 0,
+						&pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	/* Set PNC API data */
+	api_data.l2_prim_key.parse_rule_bm = parse_rule_bm;
+	if (l2_key)
+		memcpy(&(api_data.l2_prim_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			int_ret_code =
+			tpm_proc_api_entry_rulenum_inc(TPM_DS_LOAD_BALANCE_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_DS_LOAD_BALANCE_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	/* Set aging counter group nunmber and msk */
+	int_ret_code = tpm_db_pnc_get_lu_conf(TPM_PNC_DS_LOAD_BALANCE, &lu_conf);
+	IF_ERROR(int_ret_code);
+	tpm_tcam_set_lu_mask(pnc_entry, (int32_t) lu_conf.lu_mask);
+	tpm_tcam_set_cntr_group(pnc_entry, (int32_t) lu_conf.cntr_grp);
+
+	return(TPM_RC_OK);
+}
+
+
+/*******************************************************************************
+* tpm_proc_del_ds_load_balance_acl_rule()
+*
+* DESCRIPTION:    Main function for deleting DS load balance API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_ds_load_balance_acl_rule(uint32_t owner_id, uint32_t rule_idx, uint32_t ext_call)
+{
+
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_DS_LOAD_BALANCE_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
 tpm_error_code_t tpm_proc_pnc_create(tpm_pnc_ranges_t range_id, uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data)
 {
 
@@ -4900,7 +5683,7 @@
 	pnc_data.pncl_sram.add_info_data = 1 << TPM_AI_DNRT_BIT_OFF;
 	pnc_data.pncl_sram.add_info_mask = TPM_AI_DNRT_MASK;
 	/* Set SINGLE_TAG AI filter */
-	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG2_BIT_OFF;
+	pnc_data.pncl_sram.add_info_data &= (~TPM_AI_TAG2_MASK);
 	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG2_MASK;
 	pnc_data.pncl_sram.add_info_data |= 1 << TPM_AI_TAG1_BIT_OFF;
 	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG1_MASK;
@@ -4938,9 +5721,9 @@
 	pnc_data.pncl_sram.add_info_data = 1 << TPM_AI_DNRT_BIT_OFF;
 	pnc_data.pncl_sram.add_info_mask = TPM_AI_DNRT_MASK;
 	/* Set ZERO_TAG AI filter */
-	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG2_BIT_OFF;
+	pnc_data.pncl_sram.add_info_data &= (~TPM_AI_TAG2_MASK);
 	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG2_MASK;
-	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG1_BIT_OFF;
+	pnc_data.pncl_sram.add_info_data &= (~TPM_AI_TAG1_MASK);
 	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG1_MASK;
 
 	/* Do NOT set VLAN Result_Info bit */
@@ -5249,11 +6032,12 @@
 }
 
 /*******************************************************************************
-* tpm_proc_tcp_flag_init()
+* tpm_proc_tcp_flag_pnc_entry_create()
 *
 * DESCRIPTION:
 *
 * INPUTS:
+* ip_ver      - IP version, IPV4 or IPV6
 *
 * RETURNS:
 * On success, the function returns TPM_RC_OK. On error different types are returned
@@ -5263,15 +6047,16 @@
 * It is APIs caller responsibility to maintain the correct number of each rule.
 *
 *******************************************************************************/
-tpm_error_code_t tpm_proc_tcp_flag_init(void)
+tpm_error_code_t tpm_proc_tcp_flag_pnc_entry_create(tpm_ip_ver_t ip_ver)
 {
 	int32_t int_ret_code;
-	uint32_t free_entries, tcp_flag_lu, ttl_lu, pnc_entry;
+	uint32_t free_entries, tcp_flag_lu, ttl_lu = 0, pnc_entry;
 	int32_t cpu_rx_queue;
 
 	tpm_pncl_pnc_full_t pnc_data;
 	tpm_pncl_offset_t start_offset;
 	tpm_db_pnc_range_t range_data;
+	tpm_pnc_ranges_t   range_id;
 
 	/* Set Structs to zero */
 	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
@@ -5283,16 +6068,21 @@
 	/* Get default CPU Rx queue */
 	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
 
-	/* Get Next Range TTL Info */
-	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TTL, &range_data);
-	if (int_ret_code != TPM_OK) {
-		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " To create TCP Flag range, TPM_PNC_TTL range must exist \n");
-		return(int_ret_code);
-	}
-	ttl_lu = range_data.pnc_range_conf.base_lu_id;
+	if (TPM_IP_VER_4 == ip_ver) {
+		range_id = TPM_PNC_IPV4_TCP_FLAG;
+
+		/* Get Next Range TTL Info, only for IPv4 */
+		int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TTL, &range_data);
+		if (int_ret_code != TPM_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " To create TCP Flag range, TPM_PNC_TTL range must exist \n");
+			return(int_ret_code);
+		}
+		ttl_lu = range_data.pnc_range_conf.base_lu_id;
+	} else
+		range_id = TPM_PNC_IPV6_TCP_FLAG;
 
 	/* Get TCP_FLAG Range Info */
-	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TCP_FLAG, &range_data);
+	int_ret_code = tpm_db_pnc_rng_get(range_id, &range_data);
 	IF_ERROR(int_ret_code);
 	tcp_flag_lu = range_data.pnc_range_conf.base_lu_id;
 
@@ -5303,11 +6093,16 @@
 	pnc_data.pncl_tcam.start_offset.offset_sub.tcp_subf = TPM_PARSE_L4_SRC;
 
 	/* Set common SRAM params */
-	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_TCP_OFFSET;
-	pnc_data.pncl_sram.next_offset.offset_sub.tcp_subf = TPM_PARSE_TCPFLAGS;
+	if (TPM_IP_VER_4 == ip_ver) {
+		pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_TCP_OFFSET;
+		pnc_data.pncl_sram.next_offset.offset_sub.tcp_subf = TPM_PARSE_TCPFLAGS;
+		pnc_data.pncl_sram.next_lu_id = ttl_lu;
+		pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0;
+	} else {
+		pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD;
+	}
+
 	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
-	pnc_data.pncl_sram.next_lu_id = ttl_lu;
-	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0;
 	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
 
 	/* Get pnc_range tcam_start_entry, and number of free entries */
@@ -5318,25 +6113,32 @@
 	/* Create FIN FLAG=1 */
 	/*******************/
 	NO_FREE_ENTRIES();
+
 	/* Build PnC Entry */
 	/* Double check - only check packets that are MTM */
 	pnc_data.pncl_tcam.add_info_data |= (1 << TPM_AI_MTM_BIT_OFF);
 	pnc_data.pncl_tcam.add_info_mask |= TPM_AI_MTM_MASK;
+	if (TPM_IP_VER_6 == ip_ver) {
+		pnc_data.pncl_tcam.add_info_data &= ~(TPM_AI_L4P_MASK);
+		pnc_data.pncl_tcam.add_info_mask |= TPM_AI_L4P_MASK;
+	}
 
 	pnc_data.pncl_tcam.tcp_parse_bm = TPM_PARSE_TCPFLAGS;
 	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags = TPM_TCP_FIN;
 	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags_mask = TPM_TCP_FIN;
 
 	/* Build SRAM Entry */
-	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP;
+	pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_TXP;
 	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
 
-	/* Signal the packet is going to CPU */
-	pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
-	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+	if (TPM_IP_VER_4 == ip_ver) {
+		/* Signal the packet is going to CPU */
+		pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+		pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+	}
 
 	/* Create Entry in PnC */
-	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	int_ret_code = tpm_proc_pnc_create(range_id, pnc_entry, &pnc_data);
 	IF_ERROR(int_ret_code);
 	free_entries--;
 	pnc_entry++;
@@ -5350,11 +6152,15 @@
 	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags_mask = TPM_TCP_RES;
 
 	/* Create Entry in PnC */
-	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	int_ret_code = tpm_proc_pnc_create(range_id, pnc_entry, &pnc_data);
 	IF_ERROR(int_ret_code);
 	free_entries--;
 	pnc_entry++;
 
+	if (TPM_IP_VER_6 == ip_ver) {
+		/* no default rule for IPv6 */
+		return(TPM_RC_OK);
+	}
 	/***************/
 	/* All Others  */
 	/***************/
@@ -5372,7 +6178,7 @@
 	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
 
 	/* Create Entry in PnC */
-	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	int_ret_code = tpm_proc_pnc_create(range_id, pnc_entry, &pnc_data);
 	IF_ERROR(int_ret_code);
 	free_entries--;
 	pnc_entry++;
@@ -5380,6 +6186,36 @@
 }
 
 /*******************************************************************************
+* tpm_proc_tcp_flag_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_tcp_flag_init(void)
+{
+	int32_t int_ret_code;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_tcp_flag_pnc_entry_create(TPM_IP_VER_4);
+	IF_ERROR(int_ret_code);
+
+	int_ret_code = tpm_proc_tcp_flag_pnc_entry_create(TPM_IP_VER_6);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+
+/*******************************************************************************
 * tpm_proc_virt_uni_init()
 *
 * DESCRIPTION:
@@ -5530,6 +6366,80 @@
 
 	return(TPM_RC_OK);
 }
+/*******************************************************************************
+* tpm_proc_ds_load_balance_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_ds_load_balance_init(void)
+{
+	int32_t ret_code;
+	tpm_pnc_all_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data, nextphase_range_data;
+	uint32_t pnc_entry;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pnc_all_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&nextphase_range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get Range data */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_DS_LOAD_BALANCE, &range_data);
+	IF_ERROR(ret_code);
+
+	/* Get Next Range data */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_L2_MAIN, &nextphase_range_data);
+	IF_ERROR(ret_code);
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	pnc_entry = range_data.pnc_range_conf.range_end;
+
+	/* Set common TCAM params */
+	pnc_data.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.tcam_entry.port_ids = TPM_BM_PMAC;
+
+	/* Set common SRAM params */
+	pnc_data.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.sram_entry.next_lu_id = nextphase_range_data.pnc_range_conf.base_lu_id;
+
+	/* do not repeat this section again */
+	pnc_data.tcam_entry.add_info_data = 0;
+	pnc_data.tcam_entry.add_info_mask = TPM_AI_DNRT_DS_TRUNK_MASK;
+
+	/* Packet forwarded to GMAC0 */
+	pnc_data.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+	pnc_data.sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_data.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC0 << TPM_TXP_FL_SHIFT);
+
+	pnc_data.sram_entry.add_info_data |= (1 << TPM_AI_DNRT_DS_TRUNK_BIT_OFF);
+	pnc_data.sram_entry.add_info_mask |= TPM_AI_DNRT_DS_TRUNK_MASK;
+
+	/* create default rule to frwd all DS packets to GMAC0 */
+	ret_code = tpm_pnc_set(pnc_entry, 0, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(pnc_entry, &pnc_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_DS_LOAD_BALANCE);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
 
 /*******************************************************************************
 * tpm_proc_ipv4_ttl_init()
@@ -5810,7 +6720,7 @@
 		ret_code = tpm_mod2_split_mod_try_pmt_entry_del(api_section, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
 		if (TPM_OK != ret_code) {
 			/* this is not split mod entry, remove it */
-			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
+			ret_code = tpm_proc_delete_mod(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
 		}
 	}
 	IF_ERROR(ret_code);
@@ -5967,7 +6877,8 @@
 		}
 	}
 
-	if (!update_sram_only) {
+	if (    (!update_sram_only)
+	     && (SET_MOD(rule_action->pkt_act))) {
 		/* if split mod stage-2 */
 		if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
 			VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
@@ -6170,6 +7081,7 @@
 	uint32_t dst_port;
 	tpm_src_port_type_t src_port;
 	tpm_init_virt_uni_t virt_uni_info;
+	uint32_t gmac_is_uni_num, max_uni_port_num;
 
 	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "dest_port_bm(0x%x)\n", dest_port_bm);
 
@@ -6194,6 +7106,26 @@
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "TPM_TRG_UNI_VIRT is not enabled\n");
 		return ERR_MC_DST_PORT_INVALID;
 	}
+	/* Get GMAC LAN_UNI and UNI ports number */
+	tpm_proc_gmaclanuni_uninum_get(&gmac_is_uni_num, &max_uni_port_num);
+
+	/* check UNI_ANY */
+	if (dest_port_bm & TPM_TRG_PORT_UNI_ANY) {
+		/* Check UNI_ANY is supported or not */
+		if (gmac_is_uni_num > 1 ||
+		    (gmac_is_uni_num == 1 && max_uni_port_num > 1)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "dest_port UNI_ANY is not supported\n");
+			return ERR_MC_DST_PORT_INVALID;
+		}
+	}
+
+	/* Check multi des port  in bm */
+	if (dest_port_bm > TPM_TRG_UNI_1) {
+		if (gmac_is_uni_num > 1) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "dest_port bit map combine is not supported\n");
+			return ERR_MC_DST_PORT_INVALID;
+		}
+	}
 
 	return TPM_RC_OK;
 }
@@ -6219,16 +7151,18 @@
 * COMMENTS:
 *
 *******************************************************************************/
-tpm_error_code_t tpm_proc_add_ipv4_mc_check(uint32_t owner_id,
+tpm_error_code_t tpm_proc_add_ipvx_mc_check(uint32_t owner_id,
 					    uint32_t stream_num,
 					    tpm_mc_igmp_mode_t igmp_mode,
 					    uint8_t mc_stream_pppoe,
 					    uint16_t vid,
-					    uint8_t ipv4_src_add[4],
-					    uint8_t ipv4_dst_add[4],
-					    uint8_t ignore_ipv4_src,
+					    uint8_t src_add[16],
+					    uint8_t dst_add[16],
+					    uint8_t ignore_ipvx_src,
+					    uint16_t dest_queue,
 					    tpm_trg_port_type_t dest_port_bm,
-					    tpm_mc_filter_mode_t filter_mode)
+					    tpm_mc_filter_mode_t filter_mode,
+					    tpm_ip_ver_t ip_version)
 {
 	tpm_error_code_t ret_code;
 	int32_t int_ret_code, index;
@@ -6236,16 +7170,30 @@
 	uint32_t ai_bit;
 	tpm_init_virt_uni_t virt_uni;
 	uint32_t pnc_rng_free_size;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
+	tpm_pnc_ranges_t range;
+	tpm_api_sections_t api_section;
+	tpm_api_type_t api_type;
+
+	if (TPM_IP_VER_4 == ip_version) {
+		range = TPM_PNC_IPV4_MC_DS;
+		api_section = TPM_IPV4_MC;
+		api_type = TPM_API_IPV4_MC;
+	} else {
+		range = TPM_PNC_IPV6_MC_DS;
+		api_section = TPM_IPV6_MC_ACL;
+		api_type = TPM_API_IPV6_MC;
+	}
 
 	/* Check TPM was successfully initialized */
 	if (!tpm_db_init_done_get())
 		IF_ERROR(ERR_SW_NOT_INIT);
 
-	ret_code = tpm_owner_id_check(TPM_API_IPV4_MC, owner_id);
+	ret_code = tpm_owner_id_check(api_type, owner_id);
 	IF_ERROR(ret_code);
 
 	/* Get PNC Range Start */
-	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
+	int_ret_code = tpm_db_pnc_rng_get(range, &range_data);
 	IF_ERROR(int_ret_code);
 
 	if (stream_num >= range_data.pnc_range_conf.range_size)
@@ -6268,7 +7216,7 @@
 	if ((stream_num < range_data.pnc_range_conf.api_start) || (stream_num > range_data.pnc_range_conf.api_end))
 		IF_ERROR(ERR_MC_STREAM_INVALID);
 
-	tpm_db_api_entry_ind_get(TPM_IPV4_MC, stream_num, &index);
+	tpm_db_api_entry_ind_get(api_section, stream_num, &index);
 	if (-1 != index)
 		IF_ERROR(ERR_MC_STREAM_EXISTS);
 
@@ -6304,8 +7252,25 @@
 			IF_ERROR(ERR_FEAT_UNSUPPORT);
 	}
 
-	if ((ipv4_dst_add[0] < 224) || (ipv4_dst_add[0] > 239))
-		IF_ERROR(ERR_IPV4_MC_DST_IP_INVALID);
+	if (TPM_IP_VER_4 == ip_version) {
+		if ((dst_add[0] < 224) || (dst_add[0] > 239))
+			IF_ERROR(ERR_IPV4_MC_DST_IP_INVALID);
+	} else {
+		if (dst_add[0] != 0xff)
+			IF_ERROR(ERR_IPV6_MC_DST_IP_INVALID);
+
+		/* check if there is MC SIP slot */
+		if(0 == ignore_ipvx_src) {
+			if(!tpm_db_ipv6_mc_sip_index_get(src_add)) {
+				/* this is a new MC SIP */
+				if(!tpm_db_ipv6_mc_sip_free_slot_num_get())
+					IF_ERROR(ERR_OUT_OF_RESOURCES);
+			}
+		}
+	}
+
+	if ((dest_queue != TPM_INVALID_QUEUE) && (dest_queue >= TPM_MAX_NUM_RX_QUEUE))
+		IF_ERROR(ERR_MC_DST_QUEUE_INVALID);
 
 	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
 		if (virt_uni.enabled == 0)
@@ -6317,6 +7282,21 @@
 			IF_ERROR(ERR_MC_DST_PORT_INVALID);
 	}
 
+	/* when ds load balance on G0 and G1 is enabled, no Proxy stream is allowed */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	if (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable) {
+		if (    (TPM_IP_VER_4 == ip_version)
+		     && (TPM_MC_IGMP_PROXY == igmp_mode)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "when ds load balance on G0 and G1 is enabled, "
+				"no Proxy stream is allowed\n");
+			return(ERR_FEAT_UNSUPPORT);
+		}
+		if (TPM_IP_VER_6 == ip_version) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "when ds load balance on G0 and G1 is enabled, "
+				"there is no IPv6 MC feature\n");
+			return(ERR_FEAT_UNSUPPORT);
+		}
+	}
 	return(TPM_RC_OK);
 }
 
@@ -6411,7 +7391,7 @@
 }
 
 /*******************************************************************************
-* tpm_proc_l2_sram_build()
+* tpm_proc_ipvx_mc_sram_build()
 *
 * DESCRIPTION:     Function builds a logical TCAM entry from the API data
 *
@@ -6435,34 +7415,41 @@
 * COMMENTS:
 *
 *******************************************************************************/
-int32_t tpm_proc_ipv4_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+int32_t tpm_proc_ipvx_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
 				    tpm_mc_igmp_mode_t igmp_mode,
+				    uint16_t dest_queue,
 				    tpm_trg_port_type_t target_port,
 				    uint32_t mod_entry,
-				    tpm_pncl_sram_data_t *sram_data)
+				    tpm_pncl_sram_data_t *sram_data,
+				    tpm_ip_ver_t ip_version)
 {
 	tpm_db_mh_src_t ds_mh_src;
 	tpm_init_virt_uni_t virt_uni;
 	tpm_db_pnc_range_conf_t range_conf;
 	int32_t ret_code;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " target_port(%d)\n", target_port);
 
 	/* Update dummy register (offset automatically=zero) */
 	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
-	sram_data->sram_updt_bm = 0;
-
-	/*Set next lookup */
-	sram_data->next_lu_off_reg = 0;
-	/* For igmp_proxy, check TTL, for igmp_snooping do not */
-	if (igmp_mode == TPM_MC_IGMP_PROXY) {
-		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
-		IF_ERROR(ret_code);
+	if (TPM_IP_VER_4 == ip_version) {
+		sram_data->sram_updt_bm = 0;
+		/*Set next lookup */
+		sram_data->next_lu_off_reg = 0;
+		/* For igmp_proxy, check TTL, for igmp_snooping do not */
+		if (igmp_mode == TPM_MC_IGMP_PROXY) {
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
+			IF_ERROR(ret_code);
+		} else {
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
+			IF_ERROR(ret_code);
+		}
+		sram_data->next_lu_id = range_conf.base_lu_id;
 	} else {
-		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
-		IF_ERROR(ret_code);
+		sram_data->sram_updt_bm = TPM_PNCL_SET_LUD;
 	}
-	sram_data->next_lu_id = range_conf.base_lu_id;
+
 
 	/* Set MH */
 	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
@@ -6496,42 +7483,48 @@
 		sram_data->flow_id_sub.mod_cmd = mod_entry;
 	}
 
-	/* Reset AI bits for following LU */
-	sram_data->add_info_data = 0;
-	sram_data->add_info_mask = (TPM_AI_MC_VID_MASK | TPM_AI_MC_VID_VALID_MASK);
-	if (TPM_MC_IGMP_PROXY == igmp_mode) {
-	/* set MTM AI since in proxy mode */
-		sram_data->add_info_data |= (1 << TPM_AI_MTM_BIT_OFF);
-		sram_data->add_info_mask |= TPM_AI_MTM_MASK;
+	if (TPM_IP_VER_4 == ip_version) {
+		/* Reset AI bits for following LU */
+		sram_data->add_info_data = 0;
+		sram_data->add_info_mask = (TPM_AI_MC_VID_MASK | TPM_AI_MC_VID_VALID_MASK);
+		if (TPM_MC_IGMP_PROXY == igmp_mode) {
+		/* set MTM AI since in proxy mode */
+			sram_data->add_info_data |= (1 << TPM_AI_MTM_BIT_OFF);
+			sram_data->add_info_mask |= TPM_AI_MTM_MASK;
+		}
+
+		/* Final Fragment and L4 is detremined in separate stage */
+		sram_data->l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
 	}
 
-	/* Final Fragment and L4 is detremined in separate stage */
-	sram_data->l3_type = TPM_PNCL_L3_IPV4_NFRAG;
-	sram_data->l4_type = TPM_PNCL_L4_OTHER;
-
 	/* Set Target Port */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+
 	sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+	sram_data->pnc_queue = dest_queue;
 	if (target_port == TPM_TRG_PORT_CPU) {
 		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
-		sram_data->pnc_queue = tpm_db_get_mc_cpu_queue();
+	} else if (TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable){
+		sram_data->sram_updt_bm &= (~TPM_PNCL_SET_TXP);
 	} else {
 		tpm_pnc_trg_t pnc_target;
 		ret_code = tpm_db_to_lan_gmac_get(target_port, &pnc_target);
 		IF_ERROR(ret_code);
 		sram_data->flow_id_sub.pnc_target = pnc_target;
-		sram_data->pnc_queue = tpm_db_get_mc_hwf_queue();
 	}
 
 	return(TPM_OK);
 }
 
-int32_t tpm_proc_create_ipv4_mc_mod(tpm_mc_filter_mode_t filter_mode,
+int32_t tpm_proc_create_ipvx_mc_mod(tpm_mc_filter_mode_t filter_mode,
 				    tpm_mc_igmp_mode_t igmp_mode,
 				    uint8_t mc_stream_pppoe,
 				    uint16_t vid,
 				    uint8_t *group_addr,
 				    uint32_t dest_port_bm,
-				    uint32_t *mod_entry)
+				    uint32_t *mod_entry,
+				    tpm_ip_ver_t ip_version)
 {
 	int32_t ret_code;
 	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
@@ -6541,13 +7534,25 @@
 	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
 	uint8_t valid;
 	uint32_t mh_en;
-	uint32_t switch_init;
+	uint32_t switch_init, trgt_gmac;
+	tpm_pnc_trg_t pnc_target;
+	tpm_gmacs_enum_t gmac;
 	/*struct net_device *dev = NULL;*/
 
 	memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
 
+	if (TPM_TRG_PORT_CPU == dest_port_bm) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "target to CPU, no pkt mod is needed\n");
+		*mod_entry = 0;
+		return TPM_OK;
+	}
+
 	/*get MH EN */
-	ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_0, &mh_en);
+	ret_code = tpm_db_to_lan_gmac_get(dest_port_bm, &pnc_target);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_target_to_gmac(pnc_target, &gmac);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_mh_en_conf_get(gmac, &mh_en);
 	IF_ERROR(ret_code);
 
 	/*get switch init*/
@@ -6635,7 +7640,11 @@
 		pkt_mod.mac_mod.mac_sa_mask[5] = 0xff;
 #endif
 
-		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+		if (TPM_IP_VER_4 == ip_version)
+			pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+		else
+			pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+
 		tpm_db_get_mc_igmp_proxy_sa_mac(mc_mac, &valid);
 
 		if (valid) {
@@ -6646,14 +7655,20 @@
 
 		if (mc_stream_pppoe) {
 			pkt_mod_bm |= (TPM_MAC_DA_SET | TPM_PPPOE_DEL);
-			MULTI_IP_2_MAC(mc_mac, group_addr);
+
+			if (TPM_IP_VER_4 == ip_version) {
+				MULTI_IP_2_MAC(mc_mac, group_addr);
+			} else {
+				MULTI_IPV6_2_MAC(mc_mac, group_addr);
+			}
 			memcpy(pkt_mod.mac_mod.mac_da, mc_mac, 6 * sizeof(uint8_t));
 			memset(pkt_mod.mac_mod.mac_da_mask, 0xff, 6 * sizeof(uint8_t));
 		}
 	}
 
 	if (pkt_mod_bm != 0) {
-		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, pkt_mod_bm, TPM_INT_MC_MOD, &pkt_mod, mod_entry);
+		ret_code = tpm_proc_create_mod(TPM_ACTION_SET_PKT_MOD, dest_port_bm, &pkt_mod, pkt_mod_bm,
+			TPM_INT_MC_MOD, mod_entry, &trgt_gmac);
 		IF_ERROR(ret_code);
 	}
 
@@ -7067,6 +8082,7 @@
 						uint8_t ipv4_src_add[4],
 						uint8_t ipv4_dst_add[4],
 						uint8_t ignore_ipv4_src,
+						uint16_t dest_queue,
 						uint32_t dest_port_bm)
 {
 	tpm_pncl_pnc_full_t pnc_data;
@@ -7077,6 +8093,7 @@
 	tpm_db_pnc_range_t range_data;
 	tpm_db_mc_stream_entry_t mc_stream;
 	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+	tpm_gmacs_enum_t gmac;
 
 	int32_t ret_code;
 	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0xffff;
@@ -7093,8 +8110,8 @@
 
 		/*********** Create Modification Entries **********/
 		ret_code =
-		tpm_proc_create_ipv4_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv4_dst_add,
-					    dest_port_bm, &mod_entry);
+		tpm_proc_create_ipvx_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv4_dst_add,
+					    dest_port_bm, &mod_entry, TPM_IP_VER_4);
 		IF_ERROR(ret_code);
 
 		/*********** Create PNC Entries **********/
@@ -7106,7 +8123,9 @@
 
 		/* Build SRAM Entry */
 		ret_code =
-		tpm_proc_ipv4_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		tpm_proc_ipvx_mc_sram_build(filter_mode, igmp_mode, dest_queue,
+					    dest_port_bm, mod_entry,
+					    &(pnc_data.pncl_sram), TPM_IP_VER_4);
 		IF_ERROR(ret_code);
 
 		/*** Calculate PNC Entry ***/
@@ -7136,7 +8155,11 @@
 		memcpy(api_data.ipv4_mc_key.ipv4_dest_add, ipv4_dst_add, sizeof(ipv4_dst_add));
 		api_data.ipv4_mc_key.ignore_ipv4_src = ignore_ipv4_src;
 		api_data.ipv4_mc_key.dest_port_bm = dest_port_bm;
+		api_data.ipv4_mc_key.dest_queue = dest_queue;
 		api_data.ipv4_mc_key.vid = vid;
+		api_data.ipv4_mc_key.igmp_mode = igmp_mode;
+		api_data.ipv4_mc_key.mc_stream_pppoe = mc_stream_pppoe;
+		api_data.ipv4_mc_key.stream_num = stream_num;
 
 		/* Set Pnc Connection data */
 		pnc_conn.num_pnc_ranges = 1;
@@ -7145,8 +8168,11 @@
 
 		/* Set Modification Connection data */
 		mod_con.mod_cmd_ind = mod_entry;
-		mod_con.mod_cmd_mac = TPM_PNC_TRG_GMAC0;
-
+		if (mod_entry) {
+			ret_code = tpm_db_target_to_gmac(pnc_data.pncl_sram.flow_id_sub.pnc_target, &gmac);
+			IF_ERROR(ret_code);
+			mod_con.mod_cmd_mac = gmac;
+		}
 		/* Set new API Entry */
 		ret_code = tpm_db_api_entry_set(TPM_IPV4_MC, stream_num, 0 /*bi_dir */ ,
 						&api_data, &mod_con, &pnc_conn, &rule_idx);
@@ -7189,10 +8215,11 @@
 	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
 	mc_stream.src_valid = ignore_ipv4_src;
 	mc_stream.vid = vid;
+	mc_stream.dest_queue = dest_queue;
 	mc_stream.dest_port_bm = dest_port_bm;
 	mc_stream.u4_entry = rule_num;
 	memcpy(mc_stream.group_addr, ipv4_dst_add, 4 * sizeof(uint8_t));
-	if (ignore_ipv4_src)
+	if (!ignore_ipv4_src)
 		memcpy(mc_stream.src_addr, ipv4_src_add, 4 * sizeof(uint8_t));
 
 	ret_code = tpm_db_set_mc_stream_entry(stream_num, &mc_stream);
@@ -7209,6 +8236,7 @@
 						   uint8_t ipv4_src_add[4],
 						   uint8_t ipv4_dst_add[4],
 						   uint8_t ignore_ipv4_src,
+						   uint16_t dest_queue,
 						   uint32_t dest_port_bm)
 {
 	tpm_db_pnc_range_t range_data;
@@ -7226,6 +8254,11 @@
 
 	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
 
+	/* Get old API Entry */
+	ret_code = tpm_db_api_entry_get(TPM_IPV4_MC, stream_num, &rule_idx, &bi_dir,
+					&api_data, &mod_con, &pnc_conn);
+	IF_ERROR(ret_code);
+
 	/* Only MC_IP_ONLY_FILTER mode, update the multicast group member ports by mh_mod. */
 	if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
 		/* Get PNC Range Start */
@@ -7235,16 +8268,11 @@
 		if (stream_num >= range_data.pnc_range_conf.range_size)
 			IF_ERROR(ERR_MC_STREAM_INVALID);
 
-		/* Get old API Entry */
-		ret_code = tpm_db_api_entry_get(TPM_IPV4_MC, stream_num, &rule_idx, &bi_dir,
-						&api_data, &mod_con, &pnc_conn);
-		IF_ERROR(ret_code);
-
 		pnc_entry = pnc_conn.pnc_conn_tbl[0].pnc_index;
 
 		/* Create new Modification Entry */
-		ret_code = tpm_proc_create_ipv4_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
-						       vid, ipv4_dst_add, dest_port_bm, &mod_entry);
+		ret_code = tpm_proc_create_ipvx_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
+						       vid, ipv4_dst_add, dest_port_bm, &mod_entry, TPM_IP_VER_4);
 		IF_ERROR(ret_code);
 
 		/* Rebuild PnC Entry */
@@ -7254,7 +8282,9 @@
 
 		/* Rebuild SRAM Entry */
 		ret_code =
-		tpm_proc_ipv4_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		tpm_proc_ipvx_mc_sram_build(filter_mode, igmp_mode, dest_queue,
+					    dest_port_bm, mod_entry,
+					    &(pnc_data.pncl_sram), TPM_IP_VER_4);
 		IF_ERROR(ret_code);
 
 		/* Update only Sram of PNC Entry */
@@ -7263,21 +8293,11 @@
 
 		/* Delete old Modification Entry */
 		if (mod_con.mod_cmd_ind != 0) {
-			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			ret_code = tpm_proc_delete_mod(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
 			IF_ERROR(ret_code);
 		}
 		/* Update new Modification Entry */
 		mod_con.mod_cmd_ind = mod_entry;
-
-		/* Invalidate old API Entry */
-		ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_MC, stream_num);
-		IF_ERROR(ret_code);
-
-		/* Set new API Entry */
-		mod_con.mod_cmd_ind = mod_entry;
-		ret_code = tpm_db_api_entry_set(TPM_IPV4_MC, stream_num, 0 /*bi_dir */ ,
-						&api_data, &mod_con, &pnc_conn, &rule_idx);
-		IF_ERROR(ret_code);
 	}
 
 	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
@@ -7340,79 +8360,16 @@
 	ret_code = tpm_db_set_mc_stream_entry(stream_num, &mc_stream);
 	IF_ERROR(ret_code);
 
-	return(TPM_RC_OK);
-}
+	/* Update API entry */
+	/* Invalidate old API Entry */
+	ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_MC, stream_num);
+	IF_ERROR(ret_code);
 
-tpm_error_code_t tpm_proc_delete_ipv4_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
-						   uint32_t stream_num,
-						   uint32_t dest_port_bm,
-						   uint32_t u4_entry)
-{
-	tpm_db_pnc_range_t range_data;
-	tpm_rule_entry_t api_data;
-	tpm_db_mod_conn_t mod_con;
-	tpm_db_pnc_conn_t pnc_conn;
-
-	int32_t ret_code;
-	uint32_t bi_dir = 0, rule_idx = 0;
-	uint32_t pnc_range_start = 0, api_start = 0, pnc_entry = 0;
-
-	if (filter_mode != TPM_MC_MAC_ONLY_FILTER) {
-		/* Get PNC Range Start */
-		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
-		IF_ERROR(ret_code);
-
-		if (stream_num >= range_data.pnc_range_conf.range_size)
-			IF_ERROR(ERR_MC_STREAM_INVALID);
-
-		/* Check parameters */
-		ret_code = tpm_db_api_entry_get(TPM_IPV4_MC, stream_num, &rule_idx, &bi_dir,
-						&api_data, &mod_con, &pnc_conn);
-		IF_ERROR(ret_code);
-
-		/* Delete PNC Entry */
-#if 0
-		ret_code = tpm_proc_pnc_con_del(&pnc_conn);
-		IF_ERROR(ret_code);
-#endif
-		pnc_range_start = range_data.pnc_range_conf.range_start;
-		api_start = range_data.pnc_range_conf.api_start;
-
-		/* Pull range from this index untill last used entry in Pnc range */
-		pnc_entry = (pnc_range_start + api_start) + stream_num;
-
-		/* Delete PNC entry */
-		ret_code = tpm_pncl_entry_delete(pnc_entry, pnc_entry);
-		IF_ERROR(ret_code);
-
-		/* Increase number of free entries in pnc_range */
-		ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV4_MC_DS);
-		IF_ERROR(ret_code);
-
-		if (mod_con.mod_cmd_ind != 0) {
-			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
-			IF_ERROR(ret_code);
-		}
-
-		/* Delete API Rule Entry */
-		ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_MC, stream_num);
-		IF_ERROR(ret_code);
-	}
-
-	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
-		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
-			if (u4_entry != 0xffff) {
-				ret_code = tpm_proc_mc_delete_virt_uni_pnc_entry(u4_entry);
-				IF_ERROR(ret_code);
-
-				ret_code = tpm_db_mc_free_virt_uni_entry(u4_entry);
-				IF_ERROR(ret_code);
-			}
-		}
-	}
-
-	/* Remove stream entry */
-	tpm_db_reset_mc_stream_entry(stream_num);
+	/* Set new API Entry */
+	api_data.ipv4_mc_key.dest_port_bm = dest_port_bm;
+	ret_code = tpm_db_api_entry_set(TPM_IPV4_MC, stream_num, 0 /*bi_dir */ ,
+					&api_data, &mod_con, &pnc_conn, &rule_idx);
+	IF_ERROR(ret_code);
 
 	return(TPM_RC_OK);
 }
@@ -7511,6 +8468,7 @@
 					     uint8_t ipv4_src_add[4],
 					     uint8_t ipv4_dst_add[4],
 					     uint8_t ignore_ipv4_src,
+					     uint16_t dest_queue,
 					     tpm_trg_port_type_t dest_port_bm)
 {
 	tpm_error_code_t ret_code;
@@ -7533,13 +8491,21 @@
 		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
 
 	/* Check parameters */
-	ret_code = tpm_proc_add_ipv4_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
-					      ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm, filter_mode);
+	ret_code = tpm_proc_add_ipvx_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
+					      ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_queue,
+					      dest_port_bm, filter_mode, TPM_IP_VER_4);
 	IF_ERROR(ret_code);
 
+	/* get queue number */
+	if (dest_queue == TPM_INVALID_QUEUE) {
+		if (dest_port_bm & TPM_TRG_PORT_CPU)
+			dest_queue = tpm_db_get_mc_cpu_queue();
+		else
+			dest_queue = tpm_db_get_mc_hwf_queue();
+	}
 	/* Create PNC entry */
 	ret_code = tpm_proc_add_ipv4_mc_pnc_entry(filter_mode, stream_num, igmp_mode, mc_stream_pppoe, vid,
-						  ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm);
+						  ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_queue, dest_port_bm);
 	IF_ERROR(ret_code);
 
 	/* Set switch port_map for multicast MAC, but don't overwrite 224.0.0.1 (IGMP General Query) MAC */
@@ -7610,21 +8576,30 @@
 	ret_code = tpm_db_get_mc_stream_entry(stream_num, &mc_stream);
 	IF_ERROR(ret_code);
 
+	if (dest_port_bm == mc_stream.dest_port_bm) {
+		/* nothing changed, return directly */
+		TPM_OS_INFO(TPM_TPM_LOG_MOD, "dest_port_bm does not change, return directly\n");
+		return (TPM_OK);
+	}
+
 	if (((dest_port_bm & TPM_TRG_PORT_CPU) != 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) == 0) ||
 	    ((dest_port_bm & TPM_TRG_PORT_CPU) == 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) != 0)) {
-		ret_code = tpm_proc_delete_ipv4_mc_pnc_entry(filter_mode, stream_num,
-														mc_stream.dest_port_bm, mc_stream.u4_entry);
+		ret_code = tpm_proc_delete_ipvx_mc_pnc_entry(filter_mode, stream_num,
+							mc_stream.dest_port_bm, mc_stream.u4_entry,
+							TPM_IP_VER_4);
 		IF_ERROR(ret_code);
 
 		ret_code = tpm_proc_add_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
-													mc_stream.mc_stream_pppoe, mc_stream.vid,
-													mc_stream.src_addr, mc_stream.group_addr,
-													mc_stream.src_valid, dest_port_bm);
+							mc_stream.mc_stream_pppoe, mc_stream.vid,
+							mc_stream.src_addr, mc_stream.group_addr,
+							mc_stream.src_valid, mc_stream.dest_queue,
+							dest_port_bm);
 	} else {
 		ret_code = tpm_proc_update_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
-														mc_stream.mc_stream_pppoe, mc_stream.vid,
-														mc_stream.src_addr, mc_stream.group_addr,
-														mc_stream.src_valid, dest_port_bm);
+							mc_stream.mc_stream_pppoe, mc_stream.vid,
+							mc_stream.src_addr, mc_stream.group_addr,
+							mc_stream.src_valid, mc_stream.dest_queue,
+							dest_port_bm);
 	}
 	IF_ERROR(ret_code);
 
@@ -7679,7 +8654,10 @@
 	IF_ERROR(ret_code);
 
 	ret_code =
-	tpm_proc_delete_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.dest_port_bm, mc_stream.u4_entry);
+	tpm_proc_delete_ipvx_mc_pnc_entry(filter_mode, stream_num,
+	                                  mc_stream.dest_port_bm,
+	                                  mc_stream.u4_entry,
+	                                  TPM_IP_VER_4);
 	IF_ERROR(ret_code);
 
 	/* Set switch VID and multicast MAC */
@@ -8210,6 +9188,7 @@
 									       stream_data.vid, stream_data.src_addr,
 									       stream_data.group_addr,
 									       stream_data.src_valid,
+									       stream_data.dest_queue,
 									       stream_data.dest_port_bm);
 					IF_ERROR(ret_code);
 				} else {
@@ -9117,13 +10096,10 @@
 
 	return(TPM_RC_OK);
 }
-
 /*******************************************************************************
-* tpm_proc_loop_detect_add_channel()
+* tpm_proc_loop_detect_del_channel()
 *
-* DESCRIPTION:      Establishes a communication channel for the loop detection management protocol.
-*                   The API sets the Rx input queue in the CPU, and the
-*                   Tx T-CONT and queue parameters, which are configured in the driver.
+* DESCRIPTION:      remove the communication channel for the loop detection management protocol.
 *
 * INPUTS:
 * owner_id           - APP owner id  should be used for all API calls.
@@ -9138,7 +10114,73 @@
 * COMMENTS:
 *
 *******************************************************************************/
-tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id)
+tpm_error_code_t tpm_proc_loop_detect_del_channel(uint32_t owner_id)
+{
+	uint32_t pnc_entry;
+	tpm_db_pnc_range_t range_data;
+	tpm_error_code_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "owner(%d)\n", owner_id);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	memset(&range_data, 0, sizeof(range_data));
+	/* Get PNC Range data */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_LOOP_DET_US, &range_data);
+	IF_ERROR(ret_code);
+
+	if (!range_data.valid) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "range TPM_PNC_LOOP_DET_US is not valid\n");
+		return ERR_GENERAL;
+	}
+
+	if (range_data.pnc_range_conf.range_size == range_data.pnc_range_oper.free_entries) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "there is no loopback detect channel yet\n");
+		return ERR_GENERAL;
+	}
+
+	pnc_entry = range_data.pnc_range_conf.range_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "remove pnc_entry(%d)\n", pnc_entry);
+
+	ret_code = tpm_pnc_entry_inv(pnc_entry);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_LOOP_DET_US);
+	IF_ERROR(ret_code);
+
+	/* remove tag PNC rule */
+	pnc_entry++;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "remove pnc_entry(%d)\n", pnc_entry);
+
+	ret_code = tpm_pnc_entry_inv(pnc_entry);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_LOOP_DET_US);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+/*******************************************************************************
+* tpm_proc_loop_detect_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the loop detection management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* ety                    - EtherType of the loop detection Pkt.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id, tpm_ether_type_key_t ety)
 {
 	tpm_pncl_pnc_full_t pnc_data;
 	tpm_gmac_bm_t gmac_bm;
@@ -9155,51 +10197,62 @@
 	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
 
 	/* build TCAM */
-	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_ETYPE;
-	pnc_data.pncl_tcam.l3_parse_bm = 0;
-	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
-	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
-	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ETYPE;
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_TAG1_MASK;
 	pnc_data.pncl_tcam.add_info_data = 0;
 
 	/* src port */
 	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
 	pnc_data.pncl_tcam.port_ids = gmac_bm;
-	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid = 0x8100;
-	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid_mask = 0xffff;
-	pnc_data.pncl_tcam.pkt_key.l2_key.ether_type = 0xA0A0;
+	pnc_data.pncl_tcam.pkt_key.l2_key.ether_type = ety;
 	pnc_data.pncl_tcam.lu_id = 0;
 	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
 	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
 
 	/* Build SRAM */
-	pnc_data.pncl_sram.next_lu_id = 0;
-	pnc_data.pncl_sram.next_lu_off_reg = 0;
-	pnc_data.pncl_sram.next_offset.offset_base = 0;
-	pnc_data.pncl_sram.next_offset.offset_sub.l2_subf = 0;
 	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
 	pnc_data.pncl_sram.pnc_queue = 0;	/*send to queue 0 by default */
 	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_RX_SPECIAL;
-	pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
-	pnc_data.pncl_sram.mh_reg.mh_reg = 0;
-	pnc_data.pncl_sram.add_info_data = 0;
-	pnc_data.pncl_sram.add_info_mask = 0;
 	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_OTHER;
 	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
 	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
-	pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
-	pnc_data.pncl_sram.flow_id_sub.gem_port = 0;
 
-	/* Get PNC Range Start */
+	/* Get PNC Range data */
 	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_LOOP_DET_US, &range_data);
 	IF_ERROR(int_ret_code);
+
+	if ((!range_data.valid) || (range_data.pnc_range_conf.range_size < 2)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "range TPM_PNC_LOOP_DET_US is not big enough!\n");
+		return ERR_OUT_OF_RESOURCES;
+	}
+
+	if (range_data.pnc_range_conf.range_size != range_data.pnc_range_oper.free_entries) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback detect channel has already been added\n");
+		return ERR_GENERAL;
+	}
+
 	pnc_entry = range_data.pnc_range_conf.range_start;
 	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+
+	int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
 	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_LOOP_DET_US);
 	IF_ERROR(int_ret_code);
+
+	/* add tag PNC rule */
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_ETYPE;
+	pnc_data.pncl_tcam.add_info_data = TPM_AI_TAG1_MASK;
+
+	pnc_entry++;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+
 	int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
 	IF_ERROR(int_ret_code);
 
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_LOOP_DET_US);
+	IF_ERROR(int_ret_code);
+
 	return(TPM_RC_OK);
 }
 
@@ -9491,7 +10544,8 @@
 
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check owner_id */
@@ -10852,16 +11906,16 @@
 }
 
 tpm_error_code_t tpm_proc_add_ipv6_gen_5t_check(uint32_t owner_id,
-												tpm_dir_t dir,
-												uint32_t rule_num,
-												tpm_parse_fields_t parse_rule_bm,
-												tpm_parse_flags_t parse_flags_bm,
-												tpm_l4_ports_key_t *l4_key,
-												tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
-												tpm_pkt_frwd_t *pkt_frwd,
-												tpm_pkt_mod_bm_t pkt_mod_bm,
-												tpm_pkt_mod_t *pkt_mod,
-												tpm_rule_action_t *rule_action)
+						tpm_dir_t dir,
+						uint32_t rule_num,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_l4_ports_key_t *l4_key,
+						tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_mod_bm_t pkt_mod_bm,
+						tpm_pkt_mod_t *pkt_mod,
+						tpm_rule_action_t *rule_action)
 {
 	int32_t ret_code;
 	tpm_db_pon_type_t pon_type;
@@ -10871,6 +11925,7 @@
 	tpm_ipv6_gen_acl_key_t _gen_key;
 	tpm_ipv6_addr_key_t _dip_key, dip_key;
 	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_src_port_type_t src_port;
 
 	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
 	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
@@ -10909,9 +11964,16 @@
 		return(ERR_FRWD_INVALID);
 	}
 
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_bm */
@@ -11003,17 +12065,17 @@
 }
 
 tpm_error_code_t tpm_proc_add_ipv6_dip_5t_check(uint32_t owner_id,
-												tpm_dir_t dir,
-												uint32_t rule_num,
-												tpm_parse_fields_t parse_rule_bm,
-												tpm_parse_flags_t parse_flags_bm,
-												tpm_l4_ports_key_t *l4_key,
-												tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
-												tpm_ipv6_addr_key_t *ipv6_dip_key,
-												tpm_pkt_frwd_t *pkt_frwd,
-												tpm_pkt_mod_bm_t pkt_mod_bm,
-												tpm_pkt_mod_t *pkt_mod,
-												tpm_rule_action_t *rule_action)
+						tpm_dir_t dir,
+						uint32_t rule_num,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_l4_ports_key_t *l4_key,
+						tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+						tpm_ipv6_addr_key_t *ipv6_dip_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_mod_bm_t pkt_mod_bm,
+						tpm_pkt_mod_t *pkt_mod,
+						tpm_rule_action_t *rule_action)
 {
 	int32_t ret_code;
 	tpm_db_pon_type_t pon_type;
@@ -11023,6 +12085,7 @@
 	tpm_ipv6_gen_acl_key_t _gen_key;
 	tpm_ipv6_addr_key_t _dip_key;
 	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_src_port_type_t src_port;
 
 	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
 
@@ -11060,9 +12123,16 @@
 		return(ERR_FRWD_INVALID);
 	}
 
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port,
+				pkt_frwd->trg_queue, rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_bm */
@@ -11175,6 +12245,7 @@
 	tpm_ipv6_gen_acl_key_t _gen_key, gen_key;
 	tpm_ipv6_addr_key_t _dip_key, dip_key;
 	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_src_port_type_t src_port;
 
 	memset(&gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
 	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
@@ -11215,9 +12286,16 @@
 		return(ERR_FRWD_INVALID);
 	}
 
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+
 	/* Check Target_port and Queue are valid */
 	ret_code =
-	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	tpm_proc_check_valid_target(dir, pon_type, src_port, pkt_frwd->trg_port, pkt_frwd->trg_queue,
+				rule_action->pkt_act, TPM_FALSE);
 	IF_ERROR(ret_code);
 
 	/* Check parse_bm */
@@ -12778,66 +13856,6 @@
 	return(TPM_OK);
 }
 
-int32_t tpm_proc_ipv6_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
-				    tpm_mc_igmp_mode_t igmp_mode,
-				    tpm_trg_port_type_t target_port,
-				    uint32_t mod_entry,
-				    tpm_pncl_sram_data_t *sram_data)
-{
-	tpm_db_mh_src_t ds_mh_src;
-	tpm_init_virt_uni_t virt_uni;
-
-	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " target_port(%d)\n", target_port);
-
-	/* Update dummy register (offset automatically=zero) */
-	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
-	sram_data->sram_updt_bm = TPM_PNCL_SET_LUD;
-
-	/* Set MH */
-	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
-		tpm_db_ds_mh_get_conf_set(&ds_mh_src);
-
-		if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
-			if (TPM_MH_SRC_PNC_RI == ds_mh_src) {
-				sram_data->sram_updt_bm |= TPM_PNCL_SET_MH_RI;
-				sram_data->mh_reg.mh_set = TPM_TRUE;
-
-				tpm_db_virt_info_get(&virt_uni);
-				if (virt_uni.enabled)
-					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT16 | TPM_MH_RI_BIT15);
-				else
-					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT17 | TPM_MH_RI_BIT16 |
-								    TPM_MH_RI_BIT15 | TPM_MH_RI_BIT14);
-			} else {
-				sram_data->mh_reg.mh_set = TPM_FALSE;
-				sram_data->mh_reg.mh_reg = 0;
-			}
-		} else if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
-			/* Target UNI is set by Modification Entry */
-		}
-	} else {
-		/* Target UNI is set by Modification Entry */
-	}
-
-	/* Set modification command */
-	if (mod_entry != 0) {
-		sram_data->sram_updt_bm |= TPM_PNCL_SET_MOD;
-		sram_data->flow_id_sub.mod_cmd = mod_entry;
-	}
-
-	/* Set Target Port */
-	sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
-	if (target_port == TPM_TRG_PORT_CPU) {
-		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
-		sram_data->pnc_queue = tpm_db_get_mc_cpu_queue();
-	} else {
-		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC0;
-		sram_data->pnc_queue = tpm_db_get_mc_hwf_queue();
-	}
-
-	return(TPM_OK);
-}
-
 int32_t tpm_proc_ipv6_mc_sip_entry_create(uint32_t sip_index, uint8_t *ipv6_src_add)
 {
 	int32_t int_ret_code;
@@ -12932,250 +13950,6 @@
 	return TPM_RC_OK;
 }
 
-int32_t tpm_proc_create_ipv6_mc_mod(tpm_mc_filter_mode_t filter_mode,
-				    tpm_mc_igmp_mode_t igmp_mode,
-				    uint8_t mc_stream_pppoe,
-				    uint16_t vid,
-				    uint8_t *group_addr,
-				    uint32_t dest_port_bm,
-				    uint32_t *mod_entry)
-{
-	int32_t ret_code;
-	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
-	tpm_pkt_mod_t pkt_mod;
-	uint8_t mc_mac[6];
-	uint32_t lpbk_port_bm = 0, entry_id;
-	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
-	uint8_t valid;
-	uint32_t switch_init;
-	uint32_t mh_en;
-	/*struct net_device *dev = NULL;*/
-
-	memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
-
-	/*get switch init*/
-	ret_code = tpm_db_switch_init_get(&switch_init);
-	IF_ERROR(ret_code);
-
-	/*get MH EN */
-	ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_0, &mh_en);
-	IF_ERROR(ret_code);
-
-	if (filter_mode == TPM_MC_IP_ONLY_FILTER && mh_en) {
-		/* TODO: Check virt_port status. If it is not enabled, set target_port via MH_Tx_reg in RI. */
-		pkt_mod_bm |= TPM_MH_SET;
-		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(dest_port_bm);
-	}
-
-	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
-		if (vid != 0xffff) {
-			if (tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg) == TPM_OK) {
-				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
-					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSLATE) {
-						pkt_mod_bm |= TPM_VLAN_MOD;
-
-						pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD;
-						pkt_mod.vlan_mod.vlan1_out.tpid = 0x8100;
-						pkt_mod.vlan_mod.vlan1_out.pbit = 0;
-						pkt_mod.vlan_mod.vlan1_out.pbit_mask = 0x0;
-						pkt_mod.vlan_mod.vlan1_out.cfi = 0;
-						pkt_mod.vlan_mod.vlan1_out.cfi_mask = 0x0;
-						pkt_mod.vlan_mod.vlan1_out.vid = mc_vid_cfg[entry_id].uni_port_vid;
-						pkt_mod.vlan_mod.vlan1_out.vid_mask = 0xffff;
-						break;
-					} else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
-						/* Just for MC, no switch */
-						if (switch_init == 0) {
-							pkt_mod_bm |= TPM_VLAN_MOD;
-
-							pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL;
-							break;
-						}
-					}
-				}
-			} else
-				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " not found mv_vlan_cfg %d, assume as transparent! \n", vid);
-		}
-	} else if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
-		pkt_mod_bm |= TPM_MH_SET;
-
-		ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
-		IF_ERROR(ret_code);
-
-		for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
-			if (mc_vid_cfg[entry_id].tpm_src_port != TPM_SRC_PORT_UNI_VIRT) {
-				if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT ||
-				    mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
-					lpbk_port_bm |=
-					TPM_TRG_UNI_0 << (mc_vid_cfg[entry_id].tpm_src_port - TPM_SRC_PORT_UNI_0);
-				}
-			}
-		}
-		lpbk_port_bm |= TPM_TRG_UNI_VIRT;
-
-		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(lpbk_port_bm);
-	}
-
-	if (igmp_mode == TPM_MC_IGMP_PROXY) {
-#if 0
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
-		dev = dev_get_by_name("eth0");
-#else
-		dev = dev_get_by_name(&init_net, "eth0");
-#endif
-		if (dev == NULL)
-			IF_ERROR(ERR_GENERAL);
-
-		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
-		pkt_mod.mac_mod.mac_sa[0] = ((uint8_t *) dev->dev_addr)[0];
-		pkt_mod.mac_mod.mac_sa[1] = ((uint8_t *) dev->dev_addr)[1];
-		pkt_mod.mac_mod.mac_sa[2] = ((uint8_t *) dev->dev_addr)[2];
-		pkt_mod.mac_mod.mac_sa[3] = ((uint8_t *) dev->dev_addr)[3];
-		pkt_mod.mac_mod.mac_sa[4] = ((uint8_t *) dev->dev_addr)[4];
-		pkt_mod.mac_mod.mac_sa[5] = ((uint8_t *) dev->dev_addr)[5];
-
-		pkt_mod.mac_mod.mac_sa_mask[0] = 0xff;
-		pkt_mod.mac_mod.mac_sa_mask[1] = 0xff;
-		pkt_mod.mac_mod.mac_sa_mask[2] = 0xff;
-		pkt_mod.mac_mod.mac_sa_mask[3] = 0xff;
-		pkt_mod.mac_mod.mac_sa_mask[4] = 0xff;
-		pkt_mod.mac_mod.mac_sa_mask[5] = 0xff;
-#endif
-
-		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
-		tpm_db_get_mc_igmp_proxy_sa_mac(mc_mac, &valid);
-
-		if (valid) {
-			memcpy(pkt_mod.mac_mod.mac_sa, mc_mac, 6 * sizeof(uint8_t));
-			memset(pkt_mod.mac_mod.mac_sa_mask, 0xff, 6 * sizeof(uint8_t));
-		} else
-			IF_ERROR(ERR_GENERAL);
-
-		if (mc_stream_pppoe) {
-			pkt_mod_bm |= (TPM_MAC_DA_SET | TPM_PPPOE_DEL);
-			MULTI_IPV6_2_MAC(mc_mac, group_addr);
-			memcpy(pkt_mod.mac_mod.mac_da, mc_mac, 6 * sizeof(uint8_t));
-			memset(pkt_mod.mac_mod.mac_da_mask, 0xff, 6 * sizeof(uint8_t));
-		}
-	}
-
-	if (pkt_mod_bm != 0) {
-		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0,
-			pkt_mod_bm, TPM_INT_MC_MOD, &pkt_mod, mod_entry);
-		IF_ERROR(ret_code);
-	}
-
-	return(TPM_OK);
-}
-tpm_error_code_t tpm_proc_add_ipv6_mc_check(uint32_t owner_id,
-						uint32_t stream_num,
-						tpm_mc_igmp_mode_t igmp_mode,
-						uint8_t mc_stream_pppoe,
-						uint16_t vid,
-						uint8_t ipv6_src_add[16],
-						uint8_t ipv6_dst_add[16],
-						uint8_t ignore_ipv6_src,
-						tpm_trg_port_type_t dest_port_bm,
-						tpm_mc_filter_mode_t filter_mode)
-{
-	tpm_error_code_t ret_code;
-	int32_t int_ret_code, index;
-	tpm_db_pnc_range_t range_data;
-	uint32_t ai_bit;
-	tpm_init_virt_uni_t virt_uni;
-	uint32_t pnc_rng_free_size;
-
-	/* Check TPM was successfully initialized */
-	if (!tpm_db_init_done_get())
-		IF_ERROR(ERR_SW_NOT_INIT);
-
-	ret_code = tpm_owner_id_check(TPM_API_IPV6_MC, owner_id);
-	IF_ERROR(ret_code);
-
-	/* Get PNC Range Start */
-	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
-	IF_ERROR(int_ret_code);
-
-	if (stream_num >= range_data.pnc_range_conf.range_size)
-		IF_ERROR(ERR_MC_STREAM_INVALID);
-
-	ret_code = tpm_proc_check_dst_uni_port(dest_port_bm);
-	IF_ERROR(ret_code);
-
-	/*check virt range size if necessary*/
-	if(filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
-		if ((tpm_db_get_mc_per_uni_vlan_xlate() != 0) && ((dest_port_bm & TPM_TRG_UNI_VIRT) != 0)) {
-			int_ret_code = tpm_db_pnc_rng_free_ent_get(TPM_PNC_VIRT_UNI, &pnc_rng_free_size);
-			IF_ERROR(int_ret_code);
-			if(pnc_rng_free_size == 0)
-				IF_ERROR(ERR_OUT_OF_RESOURCES);
-		}
-	}
-
-	/* fix bug of adding 1-2-3 instead of 0-1-2 => when 3 is over-writing the hardcoded entry */
-	if ((stream_num < range_data.pnc_range_conf.api_start) || (stream_num > range_data.pnc_range_conf.api_end))
-		IF_ERROR(ERR_MC_STREAM_INVALID);
-
-	tpm_db_api_entry_ind_get(TPM_IPV6_MC_ACL, stream_num, &index);
-	if (-1 != index)
-		IF_ERROR(ERR_MC_STREAM_EXISTS);
-
-	tpm_db_virt_info_get(&virt_uni);
-
-	if (vid == 0xffff) {
-		if (tpm_db_get_mc_filter_mode() == TPM_MC_IP_ONLY_FILTER) {
-			if (virt_uni.enabled) {
-				TPM_OS_WARN(TPM_TPM_LOG_MOD,
-					    " filter mode fall back to MC_COMBINED_MAC_IP_FILTER \r\n");
-			}
-		}
-
-		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
-			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
-				    "when mc_per_uni_vlan_xlate is enabled, untagged mcast stream is not supported, "
-				    "and MC VID must be specified \r\n");
-			IF_ERROR(ERR_SW_VID_INVALID);
-		}
-	} else {
-		if (tpm_db_mc_vlan_get_ai_bit(vid, &ai_bit) != TPM_OK) {
-			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
-				    "MC VID must be configured first \r\n");
-			IF_ERROR(ERR_SW_VID_INVALID);
-		}
-	}
-
-	if (mc_stream_pppoe) {
-		if (tpm_db_get_mc_pppoe_enable() == 0)
-			IF_ERROR(ERR_FEAT_UNSUPPORT);
-
-		if (igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_db_get_mc_per_uni_vlan_xlate())
-			IF_ERROR(ERR_FEAT_UNSUPPORT);
-	}
-
-	if (ipv6_dst_add[0] != 0xff)
-		IF_ERROR(ERR_IPV6_MC_DST_IP_INVALID);
-
-	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
-		if (virt_uni.enabled == 0)
-			IF_ERROR(ERR_MC_DST_PORT_INVALID);
-	}
-
-	if (dest_port_bm & TPM_TRG_PORT_CPU) {
-		if (dest_port_bm & (~TPM_TRG_PORT_CPU))
-			IF_ERROR(ERR_MC_DST_PORT_INVALID);
-	}
-
-	/* check if there is MC SIP slot */
-	if(0 == ignore_ipv6_src) {
-		if(!tpm_db_ipv6_mc_sip_index_get(ipv6_src_add)) {
-			/* this is a new MC SIP */
-			if(!tpm_db_ipv6_mc_sip_free_slot_num_get())
-				IF_ERROR(ERR_OUT_OF_RESOURCES);
-		}
-	}
-
-	return(TPM_RC_OK);
-}
 tpm_error_code_t tpm_proc_add_ipv6_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
 						uint32_t stream_num,
 						tpm_mc_igmp_mode_t igmp_mode,
@@ -13184,6 +13958,7 @@
 						uint8_t ipv6_src_add[16],
 						uint8_t ipv6_dst_add[16],
 						uint8_t ignore_ipv6_src,
+						uint16_t dest_queue,
 						uint32_t dest_port_bm)
 {
 	tpm_pncl_pnc_full_t pnc_data;
@@ -13201,6 +13976,7 @@
 	uint32_t entry_id;
 	uint16_t u4_vid;
 	int32_t  sip_index = 0;
+	tpm_gmacs_enum_t gmac;
 
 	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
 
@@ -13209,8 +13985,8 @@
 
 	/*********** Create Modification Entries **********/
 	ret_code =
-	tpm_proc_create_ipv6_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv6_dst_add,
-				    dest_port_bm, &mod_entry);
+	tpm_proc_create_ipvx_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv6_dst_add,
+				    dest_port_bm, &mod_entry, TPM_IP_VER_6);
 	IF_ERROR(ret_code);
 
 	/* Handle IPv6 SSM */
@@ -13240,7 +14016,10 @@
 
 	/* Build SRAM Entry */
 	ret_code =
-	tpm_proc_ipv6_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+	tpm_proc_ipvx_mc_sram_build(filter_mode, igmp_mode,
+				    dest_queue, dest_port_bm,
+				    mod_entry, &(pnc_data.pncl_sram),
+				    TPM_IP_VER_6);
 	IF_ERROR(ret_code);
 
 	/*** Calculate PNC Entry ***/
@@ -13267,8 +14046,14 @@
 
 	/* Set API data */
 	memcpy(api_data.ipv6_mc_key.ipv6_dest_add, ipv6_dst_add, 16 * sizeof(uint8_t));
+	memcpy(api_data.ipv6_mc_key.ipv6_src_add, ipv6_src_add, 16 * sizeof(uint8_t));
 	api_data.ipv6_mc_key.dest_port_bm = dest_port_bm;
+	api_data.ipv6_mc_key.dest_queue = dest_queue;
 	api_data.ipv6_mc_key.vid = vid;
+	api_data.ipv6_mc_key.igmp_mode = igmp_mode;
+	api_data.ipv6_mc_key.mc_stream_pppoe = mc_stream_pppoe;
+	api_data.ipv6_mc_key.stream_num = stream_num;
+	api_data.ipv6_mc_key.ignore_ipv6_src = ignore_ipv6_src;
 
 	/* Set Pnc Connection data */
 	pnc_conn.num_pnc_ranges = 1;
@@ -13277,7 +14062,11 @@
 
 	/* Set Modification Connection data */
 	mod_con.mod_cmd_ind = mod_entry;
-	mod_con.mod_cmd_mac = TPM_PNC_TRG_GMAC0;
+	if (mod_entry) {
+		ret_code = tpm_db_target_to_gmac(pnc_data.pncl_sram.flow_id_sub.pnc_target, &gmac);
+		IF_ERROR(ret_code);
+		mod_con.mod_cmd_mac = gmac;
+	}
 
 	/* Set new API Entry */
 	ret_code = tpm_db_api_entry_set(TPM_IPV6_MC_ACL, stream_num, 0 /*bi_dir */ ,
@@ -13319,6 +14108,7 @@
 	mc_stream.igmp_mode = igmp_mode;
 	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
 	mc_stream.vid = vid;
+	mc_stream.dest_queue = dest_queue;
 	mc_stream.dest_port_bm = dest_port_bm;
 	mc_stream.u4_entry = rule_num;
 	mc_stream.ignore_src_addr = ignore_ipv6_src;
@@ -13339,6 +14129,7 @@
 					     uint8_t ipv6_src_add[16],
 					     uint8_t ipv6_dst_add[16],
 					     uint8_t ignore_ipv6_src,
+					     uint16_t dest_queue,
 					     tpm_trg_port_type_t dest_port_bm)
 {
 	tpm_error_code_t ret_code;
@@ -13362,14 +14153,22 @@
 		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
 
 	/* Check parameters */
-	ret_code = tpm_proc_add_ipv6_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
+	ret_code = tpm_proc_add_ipvx_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
 						  ipv6_src_add, ipv6_dst_add, ignore_ipv6_src,
-						  dest_port_bm, filter_mode);
+						  dest_queue, dest_port_bm, filter_mode, TPM_IP_VER_6);
 	IF_ERROR(ret_code);
 
+	/* get queue number */
+	if (dest_queue == TPM_INVALID_QUEUE) {
+		if (dest_port_bm & TPM_TRG_PORT_CPU)
+			dest_queue = tpm_db_get_mc_cpu_queue();
+		else
+			dest_queue = tpm_db_get_mc_hwf_queue();
+	}
 	/* Create PNC entry */
 	ret_code = tpm_proc_add_ipv6_mc_pnc_entry(filter_mode, stream_num, igmp_mode, mc_stream_pppoe, vid,
-						  ipv6_src_add, ipv6_dst_add, ignore_ipv6_src, dest_port_bm);
+						  ipv6_src_add, ipv6_dst_add, ignore_ipv6_src,
+						  dest_queue, dest_port_bm);
 	IF_ERROR(ret_code);
 
 	/* Set switch port_map for multicast MAC, but don't overwrite FF02::1 (MLD General Query) MAC */
@@ -13382,10 +14181,11 @@
 	return(TPM_RC_OK);
 }
 
-tpm_error_code_t tpm_proc_delete_ipv6_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+tpm_error_code_t tpm_proc_delete_ipvx_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
 						   uint32_t stream_num,
 						   uint32_t dest_port_bm,
-						   uint32_t u4_entry)
+						   uint32_t u4_entry,
+						   tpm_ip_ver_t ip_version)
 {
 	tpm_db_pnc_range_t range_data;
 	tpm_rule_entry_t api_data;
@@ -13398,17 +14198,27 @@
 	uint32_t pnc_range_start = 0, api_start = 0, pnc_entry = 0;
 	uint32_t sip_index = 0;
 	uint8_t	 new_ref_num = 0;
+	tpm_pnc_ranges_t range;
+	tpm_api_sections_t api_section;
+
+	if (TPM_IP_VER_4 == ip_version) {
+		range = TPM_PNC_IPV4_MC_DS;
+		api_section = TPM_IPV4_MC;
+	} else {
+		range = TPM_PNC_IPV6_MC_DS;
+		api_section = TPM_IPV6_MC_ACL;
+	}
 
 	if (filter_mode != TPM_MC_MAC_ONLY_FILTER) {
 		/* Get PNC Range Start */
-		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+		ret_code = tpm_db_pnc_rng_get(range, &range_data);
 		IF_ERROR(ret_code);
 
 		if (stream_num >= range_data.pnc_range_conf.range_size)
 			IF_ERROR(ERR_MC_STREAM_INVALID);
 
 		/* Check parameters */
-		ret_code = tpm_db_api_entry_get(TPM_IPV6_MC_ACL, stream_num, &rule_idx, &bi_dir,
+		ret_code = tpm_db_api_entry_get(api_section, stream_num, &rule_idx, &bi_dir,
 						&api_data, &mod_con, &pnc_conn);
 		IF_ERROR(ret_code);
 
@@ -13428,38 +14238,41 @@
 		IF_ERROR(ret_code);
 
 		/* Increase number of free entries in pnc_range */
-		ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV6_MC_DS);
+		ret_code = tpm_db_pnc_rng_free_ent_inc(range);
 		IF_ERROR(ret_code);
 
 		if (mod_con.mod_cmd_ind != 0) {
-			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			ret_code = tpm_proc_delete_mod(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
 			IF_ERROR(ret_code);
 		}
 
 		/* Delete API Rule Entry */
-		ret_code = tpm_db_api_entry_invalidate(TPM_IPV6_MC_ACL, stream_num);
+		ret_code = tpm_db_api_entry_invalidate(api_section, stream_num);
 		IF_ERROR(ret_code);
 
-		/* remove SIP PNC entry */
-		ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
-		IF_ERROR(ret_code);
-		if (0 == mc_stream.ignore_src_addr) {
-			/* get index of this IPv6 MC SIP */
-			sip_index = tpm_db_ipv6_mc_sip_index_get(mc_stream.src_addr);
-			if (0 == sip_index) {
-				/* SIP is not in DB, error */
-				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
-				return(ERR_IPV6_MC_SRC_IP_INVALID);
-			}
-
-			/* dec reference number in DB */
-			ret_code = tpm_db_ipv6_mc_sip_ref_num_dec(sip_index, &new_ref_num);
+		
+		if (TPM_IP_VER_6 == ip_version) {
+			/* remove SIP PNC entry */
+			ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
 			IF_ERROR(ret_code);
+			if (0 == mc_stream.ignore_src_addr) {
+				/* get index of this IPv6 MC SIP */
+				sip_index = tpm_db_ipv6_mc_sip_index_get(mc_stream.src_addr);
+				if (0 == sip_index) {
+					/* SIP is not in DB, error */
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
+					return(ERR_IPV6_MC_SRC_IP_INVALID);
+				}
 
-			/* if new ref num is 0, remove this SIP in PNC */
-			if (new_ref_num == 0) {
-				ret_code = tpm_proc_ipv6_mc_sip_entry_del(sip_index);
+				/* dec reference number in DB */
+				ret_code = tpm_db_ipv6_mc_sip_ref_num_dec(sip_index, &new_ref_num);
 				IF_ERROR(ret_code);
+
+				/* if new ref num is 0, remove this SIP in PNC */
+				if (new_ref_num == 0) {
+					ret_code = tpm_proc_ipv6_mc_sip_entry_del(sip_index);
+					IF_ERROR(ret_code);
+				}
 			}
 		}
 
@@ -13478,7 +14291,10 @@
 	}
 
 	/* Remove stream entry */
-	tpm_db_reset_ipv6_mc_stream_entry(stream_num);
+	if (TPM_IP_VER_4 == ip_version)
+		tpm_db_reset_mc_stream_entry(stream_num);
+	else
+		tpm_db_reset_ipv6_mc_stream_entry(stream_num);
 
 	return(TPM_RC_OK);
 }
@@ -13491,6 +14307,7 @@
 						   uint8_t ipv6_dst_add[16],
 						   uint8_t sip_index,
 						   uint8_t ignore_sip,
+						   uint16_t dest_queue,
 						   uint32_t dest_port_bm)
 {
 	tpm_db_pnc_range_t range_data;
@@ -13508,6 +14325,11 @@
 
 	memset(&mc_stream, 0, sizeof(tpm_db_ipv6_mc_stream_entry_t));
 
+	/* Get old API Entry */
+	ret_code = tpm_db_api_entry_get(TPM_IPV6_MC_ACL, stream_num, &rule_idx, &bi_dir,
+					&api_data, &mod_con, &pnc_conn);
+	IF_ERROR(ret_code);
+
 	/* Only MC_IP_ONLY_FILTER mode, update the multicast group member ports by mh_mod. */
 	if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
 		/* Get PNC Range Start */
@@ -13517,16 +14339,11 @@
 		if (stream_num >= range_data.pnc_range_conf.range_size)
 			IF_ERROR(ERR_MC_STREAM_INVALID);
 
-		/* Get old API Entry */
-		ret_code = tpm_db_api_entry_get(TPM_IPV6_MC_ACL, stream_num, &rule_idx, &bi_dir,
-						&api_data, &mod_con, &pnc_conn);
-		IF_ERROR(ret_code);
-
 		pnc_entry = pnc_conn.pnc_conn_tbl[0].pnc_index;
 
 		/* Create new Modification Entry */
-		ret_code = tpm_proc_create_ipv6_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
-						       vid, ipv6_dst_add, dest_port_bm, &mod_entry);
+		ret_code = tpm_proc_create_ipvx_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
+						       vid, ipv6_dst_add, dest_port_bm, &mod_entry, TPM_IP_VER_6);
 		IF_ERROR(ret_code);
 
 		/* Rebuild PnC Entry */
@@ -13536,7 +14353,9 @@
 
 		/* Rebuild SRAM Entry */
 		ret_code =
-		tpm_proc_ipv6_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		tpm_proc_ipvx_mc_sram_build(filter_mode, igmp_mode, dest_queue,
+					dest_port_bm, mod_entry, &(pnc_data.pncl_sram),
+					TPM_IP_VER_6);
 		IF_ERROR(ret_code);
 
 		/* Update only Sram of PNC Entry */
@@ -13545,22 +14364,12 @@
 
 		/* Delete old Modification Entry */
 		if (mod_con.mod_cmd_ind != 0) {
-			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			ret_code = tpm_proc_delete_mod(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
 			IF_ERROR(ret_code);
 		}
 
 		/* Update new Modification Entry */
 		mod_con.mod_cmd_ind = mod_entry;
-
-		/* Invalidate old API Entry */
-		ret_code = tpm_db_api_entry_invalidate(TPM_IPV6_MC_ACL, stream_num);
-		IF_ERROR(ret_code);
-
-		/* Set new API Entry */
-		mod_con.mod_cmd_ind = mod_entry;
-		ret_code = tpm_db_api_entry_set(TPM_IPV6_MC_ACL, stream_num, 0 /*bi_dir */ ,
-						&api_data, &mod_con, &pnc_conn, &rule_idx);
-		IF_ERROR(ret_code);
 	}
 
 	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
@@ -13620,6 +14429,17 @@
 	ret_code = tpm_db_set_ipv6_mc_stream_entry(stream_num, &mc_stream);
 	IF_ERROR(ret_code);
 
+	/* Update API entry */
+	/* Invalidate old API Entry */
+	ret_code = tpm_db_api_entry_invalidate(TPM_IPV6_MC_ACL, stream_num);
+	IF_ERROR(ret_code);
+
+	/* Set new API Entry */
+	api_data.ipv6_mc_key.dest_port_bm = dest_port_bm;
+	ret_code = tpm_db_api_entry_set(TPM_IPV6_MC_ACL, stream_num, 0 /*bi_dir */ ,
+					&api_data, &mod_con, &pnc_conn, &rule_idx);
+	IF_ERROR(ret_code);
+
 	return(TPM_RC_OK);
 }
 
@@ -13669,6 +14489,12 @@
 	ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
 	IF_ERROR(ret_code);
 
+	if (dest_port_bm == mc_stream.dest_port_bm) {
+		/* nothing changed, return directly */
+		TPM_OS_INFO(TPM_TPM_LOG_MOD, "dest_port_bm does not change, return directly\n");
+		return (TPM_OK);
+	}
+
 	/* get sip_index */
 	if (0 == mc_stream.ignore_src_addr) {
 		/* get index of this IPv6 MC SIP */
@@ -13682,19 +14508,22 @@
 
 	if (((dest_port_bm & TPM_TRG_PORT_CPU) != 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) == 0) ||
 	    ((dest_port_bm & TPM_TRG_PORT_CPU) == 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) != 0)) {
-		ret_code = tpm_proc_delete_ipv6_mc_pnc_entry(filter_mode, stream_num,
-							     mc_stream.dest_port_bm, mc_stream.u4_entry);
+		ret_code = tpm_proc_delete_ipvx_mc_pnc_entry(filter_mode, stream_num,
+							     mc_stream.dest_port_bm,
+							     mc_stream.u4_entry,
+							     TPM_IP_VER_6);
 		IF_ERROR(ret_code);
 
 		ret_code = tpm_proc_add_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
 							  mc_stream.mc_stream_pppoe, mc_stream.vid,
-							  mc_stream.group_addr, mc_stream.src_addr,
-							  mc_stream.ignore_src_addr, dest_port_bm);
+							  mc_stream.src_addr, mc_stream.group_addr,
+							  mc_stream.ignore_src_addr, mc_stream.dest_queue,
+							  dest_port_bm);
 	} else {
 		ret_code = tpm_proc_update_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
 							     mc_stream.mc_stream_pppoe, mc_stream.vid,
 							     mc_stream.group_addr, sip_index, mc_stream.ignore_src_addr,
-							     dest_port_bm);
+							     mc_stream.dest_queue, dest_port_bm);
 	}
 	IF_ERROR(ret_code);
 
@@ -13734,7 +14563,10 @@
 	IF_ERROR(ret_code);
 
 	ret_code =
-	tpm_proc_delete_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.dest_port_bm, mc_stream.u4_entry);
+	tpm_proc_delete_ipvx_mc_pnc_entry(filter_mode, stream_num,
+					  mc_stream.dest_port_bm,
+					  mc_stream.u4_entry,
+					  TPM_IP_VER_6);
 	IF_ERROR(ret_code);
 
 	/* Set switch VID and multicast MAC */
@@ -13838,6 +14670,59 @@
 
 	return(TPM_RC_OK);
 }
+tpm_error_code_t tpm_proc_set_active_wan_check(tpm_gmacs_enum_t active_wan)
+{
+	tpm_gmacs_enum_t active_wan_current;
+	tpm_eth_complex_profile_t profile_id;
+
+	if(!tpm_db_switch_active_wan_en_get()) {
+		TPM_OS_ERROR(TPM_DB_MOD, "current profile does not support switching active wan\n");
+		return ERR_FEAT_UNSUPPORT;
+	}
+
+	active_wan_current = tpm_db_active_wan_get();
+	profile_id = tpm_db_eth_cmplx_profile_get();
+
+	if (active_wan == active_wan_current) {
+		TPM_OS_ERROR(TPM_DB_MOD, "new active wan port should not be the same with current one\n");
+		return ERR_FEAT_UNSUPPORT;
+	}
+
+	if (    ((profile_id == TPM_PON_G1_WAN_G0_INT_SWITCH) || (profile_id == TPM_PON_G1_WAN_G0_SINGLE_PORT))
+	     && ((active_wan == TPM_ENUM_GMAC_1) || (active_wan == TPM_ENUM_PMAC)))
+		;/* OK */
+	else if  (    ((profile_id == TPM_PON_G0_WAN_G1_INT_SWITCH) || (profile_id == TPM_PON_G0_WAN_G1_SINGLE_PORT))
+	           && ((active_wan == TPM_ENUM_GMAC_0) || (active_wan == TPM_ENUM_PMAC)))
+		;/* OK */
+	else {
+		TPM_OS_ERROR(TPM_DB_MOD, "new active wan port is invalid according to current profile id\n");
+		return ERR_FEAT_UNSUPPORT;
+	}
+
+	return TPM_OK;
+}
+tpm_error_code_t tpm_proc_set_active_wan(tpm_gmacs_enum_t active_wan)
+{
+	int32_t db_ret;
+	tpm_error_code_t tpm_ret;
+
+	tpm_ret = tpm_proc_set_active_wan_check(active_wan);
+	if(TPM_OK != tpm_ret) {
+		TPM_OS_ERROR(TPM_DB_MOD, "input active wan is invalid, error code (%d)\n", tpm_ret);
+		return ERR_GENERAL;
+	}
+
+	db_ret = tpm_db_active_wan_set(active_wan);
+	if(TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_DB_MOD, "set current active wan failed(%d)\n", db_ret);
+		return ERR_GENERAL;
+	}
+	/* reset gmac fun */
+	tpm_db_mac_func_set();
+
+	return (TPM_OK);
+}
+
 
 tpm_error_code_t tpm_proc_ipv6_mc_sip_init(void)
 {
@@ -14236,6 +15121,7 @@
 
 	/* Set next offset and update register */
 	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
 
 	/*** Set next lookup configuration ***/
 
@@ -14719,7 +15605,6 @@
 	long long int_pkt_act = 0;
 	tpm_ai_vectors_t key_field;
 	tpm_db_pon_type_t pon_type;
-	uint32_t i;
 	int32_t ret_code;
 
 	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
@@ -14763,11 +15648,7 @@
 		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
 
 		/* Set PNC FlowId Target */
-		for (i = 0; i < 8; i++) {
-			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
-				break;
-		}
-		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+		sram_data->flow_id_sub.pnc_target = tpm_proc_cnm_pnc_trg_get(pkt_frwd->trg_port);
 
 		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
 
@@ -14877,7 +15758,6 @@
 {
 	tpm_ai_vectors_t key_field;
 	tpm_db_pon_type_t pon_type;
-	uint32_t i;
 
 	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
 
@@ -14902,11 +15782,7 @@
 		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
 
 		/* Set PNC FlowId Target */
-		for (i = 0; i < 8; i++) {
-			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
-				break;
-		}
-		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+		sram_data->flow_id_sub.pnc_target = tpm_proc_cnm_pnc_trg_get(pkt_frwd->trg_port);
 
 		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
 
@@ -14933,7 +15809,29 @@
 
 	return(TPM_OK);
 }
+tpm_pnc_trg_t tpm_proc_cnm_pnc_trg_get(tpm_trg_port_type_t trg_port)
+{
+	uint32_t i;
+	tpm_pnc_trg_t pnc_trgt = 0;
+	tpm_gmacs_enum_t   active_wan;
 
+	active_wan = tpm_db_active_wan_get();
+
+	/* Set PNC FlowId Target */
+	if (TPM_ENUM_PMAC == active_wan) {
+		for (i = 0; i < 8; i++) {
+			if (trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
+				break;
+		}
+		pnc_trgt = TPM_PNC_TRG_PMAC0 + i;
+	} else if (TPM_ENUM_GMAC_0 == active_wan)
+		pnc_trgt = TPM_PNC_TRG_GMAC0;
+	else if (TPM_ENUM_GMAC_1 == active_wan)
+		pnc_trgt = TPM_PNC_TRG_GMAC1;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", pnc_trgt);
+	return pnc_trgt;
+}
 int32_t tpm_proc_cnm_ipv4_tcam_build(tpm_src_port_type_t src_port,
 				     uint32_t precedence,
 				     tpm_parse_fields_t ipv4_parse_rule_bm,
@@ -14992,7 +15890,6 @@
 {
 	tpm_ai_vectors_t key_field;
 	tpm_db_pon_type_t pon_type;
-	uint32_t i;
 
 	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
 
@@ -15016,12 +15913,7 @@
 		/* Add Target Txp to update BM */
 		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
 
-		/* Set PNC FlowId Target */
-		for (i = 0; i < 8; i++) {
-			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
-				break;
-		}
-		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+		sram_data->flow_id_sub.pnc_target = tpm_proc_cnm_pnc_trg_get(pkt_frwd->trg_port);
 
 		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
 
@@ -15098,6 +15990,8 @@
 				 uint32_t precedence,
 				 tpm_parse_fields_t l2_parse_rule_bm,
 				 tpm_l2_acl_key_t *l2_key,
+				 tpm_parse_fields_t ipv4_parse_rule_bm,
+				 tpm_ipv4_acl_key_t *ipv4_key,
 				 uint32_t ipv4_key_idx,
 				 tpm_pkt_frwd_t *pkt_frwd,
 				 tpm_pkt_action_t pkt_act,
@@ -15190,10 +16084,13 @@
 	/* Set PNC API data */
 	api_data.cnm_key.src_port = src_port;
 	api_data.cnm_key.l2_parse_rule_bm = l2_parse_rule_bm;
+	api_data.cnm_key.ipv4_parse_rule_bm = ipv4_parse_rule_bm;
 	api_data.cnm_key.pkt_act = pkt_act;
 	api_data.cnm_key.pbits = pbits;
 	if (l2_key)
 		memcpy(&(api_data.cnm_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+	if (ipv4_key)
+		memcpy(&(api_data.cnm_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
 	if (pkt_frwd != NULL)
 		memcpy(&(api_data.cnm_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
 	else
@@ -15564,6 +16461,49 @@
 }
 
 /*******************************************************************************
+* tpm_proc_mac_learn_port_gmac_bm_map()
+*
+* DESCRIPTION:    The function get the MAC learn port by means of the GMAC Functionality
+*                 for Media convert with loopback mode.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* gmac_bm          - Bitmap of the GMACs relevant to set in TCAM
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_mac_learn_port_gmac_bm_map(tpm_gmac_bm_t *gmac_bm)
+{
+	int32_t ret_code = TPM_DB_OK;
+	uint32_t gmac_id;
+	tpm_db_gmac_func_t gfunc;
+	tpm_gmac_bm_t l_gmac_bm = 0;
+
+	/* Find the GMAC used to do MAC learn on MC */
+	for (gmac_id = TPM_ENUM_GMAC_0; gmac_id < TPM_MAX_NUM_GMACS; gmac_id ++) {
+		ret_code = tpm_db_gmac_func_get(gmac_id, &gfunc);
+		if (TPM_DB_OK == ret_code) {
+			if (TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI == gfunc)
+				l_gmac_bm |= gmac_pnc_bm[gmac_id];
+		} else {
+			TPM_OS_ERROR(TPM_DB_MOD, "GMAC%d Func get failed \n", gmac_id);
+			return ret_code;
+		}
+	}
+
+	*gmac_bm = l_gmac_bm;
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
 * tpm_proc_mac_learn_tcam_build()
 *
 * DESCRIPTION:     Function builds a logical TCAM entry from the API data
@@ -15588,10 +16528,15 @@
 	int32_t ret_code;
 	uint32_t lu_id;
 	tpm_pncl_offset_t start_offset;
+	tpm_gmac_bm_t gmac_bm;
 
 	/* L2 Parsing, according to bm in param */
 	tcam_data->l2_parse_bm = TPM_L2_PARSE_MAC_SA;
-	tcam_data->port_ids = TPM_BM_GMAC_0;
+
+	/* Get GMAC(s) */
+	ret_code = tpm_proc_mac_learn_port_gmac_bm_map(&gmac_bm);
+	IF_ERROR(ret_code);
+	tcam_data->port_ids = gmac_bm;
 
 	/* Copy in logical PnC Key */
 	if (src_mac_addr)
@@ -15959,7 +16904,7 @@
 	if (addr_exist)
 		return TPM_OK;
 	/* Get Tx queue */
-	if (tpm_db_gmac_lpk_queue_get(&gmac_num, &queue_idx)) {
+	if (tpm_db_gmac_lpk_queue_get(&gmac_num, &queue_idx, TPM_GMAC1_QUEUE_DATA_TRAFFIC)) {
 		printk("Loopback Tx queue index get failed\n");
 		return TPM_FAIL;
 	}
@@ -16045,10 +16990,11 @@
 	tpm_db_pnc_range_t range_data;
 	tpm_pnc_all_t pnc_entry;
 	uint32_t entry_id;
-	int32_t cpu_rx_queue;
 	uint32_t queue_id;
 	tpm_gmacs_enum_t lpk_gmac;
 	uint32_t switch_init;
+	uint32_t mod_idx = 0;
+	tpm_pkt_mod_t mod_data;
 
 	/* check switch init */
 	ret_code = tpm_db_switch_init_get(&switch_init);
@@ -16072,6 +17018,12 @@
 	IF_ERROR(ret_code);
 	entry_id = range_data.pnc_range_conf.range_end;
 
+	/* Get mod_idx */
+	if (TPM_DB_OK != tpm_db_mac_learn_mod_idx_get(&mod_idx)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "MAC learn mod index get failed \n");
+		return TPM_FAIL;
+	}
+
 	/* construct default rule */
 	/* Set Lookup Id */
 	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
@@ -16086,28 +17038,77 @@
 	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
 	switch (mac_conf) {
 	case TPM_UNK_MAC_TRAP:
-		/* Get default CPU queue */
-		tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
-		/* Trap to CPU */
-		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_CPU << TPM_TXP_FL_SHIFT);
-		pnc_entry.sram_entry.pnc_queue = cpu_rx_queue;
-		/* Set result info */
-		pnc_entry.sram_entry.res_info_15_0_data |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
-		pnc_entry.sram_entry.res_info_15_0_mask |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
+		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+							   &queue_id,
+							   TPM_GMAC1_QUEUE_MAC_LEARN_TRAFFIC)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback gmac queue get failed \n");
+			return TPM_FAIL;
+		}
+		/* Alloc PMT for MAC learn if needed */
+		if (mod_idx == 0) {
+			memset((uint8_t *) &mod_data, 0, sizeof(tpm_pkt_mod_t));
+			mod_data.mh_mod = TPM_MOD2_MAC_LEARN_MH;
+			if (tpm_mod2_entry_set(owner_id,
+					       lpk_gmac,
+					       TPM_MH_SET,
+					       0,
+					       &mod_data,
+					       &mod_idx)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "PMT entry for MAC leanrn get failed\n");
+				return TPM_FAIL;
+			}
+			/* store mod_idx in TPM_DB */
+			if (TPM_DB_OK != tpm_db_mac_learn_mod_idx_set(mod_idx)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Mod index set to tpm db failed \n");
+				return TPM_FAIL;
+			}
+		}
+		/* Frwd to loopback GMAC1 */
+		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC1 << TPM_TXP_FL_SHIFT);
+		pnc_entry.sram_entry.pnc_queue = queue_id;
+		/* Set MH */
+		pnc_entry.sram_entry.flowid_val |= mod_idx;
+		pnc_entry.sram_entry.flowid_updt_mask |= TPM_MOD_FL_UPDT_MASK;
 		break;
 	case TPM_UNK_MAC_DROP:
 		/* Drop the packet */
 		pnc_entry.sram_entry.res_info_15_0_data |= (1 << TPM_PNC_RI_DISC_BIT);
 		pnc_entry.sram_entry.res_info_15_0_mask |= (1 << TPM_PNC_RI_DISC_BIT);
+		/* delete MAC learn PMT entry if there is */
+		if (mod_idx) {
+			if (tpm_mod2_entry_del(owner_id, TPM_ENUM_GMAC_1, mod_idx)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "PMT entry del failed\n");
+				return TPM_FAIL;
+			}
+			/* clearn mod index in TPM_DB */
+			if (TPM_DB_OK != tpm_db_mac_learn_mod_idx_set(0)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "MAC learn mod index clear failed \n");
+				return TPM_FAIL;
+			}
+		}
 		break;
 	case TPM_UNK_MAC_CONTINUE:
-		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
+		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+							   &queue_id,
+							   TPM_GMAC1_QUEUE_DATA_TRAFFIC)) {
 			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback gmac queue get failed \n");
 			return TPM_FAIL;
 		}
 		/* Frwd to loopback GMAC1 */
 		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC1 << TPM_TXP_FL_SHIFT);
 		pnc_entry.sram_entry.pnc_queue = queue_id;
+		/* delete MAC learn PMT entry if there is */
+		if (mod_idx) {
+			if (tpm_mod2_entry_del(owner_id, TPM_ENUM_GMAC_1, mod_idx)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "PMT entry del failed\n");
+				return TPM_FAIL;
+			}
+			/* clearn mod index in TPM_DB */
+			if (TPM_DB_OK != tpm_db_mac_learn_mod_idx_set(0)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "MAC learn mod index clear failed \n");
+				return TPM_FAIL;
+			}
+		}
 		break;
 	default:
 		break;
@@ -16123,6 +17124,626 @@
 	return TPM_OK;
 }
 
+tpm_error_code_t tpm_acl_rcvr_func_mac_learn(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_static_mac_rule(owner_id, &(api_data->api_rule_data.l2_prim_key.l2_key));
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ds_load_balance(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_ds_load_balance_acl_rule(owner_id, api_data->rule_num, &rule_index_tmp,
+					api_data->api_rule_data.l2_prim_key.parse_rule_bm,
+					api_data->api_rule_data.l2_prim_key.parse_flags_bm,
+					&(api_data->api_rule_data.l2_prim_key.l2_key),
+					api_data->api_rule_data.l2_prim_key.pkt_frwd.trg_port);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_api_entry_update_rule_idx(TPM_DS_LOAD_BALANCE_ACL, rule_index_tmp, api_data->rule_idx);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_cpu_loopback(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_cpu_loopback_rule(owner_id, api_data->rule_num, &rule_index_tmp,
+					&(api_data->api_rule_data.l2_prim_key.pkt_frwd));
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_api_entry_update_rule_idx(TPM_CPU_LOOPBACK_ACL, rule_index_tmp, api_data->rule_idx);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_l2_prim(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_l2_prim_acl_rule(owner_id, api_data->api_rule_data.l2_prim_key.src_port,
+					api_data->rule_num, &rule_index_tmp,
+					api_data->api_rule_data.l2_prim_key.parse_rule_bm,
+					api_data->api_rule_data.l2_prim_key.parse_flags_bm,
+					&(api_data->api_rule_data.l2_prim_key.l2_key),
+					&(api_data->api_rule_data.l2_prim_key.pkt_frwd),
+					&(api_data->api_rule_data.l2_prim_key.pkt_mod),
+					api_data->api_rule_data.l2_prim_key.pkt_mod_bm,
+					&(api_data->api_rule_data.l2_prim_key.rule_action));
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_L2_PRIM_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_l3_type(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_l3_type_acl_rule(owner_id, api_data->api_rule_data.l3_type_key.src_port,
+					api_data->rule_num, &rule_index_tmp,
+					api_data->api_rule_data.l3_type_key.parse_rule_bm,
+					api_data->api_rule_data.l3_type_key.parse_flags_bm,
+					&(api_data->api_rule_data.l3_type_key.l3_key),
+					&(api_data->api_rule_data.l3_type_key.pkt_frwd),
+					&(api_data->api_rule_data.l3_type_key.rule_action));
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_L3_TYPE_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv4(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	ret_code = tpm_proc_add_ipv4_acl_rule(owner_id, api_data->api_rule_data.ipv4_key.src_port,
+					api_data->rule_num, &rule_index_tmp,
+					api_data->api_rule_data.ipv4_key.parse_rule_bm,
+					api_data->api_rule_data.ipv4_key.parse_flags_bm,
+					&(api_data->api_rule_data.ipv4_key.ipv4_key),
+					&(api_data->api_rule_data.ipv4_key.pkt_frwd),
+					&(api_data->api_rule_data.ipv4_key.pkt_mod),
+					api_data->api_rule_data.ipv4_key.pkt_mod_bm,
+					&(api_data->api_rule_data.ipv4_key.rule_action));
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_IPV4_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv4_mc(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	ret_code = tpm_proc_add_ipv4_mc_stream(owner_id,
+					api_data->api_rule_data.ipv4_mc_key.stream_num,
+					api_data->api_rule_data.ipv4_mc_key.igmp_mode,
+					api_data->api_rule_data.ipv4_mc_key.mc_stream_pppoe,
+					api_data->api_rule_data.ipv4_mc_key.vid,
+					api_data->api_rule_data.ipv4_mc_key.ipv4_src_add,
+					api_data->api_rule_data.ipv4_mc_key.ipv4_dest_add,
+					api_data->api_rule_data.ipv4_mc_key.ignore_ipv4_src,
+					api_data->api_rule_data.ipv4_mc_key.dest_queue,
+					api_data->api_rule_data.ipv4_mc_key.dest_port_bm);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_gen(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_dir_t src_dir;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	/* Check 5_tuple feature is enable/disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		ret_code = tpm_proc_add_ipv6_gen_acl_rule(owner_id, api_data->api_rule_data.ipv6_gen_key.src_port,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_gen_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_gen_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_gen_key.ipv6_gen_key),
+						&(api_data->api_rule_data.ipv6_gen_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_gen_key.pkt_mod),
+						api_data->api_rule_data.ipv6_gen_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_gen_key.rule_action));
+	else {
+		/* get direction */
+		if (FROM_LAN(api_data->api_rule_data.ipv6_gen_key.src_port))
+			src_dir = TPM_DIR_US;
+		else
+			src_dir = TPM_DIR_DS;
+		ret_code = tpm_proc_add_ipv6_gen_5t_rule(owner_id, src_dir,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_gen_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_gen_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_gen_key.l4_key),
+						&(api_data->api_rule_data.ipv6_gen_key.ipv6_gen_key),
+						&(api_data->api_rule_data.ipv6_gen_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_gen_key.pkt_mod),
+						api_data->api_rule_data.ipv6_gen_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_gen_key.rule_action));
+	}
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_IPV6_GEN_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_dip(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_dir_t src_dir;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	/* Check 5_tuple feature is enable/disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		ret_code = tpm_proc_add_ipv6_dip_acl_rule(owner_id, api_data->api_rule_data.ipv6_dip_key.src_port,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_dip_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_dip_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_dip_key.ipv6_dipkey),
+						&(api_data->api_rule_data.ipv6_dip_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_dip_key.pkt_mod),
+						api_data->api_rule_data.ipv6_dip_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_dip_key.rule_action));
+	else {
+		/* get direction */
+		if (FROM_LAN(api_data->api_rule_data.ipv6_dip_key.src_port))
+			src_dir = TPM_DIR_US;
+		else
+			src_dir = TPM_DIR_DS;
+		ret_code = tpm_proc_add_ipv6_dip_5t_rule(owner_id, src_dir,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_dip_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_dip_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_dip_key.l4_key),
+						&(api_data->api_rule_data.ipv6_dip_key.ipv6_gen_key),
+						&(api_data->api_rule_data.ipv6_dip_key.ipv6_dipkey),
+						&(api_data->api_rule_data.ipv6_dip_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_dip_key.pkt_mod),
+						api_data->api_rule_data.ipv6_dip_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_dip_key.rule_action));
+	}
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_IPV6_DIP_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_mc(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	ret_code = tpm_proc_add_ipv6_mc_stream(owner_id,
+					api_data->api_rule_data.ipv6_mc_key.stream_num,
+					api_data->api_rule_data.ipv6_mc_key.igmp_mode,
+					api_data->api_rule_data.ipv6_mc_key.mc_stream_pppoe,
+					api_data->api_rule_data.ipv6_mc_key.vid,
+					api_data->api_rule_data.ipv6_mc_key.ipv6_src_add,
+					api_data->api_rule_data.ipv6_mc_key.ipv6_dest_add,
+					api_data->api_rule_data.ipv6_mc_key.ignore_ipv6_src,
+					api_data->api_rule_data.ipv6_mc_key.dest_queue,
+					api_data->api_rule_data.ipv6_mc_key.dest_port_bm);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_nh(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	ret_code = tpm_proc_add_ipv6_nh_acl_rule(owner_id,
+					api_data->rule_num, &rule_index_tmp,
+					api_data->api_rule_data.ipv6_nh_key.parse_flags_bm,
+					api_data->api_rule_data.ipv6_nh_key.nh_iter,
+					api_data->api_rule_data.ipv6_nh_key.nh,
+					&(api_data->api_rule_data.ipv6_nh_key.pkt_frwd),
+					&(api_data->api_rule_data.ipv6_nh_key.rule_action));
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_IPV6_NH_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_l4(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	uint32_t rule_index_tmp;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_dir_t src_dir;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+
+	/* Check 5_tuple feature is enable/disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		ret_code = tpm_proc_add_ipv6_l4_ports_acl_rule(owner_id, api_data->api_rule_data.ipv6_l4_key.src_port,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_l4_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_l4_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_l4_key.l4_key),
+						&(api_data->api_rule_data.ipv6_l4_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_l4_key.pkt_mod),
+						api_data->api_rule_data.ipv6_l4_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_l4_key.rule_action));
+	else {
+		/* get direction */
+		if (FROM_LAN(api_data->api_rule_data.ipv6_l4_key.src_port))
+			src_dir = TPM_DIR_US;
+		else
+			src_dir = TPM_DIR_DS;
+		ret_code = tpm_proc_add_ipv6_l4_ports_5t_rule(owner_id, src_dir,
+						api_data->rule_num, &rule_index_tmp,
+						api_data->api_rule_data.ipv6_l4_key.parse_rule_bm,
+						api_data->api_rule_data.ipv6_l4_key.parse_flags_bm,
+						&(api_data->api_rule_data.ipv6_l4_key.l4_key),
+						&(api_data->api_rule_data.ipv6_l4_key.pkt_frwd),
+						&(api_data->api_rule_data.ipv6_l4_key.pkt_mod),
+						api_data->api_rule_data.ipv6_l4_key.pkt_mod_bm,
+						&(api_data->api_rule_data.ipv6_l4_key.rule_action));
+	}
+	IF_ERROR(ret_code);
+
+	if (rule_idx_updt_en) {
+		ret_code = tpm_db_api_entry_update_rule_idx(TPM_L4_ACL, rule_index_tmp, api_data->rule_idx);
+		IF_ERROR(ret_code);
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_acl_rcvr_func_cnm(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en)
+{
+	tpm_error_code_t ret_code;
+	static tpm_src_port_type_t src_port = TPM_SRC_PORT_UNI_0;
+	static uint32_t precedence_base = 0;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "rule_index:[%d]\n", api_data->rule_idx);
+	if (src_port < api_data->api_rule_data.cnm_key.src_port) {
+		src_port = api_data->api_rule_data.cnm_key.src_port;
+		precedence_base = api_data->rule_num;
+	} else if (src_port > api_data->api_rule_data.cnm_key.src_port) {
+		src_port = api_data->api_rule_data.cnm_key.src_port;
+		precedence_base = 0;
+	}
+	ret_code = tpm_ctc_cm_acl_rule_add(owner_id, api_data->api_rule_data.cnm_key.src_port,
+					api_data->rule_num - precedence_base,
+					api_data->api_rule_data.cnm_key.l2_parse_rule_bm,
+					api_data->api_rule_data.cnm_key.ipv4_parse_rule_bm,
+					api_data->api_rule_data.cnm_key.ipv6_parse_rule_bm,
+					&(api_data->api_rule_data.cnm_key.l2_key),
+					&(api_data->api_rule_data.cnm_key.ipv4_key),
+					&(api_data->api_rule_data.cnm_key.ipv6_key),
+					&(api_data->api_rule_data.cnm_key.pkt_frwd),
+					api_data->api_rule_data.cnm_key.pkt_act,
+					api_data->api_rule_data.cnm_key.pbits);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+
+tpm_error_code_t tpm_acl_rcvr_func_get(tpm_api_type_t api_type, tpm_acl_recovery_func *func)
+{
+	uint32_t api_loop;
+	uint32_t api_max;
+
+	api_max = sizeof(tpm_hot_swap_acl_recovery)/sizeof(tpm_hot_swap_acl_recovery_t);
+
+	for (api_loop = 0; api_loop < api_max; api_loop++) {
+
+		if (tpm_hot_swap_acl_recovery[api_loop].api_type == api_type) {
+			*func = tpm_hot_swap_acl_recovery[api_loop].func;
+			return TPM_OK;
+		}
+	}
+	return (TPM_OK);
+}
+#ifdef CONFIG_MV_ETH_WAN_SWAP
+
+tpm_error_code_t tpm_proc_check_hot_swap_profile(uint32_t owner_id,
+				    			tpm_eth_complex_profile_t profile_id)
+{
+	tpm_error_code_t ret_code;
+	tpm_api_type_t api_type;
+	tpm_eth_complex_profile_t profile_current;
+
+	/* Check owner_id */
+	for (api_type = TPM_API_MAC_LEARN; api_type < TPM_MAX_API_TYPES; api_type++) {
+		ret_code = tpm_owner_id_check(api_type, owner_id);
+		IF_ERROR(ret_code);
+	}
+
+	/* check profile id */
+	profile_current = tpm_db_eth_cmplx_profile_get();
+	if (    TPM_G0_WAN_G1_INT_SWITCH == profile_current
+	     && TPM_G1_WAN_G0_INT_SWITCH == profile_id)
+		/* allowed */
+		;
+	else if (    TPM_G1_WAN_G0_INT_SWITCH == profile_current
+	          && TPM_G0_WAN_G1_INT_SWITCH == profile_id)
+		/* allowed */
+		;
+	else {
+		/* not support */
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "So far only swapping  from TPM_PON_G1_WAN_G0_INT_SWITCH "
+				"to TPM_PON_G0_WAN_G1_INT_SWITCH or vice versa are supported,"
+				"current profile: [%d], new profile: [%d]\n", profile_current, profile_id);
+		return ERR_FEAT_UNSUPPORT;
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_proc_hot_swap_update_acl_rules(uint32_t owner_id)
+{
+	tpm_db_api_entry_t api_data;
+	tpm_api_type_t api_type;
+	tpm_acl_recovery_func func = NULL;
+	tpm_api_sections_t api_section;
+	int32_t db_ret = 0;
+	int32_t next_rule = 0;
+	uint32_t current_rule = 0;
+	uint32_t rule_index = 0;
+	uint32_t rule_index_max = 0;
+	tpm_error_code_t ret_code;
+	uint32_t rule_idx_updt_en = 0;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	//tpm_glob_trace = ~0;
+
+	rule_index_max = 1000;
+
+	/* add ACL rules again */
+	for (api_type = TPM_API_MAC_LEARN; api_type < TPM_MAX_API_TYPES; api_type++) {
+
+		/* Get acl recovery func */
+		ret_code = tpm_acl_rcvr_func_get(api_type, &func);
+		IF_ERROR(ret_code);
+
+		/* Get the api_section */
+		ret_code = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+		IF_ERROR(ret_code);
+
+		current_rule = -1;
+
+		TPM_OS_INFO(TPM_DB_MOD, "api_type(%d)\n\n", api_type);
+
+		ret_code = tpm_db_api_entry_bak_get_next(api_section, current_rule, &next_rule);
+		IF_ERROR(ret_code);
+
+		if (-1 == next_rule) {
+			continue;
+		}
+
+		/* Get Range_Id */
+		tpm_db_api_section_main_pnc_get(api_section, &range_id);
+
+		/* Get Range Conf */
+		ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+		IF_ERROR(ret_code);
+
+		if (range_conf.range_type == TPM_RANGE_TYPE_ACL)
+			rule_idx_updt_en = TPM_TRUE;
+		else
+			rule_idx_updt_en = TPM_FALSE;
+
+		while (-1 != next_rule) {
+			/*get api section table entry*/
+			if (tpm_db_api_section_bak_ent_tbl_get(api_section, &api_data, next_rule)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get API data failed, api_section:[%d], rule_index:[%d] \n",
+						api_section, rule_index);
+				return TPM_FAIL;
+			}
+
+			if (api_data.valid != TPM_DB_VALID) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "API data is not valid, api_section:[%d], rule_index:[%d] \n",
+						api_section, rule_index);
+				return TPM_FAIL;
+			}
+			TPM_OS_INFO(TPM_DB_MOD, "rule_num(%d), rule_idx(%d) \n", api_data.rule_num, api_data.rule_idx);
+
+			ret_code = (*func)(owner_id, &api_data, rule_idx_updt_en);
+			IF_ERROR(ret_code);
+
+			if (rule_index_max < api_data.rule_idx)
+				rule_index_max = api_data.rule_idx;
+
+			ret_code = tpm_db_api_entry_bak_get_next(api_section, api_data.rule_num, &next_rule);
+			IF_ERROR(ret_code);
+		}
+
+		IF_ERROR(ret_code);
+	}
+
+	/* update the max rule index */
+	db_ret = tpm_db_rule_index_set(rule_index_max + 1);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "update rule_index failed, before hot swap, max rule_index:[%d]\n", rule_index_max);
+		return TPM_FAIL;
+	}
+	return (TPM_OK);
+}
+tpm_error_code_t tpm_proc_hot_swap_misc_cfg(tpm_eth_complex_profile_t profile_id)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_gmac_conn_conf_t	gmac_port_conf[TPM_NUM_GMACS];
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t gmac0_mh_en = 0;
+	uint32_t gmac1_mh_en = 0;
+	tpm_db_mh_src_t ds_mh_set_conf;
+
+	/* keep current API data */
+	tpm_db_api_data_backup();
+
+	/* do not update switch */
+	tpm_db_switch_init_set(false);
+
+	/* restore normal IPG of GMAC and switch */
+	ret_code = tpm_init_ipg(TPM_MH_LEN);
+	IF_ERROR(ret_code);
+
+	/* set new profile_id */
+	tpm_db_eth_cmplx_profile_set(profile_id);
+
+	/* update active wan and GMAC conf */
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++)
+		tpm_db_gmac_conn_conf_get(gmac_i, &(gmac_port_conf[gmac_i]));
+
+	if (TPM_G0_WAN_G1_INT_SWITCH == profile_id) {
+		tpm_db_active_wan_set(TPM_ENUM_GMAC_0);
+		gmac_port_conf[TPM_ENUM_GMAC_0].conn = TPM_GMAC_CON_RGMII2;
+		gmac_port_conf[TPM_ENUM_GMAC_0].port_src = TPM_SRC_PORT_WAN;
+		gmac_port_conf[TPM_ENUM_GMAC_1].conn = TPM_GMAC_CON_SWITCH_5;
+		gmac_port_conf[TPM_ENUM_GMAC_1].port_src = TPM_SRC_PORT_ILLEGAL;
+		gmac0_mh_en = TPM_FALSE;
+		gmac1_mh_en = TPM_TRUE;
+	} else if (TPM_G1_WAN_G0_INT_SWITCH == profile_id){
+		tpm_db_active_wan_set(TPM_ENUM_GMAC_1);
+		gmac_port_conf[TPM_ENUM_GMAC_0].conn = TPM_GMAC_CON_SWITCH_4;
+		gmac_port_conf[TPM_ENUM_GMAC_0].port_src = TPM_SRC_PORT_ILLEGAL;
+		gmac_port_conf[TPM_ENUM_GMAC_1].conn = TPM_GMAC_CON_GE_PHY;
+		gmac_port_conf[TPM_ENUM_GMAC_1].port_src = TPM_SRC_PORT_WAN;
+		gmac0_mh_en = TPM_TRUE;
+		gmac1_mh_en = TPM_FALSE;
+	}
+
+	/* Set GMAC Port Config */
+	ret_code = tpm_db_gmac_conn_conf_set(gmac_port_conf, TPM_NUM_GMACS);
+	IF_ERROR(ret_code);
+
+	/* update GMAC func */
+	tpm_db_mac_func_set();
+
+	tpm_db_ds_mh_get_conf_set(&ds_mh_set_conf);
+
+	/* update MH conf */
+	ret_code = tpm_init_mh(ds_mh_set_conf, gmac0_mh_en, gmac1_mh_en, gmac_port_conf);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_gmac_mh_en_conf_set(TPM_ENUM_GMAC_0, gmac0_mh_en);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_mh_en_conf_set(TPM_ENUM_GMAC_1, gmac1_mh_en);
+	IF_ERROR(ret_code);
+
+	/* update rate limitation */
+	ret_code = tpm_init_get_gmac_queue_rate_limit();
+	IF_ERROR(ret_code);
+
+	/* exchange rate limitation between G0/G1 */
+	tpm_init_get_gmac_queue_rate_limit();
+	tpm_db_wan_lan_rate_limit_exchange();
+
+	/* set new IPG of GMAC and switch */
+	ret_code = tpm_init_ipg((-TPM_MH_LEN));
+	IF_ERROR(ret_code);
+
+	/* switch pppoe length reg's value */
+	tpm_mod2_registers_init(TPM_ENUM_GMAC_0, 0);
+	tpm_mod2_registers_init(TPM_ENUM_GMAC_1, 0);
+
+#if 0
+	/* Set GMAC mh_enable */
+	if (mv_eth_ctrl_flag(TPM_ENUM_GMAC_0, MV_ETH_F_MH, gmac0_mh_en)){
+		TPM_OS_ERROR(TPM_INIT_MOD, " set GMAC0 MH en (%d) failed\n", gmac0_mh_en);
+		return (TPM_FAIL);
+	}
+	if (mv_eth_ctrl_flag(TPM_ENUM_GMAC_1, MV_ETH_F_MH, gmac1_mh_en)){
+		TPM_OS_ERROR(TPM_INIT_MOD, " set GMAC1 MH en (%d) failed\n", gmac1_mh_en);
+		return (TPM_FAIL);
+	}
+#endif
+
+	return (TPM_OK);
+}
+
+extern int mv_eth_wan_swap(int wan_mode);
+tpm_error_code_t tpm_proc_hot_swap_lsp(tpm_eth_complex_profile_t profile_id)
+{
+	int lsp_ret = 0;
+
+	if (TPM_G0_WAN_G1_INT_SWITCH == profile_id)
+		lsp_ret = mv_eth_wan_swap(0);
+	else if (TPM_G1_WAN_G0_INT_SWITCH == profile_id)
+		lsp_ret = mv_eth_wan_swap(1);
+
+	if (lsp_ret) {
+		TPM_OS_ERROR(TPM_HWM_MOD, "LSP hot swap failed, return value (%d)\n", lsp_ret);
+		return (TPM_FAIL);
+	}
+	return (TPM_OK);
+}
+
+tpm_error_code_t tpm_proc_hot_swap_profile(uint32_t owner_id,
+				    tpm_eth_complex_profile_t profile_id)
+{
+	tpm_error_code_t ret_code = TPM_OK;
+
+	ret_code = tpm_proc_check_hot_swap_profile(owner_id, profile_id);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_hot_swap_lsp(profile_id);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_hot_swap_misc_cfg(profile_id);
+	IF_ERROR(ret_code);
+
+	/* perform mib-reset */
+	tpm_proc_mib_reset(owner_id, TPM_ENUM_RESET_LEVEL0);
+
+	/* tpm_db recovery */
+	tpm_db_api_data_rcvr();
+
+	ret_code = tpm_proc_hot_swap_update_acl_rules(owner_id);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+#endif /* CONFIG_MV_ETH_WAN_SWAP */
+
 /*******************************************************************************
 * tpm_proc_mac_learn_entry_num_get()
 *
@@ -16171,3 +17792,100 @@
 	return TPM_OK;
 }
 
+/*******************************************************************************
+* tpm_proc_hwf_admin_set()
+*
+* DESCRIPTION:    Function used to enable/disable hwf to certain port.
+*
+* INPUTS:
+*
+* port
+* txp
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_hwf_admin_set(tpm_gmacs_enum_t port, uint8_t txp, uint8_t enable)
+{
+	uint32_t valid, q_num;
+	tpm_db_sched_t sched_method;
+	tpm_db_txq_owner_t queue_owner;
+	uint32_t owner_queue_num;
+	uint32_t queue_size;
+	uint32_t queue_weight;
+	int32_t db_ret;
+	tpm_db_tx_mod_t tx_mod;
+	uint32_t curr_state = 0;
+
+	//TPM_OS_INFO(TPM_PNCL_MOD, "port = %d txp = %d enable = %d\n", port, txp, enable);
+
+	printk("TPM T-Cont API, port(%d), txp(%d) enable(%d)\n", port, txp, enable);
+
+	tx_mod = port + txp;
+
+	if (tx_mod >= TPM_MAX_NUM_TX_PORTS) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "input invalid, port = %d txp = %d\n", port, txp);
+		return ERR_OMCI_TCONT_INVALID;
+	}
+
+	for (q_num = 0; q_num < TPM_MAX_NUM_TX_QUEUE; q_num++) {
+		db_ret = tpm_db_gmac_tx_q_conf_get(tx_mod, q_num, &valid, &sched_method,
+					&queue_owner, &owner_queue_num, &queue_size,
+					&queue_weight);
+		if (!valid)
+		{
+			//TPM_OS_INFO(TPM_PNCL_MOD, "Q-num = %d not valid, continue\n", q_num);
+			continue;
+		}
+
+		/* HWF Traffic */
+		/* =========== */
+		if (queue_owner != TPM_Q_OWNER_CPU)
+		{
+			/* get the hwf en first */
+			curr_state = NETA_HWF_TX_PORT_MASK(port + txp) | NETA_HWF_TXQ_MASK(q_num);
+			MV_REG_WRITE(NETA_HWF_TX_PTR_REG((queue_owner - 1)), curr_state);
+			curr_state = MV_REG_READ(NETA_HWF_TXQ_ENABLE_REG((queue_owner - 1)));
+
+			/* enable/disable hwf */
+			if (enable == true)
+				printk("HWF T-Cont active, port(%d), txp(%d), que(%d)\n", port, txp, q_num);
+
+			mvNetaHwfTxqEnable((queue_owner - 1), port, txp, q_num, enable);
+
+			//TPM_OS_INFO(TPM_PNCL_MOD,"GMAC = %d TCONT = %d Q = %d HWF: owner_rx %d\n", port, txp, q_num, (queue_owner - 1));
+
+			if ((!enable) && (curr_state))
+			{
+				//TPM_OS_INFO(TPM_PNCL_MOD, "Call mv_eth_txq_clean - current state: %d, enable %d\n", curr_state, enable);
+				printk("HWF T-Cont stop/clean, port(%d), txp(%d), que(%d)\n", port, txp, q_num);
+				mv_eth_txq_clean(port, txp, q_num);
+			}
+		}
+		/* SWF Traffic */
+		/* =========== */
+		else
+		{
+			if (!enable)
+			{
+				printk("SWF T-Cont stop/clean, port(%d), txp(%d), que(%d)\n", port, txp, q_num);
+				mv_cust_set_tcont_state(txp, false);
+				mv_eth_txq_clean(port, txp, q_num);
+			}
+			else
+			{
+				printk("SWF T-Cont active, port(%d), txp(%d), que(%d)\n", port, txp, q_num);
+				mv_cust_set_tcont_state(txp, true);
+			}
+		}
+	}
+
+	return TPM_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h
index 2899e15..9f47c12 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h
@@ -141,6 +141,10 @@
 #define      TPM_AI_DNRT_BIT_SIZE               (1)
 #define      TPM_AI_DNRT_MASK                   (AI_TO_MASK(TPM_AI_DNRT_BIT_OFF, TPM_AI_DNRT_BIT_SIZE))
 
+#define      TPM_AI_DNRT_DS_TRUNK_BIT_OFF       (3)
+#define      TPM_AI_DNRT_DS_TRUNK_BIT_SIZE      (1)
+#define      TPM_AI_DNRT_DS_TRUNK_MASK          (AI_TO_MASK(TPM_AI_DNRT_DS_TRUNK_BIT_OFF, TPM_AI_DNRT_DS_TRUNK_BIT_SIZE))
+
 #define      TPM_AI_MTM_BIT_OFF                 (2)
 #define      TPM_AI_MTM_BIT_SIZE                (1)
 #define      TPM_AI_MTM_MASK                    (AI_TO_MASK(TPM_AI_MTM_BIT_OFF, TPM_AI_MTM_BIT_SIZE))
@@ -232,6 +236,7 @@
 #define GMAC_IS_WAN(gmac_func)          ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_WAN))
 #define GMAC_IS_UNI_LAN(gmac_func)      (gmac_func == TPM_GMAC_FUNC_LAN_UNI)
 #define GMAC_IS_UNI_VIRT(gmac_func)     (gmac_func == TPM_GMAC_FUNC_VIRT_UNI)
+#define GMAC_IS_DS_UNI_LAN(gmac_func)   (gmac_func == TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI)
 
 
 #define TPM_CNM_L2_MAIN_LUID_OFFSET      (0)
@@ -249,6 +254,7 @@
 } ttl_illegal_action_t;
 
 typedef enum {
+	TPM_ADD_DS_LOAD_BALANCE_RULE,
 	TPM_ADD_L2_PRIM_ACL_RULE,
 	TPM_ADD_L3_TYPE_ACL_RULE,
 	TPM_ADD_IPV4_ACL_RULE,
@@ -306,6 +312,13 @@
 	del_cnm_ipv4_pre_filter_key_fn_t del_cnm_ipv4_pre_filter;
 } tpm_cnm_ipv4_pre_filter_rule_oper_t;
 
+typedef tpm_error_code_t (*tpm_acl_recovery_func)(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+
+typedef struct {
+	tpm_api_type_t api_type;
+	tpm_acl_recovery_func func;
+} tpm_hot_swap_acl_recovery_t;
+
 
 /* API's */
 
@@ -335,6 +348,14 @@
 					       uint32_t *mod_idx);
 
 tpm_error_code_t tpm_proc_del_cpu_wan_loopback(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd);
+tpm_error_code_t tpm_proc_add_ds_load_balance_acl_rule(uint32_t owner_id,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l2_acl_key_t *l2_key,
+					       tpm_ds_load_balance_tgrt_t tgrt_port);
+tpm_error_code_t tpm_proc_del_ds_load_balance_acl_rule(uint32_t owner_id, uint32_t rule_idx, uint32_t ext_call);
 
 int32_t tpm_proc_l2_tcam_build(tpm_src_port_type_t src_port,
 			       tpm_dir_t dir,
@@ -409,7 +430,9 @@
 					       uint32_t cpu_rx_queue,
 					       tpm_trg_port_type_t llid_num);
 
-tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id);
+tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id, tpm_ether_type_key_t ety);
+
+tpm_error_code_t tpm_proc_loop_detect_del_channel(uint32_t owner_id);
 
 tpm_error_code_t tpm_proc_oam_loopback_add_channel(uint32_t owner_id);
 
@@ -450,6 +473,7 @@
 					     uint8_t ipv4_src_add[4],
 					     uint8_t ipv4_dst_add[4],
 					     uint8_t ignore_ipv4_src,
+					     uint16_t dest_queue,
 					     tpm_trg_port_type_t dest_port_bm);
 
 int32_t tpm_proc_ipv4_sram_build(tpm_src_port_type_t src_port,
@@ -486,11 +510,13 @@
 				    uint8_t ignore_ipv4_src,
 				    tpm_pncl_tcam_data_t *tcam_data);
 
-int32_t tpm_proc_ipv4_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+int32_t tpm_proc_ipvx_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
 				    tpm_mc_igmp_mode_t igmp_mode,
+				    uint16_t dest_queue,
 				    tpm_trg_port_type_t target_port,
 				    uint32_t mod_entry,
-				    tpm_pncl_sram_data_t *sram_data);
+				    tpm_pncl_sram_data_t *sram_data,
+				    tpm_ip_ver_t ip_version);
 
 tpm_error_code_t tpm_proc_updt_ipv4_mc_stream(uint32_t owner_id,
 					      uint32_t stream_num, tpm_trg_port_type_t dest_port_bm);
@@ -506,12 +532,6 @@
 				    uint8_t ignore_sip,
 				    tpm_pncl_tcam_data_t *tcam_data);
 
-int32_t tpm_proc_ipv6_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
-				    tpm_mc_igmp_mode_t igmp_mode,
-				    tpm_trg_port_type_t target_port,
-				    uint32_t mod_entry,
-				    tpm_pncl_sram_data_t *sram_data);
-
 tpm_error_code_t tpm_proc_add_ipv6_mc_stream(uint32_t owner_id,
 					     uint32_t stream_num,
 					     tpm_mc_igmp_mode_t igmp_mode,
@@ -520,6 +540,7 @@
 					     uint8_t ipv6_src_add[16],
 					     uint8_t ipv6_dst_add[16],
 					     uint8_t ignore_ipv6_src,
+					     uint16_t dest_queue,
 					     tpm_trg_port_type_t dest_port_bm);
 
 tpm_error_code_t tpm_proc_updt_ipv6_mc_stream(uint32_t owner_id,
@@ -532,6 +553,8 @@
 
 tpm_error_code_t tpm_proc_l2_num_vlan_tags_init(void);
 tpm_error_code_t tpm_proc_ipv4_ttl_init(uint32_t ttl_illegal_action);
+tpm_error_code_t tpm_proc_ds_load_balance_init(void);
+
 tpm_error_code_t tpm_proc_tcp_flag_init(void);
 tpm_error_code_t tpm_proc_ipv4_len_init(void);
 tpm_error_code_t tpm_proc_ipv4_igmp_init(void);
@@ -691,6 +714,11 @@
 tpm_error_code_t tpm_proc_set_mc_vid_port_vids(uint32_t owner_id,
 					       uint32_t mc_vid,
 					       tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config);
+tpm_error_code_t tpm_proc_delete_ipvx_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						   uint32_t stream_num,
+						   uint32_t dest_port_bm,
+						   uint32_t u4_entry,
+						   tpm_ip_ver_t ip_version);
 
 tpm_error_code_t tpm_proc_catch_all_init(void);
 
@@ -828,12 +856,24 @@
 				     tpm_pkt_action_t pkt_act,
 				     uint32_t mod_cmd,
 				     tpm_pncl_sram_data_t *sram_data);
+tpm_pnc_trg_t tpm_proc_cnm_pnc_trg_get(tpm_trg_port_type_t trg_port);
 
 uint8_t tpm_proc_if_ipv4_pre_range_is_full(tpm_src_port_type_t src_port, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
 uint8_t tpm_proc_if_cnm_main_range_is_full(tpm_src_port_type_t src_port, uint32_t precedence);
 int32_t tpm_proc_add_cnm_ipv4_pre_filter_key(uint32_t owner_id, tpm_src_port_type_t src_port, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key, uint32_t *key_idx);
 int32_t tpm_proc_del_cnm_ipv4_pre_filter_key(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t key_idx);
-int32_t tpm_proc_add_l2_cnm_rule(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t precedence, tpm_parse_fields_t l2_parse_rule_bm, tpm_l2_acl_key_t *l2_key, uint32_t ipv4_key_idx, tpm_pkt_frwd_t *pkt_frwd, tpm_pkt_action_t pkt_act, uint32_t pbits, uint32_t *rule_idx);
+int32_t tpm_proc_add_l2_cnm_rule(uint32_t owner_id,
+				 tpm_src_port_type_t src_port,
+				 uint32_t precedence,
+				 tpm_parse_fields_t l2_parse_rule_bm,
+				 tpm_l2_acl_key_t *l2_key,
+				 tpm_parse_fields_t ipv4_parse_rule_bm,
+				 tpm_ipv4_acl_key_t *ipv4_key,
+				 uint32_t ipv4_key_idx,
+				 tpm_pkt_frwd_t *pkt_frwd,
+				 tpm_pkt_action_t pkt_act,
+				 uint32_t pbits,
+				 uint32_t *rule_idx);
 int32_t tpm_proc_del_l2_cnm_rule(uint32_t owner_id, uint32_t rule_idx);
 int32_t tpm_proc_add_ipv4_cnm_rule(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t precedence, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key, tpm_pkt_frwd_t *pkt_frwd, tpm_pkt_action_t pkt_act, uint32_t pbits, uint32_t *rule_idx);
 int32_t tpm_proc_add_ipv6_cnm_rule(uint32_t owner_id,
@@ -853,20 +893,42 @@
 tpm_error_code_t tpm_proc_del_static_mac_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr);
 tpm_error_code_t tpm_proc_mac_learn_default_rule_act_set(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf);
 tpm_error_code_t tpm_proc_mac_learn_entry_num_get(uint32_t *entry_num);
+#ifdef CONFIG_MV_ETH_WAN_SWAP
+tpm_error_code_t tpm_proc_hot_swap_profile(uint32_t owner_id,
+				    tpm_eth_complex_profile_t profile_id);
+#endif /* CONFIG_MV_ETH_WAN_SWAP */
 
 
 int32_t tpm_proc_check_api_busy(tpm_api_type_t api_type, uint32_t rule_num);
 int32_t tpm_proc_api_busy_done(tpm_api_type_t api_type, uint32_t rule_num);
 int32_t tpm_proc_src_port_dir_map(tpm_src_port_type_t src_port, tpm_dir_t *dir);
+int32_t tpm_proc_check_all_api_busy(void);
+int32_t tpm_proc_all_api_busy_done(void);
 
 bool tpm_split_mod_stage1_check(tpm_pkt_mod_bm_t pkt_mod_bm,
 				tpm_pkt_mod_t *pkt_mod,
 				tpm_rule_action_t *rule_action,
 				bool check_vlan_noop);
 int32_t tpm_proc_calc_cnm_precedence(tpm_src_port_type_t src_port, uint32_t rule_num, uint32_t *precedence);
+tpm_error_code_t tpm_proc_hwf_admin_set(tpm_gmacs_enum_t port, uint8_t txp, uint8_t enable);
 
 tpm_error_code_t tpm_proc_check_dst_uni_port(tpm_trg_port_type_t dest_port_bm);
+tpm_error_code_t tpm_proc_set_active_wan(tpm_gmacs_enum_t active_wan);
 
+/* hot swap profile acl recovery func api section */
+tpm_error_code_t tpm_acl_rcvr_func_mac_learn(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ds_load_balance(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_cpu_loopback(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_l2_prim(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_l3_type(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv4(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv4_mc(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_gen(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_dip(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_mc(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_nh(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_ipv6_l4(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
+tpm_error_code_t tpm_acl_rcvr_func_cnm(uint32_t owner_id, tpm_db_api_entry_t *api_data, uint32_t rule_idx_updt_en);
 
 #ifdef __cplusplus
 }
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c
index 733e952..447de4e 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c
@@ -439,6 +439,7 @@
 	int32_t ret_code;
 	uint16_t mh = 0;
 	tpm_db_pon_type_t pon_type;
+	uint32_t switch_init;
 
 	/* Parse MH, depending on field parse request */
 
@@ -483,8 +484,20 @@
 		TPM_OS_DEBUG(TPM_PNCL_MOD, "MH from GemPort\n");
 	} else {
 		if (tcam_in->pkt_key.src_port == TPM_SRC_PORT_WAN) {
-			/* DS, from WAN, no MH need to be parsed */
-			mh = 0;
+			/* it is for multicast per uni vlan feature
+			   in the first loop, pkt goes to G1 from G0 through Switch.
+			 */
+			ret_code = tpm_db_switch_init_get(&switch_init);
+			IF_ERROR(ret_code);
+			if (switch_init) {
+				mh = tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_WAN);
+				if (TPM_DB_ERR_PORT_NUM == mh) {
+					TPM_OS_ERROR(TPM_PNCL_MOD, "tpm_db_eth_port_switch_port_get returned %d\n", mh);
+					return(TPM_FAIL);
+				}
+			} else
+				mh = 0;
+
 			/* Update TCAM Data and Mask */
 			*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(mh);
 			*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(MH_UNI_PORT_MASK);
@@ -3425,6 +3438,7 @@
 	uint32_t free_entry = 0, entry_id;
 	uint32_t queue_id;
 	tpm_gmacs_enum_t lpk_gmac;
+	int32_t cpu_rx_queue;
 
 	/* Set Structs to zero */
 	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
@@ -3439,14 +3453,15 @@
 	IF_ERROR(ret_code);
 
 	free_entry = range_data.pnc_range_oper.free_entries;
-	entry_id = range_data.pnc_range_conf.range_end;
 	/* check the free size in the range for default rule*/
-	if (free_entry == 0) {
-		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");
+	if (free_entry < 2) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No enough entries(%d) for MAC learn default rules\n",
+			     free_entry);
 		return(TPM_FAIL);
 	}
 
-	/* construct default rule */
+	/* construct default rule on GMAC0 forward packet to GMAC1*/
+	entry_id = range_data.pnc_range_conf.range_end;
 	/* Set Lookup Id */
 	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
 	/* Set port_id */
@@ -3460,11 +3475,13 @@
 	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
 
 	/*forward packet to GMAC1 as default*/
-	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
+	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+						   &queue_id,
+						   TPM_GMAC1_QUEUE_DATA_TRAFFIC)) {
 		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback gmac queue get failed \n");
 		return TPM_FAIL;
 	}
-	/* Set target GMAC1 */
+	/* Set target GMAC1, queue id changed to cpu_rate_limit queue*/
 	pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC1 << TPM_TXP_FL_SHIFT);
 	pnc_entry.sram_entry.pnc_queue = queue_id;
 
@@ -3478,6 +3495,45 @@
 	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
 	IF_ERROR(ret_code);
 
+	/*CPU rate limit*/
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+	entry_id = range_data.pnc_range_conf.range_end - 1;
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
+	/* Set port_id */
+	pnc_entry.tcam_entry.port_ids = TPM_BM_GMAC_1;
+	/* check MH, 0xAACC indicates MAC learning packets */
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[0] = TPM_MOD2_MAC_LEARN_MH >> 8;
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[1] = TPM_MOD2_MAC_LEARN_MH & 0xFF;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[0] = 0xFF;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[1] = 0xFF;
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = TPM_TRUE;
+
+	pnc_entry.sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+
+	/* Get default CPU queue */
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+	/* Trap to CPU */
+	pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_CPU << TPM_TXP_FL_SHIFT);
+	pnc_entry.sram_entry.pnc_queue = cpu_rx_queue;
+	/* Set result info */
+	pnc_entry.sram_entry.res_info_15_0_data |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
+	pnc_entry.sram_entry.res_info_15_0_mask |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_MAC_LEARN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
 	return(TPM_OK);
 }
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c
index caa9ea0..7fc477a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c
@@ -83,6 +83,7 @@
 #include "tpm_common.h"
 #include "tpm_header.h"
 #include "tpm_sysfs_utils.h"
+#include "dbg-trace.h"
 
 /*TODO - currently some printing funtions are directly accessing DB */
 extern tpm_db_t tpm_db;
@@ -152,6 +153,7 @@
 	BuildEnumString(TPM_GMAC_FUNC_LAN_AND_WAN),
 	BuildEnumString(TPM_GMAC_FUNC_VIRT_UNI),
 	BuildEnumString(TPM_GMAC_FUNC_LAN_UNI),
+	BuildEnumString(TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI),
 };
 
 db_enum_string_t tpm_pnc_ranges_str[] = {
@@ -159,6 +161,7 @@
 	BuildEnumString(TPM_PNC_MAC_LEARN),
 	BuildEnumString(TPM_PNC_CPU_WAN_LPBK_US),
 	BuildEnumString(TPM_PNC_NUM_VLAN_TAGS),
+	BuildEnumString(TPM_PNC_DS_LOAD_BALANCE),
 	BuildEnumString(TPM_PNC_VIRT_UNI),
 	BuildEnumString(TPM_PNC_MULTI_LPBK),
 	BuildEnumString(TPM_PNC_LOOP_DET_US),
@@ -167,7 +170,7 @@
 	BuildEnumString(TPM_PNC_IGMP),
 	BuildEnumString(TPM_PNC_IPV4_MC_DS),
 	BuildEnumString(TPM_PNC_IPV4_MAIN),
-	BuildEnumString(TPM_PNC_TCP_FLAG),
+	BuildEnumString(TPM_PNC_IPV4_TCP_FLAG),
 	BuildEnumString(TPM_PNC_TTL),
 	BuildEnumString(TPM_PNC_IPV4_PROTO),
 	BuildEnumString(TPM_PNC_IPV4_FRAG),
@@ -179,6 +182,7 @@
 	BuildEnumString(TPM_PNC_IPV6_MC_DS),
 	BuildEnumString(TPM_PNC_IPV6_NH),
 	BuildEnumString(TPM_PNC_IPV6_L4_MC_DS),
+	BuildEnumString(TPM_PNC_IPV6_TCP_FLAG),
 	BuildEnumString(TPM_PNC_IPV6_L4),
 	BuildEnumString(TPM_PNC_CNM_IPV4_PRE),
 	BuildEnumString(TPM_PNC_CNM_MAIN),
@@ -209,16 +213,22 @@
 
 static tpm_str_map_t api_type_str[] = {
 	{TPM_API_MGMT, "MNGMT"},
-	{TPM_API_CPU_LOOPBACK, "CPU_LOOPBACK"},
+	{TPM_API_MAC_LEARN,       "MAC_LEARN   "},
+	{TPM_API_DS_LOAD_BALANCE, "DS_LOAD_BAL "},
+	{TPM_API_CPU_LOOPBACK,    "CPU_LOOPBACK"},
 	{TPM_API_L2_PRIM, "L2      "},
 	{TPM_API_L3_TYPE, "L3      "},
-	{TPM_API_IPV4, "IPV4    "},
+	{TPM_API_IPV4,    "IPV4    "},
 	{TPM_API_IPV4_MC, "IPV4_MC "},
 	{TPM_API_IPV6_GEN, "IPV6_GEN"},
 	{TPM_API_IPV6_DIP, "IPV6_DIP"},
+	{TPM_API_IPV6_MC, "IPV6_MC"},
 	{TPM_API_IPV6_NH, "IPV6_NH "},
 	{TPM_API_IPV6_L4, "L4      "},
+	{TPM_API_CNM,     "CNM     "},
 };
+char *tpm_db_params_illegal_str = "??";
+
 
 
 /********************************************************************************/
@@ -306,7 +316,7 @@
 * COMMENTS:
 *
 *******************************************************************************/
-static uint8_t *api_type_to_str(tpm_api_type_t api_type)
+uint8_t *api_type_to_str(tpm_api_type_t api_type)
 {
 	uint32_t i;
 
@@ -314,7 +324,7 @@
 		if (api_type_str[i].enum_in == api_type)
 			return (&(api_type_str[i].str_out[0]));
 	}
-	return (NULL);
+	return (tpm_db_params_illegal_str);
 }
 
 /*******************************************************************************
@@ -824,10 +834,10 @@
 	printk("Debug port          %4d\n", tpm_db.init_misc.pnc_init_debug_port);
 	printk("PON type            %s\n", pon_type[tpm_db.init_misc.pon_type]);
 
-	if ((tpm_db.init_misc.backup_wan < TPM_MAX_GMAC) && (tpm_db.init_misc.backup_wan >= TPM_ENUM_GMAC_0))
-		printk("Backup WAN          %s\n", gmac_name[tpm_db.init_misc.backup_wan]);
+	if ((tpm_db.init_misc.active_wan <= TPM_MAX_GMAC) && (tpm_db.init_misc.active_wan >= TPM_ENUM_GMAC_0))
+		printk("Active WAN          %s\n", gmac_name[tpm_db.init_misc.active_wan]);
 	else
-		printk("Backup WAN          N/A");
+		printk("Active WAN          N/A");
 	printk("DS MH select source %4d\n", tpm_db.init_misc.ds_mh_set_conf);
 	printk("CFG PNC parse       %4d\n", tpm_db.init_misc.cfg_pnc_parse);
 	printk("CPU loopback        %4d\n", tpm_db.init_misc.cpu_loopback);
@@ -1067,24 +1077,6 @@
 	printk("==========================================================================================================================================================\n");
 }
 
-char *tpm_db_params_illegal_str = "??";
-
-char *tpm_db_api_type_str[TPM_MAX_API_TYPES] = {
-	"MGNT",
-	"MAC_LEARN",
-	"CPU_LPBK",
-	"L2",
-	"L3",
-	"IPV4",
-	"IPV4_MC",
-	"IPV6_GEN",
-	"IPV6_DIP",
-	"IPV6_MC",
-	"IPV6_NH",
-	"IPV6_L4",
-	"CTC_CNM"
-};
-
 char *tpm_db_src_port_str[] = {
        "UNI_0",
 	"UNI_1",
@@ -1225,6 +1217,8 @@
 	tpm_db_none_parse_type_str,
 	/* TPM_API_MAC_LEARN */
 	tpm_db_none_parse_type_str,
+	/* TPM_API_DS_LOAD_BALANCE */
+	tpm_db_l2_parse_type,
 	/* TPM_API_CPU_LOOPBACK */
 	tpm_db_none_parse_type_str,
 	/* TPM_API_L2_PRIM */
@@ -1235,16 +1229,16 @@
 	tpm_db_ipv4_parse_type,
 	/* TPM_API_IPV4_MC */
 	tpm_db_ipv4_mc_parse_type,
+	/* TPM_API_IPV6_NH */
+	tpm_db_ipv6_nh_parse_type,
+	/* TPM_API_IPV6_L4 */
+	tpm_db_ipv6_l4_parse_type,
 	/* TPM_API_IPV6_GEN */
 	tpm_db_ipv6_gen_parse_type,
 	/* TPM_API_IPV6_DIP */
 	tpm_db_ipv6_dip_parse_type,
 	/* TPM_API_IPV6_MC */
 	tpm_db_ipv6_mc_parse_type,
-	/* TPM_API_IPV6_NH */
-	tpm_db_ipv6_nh_parse_type,
-	/* TPM_API_IPV6_L4 */
-	tpm_db_ipv6_l4_parse_type,
 	/* TPM_API_CTC_CM */
 	tpm_db_ctc_cm_parse_type,
 };
@@ -1485,7 +1479,7 @@
 
 		if (first_rule) {
 			if (api_type < TPM_MAX_API_TYPES)
-				api_type_str = tpm_db_api_type_str[api_type];
+				api_type_str = api_type_to_str(api_type);
 			else
 				api_type_str = tpm_db_params_illegal_str;
 		}
@@ -1743,7 +1737,7 @@
 
 	if (-1 == next_rule) {
 		if (api_type < TPM_MAX_API_TYPES)
-			api_type_str = tpm_db_api_type_str[api_type];
+			api_type_str = api_type_to_str(api_type);
 		else
 			api_type_str = tpm_db_params_illegal_str;
 
@@ -2475,6 +2469,8 @@
 		return;
 	}
 
+	//TRC_OUTPUT(0,1);
+
 	printk(KERN_INFO "---------------------------------------------------------------------------------\n");
 	printk(KERN_INFO "FC is %s\n", (tpm_fc_is_running() == MV_TRUE) ? "ENABLED" : "DISABLED");
 	printk(KERN_INFO "The Flow Control engine settings:\n");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h
index d1909fb..9e7deca 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h
@@ -146,6 +146,7 @@
 void tpm_print_fc(unsigned int print_only);
 void tpm_init_eth_cmplx_setup_error_print(uint32_t hwEthCmplx, bool sysfs_call);
 void tpm_print_mac_learn_entry_count(void);
+uint8_t *api_type_to_str(tpm_api_type_t api_type);
 
 
 #endif /* _TPM_PRINT_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c
index 1438a48..6e2b416 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c
@@ -284,7 +284,7 @@
 		tpm_setup.mc_setting.mc_hwf_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
 		tpm_setup.mc_setting.mc_cpu_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
 	}
-	
+
 	app_rc = get_ipv4_mc_support(&tpm_setup.mc_setting.ipv4_mc_support);
 	if (app_rc == TPM_FAIL)
 		rc = TPM_FAIL;
@@ -365,16 +365,29 @@
 	return rc;
 }
 
-int32_t tpm_init_backup_wan_get_para(void)
+int32_t tpm_init_active_wan_get_para(void)
 {
 	int32_t	rc = TPM_OK;
 	int 	app_rc;
 
-	app_rc = get_backup_wan_params(&(tpm_setup.backup_wan));
+	app_rc = get_active_wan_params(&(tpm_setup.active_wan));
 	if (app_rc == TPM_FAIL)
 		rc = TPM_FAIL;
 	else if (app_rc == TPM_NOT_FOUND)
-		tpm_setup.backup_wan = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		tpm_setup.active_wan = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+int32_t tpm_init_ds_mac_based_trunking_get_para(void)
+{
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_ds_mac_based_trunking_enable(&(tpm_setup.ds_mac_based_trunk_enable));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ds_mac_based_trunk_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
 
 	return rc;
 }
@@ -808,7 +821,7 @@
 	tpm_init_eth_cmplx_profile_get_para();
 	tpm_init_eth_port_conf_get_para();
 	tpm_init_gmac_port_conf_get_para();
-	tpm_init_backup_wan_get_para();
+	tpm_init_active_wan_get_para();
 	tpm_init_gmac_conn_get_para();
 	tpm_init_gmac_rx_get_para();
 	tpm_init_gmac_tx_get_para();
@@ -824,6 +837,7 @@
 	tpm_init_ctc_cm_ipv6_parse_window_get_para();
 	tpm_init_pnc_mac_learn_enable_get_para();
 	tpm_init_switch_init_get_para();
+	tpm_init_ds_mac_based_trunking_get_para();
 
 	free_xml_head_ptr();
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c
index 3c88ca6..d9af0f8 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c
@@ -79,6 +79,51 @@
 #include "tpm_common.h"
 #include "tpm_header.h"
 
+uint32_t tpm_tm_lan_gmac_get(uint32_t *lan_gmac)
+{
+	int32_t  db_ret;
+	tpm_pnc_trg_t pnc_target;
+
+	db_ret = tpm_db_to_lan_gmac_get(TPM_TRG_PORT_UNI_ANY, &pnc_target);
+	if (db_ret != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+			"can not get GMAC that works as LAN\n\r");
+		return ERR_GENERAL;
+	}
+	if (pnc_target == TPM_PNC_TRG_GMAC0)
+		*lan_gmac = SW_GMAC_0;
+	else if (pnc_target == TPM_PNC_TRG_GMAC1)
+		*lan_gmac = SW_GMAC_1;
+	else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+			"GMAC works as LAN is not valid: (%d)\n\r", pnc_target);
+		return ERR_GENERAL;
+	}
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "GMAC works as LAN is: (%d)\n\r", *lan_gmac);
+
+	return TPM_OK;
+}
+uint32_t tpm_tm_wan_gmac_get(uint32_t *wan_gmac)
+{
+	tpm_gmacs_enum_t wan_gmac_tmp;
+
+	wan_gmac_tmp = tpm_db_active_wan_get();
+
+	if (wan_gmac_tmp == TPM_ENUM_GMAC_0)
+		*wan_gmac = SW_GMAC_0;
+	else if (wan_gmac_tmp == TPM_ENUM_GMAC_1)
+		*wan_gmac = SW_GMAC_1;
+	else if (wan_gmac_tmp == TPM_ENUM_PMAC)
+		*wan_gmac = PON_PORT;
+	else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+			"GMAC works as WAN is not valid: (%d)\n\r", wan_gmac_tmp);
+		return ERR_GENERAL;
+	}
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "GMAC works as WAN is: (%d)\n\r", *wan_gmac);
+
+	return TPM_OK;
+}
 /*******************************************************************************
 * tpm_tm_set_wan_egr_queue_sched()
 *
@@ -108,13 +153,14 @@
 	tpm_error_code_t retVal = TPM_RC_OK;
 	uint32_t i = 0;
 	uint32_t num_tcont_llid = 0;
+	uint32_t wan_gmac = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],sched_mode[%d],"
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],sched_ent[%d],sched_mode[%d],"
 		"             queue_id[%d], wrr_weight[%d]\n\r",
 		__func__, owner_id, sched_ent, sched_mode, queue_id, wrr_weight);
 
 	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
-		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],sched_mode[%d],"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],sched_mode[%d],"
 			"                                    queue_id[%d], wrr_weight[%d]\n\r",
 			__func__, owner_id, sched_ent, sched_mode, queue_id, wrr_weight);
 		return ERR_SW_TM_QUEUE_INVALID;
@@ -122,22 +168,26 @@
 
 	if ((sched_mode == TPM_PP_SCHED_WRR) && (wrr_weight > TPM_MAX_WRR_WEIGHT)) {
 
-		printk(KERN_INFO "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
 			"                                   queue_id[%d], wrr_weight[%d]\n\r",
 			__func__, owner_id, sched_mode, queue_id, wrr_weight);
 		return ERR_SW_TM_QUEUE_INVALID;
 	}
+	retVal = tpm_tm_wan_gmac_get(&wan_gmac);
+	if (retVal != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
 
 	tpm_db_num_tcont_llid_get(&num_tcont_llid);
 	for (i = 0; i < num_tcont_llid; i++) {
 		if (sched_ent & 0x1) {
 			switch (sched_mode) {
 			case TPM_PP_SCHED_STRICT:
-				mvNetaTxqFixPrioSet(PON_PORT, i, queue_id);
+				mvNetaTxqFixPrioSet(wan_gmac, i, queue_id);
 				break;
 
 			case TPM_PP_SCHED_WRR:
-				mvNetaTxqWrrPrioSet(PON_PORT, i, queue_id, wrr_weight);
+				mvNetaTxqWrrPrioSet(wan_gmac, i, queue_id, wrr_weight);
 				break;
 
 			default:
@@ -150,9 +200,9 @@
 			break;
 	}
 	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
-		printk(KERN_INFO "TCONT doesn't not exist\n");
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "TCONT doesn't not exist\n");
 
-	printk(KERN_INFO "==EXIT== %s:\n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s:\n\r", __func__);
 
 	return retVal;
 }
@@ -184,31 +234,38 @@
 {
 	uint32_t i = 0;
 	uint32_t num_tcont_llid = 0;
+	uint32_t wan_gmac = 0;
+	uint32_t tpm_ret = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],rate_limit_val[%d], bucket_size[%d]\n\r",
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],sched_ent[%d],rate_limit_val[%d], bucket_size[%d]\n\r",
 		__func__, owner_id, sched_ent, rate_limit_val, bucket_size);
 
+	tpm_ret = tpm_tm_wan_gmac_get(&wan_gmac);
+	if (tpm_ret != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
+
 	tpm_db_num_tcont_llid_get(&num_tcont_llid);
 	for (i = 0; i < num_tcont_llid; i++) {
 		if (sched_ent & 0x1) {
 
-			if (mvNetaTxpBurstSet(PON_PORT, i, bucket_size) != MV_OK) {
-				printk(KERN_INFO
+			if (mvNetaTxpBurstSet(wan_gmac, i, bucket_size) != MV_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, 
 					"==ERROE==%s: Invalid bucket size value: "
 					"owner_id[%d],sched_ent[%d] bucket_size[%d]\n\r",
 					__func__, owner_id, i, bucket_size);
 				return ERR_SW_TM_BUCKET_SIZE_INVALID;
 			}
-			mvNetaTxpRateSet(PON_PORT, i, rate_limit_val);
+			mvNetaTxpRateSet(wan_gmac, i, rate_limit_val);
 		}
 		sched_ent = sched_ent >> 1;
 		if (sched_ent == 0)
 			break;
 	}
 	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
-		printk(KERN_INFO "TCONT doesn't not exist\n");
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "TCONT doesn't not exist\n");
 
-	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
 
 	return TPM_RC_OK;
 
@@ -244,8 +301,10 @@
 {
 	uint32_t i = 0;
 	uint32_t num_tcont_llid = 0;
+	uint32_t wan_gmac = 0;
+	uint32_t tpm_ret = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],queue_id[%d]"
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],sched_ent[%d],queue_id[%d]"
 		"             rate_limit_val[%d], bucket_size[%d] \n\r",
 		__func__, owner_id, sched_ent, queue_id, rate_limit_val, bucket_size);
 
@@ -253,32 +312,37 @@
 
 	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
 
-		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],queue_id[%d]"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],queue_id[%d]"
 			"                                   rate_limit_val[%d], bucket_size[%d] \n\r",
 			__func__, owner_id, sched_ent, queue_id, rate_limit_val, bucket_size);
 		return ERR_SW_TM_QUEUE_INVALID;
 	}
 
+	tpm_ret = tpm_tm_wan_gmac_get(&wan_gmac);
+	if (tpm_ret != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
+
 	for (i = 0; i < num_tcont_llid; i++) {
 		if (sched_ent & 0x1) {
 
-			if (mvNetaTxqBurstSet(PON_PORT, i, queue_id, bucket_size) != MV_OK) {
-				printk(KERN_INFO
+			if (mvNetaTxqBurstSet(wan_gmac, i, queue_id, bucket_size) != MV_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, 
 					"==ERROE==%s: Invalid bucket size value: owner_id[%d], sched_ent[%d], queue_id[%d]"
 					"             rate_limit_val[%d], bucket_size[%d] \n\r", __func__, owner_id,
 					i, queue_id, rate_limit_val, bucket_size);
 				return ERR_SW_TM_BUCKET_SIZE_INVALID;
 			}
-			mvNetaTxqRateSet(PON_PORT, i, queue_id, rate_limit_val);
+			mvNetaTxqRateSet(wan_gmac, i, queue_id, rate_limit_val);
 		}
 		sched_ent = sched_ent >> 1;
 		if (sched_ent == 0)
 			break;
 	}
 	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
-		printk(KERN_INFO "TCONT doesn't not exist\n");
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "TCONT doesn't not exist\n");
 
-	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
 
 	return TPM_RC_OK;
 }
@@ -309,14 +373,21 @@
 						IN uint16_t wrr_weight)
 {
 	uint32_t tmp_tcont = 0;
+	uint32_t lan_gmac = 0;
+	uint32_t tpm_ret = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_mode[%d],"
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],sched_mode[%d],"
 		"             queue_id[%d], wrr_weight[%d]\n\r",
 		__func__, owner_id, sched_mode, queue_id, wrr_weight);
 
+	tpm_ret = tpm_tm_lan_gmac_get(&lan_gmac);
+	if (tpm_ret != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
+
 	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
 
-		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_mode[%d],"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: Invalid queue number: owner_id[%d],sched_mode[%d],"
 			"                                   queue_id[%d], wrr_weight[%d]\n\r",
 			__func__, owner_id, sched_mode, queue_id, wrr_weight);
 		return ERR_SW_TM_QUEUE_INVALID;
@@ -324,7 +395,7 @@
 
 	if ((sched_mode == TPM_PP_SCHED_WRR) && (wrr_weight > TPM_MAX_WRR_WEIGHT)) {
 
-		printk(KERN_INFO "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
 			"                                   queue_id[%d], wrr_weight[%d]\n\r",
 			__func__, owner_id, sched_mode, queue_id, wrr_weight);
 		return ERR_SW_TM_QUEUE_INVALID;
@@ -332,20 +403,20 @@
 
 	switch (sched_mode) {
 	case TPM_PP_SCHED_STRICT:
-		mvNetaTxqFixPrioSet(SW_GMAC_0, tmp_tcont, queue_id);
+		mvNetaTxqFixPrioSet(lan_gmac, tmp_tcont, queue_id);
 		break;
 
 	case TPM_PP_SCHED_WRR:
-		mvNetaTxqWrrPrioSet(SW_GMAC_0, tmp_tcont, queue_id, wrr_weight);
+		mvNetaTxqWrrPrioSet(lan_gmac, tmp_tcont, queue_id, wrr_weight);
 		break;
 
 	default:
-		printk(KERN_ERR " Unknown TXQ command \n");
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD," Unknown TXQ command \n");
 		return ERR_GENERAL;
 
 	}
 
-	printk(KERN_INFO "==EXIT== %s:\n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s:\n\r", __func__);
 
 	return TPM_RC_OK;
 
@@ -375,20 +446,27 @@
 						IN uint32_t bucket_size)
 {
 	uint32_t tmp_tcont = 0;
+	uint32_t lan_gmac = 0;
+	uint32_t tpm_ret = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
 		__func__, owner_id, rate_limit_val, bucket_size);
 
-	if (mvNetaTxpBurstSet(SW_GMAC_0, tmp_tcont, bucket_size) != MV_OK) {
-		printk(KERN_INFO
+	tpm_ret = tpm_tm_lan_gmac_get(&lan_gmac);
+	if (tpm_ret != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
+
+	if (mvNetaTxpBurstSet(lan_gmac, tmp_tcont, bucket_size) != MV_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, 
 			"==ERROE==%s: Invalid bucket size value: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
 			__func__, owner_id, rate_limit_val, bucket_size);
 		return ERR_SW_TM_BUCKET_SIZE_INVALID;
 	}
 
-	mvNetaTxpRateSet(SW_GMAC_0, tmp_tcont, rate_limit_val);
+	mvNetaTxpRateSet(lan_gmac, tmp_tcont, rate_limit_val);
 
-	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
 
 	return TPM_RC_OK;
 }
@@ -420,28 +498,35 @@
 						IN uint32_t bucket_size)
 {
 	uint32_t tmp_tcont = 0;
+	uint32_t lan_gmac = 0;
+	uint32_t tpm_ret = 0;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d], queue_id[%d]"
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d], queue_id[%d]"
 		"             rate_limit_val[%d], bucket_size[%d] \n\r",
 		__func__, owner_id, queue_id, rate_limit_val, bucket_size);
 
 	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
-		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d], queue_id[%d]"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: Invalid queue number: owner_id[%d], queue_id[%d]"
 			"                                   rate_limit_val[%d], bucket_size[%d] \n\r",
 			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
 		return ERR_SW_TM_QUEUE_INVALID;
 	}
 
-	if (mvNetaTxqBurstSet(SW_GMAC_0, tmp_tcont, queue_id, bucket_size) != MV_OK) {
-		printk(KERN_INFO "==ERROE==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
+	tpm_ret = tpm_tm_lan_gmac_get(&lan_gmac);
+	if (tpm_ret != TPM_OK) {
+		return ERR_SRC_PORT_INVALID;
+	}
+
+	if (mvNetaTxqBurstSet(lan_gmac, tmp_tcont, queue_id, bucket_size) != MV_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROE==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
 			"              rate_limit_val[%d], bucket_size[%d] \n\r",
 			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
 		return ERR_SW_TM_BUCKET_SIZE_INVALID;
 	}
 
-	mvNetaTxqRateSet(SW_GMAC_0, tmp_tcont, queue_id, rate_limit_val);
+	mvNetaTxqRateSet(lan_gmac, tmp_tcont, queue_id, rate_limit_val);
 
-	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
 
 	return TPM_RC_OK;
 }
@@ -473,17 +558,19 @@
 	uint32_t queue_id;
 	tpm_gmacs_enum_t lpk_gmac;
 
-	printk(KERN_INFO "==ENTER==%s: owner_id[%d], rate_limit_val[%d], bucket_size[%d] \n\r",
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, "==ENTER==%s: owner_id[%d], rate_limit_val[%d], bucket_size[%d] \n\r",
 		__func__, owner_id, rate_limit_val, bucket_size);
 
 	/*Get Tx queue on loopback gmac*/
-	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
-		printk(KERN_INFO "==ERROR==%s: loopback gmac queue get failed \n\r", __func__);
+	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac,
+						   &queue_id,
+						   TPM_GMAC1_QUEUE_DATA_TRAFFIC)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROR==%s: loopback gmac queue get failed \n\r", __func__);
 		return ERR_GENERAL;
 	}
 
 	if (mvNetaTxqBurstSet((int)lpk_gmac, tmp_tcont, queue_id, bucket_size) != MV_OK) {
-		printk(KERN_INFO "==ERROR==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD,  "==ERROR==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
 			"              rate_limit_val[%d], bucket_size[%d] \n\r",
 			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
 		return ERR_SW_TM_BUCKET_SIZE_INVALID;
@@ -491,9 +578,56 @@
 
 	mvNetaTxqRateSet(SW_GMAC_1, tmp_tcont, queue_id, rate_limit_val);
 
-	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
 
 	return TPM_RC_OK;
 
 }
 EXPORT_SYMBOL(tpm_tm_set_gmac0_ingr_rate_lim);
+
+/*******************************************************************************
+* tpm_tm_set_tx_port_rate_lim()
+*
+* DESCRIPTION:      Configures the rate limit of tx port wanted.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       port              - port want to do rate limit
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value, if set 0, use the current bucket size
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_tx_port_rate_lim(IN uint32_t owner_id,
+					     IN uint32_t port,
+					     IN uint32_t rate_limit_val,
+					     IN uint32_t bucket_size)
+{
+	uint32_t tmp_tcont = 0;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==ENTER==%s: owner_id[%d],port[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
+		__func__, owner_id, port, rate_limit_val, bucket_size);
+
+	if (bucket_size) {
+		if (mvNetaTxpBurstSet(port, tmp_tcont, bucket_size) != MV_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				"==ERROE==%s: Invalid bucket size value: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
+				__func__, owner_id, rate_limit_val, bucket_size);
+			return ERR_SW_TM_BUCKET_SIZE_INVALID;
+		}
+	}
+
+	mvNetaTxpRateSet(port, tmp_tcont, rate_limit_val);
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD,  "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_tm_set_tx_port_rate_lim);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h
index dabec88..6aae62d 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h
@@ -250,4 +250,29 @@
 tpm_error_code_t tpm_tm_set_gmac0_ingr_rate_lim(IN uint32_t owner_id,
 						IN uint32_t rate_limit_val,
 						IN uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_tx_port_rate_lim()
+*
+* DESCRIPTION:      Configures the rate limit of tx port wanted.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       port              - port want to do rate limit
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_tx_port_rate_lim(IN uint32_t owner_id,
+					     IN uint32_t port,
+					     IN uint32_t rate_limit_val,
+					     IN uint32_t bucket_size);
+
 #endif /* _TPM_TM_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h
index 8053dd7..4f85779 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h
@@ -114,16 +114,17 @@
 typedef enum {
 	TPM_API_MGMT,
 	TPM_API_MAC_LEARN,
+	TPM_API_DS_LOAD_BALANCE,
 	TPM_API_CPU_LOOPBACK,
 	TPM_API_L2_PRIM,
 	TPM_API_L3_TYPE,
 	TPM_API_IPV4,
 	TPM_API_IPV4_MC,
+	TPM_API_IPV6_NH,
+	TPM_API_IPV6_L4,
 	TPM_API_IPV6_GEN,
 	TPM_API_IPV6_DIP,
 	TPM_API_IPV6_MC,
-	TPM_API_IPV6_NH,
-	TPM_API_IPV6_L4,
 	TPM_API_CNM,
 	TPM_API_TYPE_ILLEGAL,
 	TPM_MAX_API_TYPES = TPM_API_TYPE_ILLEGAL
@@ -247,10 +248,19 @@
 #define	TPM_TRG_PORT_CPU		(0x00020000)	/* upstream / downstream - CPU port */
 #define	TPM_TRG_PORT_UNI_ANY		(0x00040000)	/* downstream - all UNI ports */
 #define	TPM_TRG_PORT_UNI_CPU_LOOP	(0x00080000)	/* downstream - loop to the CPU port */
+
+#define TPM_TRG_LOAD_BAL                (0x80000000)    /* for 2G DS Load-Balancing,
+							   set target_gmac to GMAC1 */
+
 #define	TPM_TRG_PORT_ILLEGAL		(0xFFFFFFFF)	/* illegal port number value */
 #define	TPM_TRG_UNI_OFFSET		8
 #define	TPM_TRG_UNI_MASK		0x1FF
 
+typedef enum {
+	TPM_DS_TGRT_G0,
+	TPM_DS_TGRT_G1,
+	TPM_DS_TGRT_CPU,
+} tpm_ds_load_balance_tgrt_t;
 
 /* target port type - bitmap */
 typedef uint32_t tpm_trg_port_type_t;	/*ex: TPM_TRG_PORT_WAN or TPM_TRG_TCONT_0 */
@@ -448,6 +458,20 @@
 /****************************************************************/
 /*          IPV4 Multicast definitions                          */
 /****************************************************************/
+typedef enum {
+	TPM_MC_ALL_CPU_FRWD,
+	TPM_MC_MAC_ONLY_FILTER,
+	TPM_MC_COMBINED_IP_MAC_FILTER,
+	TPM_MC_IP_ONLY_FILTER,
+	TPM_MC_FILTER_MODE_MAX,
+} tpm_mc_filter_mode_t;
+
+typedef enum {
+	TPM_MC_IGMP_SNOOPING,
+	TPM_MC_IGMP_PROXY,
+	TPM_MC_IGMP_MODE_MAX,
+} tpm_mc_igmp_mode_t;
+
 typedef enum tpm_mc_port_mode {
 	TPM_MC_UNI_MODE_EXCLUDE,
 	TPM_MC_UNI_MODE_TRANSPARENT,
@@ -586,16 +610,26 @@
 } tpm_rule_ipv4_key_t;
 
 typedef struct tpm_rule_ipv4_mc_key {
+	uint32_t stream_num;
+	tpm_mc_igmp_mode_t igmp_mode;
+	uint8_t mc_stream_pppoe;
 	uint16_t vid;
 	uint8_t ipv4_src_add[4];
 	uint8_t ipv4_dest_add[4];
 	uint8_t ignore_ipv4_src;
+	uint16_t dest_queue;
 	tpm_trg_port_type_t dest_port_bm;
 } tpm_rule_ipv4_mc_key_t;
 
 typedef struct tpm_rule_ipv6_mc_key {
+	uint32_t stream_num;
+	tpm_mc_igmp_mode_t igmp_mode;
+	uint8_t mc_stream_pppoe;
 	uint16_t vid;
+	uint8_t ipv6_src_add[16];
 	uint8_t ipv6_dest_add[16];
+	uint8_t ignore_ipv6_src;
+	uint16_t dest_queue;
 	tpm_trg_port_type_t dest_port_bm;
 } tpm_rule_ipv6_mc_key_t;
 
@@ -836,6 +870,14 @@
 	uint16_t dummy2;
 } tpm_sw_mirror_t;
 
+/* Switch trunk type */
+typedef struct {
+	uint32_t trunk_id;
+	uint32_t port_mask;
+	uint32_t mask_num;
+	uint32_t trunk_mask;
+} tpm_sw_trunk_t;
+
 /*  typedef: struct tpm_sw_pirl_customer_t*/
 typedef struct {
 	uint32_t ebsLimit;
@@ -891,6 +933,46 @@
 	uint32_t packets_1024_1518Octets;
 } tpm_swport_pm_3_t;
 
+/*
+  All counter set 3 is used by 88E6093 and 88E6065
+*/
+typedef struct {
+	uint32_t  dropEvents;
+	uint32_t  InGoodOctetsLo;
+	uint32_t  InGoodOctetsHi;
+	uint32_t  InBadOctets;
+	uint32_t  OutFCSErr;
+	uint32_t  InUnicasts;
+	uint32_t  Deferred;
+	uint32_t  InBroadcasts;
+	uint32_t  InMulticasts;
+	uint32_t  Octets64;
+	uint32_t  Octets127;
+	uint32_t  Octets255;
+	uint32_t  Octets511;
+	uint32_t  Octets1023;
+	uint32_t  OctetsMax;
+	uint32_t  OutOctetsLo;
+	uint32_t  OutOctetsHi;
+	uint32_t  OutUnicasts;
+	uint32_t  Excessive;
+	uint32_t  OutMulticasts;
+	uint32_t  OutBroadcasts;
+	uint32_t  Single;
+	uint32_t  OutPause;
+	uint32_t  InPause;
+	uint32_t  Multiple;
+	uint32_t  Undersize;
+	uint32_t  Fragments;
+	uint32_t  Oversize;
+	uint32_t  Jabber;
+	uint32_t  InMACRcvErr;
+	uint32_t  InFCSErr;
+	uint32_t  Collisions;
+	uint32_t  Late;
+
+} tpm_swport_pm_3_all_t;
+
 /******************************************************************************/
 /********************************** Initialisation defs ***********************/
 /******************************************************************************/
@@ -930,7 +1012,8 @@
 	TPM_PON_WAN_G1_SINGLE_PORT,
 	TPM_PON_G1_WAN_G0_SINGLE_PORT,
 	TPM_PON_G0_WAN_G1_SINGLE_PORT,
-	TPM_PON_WAN_G0_G1_LPBK
+	TPM_PON_WAN_G0_G1_LPBK,
+	TPM_PON_WAN_G0_G1_DUAL_LAN
 } tpm_eth_complex_profile_t;
 
 typedef enum {
@@ -1023,26 +1106,6 @@
 	TPM_MAX_NUM_TX_PORTS
 } tpm_init_tx_mod_t;
 
-typedef struct {
-	uint32_t omci_etype;
-
-	uint32_t oam_channel_configured;	/* omci or oam channel configured */
-	uint16_t omci_gemport;
-	uint32_t oam_cpu_rx_q;	/* omci cpu rx q or oam cpu rx q */
-	uint32_t oam_cpu_tx_q;	/* omci cpu tx q or oam cpu tx q */
-	uint32_t oam_cpu_tx_port;	/* omci tcount or oam llid */
-	uint32_t pnc_init_debug_port;
-	tpm_init_pon_type_t pon_type;
-
-} tpm_init_misc_t;
-
-/* Structure holds the IGMP/MLD settings */
-typedef struct {
-	uint32_t valid;
-	uint32_t igmp_snoop;
-	uint32_t igmp_cpu_queue;
-} tpm_init_igmp_t;
-
 /* Structure holds the physical connections of all external Ethernet ports */
 typedef struct {
 	uint32_t		valid;
@@ -1099,6 +1162,7 @@
 	TPM_PNC_MAC_LEARN,
 	TPM_PNC_CPU_WAN_LPBK_US,
 	TPM_PNC_NUM_VLAN_TAGS,
+	TPM_PNC_DS_LOAD_BALANCE,
 	TPM_PNC_MULTI_LPBK,
 	TPM_PNC_VIRT_UNI,
 	TPM_PNC_LOOP_DET_US,
@@ -1107,13 +1171,14 @@
 	TPM_PNC_IGMP,
 	TPM_PNC_IPV4_MC_DS,
 	TPM_PNC_IPV4_MAIN,
-	TPM_PNC_TCP_FLAG,
+	TPM_PNC_IPV4_TCP_FLAG,
 	TPM_PNC_TTL,
 	TPM_PNC_IPV4_PROTO,
 	TPM_PNC_IPV4_FRAG,
 	TPM_PNC_IPV4_LEN,
 	TPM_PNC_IPV6_NH,
 	TPM_PNC_IPV6_L4_MC_DS,
+	TPM_PNC_IPV6_TCP_FLAG,
 	TPM_PNC_IPV6_L4,
 	TPM_PNC_IPV6_HOPL,
 	TPM_PNC_IPV6_MC_SIP,
@@ -1152,6 +1217,10 @@
 	TPM_IPV6_5T_DISABLED = 0,
 	TPM_IPV6_5T_ENABLED,
 } tpm_init_ipv6_5t_enable_t;
+typedef enum {
+	TPM_DS_MAC_BASED_TRUNK_DISABLED = 0,
+	TPM_DS_MAC_BASED_TRUNK_ENABLED,
+} tpm_init_ds_mac_based_trunk_enable_t;
 
 typedef enum {
 	TPM_CTC_CM_DISABLED = 0,
@@ -1277,20 +1346,6 @@
 } tpm_init_split_mod_enable_t;
 
 typedef enum {
-	TPM_MC_ALL_CPU_FRWD,
-	TPM_MC_MAC_ONLY_FILTER,
-	TPM_MC_COMBINED_IP_MAC_FILTER,
-	TPM_MC_IP_ONLY_FILTER,
-	TPM_MC_FILTER_MODE_MAX,
-} tpm_mc_filter_mode_t;
-
-typedef enum {
-	TPM_MC_IGMP_SNOOPING,
-	TPM_MC_IGMP_PROXY,
-	TPM_MC_IGMP_MODE_MAX,
-} tpm_mc_igmp_mode_t;
-
-typedef enum {
 	TPM_MTU_IPV4,	/* IPV4 */
 	TPM_MTU_IPV6,	/* IPV6 */
 } tpm_mtu_ethertype_t;
@@ -1337,6 +1392,16 @@
 	uint32_t ipv6_mc_support;
 } tpm_init_mc_setting_t;
 
+typedef enum {
+	TPM_INVALID_GMAC = -1,
+	TPM_ENUM_GMAC_0,
+	TPM_ENUM_GMAC_1,
+	TPM_ENUM_PMAC,
+	TPM_MAX_GMAC = TPM_ENUM_PMAC,
+	TPM_MAX_NUM_GMACS
+} tpm_gmacs_enum_t;
+
+
 typedef struct {
 	tpm_init_split_mod_enable_t split_mod_enable;
 	uint8_t p_bit[8];
@@ -1370,7 +1435,8 @@
 	tpm_eth_complex_profile_t	eth_cmplx_profile;
 	tpm_init_eth_port_conf_t	eth_port_conf[TPM_MAX_NUM_ETH_PORTS];
 	tpm_init_gmac_conn_conf_t	gmac_port_conf[TPM_NUM_GMACS];
-	uint32_t			backup_wan;
+	uint32_t			active_wan;
+	tpm_init_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	tpm_init_gmac_tx_t gmac_tx[TPM_MAX_NUM_TX_PORTS];
 	tpm_init_gmac_rx_t gmac_rx[TPM_NUM_GMACS];
@@ -1436,6 +1502,7 @@
 	ERR_MC_STREAM_INVALID,	/*Illegal stream number. */
 	ERR_MC_STREAM_EXISTS,	/*Stream number already exists. */
 	ERR_MC_DST_PORT_INVALID,	/*Destination port bitmap does not match the UNI ports. */
+	ERR_MC_DST_QUEUE_INVALID,	/*Destination queue number invalid. */
 	ERR_IPV4_MC_DST_IP_INVALID,	/*Destination IP address is not in the MC range. */
 	ERR_IPV6_MC_DST_IP_INVALID,	/*Destination IPv6 address is not in the MC range. */
 	ERR_IPV6_MC_SRC_IP_INVALID,	/*SRC IPv6 address is not in the MC_SIP range. */
@@ -1489,6 +1556,8 @@
 	ERR_TPMCHECK_PMT_DB_MISMATCH,/*DB PMT check FAIL */
 	ERR_TPMCHECK_PMT_HW_MISMATCH,/*HW PMT check FAIL */
 	ERR_UNKNOWN_MAC_CONF_INVALID,/*Illegal MAC learn default conf*/
+	ERR_PHY_SRC_PORT_CONN_INVALID,/*PHY and source port connection invalid*/
+	ERR_PHY_STATUS_UNKNOWN,/*PHY status info is unknown*/
 } tpm_error_code_t;
 
 #ifdef __cplusplus
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c
index 49f9876..97373e2 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c
@@ -634,6 +634,56 @@
 }
 
 /*******************************************************************************
+* get_ds_mac_based_trunking_enable()
+*
+* DESCRIPTION:      Get DS load balance parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether DS load balance is enabled
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ds_mac_based_trunking_enable(uint32_t *enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_DS_MAC_BASED_TRUNKING_E, enable);
+
+#ifdef US_DEBUG_PRINT
+		printk("ds_mac_based_trunking enable %d \n", *enable);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
 * get_igmp_snoop_params_cpu_queue()
 *
 * DESCRIPTION:      Get IGMP snooping parameters from XML configuration file
@@ -1191,7 +1241,7 @@
 			rc = US_RC_FAIL;
 			break;
 		}
-		
+
 		/* mandatory field */
 		xmlStr = ezxml_attr(xmlPort, US_XML_ETH_PORT_SRC_ATTR);
 		if (xmlStr == NULL) {
@@ -1213,7 +1263,7 @@
 		if (eth_port_bufs[port_nr].valid) {
 			printk("%d)  src_port %d  switch_port %d\n",
 			       port_nr,
-			       eth_port_bufs[port_nr].port_src, 
+			       eth_port_bufs[port_nr].port_src,
 			       eth_port_bufs[port_nr].switch_port);
 		}
 	}
@@ -1224,7 +1274,7 @@
 }
 
 /*******************************************************************************
-* get_backup_wan_params()
+* get_active_wan_params()
 *
 * DESCRIPTION:      Get GMAC connection parameters from XML configuration file
 *
@@ -1237,20 +1287,20 @@
 * RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
 *
 *******************************************************************************/
-int get_backup_wan_params(uint32_t *backup_wan)
+int get_active_wan_params(uint32_t *active_wan)
 {
 	ezxml_t xmlHead;
 	ezxml_t xmlElement;
 	int rc = US_RC_OK;
 
-	if (backup_wan == NULL) {
+	if (active_wan == NULL) {
 #ifdef US_DEBUG_PRINT
 		printk(KERN_ERR "%s: NULL pointer\n", __func__);
 #endif
 		return US_RC_FAIL;
 	}
 
-	*backup_wan = 0;
+	*active_wan = 0;
 
 	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
 
@@ -1264,12 +1314,12 @@
 #endif
 		rc = US_RC_NOT_FOUND;
 	} else {
-		rc = get_int_param(xmlElement, US_XML_BACKUP_WAN_E, backup_wan);
+		rc = get_int_param(xmlElement, US_XML_ACTIVE_WAN_E, active_wan);
 #ifdef US_DEBUG_PRINT
 		printk("======================================\n");
 		printk("            ETH COMPLEX               \n");
 		printk("======================================\n");
-		printk("backup_wan %d \n", *backup_wan);
+		printk("active_wan %d \n", *active_wan);
 #endif
 	}
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h
index ac14460..88d65ae 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h
@@ -147,6 +147,7 @@
 #define US_XML_OMCI_E              "OMCI"
 #define US_XML_OMCI_ETY_E          "OMCI_ETY"
 
+#define US_XML_DS_MAC_BASED_TRUNKING_E        "ds_mac_based_trunking"
 #define US_XML_IGMP_SNOOP_E        "igmp_snoop"
 #define US_XML_IGMP_SNOOP_ALL_E    "snoop_all"
 #define US_XML_ENABLED_E           "enabled"
@@ -181,7 +182,7 @@
 #define US_XML_ETH_PORT_INTCON_ATTR "intr_conn"
 #define US_XML_ETH_CMPLX_CONFIG_E  "eth_complex_config"
 #define US_XML_WAN_E		    "WAN"
-#define US_XML_BACKUP_WAN_E        "backup_wan"
+#define US_XML_ACTIVE_WAN_E        "active_wan"
 #define US_XML_VIRTUAL_UNI_E       "virtual_uni"
 
 #define US_XML_ETH_PROFILE_E       "profile"
@@ -309,6 +310,7 @@
 int get_omci_etype_param(uint32_t *ety);
 int get_debug_port_params(uint32_t *valid, uint32_t *num);
 int get_igmp_snoop_params_enable(uint32_t *enable);
+int get_ds_mac_based_trunking_enable(uint32_t *enable);
 int get_igmp_snoop_params_cpu_queue(uint32_t *que);
 int get_igmp_snoop_params_port_frwd_mode(uint32_t *mode, tpm_src_port_type_t port);
 int get_gmac_conn_params(uint32_t *num_tcont_llid);
@@ -316,7 +318,7 @@
 int get_eth_cmplx_profile_params(tpm_eth_complex_profile_t *eth_cmplx_profile);
 int get_gmac_port_conf_params(tpm_init_gmac_conn_conf_t *gmac_port_conf_bufs, int max_gmac_port_num);
 int get_eth_port_conf_params(tpm_init_eth_port_conf_t *eth_port_bufs, int max_eth_port_num);
-int get_backup_wan_params(uint32_t *backup_wan);
+int get_active_wan_params(uint32_t *active_wan);
 
 int get_gmac_pool_bufs_params(tpm_init_gmac_bufs_t *gmac_bufs, int max_gmacs_num);
 int get_trace_debug_info_param(uint32_t *trace_debug_info);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c
index b87da74..2b1c4f6 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 Copyright (C) Marvell International Ltd. and its affiliates
 
-This software file (the "File") is owned and distributed by Marvell 
+This software file (the "File") is owned and distributed by Marvell
 International Ltd. and/or its affiliates ("Marvell") under the following
 alternative licensing terms.  Once you have made an election to distribute the
 File under one of the following license alternatives, please (i) delete this
@@ -19,45 +19,45 @@
 ********************************************************************************
 Marvell GPL License Option
 
-If you received this File from Marvell, you may opt to use, redistribute and/or 
-modify this File in accordance with the terms and conditions of the General 
-Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
-available along with the File in the license.txt file or by writing to the Free 
-Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
-on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
 
-THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
-DISCLAIMED.  The GPL License provides additional details about this warranty 
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
 disclaimer.
 ********************************************************************************
 Marvell BSD License Option
 
-If you received this File from Marvell, you may opt to use, redistribute and/or 
-modify this File under the following licensing terms. 
-Redistribution and use in source and binary forms, with or without modification, 
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     *   Redistributions of source code must retain the above copyright notice,
-	    this list of conditions and the following disclaimer. 
+	    this list of conditions and the following disclaimer.
 
     *   Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in the
-        documentation and/or other materials provided with the distribution. 
+        documentation and/or other materials provided with the distribution.
 
-    *   Neither the name of Marvell nor the names of its contributors may be 
-        used to endorse or promote products derived from this software without 
-        specific prior written permission. 
-    
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
@@ -67,11 +67,11 @@
 **                                                                           **
 **  DESCRIPTION : This file implements TPM BringUp handling                  **
 *******************************************************************************
-*                                                                             *                              
+*                                                                             *
 *  MODIFICATION HISTORY:                                                      *
 *                                                                             *
-*   11Aug10  Yuval Caduri   created                                         *  
-* =========================================================================== *      
+*   11Aug10  Yuval Caduri   created                                         *
+* =========================================================================== *
 ******************************************************************************/
 
 /* Include Files
@@ -80,7 +80,7 @@
 #include "tpm_header.h"
 
 /* Local Constant
-------------------------------------------------------------------------------*/                                               
+------------------------------------------------------------------------------*/
 
 /* Global Variables
 ------------------------------------------------------------------------------*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c
index e6ad713..6a467be 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c
@@ -117,6 +117,7 @@
   tpm_ioctl_tm_tm_t           tpm_ioctl_tm_tm;
   tpm_ioctl_igmp_t            tpm_ioctl_igmp;
   tpm_ioctl_mib_reset_t       tpm_ioctl_mib_reset;
+  tpm_ioctl_set_active_wan_t  tpm_ioctl_set_active_wan;
   tpm_ioctl_swport_pm_3_t     apm_ioctl_pm_ethernet_3;
   tpm_ioctl_rx_igmp_t         tpm_ioctl_rx_igmp;
   tpm_ioctl_tx_igmp_t         tpm_ioctl_tx_igmp;
@@ -654,7 +655,7 @@
 
                   ret = 0;
                   break;
-		  
+
 	      /* ====== MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE ========= */
 	      case MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE:
 	      	  rcode = tpm_add_ctc_cm_acl_rule(tpm_add_acl_rule->owner_id,
@@ -695,6 +696,24 @@
 	           }
 	           ret = 0;
 	           break;
+              /* ====== MV_TPM_IOCTL_ADD_DS_LOAD_BALANCE_RULE ========= */
+	      case MV_TPM_IOCTL_ADD_DS_LOAD_BALANCE_RULE:
+	          rcode = tpm_add_ds_load_balance_rule(tpm_add_acl_rule->owner_id,
+				    tpm_add_acl_rule->rule_num,
+				    &tpm_add_acl_rule->rule_idx,
+				    tpm_add_acl_rule->parse_rule_bm,
+				    tpm_add_acl_rule->ds_load_balance_acl_rule.parse_flags_bm,
+				    &tpm_add_acl_rule->ds_load_balance_acl_rule.l2_key,
+				    tpm_add_acl_rule->ds_load_balance_acl_rule.tgrt);
+	           if (rcode != TPM_OK)
+		         goto ioctlErr;
+
+                   if (copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t))) {
+		           printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+		           goto ioctlErr;
+	           }
+	           ret = 0;
+	           break;
 
               /* ====== MV_TPM_IOCTL_SET_MOD_RULE ========= */
               case MV_TPM_IOCTL_SET_MOD_RULE:
@@ -762,6 +781,24 @@
                   ret = 0;
                   break;
 
+              /* ====== MV_TPM_IOCTL_DEL_DS_LOAD_BALANCE_RULE ========= */
+              case MV_TPM_IOCTL_DEL_DS_LOAD_BALANCE_RULE:
+
+                  rcode = tpm_del_ds_load_balance_rule(  tpm_del_acl_rule->owner_id,
+                                            tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
 		  /* ====== MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE ========= */
 		  case MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE:
 		      rcode = tpm_del_mac_learn_rule(tpm_del_acl_rule->owner_id,
@@ -936,19 +973,19 @@
                   break;
 	       /* ====== MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE ========= */
 	       case MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE:
-		  
+
 		   rcode = tpm_del_ctc_cm_acl_rule(tpm_del_acl_rule->owner_id,
 						tpm_del_acl_rule->src_port,
 						tpm_del_acl_rule->precedence);
-		  
+
 		   if (rcode != TPM_OK)
 		   	goto ioctlErr;
-		  
+
 		   if (copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t))) {
 			printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
 			goto ioctlErr;
 		   }
-		  
+
 		   ret = 0;
 		   break;
 
@@ -1142,6 +1179,25 @@
 
                   ret = 0;
                   break;
+              /* ====== MV_TPM_IOCTL_ADD_IPv4_MC_STREAM_SET_QUEUE ========= */
+              case MV_TPM_IOCTL_ADD_IPv4_MC_STREAM_SET_QUEUE:
+
+
+                  rcode = tpm_add_ipv4_mc_stream_set_queue(  tpm_mc_rule->owner_id,
+                                                   tpm_mc_rule->stream_num,
+                                                   tpm_mc_rule->igmp_mode,
+                                                   tpm_mc_rule->mc_stream_pppoe,
+                                                   tpm_mc_rule->vid,
+                                                 &(tpm_mc_rule->ipv4_mc.ipv4_src_add[0]),
+                                                 &(tpm_mc_rule->ipv4_mc.ipv4_dst_add[0]),
+                                                   tpm_mc_rule->ipv4_mc.ignore_ipv4_src,
+                                                   tpm_mc_rule->dest_queue,
+                                                   tpm_mc_rule->dest_port_bm);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
 
               /* ====== MV_TPM_IOCTL_MOD_IPv4_MC_STREAM ========= */
               case MV_TPM_IOCTL_MOD_IPv4_MC_STREAM:
@@ -1166,46 +1222,65 @@
                   ret = 0;
                   break;
 
-			  /* ====== MV_TPM_IOCTL_ADD_IPv6_MC_STREAM ========= */
-			  case MV_TPM_IOCTL_ADD_IPv6_MC_STREAM:
+	      /* ====== MV_TPM_IOCTL_ADD_IPv6_MC_STREAM ========= */
+	      case MV_TPM_IOCTL_ADD_IPv6_MC_STREAM:
 
-				  rcode = tpm_add_ipv6_mc_stream(  tpm_mc_rule->owner_id,
-								   tpm_mc_rule->stream_num,
-								   tpm_mc_rule->igmp_mode,
-								   tpm_mc_rule->mc_stream_pppoe,
-								   tpm_mc_rule->vid,
-								   &(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]),
-								   &(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]),
-								   tpm_mc_rule->ipv6_mc.ignore_ipv6_src,
-								   tpm_mc_rule->dest_port_bm);
-				  if(rcode != TPM_OK)
-					goto ioctlErr;
+		      rcode = tpm_add_ipv6_mc_stream(  tpm_mc_rule->owner_id,
+						       tpm_mc_rule->stream_num,
+						       tpm_mc_rule->igmp_mode,
+						       tpm_mc_rule->mc_stream_pppoe,
+						       tpm_mc_rule->vid,
+						       &(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]),
+						       &(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]),
+						       tpm_mc_rule->ipv6_mc.ignore_ipv6_src,
+						       tpm_mc_rule->dest_port_bm);
+		      if(rcode != TPM_OK)
+			    goto ioctlErr;
 
-				  ret = 0;
-				  break;
+		      ret = 0;
+		      break;
 
-			  /* ====== MV_TPM_IOCTL_MOD_IPv6_MC_STREAM ========= */
-			  case MV_TPM_IOCTL_MOD_IPv6_MC_STREAM:
+	      /* ====== MV_TPM_IOCTL_ADD_IPv6_MC_STREAM_SET_QUEUE ========= */
+	      case MV_TPM_IOCTL_ADD_IPv6_MC_STREAM_SET_QUEUE:
 
-				  rcode = tpm_updt_ipv6_mc_stream(tpm_mc_rule->owner_id,
-												  tpm_mc_rule->stream_num,
-												  tpm_mc_rule->dest_port_bm);
-				  if(rcode != TPM_OK)
-					goto ioctlErr;
+		      rcode = tpm_add_ipv6_mc_stream_set_queue(tpm_mc_rule->owner_id,
+						       tpm_mc_rule->stream_num,
+						       tpm_mc_rule->igmp_mode,
+						       tpm_mc_rule->mc_stream_pppoe,
+						       tpm_mc_rule->vid,
+						       &(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]),
+						       &(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]),
+						       tpm_mc_rule->ipv6_mc.ignore_ipv6_src,
+						       tpm_mc_rule->dest_queue,
+						       tpm_mc_rule->dest_port_bm);
+		      if(rcode != TPM_OK)
+			    goto ioctlErr;
 
-				  ret = 0;
-				  break;
+		      ret = 0;
+		      break;
 
-			  /* ====== MV_TPM_IOCTL_DEL_IPv6_MC_STREAM ========= */
-			  case MV_TPM_IOCTL_DEL_IPv6_MC_STREAM:
+	      /* ====== MV_TPM_IOCTL_MOD_IPv6_MC_STREAM ========= */
+	      case MV_TPM_IOCTL_MOD_IPv6_MC_STREAM:
 
-				  rcode = tpm_del_ipv6_mc_stream(tpm_mc_rule->owner_id,
-												 tpm_mc_rule->stream_num);
-				  if(rcode != TPM_OK)
-					goto ioctlErr;
+		      rcode = tpm_updt_ipv6_mc_stream(tpm_mc_rule->owner_id,
+										      tpm_mc_rule->stream_num,
+										      tpm_mc_rule->dest_port_bm);
+		      if(rcode != TPM_OK)
+			    goto ioctlErr;
 
-				  ret = 0;
-				  break;
+		      ret = 0;
+		      break;
+
+	      /* ====== MV_TPM_IOCTL_DEL_IPv6_MC_STREAM ========= */
+	      case MV_TPM_IOCTL_DEL_IPv6_MC_STREAM:
+
+		      rcode = tpm_del_ipv6_mc_stream(tpm_mc_rule->owner_id,
+										     tpm_mc_rule->stream_num);
+		      if(rcode != TPM_OK)
+			    goto ioctlErr;
+
+		      ret = 0;
+		      break;
 
               default:
                 ret = -EINVAL;
@@ -1294,7 +1369,18 @@
               /* ====== MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL ========= */
               case MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL:
 
-                  rcode = tpm_loop_detect_add_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
+                  rcode = tpm_loop_detect_add_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id,
+		  				      tpm_mng_ch->loopback_detect_ety);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL ========= */
+              case MV_TPM_IOCTL_DEL_LOOP_DETECT_CHNL:
+
+                  rcode = tpm_loop_detect_del_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
                   if(rcode != TPM_OK)
                     goto ioctlErr;
 
@@ -1540,6 +1626,26 @@
                     goto ioctlErr;
                   ret = 0;
                   break;
+              /* ====== MV_TPM_IOCTL_SW_SET_TRUNK_PORT ========= */
+              case MV_TPM_IOCTL_SW_SET_TRUNK_PORT:
+                  rcode = tpm_sw_set_trunk_ports(tpm_sw_mac_security->owner_id,
+						 tpm_sw_mac_security->trunk.trunk_id,
+						 tpm_sw_mac_security->trunk.trunk_mask);
+
+		   if(rcode != TPM_OK)
+		       goto ioctlErr;
+		   ret = 0;
+		   break;
+              /* ====== MV_TPM_IOCTL_SW_SET_TRUNK_MASK ========= */
+              case MV_TPM_IOCTL_SW_SET_TRUNK_MASK:
+              rcode = tpm_sw_set_trunk_mask(tpm_sw_mac_security->owner_id,
+                                            tpm_sw_mac_security->trunk.mask_num,
+                                            tpm_sw_mac_security->trunk.trunk_mask);
+
+              if(rcode != TPM_OK)
+                  goto ioctlErr;
+              ret = 0;
+              break;
 
               /* ====== MV_TPM_IOCTL_SW_GET_MIRROR ========= */
               case MV_TPM_IOCTL_SW_GET_MIRROR:
@@ -1770,6 +1876,18 @@
             }
             ret = 0;
             break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_ADD_VID_SET_EGRESS_MODE ========= */
+          case MV_TPM_IOCTL_SW_PORT_ADD_VID_SET_EGRESS_MODE:
+            rcode = tpm_sw_port_add_vid_set_egrs_mode(tpm_sw_vlan_filter->owner_id,
+                                                      tpm_sw_vlan_filter->port,
+                                                      tpm_sw_vlan_filter->vid,
+                                                      tpm_sw_vlan_filter->egress_mode);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
           default:
             ret = -EINVAL;
           }
@@ -2106,6 +2224,18 @@
 
                   ret = 0;
                   break;
+
+              /* ====== MV_TPM_IOCTL_UNI_2_SW_PORT ========= */
+              case MV_TPM_IOCTL_UNI_2_SW_PORT:
+                  rcode = tpm_xlate_uni_2_switch_port(  tpm_sw_phy->owner_id,
+                                                        tpm_sw_phy->extern_port_id,
+                                                        &(tpm_sw_phy->switch_port_id));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
              default:
                ret = -EINVAL;
           }
@@ -2120,7 +2250,8 @@
                            tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_SPEED_MODE    ||
                            tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_STATE||
                            tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_FC_STATE ||
-                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX))
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_UNI_2_SW_PORT))
           {
               if(copy_to_user((tpm_ioctl_sw_phy_t*)arg, tpm_sw_phy, sizeof(tpm_ioctl_sw_phy_t)))
               {
@@ -2556,6 +2687,79 @@
           break;
 
       /* ================================ */
+      /* ====== SET active wan Section == */
+      /* ================================ */
+      case MV_TPM_IOCTL_SET_ACTIVE_WAN_SECTION:
+      {
+          tpm_ioctl_set_active_wan_t   set_active_wan;
+          if(copy_from_user(&set_active_wan, (tpm_ioctl_set_active_wan_t*)arg, sizeof(tpm_ioctl_set_active_wan_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          rcode = tpm_set_active_wan(set_active_wan.owner_id, set_active_wan.active_wan);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+      }
+      /* ================================ */
+      /* ====== SET GMAC LPBK Section                    == */
+      /* ================================ */
+      case MV_TPM_IOCTL_SET_GMAC_LPBK_SECTION:
+      {
+          tpm_ioctl_set_gmac_loopback_t   set_gmac_lpbk;
+          if(copy_from_user(&set_gmac_lpbk, (tpm_ioctl_set_gmac_loopback_t*)arg, sizeof(tpm_ioctl_set_gmac_loopback_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          rcode = tpm_set_gmac_loopback(set_gmac_lpbk.owner_id, set_gmac_lpbk.gmac, set_gmac_lpbk.enable);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+      }
+      /* ================================ */
+      /* ====== hot swap profile Section == */
+      /* ================================ */
+      case MV_TPM_IOCTL_HOT_SWAP_PROFILE_SECTION:
+      {
+          tpm_ioctl_hot_swap_profile_t  swap_profile;
+          if(copy_from_user(&swap_profile, (tpm_ioctl_hot_swap_profile_t*)arg, sizeof(tpm_ioctl_hot_swap_profile_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          rcode = tpm_hot_swap_profile(swap_profile.owner_id, swap_profile.profile_id);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+      }
+      /* ================================ */
+      /* ====== set hwf admin Section == */
+      /* ================================ */
+      case MV_TPM_IOCTL_SET_PORT_HWF_ADMIN_SECTION:
+      {
+          tpm_ioctl_set_port_hwf_admin_t  set_port_hwf_admin;
+          if(copy_from_user(&set_port_hwf_admin, (tpm_ioctl_set_port_hwf_admin_t*)arg, sizeof(tpm_ioctl_set_port_hwf_admin_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          rcode = tpm_proc_hwf_admin_set(set_port_hwf_admin.port, set_port_hwf_admin.txp, set_port_hwf_admin.enable);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+      }
+      /* ================================ */
       /* ====== ALARM  Section ======= */
       /* ================================ */
       case MV_TPM_IOCTL_ALARM_SECTION:
@@ -2847,7 +3051,7 @@
                 (tpm_ioctl_pnc_hit_cnt_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_h);
             if (tpm_ioctl_pnc_hit_cnt == NULL)
             {
-                printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", 
+                printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n",
                         __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_h);
                 ret = -ENOMEM;
                 goto ioctlErr;
@@ -2882,7 +3086,7 @@
           } /* MV_TPM_IOCTL_GET_ALL_HIT_COUNTERS */
           else
           {
-            tpm_ioctl_age_count_t *tpm_ioctl_age_count = 
+            tpm_ioctl_age_count_t *tpm_ioctl_age_count =
                 (tpm_ioctl_age_count_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_m);
             if (tpm_ioctl_age_count == NULL)
             {
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h
index ce4787c..9ceffc6 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h
@@ -107,6 +107,10 @@
 #define MV_TPM_IOCTL_FLUSH_ATU_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 28, unsigned int)
 #define MV_TPM_IOCTL_FLUSH_VTU_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 29, unsigned int)
 #define MV_TPM_IOCTL_SET_IPV6_CM_PARSE_WIN_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 30, unsigned int)
+#define MV_TPM_IOCTL_SET_ACTIVE_WAN_SECTION            _IOWR(MV_TPM_IOCTL_MAGIC, 31, unsigned int)
+#define MV_TPM_IOCTL_HOT_SWAP_PROFILE_SECTION          _IOWR(MV_TPM_IOCTL_MAGIC, 32, unsigned int)
+#define MV_TPM_IOCTL_SET_GMAC_LPBK_SECTION             _IOWR(MV_TPM_IOCTL_MAGIC, 33, unsigned int)
+#define MV_TPM_IOCTL_SET_PORT_HWF_ADMIN_SECTION        _IOWR(MV_TPM_IOCTL_MAGIC, 34, unsigned int)
 
 
 #define MV_APM_IOCTL_MAGIC  ('A')
@@ -218,6 +222,7 @@
     MV_TPM_IOCTL_ALARM_GET_ETH_PORT,
     MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX,
     MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL,
+    MV_TPM_IOCTL_DEL_LOOP_DETECT_CHNL,
     MV_TPM_IOCTL_ADD_OAM_LOOPBACK_CHNL,
     MV_TPM_IOCTL_DEL_OAM_LOOPBACK_CHNL,
     MV_TPM_IOCTL_SW_PHY_SET_PORT_DUPLEX_MODE,
@@ -225,6 +230,7 @@
     MV_TPM_IOCTL_SW_GET_MAC_AGE_TIME,
     MV_TPM_IOCTL_SW_SET_MAC_LEARN,
     MV_TPM_IOCTL_SW_GET_PORT_FLOOD,
+    MV_TPM_IOCTL_UNI_2_SW_PORT,
 
     MV_TPM_IOCTL_RESERVED_3,
     MV_TPM_IOCTL_RESERVED_4,
@@ -237,6 +243,8 @@
     MV_TPM_IOCTL_SW_SET_MIRROR,
     MV_TPM_IOCTL_SW_GET_MIRROR,
     MV_TPM_IOCTL_SW_GET_MAC_LEARN,
+    MV_TPM_IOCTL_SW_SET_TRUNK_PORT,
+    MV_TPM_IOCTL_SW_SET_TRUNK_MASK,
     MV_TPM_IOCTL_SW_PHY_GET_PORT_DUPLEX_MODE,
     MV_TPM_IOCTL_SET_MTU_SIZE,
     MV_TPM_IOCTL_GET_MTU_SIZE,
@@ -286,9 +294,9 @@
 
     MV_TPM_IOCTL_SET_IGMP_PROXY_SA_MAC,
     MV_TPM_IOCTL_GET_IGMP_PROXY_SA_MAC,
-	MV_TPM_IOCTL_ADD_IPv6_MC_STREAM,
-	MV_TPM_IOCTL_MOD_IPv6_MC_STREAM,
-	MV_TPM_IOCTL_DEL_IPv6_MC_STREAM,
+    MV_TPM_IOCTL_ADD_IPv6_MC_STREAM,
+    MV_TPM_IOCTL_MOD_IPv6_MC_STREAM,
+    MV_TPM_IOCTL_DEL_IPv6_MC_STREAM,
 
     MV_TPM_IOCTL_ADD_IPV6_GEN_5T_RULE,
     MV_TPM_IOCTL_DEL_IPV6_GEN_5T_RULE,
@@ -306,6 +314,11 @@
     MV_TPM_IOCTL_SET_MAC_LEARN_DEFAULT_ACTION,
     MV_TPM_IOCTL_TM_SET_GMAC0_INGR_RATE_LIMIT,
     MV_TPM_IOCTL_GET_MAC_LEARN_ENTRY_NUM,
+    MV_TPM_IOCTL_ADD_DS_LOAD_BALANCE_RULE,
+    MV_TPM_IOCTL_DEL_DS_LOAD_BALANCE_RULE,
+    MV_TPM_IOCTL_ADD_IPv4_MC_STREAM_SET_QUEUE,
+    MV_TPM_IOCTL_ADD_IPv6_MC_STREAM_SET_QUEUE,
+    MV_TPM_IOCTL_SW_PORT_ADD_VID_SET_EGRESS_MODE,
 
 } tpm_ioctl_cmd_type_t;
 
@@ -526,6 +539,14 @@
     tpm_pkt_action_t   pkt_act;
 } ctc_cm_acl_rule_t;
 
+/* DS load balance */
+typedef struct
+{
+    tpm_l2_acl_key_t   l2_key;
+    tpm_parse_flags_t  parse_flags_bm;
+    tpm_ds_load_balance_tgrt_t tgrt;
+} ds_load_balance_acl_rule_t;
+
 /* Pkt modification */
 typedef struct
 {
@@ -559,6 +580,7 @@
       ipv6_l4_ports_5t_rule_t  ipv6_l4_ports_5t_rule;
       ctc_cm_acl_rule_t        ctc_cm_acl_rule;
       pkt_mod_rule_t           mod_rule;
+      ds_load_balance_acl_rule_t ds_load_balance_acl_rule;
     };
 } tpm_ioctl_add_acl_rule_t;
 
@@ -668,6 +690,7 @@
     tpm_mc_igmp_mode_t   igmp_mode;
     uint8_t              mc_stream_pppoe;
     uint16_t             vid;
+    uint16_t             dest_queue;
     tpm_trg_port_type_t  dest_port_bm;
 
     union
@@ -712,6 +735,7 @@
     uint32_t              mng_cmd;
     tpm_ioctl_omci_ch_t   tpm_ioctl_omci_ch;
     tpm_ioctl_oam_ch_t    tpm_ioctl_oam_ch;
+    uint32_t              loopback_detect_ety;
 } tpm_ioctl_mng_ch_t;
 
 /* Switch Section
@@ -751,6 +775,7 @@
     tpm_mru_type_t        mtu_type;
     uint32_t              mtu_size;
     uint32_t              port_vector;
+    tpm_sw_trunk_t        trunk;
 } tpm_ioctl_sw_mac_security_t;
 
 /* Switch Vlan filtering */
@@ -864,6 +889,37 @@
     tpm_reset_level_enum_t reset_level;
 } tpm_ioctl_mib_reset_t;
 
+/* set active wan port */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_gmacs_enum_t       active_wan;
+} tpm_ioctl_set_active_wan_t;
+
+/* set gmac loopback */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_gmacs_enum_t       gmac;
+    uint8_t                enable;
+} tpm_ioctl_set_gmac_loopback_t;
+
+/* hot swap profile */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_eth_complex_profile_t       profile_id;
+} tpm_ioctl_hot_swap_profile_t;
+
+/* set port hwf admin */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_gmacs_enum_t       port;
+    uint8_t                txp;
+    uint8_t                enable;
+} tpm_ioctl_set_port_hwf_admin_t;
+
 /* ALARM Section */
 typedef struct
 {
@@ -889,7 +945,7 @@
 {
   tpm_src_port_type_t  port;
   uint32_t             owner_id;
-  tpm_swport_pm_3_t    tpm_swport_pm_3;
+  tpm_swport_pm_3_all_t tpm_swport_pm_3;
 
 } tpm_ioctl_swport_pm_3_t;
 
@@ -1017,6 +1073,9 @@
     tpm_ioctl_flush_vtu_t       tpm_ioctl_flush_vtu;
     tpm_ioctl_flush_atu_t       tpm_ioctl_flush_atu;
     tpm_ioctl_ipv6_parse_window_t   tpm_ipv6_parse_window;
+    tpm_ioctl_set_active_wan_t      tpm_set_active_wan_param;
+    tpm_ioctl_hot_swap_profile_t    tpm_hot_swap_profile_param;
+    tpm_ioctl_set_port_hwf_admin_t  tpm_set_port_hwf_admin_param;
 } tpm_cmd_data_t;
 
 /* this structure is used for passing sysfs request from kernel to userspace
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c
index 2f33320..097d2b6 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c
@@ -85,7 +85,6 @@
 #define TPM_CHECK_DIV_BY_32(x)   ((x) >> 5)
 #define TPM_CHECK_MOD_32(x)      ((x) & 0x1f)
 
-extern char *tpm_db_api_type_str[TPM_MAX_API_TYPES];
 extern char *opCodeOperationStr[30];
 
 /*******************************************************************************
@@ -872,6 +871,7 @@
 	tpm_mc_filter_mode_t filter_mode;
 	uint8_t mc_stream_pppoe, ignore_ipv4_src, ipv4_src_add[4], ipv4_dst_add[4];
 	uint16_t mc_vid;
+	uint16_t dest_queue;
 	uint32_t stream_num, igmp_mode, dest_port_bm;
 	int32_t tpm_ret = 0;
 
@@ -893,6 +893,7 @@
 	mc_vid = tpm_rule->ipv4_mc_key.vid;
 	ignore_ipv4_src = tpm_rule->ipv4_mc_key.ignore_ipv4_src;
 	*mod_entry = mod_con->mod_cmd_ind;
+	dest_queue = tpm_rule->ipv4_mc_key.dest_queue;
 
 	/*******************generate PnC Rule Start********************/
 	/*generate tcam entry*/
@@ -906,11 +907,13 @@
 					      &(pnc_data->pncl_tcam));
 	IF_ERROR(tpm_ret);
 	/* Build SRAM Entry */
-	tpm_ret = tpm_proc_ipv4_mc_sram_build(filter_mode,
+	tpm_ret = tpm_proc_ipvx_mc_sram_build(filter_mode,
 					      igmp_mode,
+					      dest_queue,
 					      dest_port_bm,
 					      mod_con->mod_cmd_ind,
-					      &(pnc_data->pncl_sram));
+					      &(pnc_data->pncl_sram),
+					      TPM_IP_VER_4 );
 	IF_ERROR(tpm_ret);
 
 	return TPM_OK;
@@ -1206,6 +1209,7 @@
 	uint8_t ipv6_dst_add[16];
 	int32_t tpm_ret = 0;
 	uint8_t sip_index = 0;
+	uint16_t dest_queue;
 
 	/*params check*/
 	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
@@ -1223,6 +1227,7 @@
 	rule_action->pkt_act = 0;
 	mc_vid = tpm_rule->ipv6_mc_key.vid;
 	*mod_entry = mod_con->mod_cmd_ind;
+	dest_queue = tpm_rule->ipv6_mc_key.dest_queue;
 
 	/* get sip_index */
 	if (0 == ipv6_mc_stream_entry.ignore_src_addr) {
@@ -1246,11 +1251,13 @@
 					      &(pnc_data->pncl_tcam));
 	IF_ERROR(tpm_ret);
 	/*generate sram*/
-	tpm_ret = tpm_proc_ipv6_mc_sram_build(filter_mode,
+	tpm_ret = tpm_proc_ipvx_mc_sram_build(filter_mode,
 					      igmp_mode,
+					      dest_queue,
 					      dest_port_bm,
 					      mod_con->mod_cmd_ind,
-					      &(pnc_data->pncl_sram));
+					      &(pnc_data->pncl_sram),
+					      TPM_IP_VER_6);
 	IF_ERROR(tpm_ret);
 
 	return TPM_OK;
@@ -1659,10 +1666,10 @@
 	if (tpm_check_main_chain_type(trg_gmac, pkt_mod_bm, int_mod_bm, *mod_entry,
 				      &main_chain_check)) {
 		printk("(Warn) main chain type check failed, API: %s, PnC index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	} else if (main_chain_check) {
 		printk("main chain type mismatch, API: %s, PnC index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	}
 
 	/*clear structure*/
@@ -1681,11 +1688,11 @@
 	if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
 			  TPM_CHECK_WITH_DB)) {
 		printk("SW PMT check error, API type: %s, PnC rule index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	} else if (pmt_check_result) {
 		*pmt_sw_error_count = *pmt_sw_error_count + 1;
 		printk("SW PMT mismatch, API type: %s, PnC rule index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	}
 	/*clear structure*/
 	memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
@@ -1703,11 +1710,11 @@
 	if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
 			  TPM_CHECK_WITH_HW)) {
 		printk("HW PMT check error, API type: %s, PnC rule index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	} else if (pmt_check_result) {
 		*pmt_hw_error_count = *pmt_hw_error_count + 1;
 		printk("HW PMT mismatch, API type: %s, PnC rule index %d\n",
-			tpm_db_api_type_str[api_type], rule_index);
+			api_type_to_str(api_type), rule_index);
 	}
 
 	return TPM_OK;
@@ -1785,7 +1792,7 @@
 		/* Get the api_section */
 		tpm_ret = tpm_db_api_section_get_from_api_type(api_type, &api_section);
 		if (tpm_ret != TPM_RC_OK) {
-			printk("Get API_SECTION Failed-%s\n", tpm_db_api_type_str[api_type]);
+			printk("Get API_SECTION Failed-%s\n", api_type_to_str(api_type));
 			continue;
 		}
 
@@ -1842,7 +1849,7 @@
 										   &rule_action);
 				if (tpm_ret) {
 					printk("API type: %s, the %d th PnC Rule Rebuild Failed\n",
-						tpm_db_api_type_str[api_type], rule_index);
+						api_type_to_str(api_type), rule_index);
 					unnormal_end_count++;
 					break;
 				}
@@ -1873,7 +1880,7 @@
 				tpm_check_update_sram(&shadow_pnc.sram_entry, &rule_action);
 				if (memcmp(&pnc_out, &read_pnc, sizeof(tpm_pnc_all_t))) {
 					printk("HW PNC mismatch, API type: %s, PnC rule index %d\n",
-						tpm_db_api_type_str[api_type], rule_index);
+						api_type_to_str(api_type), rule_index);
 					pnc_mismatch_info_show(&pnc_out, &read_pnc);
 					pnc_hw_error_count++;
 					/*correct the bad tpm rule, TODO done in future*/
@@ -1881,7 +1888,7 @@
 				}
 				if (memcmp(&pnc_out, &shadow_pnc, sizeof(tpm_pnc_all_t))) {
 					printk("SW PNC mismatch, API type: %s, PnC rule index %d\n",
-						tpm_db_api_type_str[api_type], rule_index);
+						api_type_to_str(api_type), rule_index);
 					pnc_mismatch_info_show(&pnc_out, &shadow_pnc);
 					pnc_sw_error_count++;
 				}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c
index 02e096c..59cf9fd 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c
@@ -116,6 +116,7 @@
     off += sprintf(buf+off, "cat help_l3_rule_add                          - show add L3 rule help\n");
     off += sprintf(buf+off, "cat help_mc_ipvx_stream_add                   - show add multicast IPV4 stream help\n");
     off += sprintf(buf+off, "cat help_mib_reset                            - show MIB reset help\n");
+    off += sprintf(buf+off, "cat help_set_active_wan                       - show set active wan help\n");
     off += sprintf(buf+off, "cat help_mod_rule_cfg                         - show mod rule help\n");
     off += sprintf(buf+off, "cat help_no_mc_stream_add                     - show delete multicast stream help\n");
     off += sprintf(buf+off, "cat help_no_oam_omci_channel                  - show delete OAM/OMCI channel help\n");
@@ -161,7 +162,7 @@
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_5              %#.5X     TPM_TRG_UNI_6        %#.5X\n",TPM_TRG_UNI_5, TPM_TRG_UNI_6);
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_7              %#.5X     TPM_TRG_UNI_VIRT     %#.5X\n",TPM_TRG_UNI_7, TPM_TRG_UNI_VIRT);
 	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_CPU           %#.5X     TPM_TRG_PORT_UNI_ANY %#.5X\n",TPM_TRG_PORT_CPU, TPM_TRG_PORT_UNI_ANY);
-	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_CPU_LOOP  %#.5X\n", TPM_TRG_PORT_UNI_CPU_LOOP);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_CPU_LOOP  %#.5X     TPM_TRG_LOAD_BAL     %#.5X\n",TPM_TRG_PORT_UNI_CPU_LOOP, TPM_TRG_LOAD_BAL);
 	off += sprintf(buf+off, "\tqueue               (dec)Queue number\n");
 	off += sprintf(buf+off, "\tgem_port            (dec)GEM port\n");
 
@@ -459,6 +460,44 @@
 
 /*******************************************************************************
 **
+**  sfs_help_ds_load_balance_rule - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ds_load_balance_rule(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [rule_num] [parse_rule_bm] [parse_flags_bm] [key_name] [target] > add_ds_load_balance\n");
+    off += sprintf(buf+off, "Creates a new ds load balance ACL\n");
+
+    off += sprintf(buf+off, "\towner_id        (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trule_num        (dec)Entry number to be added to the current ACL\n");
+    off += sprintf(buf+off, "\tparse_rule_bm   (hex)Bitmap containing the significant flags for parsing fields of the packet:\n");
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_DA		 %#.4X\n", TPM_L2_PARSE_MAC_DA);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_SA		 %#.4X\n", TPM_L2_PARSE_MAC_SA);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ONE_VLAN_TAG	 %#.4X\n", TPM_L2_PARSE_ONE_VLAN_TAG);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_TWO_VLAN_TAG	 %#.4X\n", TPM_L2_PARSE_TWO_VLAN_TAG);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ETYPE		 %#.4X\n", TPM_L2_PARSE_ETYPE);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPPOE_SES 	 %#.4X\n", TPM_L2_PARSE_PPPOE_SES);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPP_PROT		 %#.4X\n", TPM_L2_PARSE_PPP_PROT);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_GEMPORT		 %#.4X\n", TPM_L2_PARSE_GEMPORT);
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG2_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG2_FALSE);
+    off += sprintf(buf+off, "\tkey_name        (str)Name of L2 key data which has been defined by user [or l2_key_empty]\n");
+    off += sprintf(buf+off, "\ttarget          (dec)0 for GMAC0, 1 for GMAC1, 2 for CPU\n");
+
+    off += sprintf(buf+off, "\n\necho [owner_id] [rule_idx] > del_ds_load_balance       - delete a DS load balance ACL\n");
+    off += sprintf(buf+off, "\towner_id	    (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trule_idx	    (dec)Rule Id returned from the create call\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
 **  sfs_help_l2_rule_add - see header of sfs_tpm_cfg_index
 **
 *******************************************************************************/
@@ -499,7 +538,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_MTM                  %#.4X\n", TPM_ACTION_MTM);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.4X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
     off += sprintf(buf+off, "\t\tTPM_ACTION_SPEC_MC_VID          %#.4X\n", TPM_ACTION_SPEC_MC_VID);
-    off += sprintf(buf+off, "\tnext_phase      (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+    off += sprintf(buf+off, "\tnext_phase      (str)Parse stage (l3/done)\n");
     off += sprintf(buf+off, "\tkey_name        (str)Name of L2 key data which has been defined by user [or l2_key_empty]\n");
     off += sprintf(buf+off, "\tfrwd_name       (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
     off += sprintf(buf+off, "\tmod_name        (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
@@ -560,7 +599,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
     off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
-    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv4/ipv6_gen/ipv6_nh/ctc_cm/done)\n");
     off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
     off += sprintf(buf+off, "\tkey_name         (str)Name of L3 key data which has been defined by user [or l3_key_empty]\n");
 
@@ -604,7 +643,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.4X\n", TPM_ACTION_TO_CPU);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.4X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
     off += sprintf(buf+off, "\t\tTPM_ACTION_UDP_CHKSUM_CALC      %#.4X\n", TPM_ACTION_UDP_CHKSUM_CALC);
-    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ctc_cm/done)\n");
     off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
     off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
     off += sprintf(buf+off, "\t\tThis is the only packet modification supported in this version. \n");
@@ -652,7 +691,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
 
-    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_dip/done)\n");
 
     off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
     off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
@@ -726,23 +765,6 @@
 	off += sprintf(buf+off, "\tdst_ip           Destination IP address\n");
 	off += sprintf(buf+off, "\tignore           (str)true/false. When true, the source IP address is not part of the key\n");
 	off += sprintf(buf+off, "\ttarget_ports     (hex)Bitmap of port targets \n");
-	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_WAN            %#.4X\n", TPM_TRG_PORT_WAN);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_0             %#.4X\n", TPM_TRG_TCONT_0);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_1             %#.4X\n", TPM_TRG_TCONT_1);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_2             %#.4X\n", TPM_TRG_TCONT_2);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_3             %#.4X\n", TPM_TRG_TCONT_3);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_4             %#.4X\n", TPM_TRG_TCONT_4);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_5             %#.4X\n", TPM_TRG_TCONT_5);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_6             %#.4X\n", TPM_TRG_TCONT_6);
-	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_7             %#.4X\n", TPM_TRG_TCONT_7);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_0              %#.4X\n", TPM_TRG_LLID_0);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_1              %#.4X\n", TPM_TRG_LLID_1);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_2              %#.4X\n", TPM_TRG_LLID_2);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_3              %#.4X\n", TPM_TRG_LLID_3);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_4              %#.4X\n", TPM_TRG_LLID_4);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_5              %#.4X\n", TPM_TRG_LLID_5);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_6              %#.4X\n", TPM_TRG_LLID_6);
-	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_7              %#.4X\n", TPM_TRG_LLID_7);
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_0               %#.5X\n", TPM_TRG_UNI_0);
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_1               %#.5X\n", TPM_TRG_UNI_1);
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_2               %#.5X\n", TPM_TRG_UNI_2);
@@ -754,7 +776,6 @@
 	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_VIRT            %#.5X\n", TPM_TRG_UNI_VIRT);
 	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_CPU            %#.5X\n", TPM_TRG_PORT_CPU);
 	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_ANY        %#.5X\n", TPM_TRG_PORT_UNI_ANY);
-	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_CPU_LOOP   %#.5X\n", TPM_TRG_PORT_UNI_CPU_LOOP);
 
 	off += sprintf(buf+off, "\n\tIPV4 address: dst_ip 224.x.y.z  - 239.x.y.z.  Source address w.x.y.z. Each part is decimal value in range 0..255.\n");
 	off += sprintf(buf+off, "\n\n");
@@ -763,9 +784,20 @@
 	off += sprintf(buf+off, "\tstream           (dec)Stream number\n");
 	off += sprintf(buf+off, "\ttarget_ports     (hex)Bitmap of port targets - SEE ABOVE\n");
 
+	off += sprintf(buf+off, "\n\n");
+	off += sprintf(buf+off, "echo [owner_id] [stream] [igmp_mode] [mc_stream_pppoe] [vid] [src_ip] [dst_ip] [ignore] [target_queue] [target_ports] > mc_ipv4_stream_set_queue_add\n");
+	off += sprintf(buf+off, "\tdest_queue       (dec)destination queue number\n");
+	off += sprintf(buf+off, "Creates a new multicast stream with specified dest queue number\n");
+
 	off += sprintf(buf+off, "\nIPV6: echo [owner_id] [stream] [igmp_mode] [mc_stream_pppoe] [vid] [src_ip] [dst_ip] [ignore] [target_ports] > mc_ipv6_stream_add\n");
 	off += sprintf(buf+off, "Creates a new multicast stream, params refer to IPv4 MC stream add interface, except dst_ip.\n");
 	off += sprintf(buf+off, "\tIPV6 address: ff00:aabb:bbcc:ccdd:ddee:eeff:1111:2222. Each part is Hex value in range 0..ffff.\n");
+
+	off += sprintf(buf+off, "\n\n");
+	off += sprintf(buf+off, "echo [owner_id] [stream] [igmp_mode] [mc_stream_pppoe] [vid] [src_ip] [dst_ip] [ignore] [target_queue] [target_ports] > mc_ipv6_stream_set_queue_add\n");
+	off += sprintf(buf+off, "\tdest_queue       (dec)destination queue number\n");
+	off += sprintf(buf+off, "Creates a new multicast stream with specified dest queue number\n");
+
 	off += sprintf(buf+off, "\n\n");
 	off += sprintf(buf+off, "echo [owner_id] [stream] [target_ports] > mc_ipv6_stream_update\n");
 	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
@@ -951,6 +983,56 @@
 
     return(off);
 }
+/*******************************************************************************
+**
+**  sfs_help_set_active_wan - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_set_active_wan(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [active_wan] > set_active_wan\n");
+    off += sprintf(buf+off, "\t[owner_id]      (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[active_wan]    (dec)GMAC0: 0; GMAC1: 1; PON: 2\n");
+
+    return(off);
+}
+/*******************************************************************************
+**
+**  sfs_help_hot_swap_profile - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_hot_swap_profile(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [profile_id] > hot_swap_profile\n");
+    off += sprintf(buf+off, "before hot swap profile, eth0, eth1 and pon0 must be taken down by ifconfig command; and be bring up after\n");
+    off += sprintf(buf+off, "\t[owner_id]      (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[profile_id]    (dec)TPM_G0_WAN_G1_INT_SWITCH: %d; TPM_G1_WAN_G0_INT_SWITCH: %d\n",
+			TPM_G0_WAN_G1_INT_SWITCH, TPM_G1_WAN_G0_INT_SWITCH);
+
+    return(off);
+}
+/*******************************************************************************
+**
+**  sfs_help_set_port_hwf_admin - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_set_port_hwf_admin(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [port] [txp] [enable] > set_port_hwf_admin\n");
+    off += sprintf(buf+off, "disable/enable HWF to port\n");
+    off += sprintf(buf+off, "\t[owner_id]      (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[port]          (dec)GMAC0: 0; GMAC1: 1; PON: 2\n");
+    off += sprintf(buf+off, "\t[txp]           (dec)T-CONT or LLID, for GMAC0/1 it should be 0\n");
+    off += sprintf(buf+off, "\t[enable]        (dec)disable: 0; enable: 1\n");
+
+    return(off);
+}
 
 /*******************************************************************************
 **
@@ -1268,7 +1350,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
 
-    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (done)\n");
 
     off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
     off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
@@ -1360,7 +1442,7 @@
     off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
     off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
     off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
-    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_gen/ipv6_dip/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_gen/ctc_cm/done)\n");
     off += sprintf(buf+off, "\tl4_src_port      (dec)L4 source port\n");
     off += sprintf(buf+off, "\tl4_dst_port      (dec)L4 destination port\n");
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h
index 6bac650..15de3bb 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h
@@ -97,6 +97,7 @@
 extern int sfs_help_ipv6_dip_key_cfg        (char *buf);
 extern int sfs_help_ipv6_l4_key_cfg         (char *buf);
 extern int sfs_help_ipv6_ctc_cm_key_cfg     (char *buf);
+extern int sfs_help_ds_load_balance_rule    (char* buf);
 extern int sfs_help_key_rule_delete         (char *buf);
 extern int sfs_help_l2_rule_add             (char *buf);
 extern int sfs_help_l3_rule_add             (char *buf);
@@ -111,6 +112,9 @@
 extern int sfs_help_no_oam_omci_channel     (char *buf);
 extern int sfs_help_setup                   (char *buf);
 extern int sfs_help_mib_reset               (char *buf);
+extern int sfs_help_set_active_wan          (char *buf);
+extern int sfs_help_hot_swap_profile    (char* buf);
+extern int sfs_help_set_port_hwf_admin(char* buf);
 extern int sfs_help_cfg_cpu_lpbk            (char *buf);
 extern int sfs_help_cfg_age_count           (char *buf);
 extern int sfs_help_rate_limit              (char *buf);
@@ -170,6 +174,9 @@
 #define  sfs_help_no_oam_omci_channel     NULL
 #define  sfs_help_setup                   NULL
 #define  sfs_help_mib_reset               NULL
+#define  sfs_help_set_active_wan          NULL
+#define  sfs_help_hot_swap_profile        NULL
+#define  sfs_help_set_port_hwf_admin      NULL
 #define  sfs_help_erase_section           NULL
 #define  sfs_help_cfg_cpu_lpbk            NULL
 #define  sfs_help_cfg_age_count           NULL
@@ -193,6 +200,7 @@
 #define sfs_help_flush_atu           NULL
 #define sfs_help_mac_learn_rule_add       NULL
 #define sfs_help_mac_learn_def_act_set    NULL
+#define sfs_help_ds_load_balance_rule     NULL
 
 
 #endif /* CONFIG_MV_TPM_SYSFS_HELP */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c
index 0324869..9764ca8 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c
@@ -735,6 +735,287 @@
     }
 }
 
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv4_mc_stream_set_queue_bounce(
+					      uint32_t                 owner_id,
+                                              uint32_t                  stream_num,
+                                              tpm_mc_igmp_mode_t        igmp_mode,
+                                              uint8_t                   mc_stream_pppoe,
+                                              uint16_t                  vid,
+                                              uint8_t                   ipv4_src_add[4],
+                                              uint8_t                   ipv4_dst_add[4],
+                                              uint8_t                   ignore_ipv4_src,
+                                              uint16_t                  dest_queue,
+                                              tpm_trg_port_type_t       dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd             = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd                     = MV_TPM_IOCTL_ADD_IPv4_MC_STREAM_SET_QUEUE;
+    tpm_mc_rule->stream_num                 = stream_num;
+    tpm_mc_rule->igmp_mode                  = igmp_mode;
+    tpm_mc_rule->mc_stream_pppoe            = mc_stream_pppoe;
+    tpm_mc_rule->vid                        = vid;
+    tpm_mc_rule->ipv4_mc.ignore_ipv4_src    = ignore_ipv4_src;
+    tpm_mc_rule->dest_queue                 = dest_queue;
+    tpm_mc_rule->dest_port_bm               = dest_port_bm;
+    memcpy(&(tpm_mc_rule->ipv4_mc.ipv4_src_add[0]), ipv4_src_add, sizeof(uint8_t)*4);
+    memcpy(&(tpm_mc_rule->ipv4_mc.ipv4_dst_add[0]), ipv4_dst_add, sizeof(uint8_t)*4);
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv4_mc_stream_set_queue tpm_add_ipv4_mc_stream_set_queue_bounce
+#else
+ #define _tpm_add_ipv4_mc_stream_set_queue tpm_add_ipv4_mc_stream_set_queue
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv4_stream_set_queue_add
+*
+* DESCRIPTION:
+*           This function creates a multicast IPV4 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv4_stream_set_queue_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcipv4add_owner=0, mcipv4add_stream, mcipv4add_mode,   mcipv4add_pppoe,        mcipv4add_vid,
+        mcipv4add_src_ip,  mcipv4add_dst_ip, mcipv4add_ignore, mcipv4add_target_ports, mcipv4add_target_queue,
+        mcipv4add_max
+    } mcipv4add_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream;
+    uint32_t                 mode;
+    char                     mc_pppoe_str[20];
+    uint32_t                 mc_stream_pppoe;
+    uint32_t                 vid;
+    char                     srcip_str[30];
+    char                     dstip_str[30];
+    uint32_t                 temp_srcip[4];
+    uint32_t                 temp_dstip[4];
+    uint8_t                  srcip[4];
+    uint8_t                  dstip[4];
+    char                     ignore_str[20];
+    uint32_t                 ignore;
+    uint32_t                 target_queue;
+    uint32_t                 target_ports;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcipv4add_max)
+    {
+        parm_error_completion(numparms, mcipv4add_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d %s %d %s %s %s %d 0x%x",
+                            &ownerid, &stream, &mode, mc_pppoe_str, &vid, srcip_str, dstip_str, ignore_str, &target_queue, &target_ports);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d], vid[%d], srcip_str[%s], dstip_str[%s], ignore_str[%s], target_ports[0x%x]\n",
+//               len, parsedargs, ownerid, stream, vid, srcip_str, dstip_str, ignore_str, target_ports);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_bool_value(mc_pppoe_str, &mc_stream_pppoe) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else if (parse_ipv4_address(srcip_str, temp_srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_ip [%s]\n", srcip_str);
+        }
+        else if (parse_ipv4_address(dstip_str, temp_dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dst_ip [%s]\n", dstip_str);
+        }
+        else if (get_bool_value(ignore_str, &ignore) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else
+        {
+            int indx;
+
+            for (indx = 0; indx < sizeof(srcip); indx++)
+            {
+                srcip[indx] = (uint8_t)temp_srcip[indx];
+                dstip[indx] = (uint8_t)temp_dstip[indx];
+            }
+
+            if ((rc = _tpm_add_ipv4_mc_stream_set_queue(ownerid,
+                                              stream,
+                                              mode,
+                                              (uint8_t)mc_stream_pppoe,
+                                              vid,
+                                              srcip,
+                                              dstip,
+                                              (uint8_t)ignore,
+                                              target_queue,
+                                              target_ports)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv4_mc_stream_set_queue failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_mc_stream_set_queue_bounce(uint32_t owner_id,
+						uint32_t stream_num,
+						tpm_mc_igmp_mode_t igmp_mode,
+						uint8_t mc_stream_pppoe,
+						uint16_t vid,
+						uint8_t ipv6_src_add[16],
+						uint8_t ipv6_dst_add[16],
+						uint8_t ignore_ipv6_src,
+						uint16_t dest_queue,
+						tpm_trg_port_type_t dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd             = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd                     = MV_TPM_IOCTL_ADD_IPv6_MC_STREAM_SET_QUEUE;
+    tpm_mc_rule->stream_num                 = stream_num;
+    tpm_mc_rule->igmp_mode                  = igmp_mode;
+    tpm_mc_rule->mc_stream_pppoe            = mc_stream_pppoe;
+    tpm_mc_rule->vid                        = vid;
+    tpm_mc_rule->dest_port_bm               = dest_port_bm;
+    tpm_mc_rule->dest_queue                 = dest_queue;
+    memcpy(&(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]), ipv6_dst_add, sizeof(uint8_t) * 16);
+    memcpy(&(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]), ipv6_src_add, sizeof(uint8_t) * 16);
+    tpm_mc_rule->ipv6_mc.ignore_ipv6_src = ignore_ipv6_src;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_mc_stream_set_queue tpm_add_ipv6_mc_stream_set_queue_bounce
+#else
+ #define _tpm_add_ipv6_mc_stream_set_queue tpm_add_ipv6_mc_stream_set_queue
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv6_stream_add_set_queue
+*
+* DESCRIPTION:
+*           This function creates a multicast ipv6 rule with destination queue
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv6_stream_set_queue_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcipv6add_owner=0, mcipv6add_stream, mcipv6add_mode,   mcipv6add_pppoe,        mcipv6add_vid,
+        mcipv6add_src_ip, mcipv6add_dst_ip, mcipv6add_ignor_src_ip, mcipv6add_target_queue, mcipv6add_target_ports, mcipv6add_max
+    } mcipv6add_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream;
+    uint32_t                 mode;
+    char                     mc_pppoe_str[20];
+    uint32_t                 mc_stream_pppoe;
+    uint32_t                 vid;
+    char                     dstip_str[60];
+    uint32_t                 temp_dstip[16];
+    char                     srcip_str[60];
+    uint32_t                 temp_srcip[16];
+    uint8_t                  dstip[16];
+    uint8_t                  srcip[16];
+    uint32_t                 ignor_srcip;
+    char                     ignore_str[20];
+    uint32_t                 target_ports;
+    uint32_t                 target_queue;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcipv6add_max)
+    {
+        parm_error_completion(numparms, mcipv6add_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d %s %d %s %s %s %d 0x%x",
+                            &ownerid, &stream, &mode, mc_pppoe_str, &vid, srcip_str, dstip_str, ignore_str, &target_queue, &target_ports);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d], vid[%d], srcip_str[%s],  "
+		"dstip_str[%s],  ignor_srcip[%s], target_queue[%d], target_ports[0x%x]\n",
+               len, parsedargs, ownerid, stream, vid, srcip_str, dstip_str, ignore_str, target_queue, target_ports);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_bool_value(mc_pppoe_str, &mc_stream_pppoe) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid mc_pppoe_str[%s]\n", mc_pppoe_str);
+        }
+        else if (parse_ipv6_address(dstip_str, temp_dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dst_ip [%s]\n", dstip_str);
+        }
+        else if (parse_ipv6_address(srcip_str, temp_srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip_str [%s]\n", srcip_str);
+	}
+	else if (get_bool_value(ignore_str, &ignor_srcip) == GT_FALSE)
+	{
+	    printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else
+        {
+            int indx;
+
+            for (indx = 0; indx < sizeof(dstip); indx++)
+            {
+                dstip[indx] = (uint8_t)temp_dstip[indx];
+                srcip[indx] = (uint8_t)temp_srcip[indx];
+            }
+
+            if ((rc = _tpm_add_ipv6_mc_stream_set_queue(ownerid,
+                                              stream,
+                                              mode,
+                                              (uint8_t)mc_stream_pppoe,
+                                              vid,
+                                              srcip,
+                                              dstip,
+                                              ignor_srcip,
+                                              target_queue,
+                                              target_ports)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_mc_stream_set_queue failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
 #ifdef CONFIG_MV_TPM_SFS_2_IOCTL
 tpm_error_code_t tpm_add_ipv6_mc_stream_bounce(uint32_t owner_id,
 						uint32_t stream_num,
@@ -2448,6 +2729,242 @@
     }
 }
 
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_active_wan_bounce(uint32_t     owner_id,
+                                           tpm_gmacs_enum_t active_wan)
+{
+    tpm_ioctl_set_active_wan_t *tpm_set_active_wan_param = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_set_active_wan_param;
+
+    tpm_sfs_2_ioctl_command.cmd              = MV_TPM_IOCTL_SET_ACTIVE_WAN_SECTION;
+    tpm_set_active_wan_param->owner_id       = owner_id;
+    tpm_set_active_wan_param->active_wan     = active_wan;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_active_wan tpm_set_active_wan_bounce
+#else
+ #define _tpm_set_active_wan tpm_set_active_wan
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_set_active_wan
+*
+* DESCRIPTION:
+*           This function sets active wan port
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_active_wan  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+	activewan_owner=0, activewan_active_wan,  activewan_max
+    } activewan_parm_indx_t;
+    // shell line parsing
+    uint32_t		     ownerid;
+    int 		     parsedargs;
+    int 		     numparms;
+    //Used in API call
+    tpm_error_code_t	     rc;
+    tpm_gmacs_enum_t	     active_wan;
+
+    numparms = count_parameters(buf);
+    if (numparms != activewan_max)
+    {
+	parm_error_completion(numparms, activewan_max, buf, sfs_help_set_active_wan);
+    }
+    else
+    {
+	// Get parameters
+	parsedargs = sscanf(buf, "%d %d", &ownerid, &active_wan);
+//	  printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], active_wan_int[%d]\n",
+//			len, parsedargs, ownerid, active_wan);
+
+	if (parsedargs != numparms)
+	{
+	    printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+	}
+	else if (active_wan >= TPM_MAX_NUM_GMACS)
+	{
+	    printk(KERN_INFO "Invalid active_wan[%d]\n", active_wan);
+	}
+	else
+	{
+	    if ((rc = _tpm_set_active_wan(ownerid,
+					  active_wan)) == TPM_RC_OK)
+	    {
+		printk(KERN_INFO "OK\n");
+	    }
+	    else
+	    {
+		printk(KERN_INFO "%s: tpm_set_active_wan failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+	    }
+	}
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_hot_swap_profile_bounce(uint32_t     owner_id,
+                                           tpm_eth_complex_profile_t profile_id)
+{
+    tpm_ioctl_hot_swap_profile_t *tpm_hot_swap_profile_param = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_hot_swap_profile_param;
+
+    tpm_sfs_2_ioctl_command.cmd              = MV_TPM_IOCTL_HOT_SWAP_PROFILE_SECTION;
+    tpm_hot_swap_profile_param->owner_id       = owner_id;
+    tpm_hot_swap_profile_param->profile_id     = profile_id;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_hot_swap_profile tpm_hot_swap_profile_bounce
+#else
+ #define _tpm_hot_swap_profile tpm_hot_swap_profile
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_hot_swap_profile
+*
+* DESCRIPTION:
+*           This function swap profile in run time
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_hot_swap_profile  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+	hotswap_owner=0, hotswap_profile_id,  hotswap_max
+    } hotswap_parm_indx_t;
+    // shell line parsing
+    uint32_t		     ownerid;
+    int 		     parsedargs;
+    int 		     numparms;
+    //Used in API call
+    tpm_error_code_t	     rc;
+    uint32_t	     profile_id;
+
+    numparms = count_parameters(buf);
+    if (numparms != hotswap_max)
+    {
+	parm_error_completion(numparms, hotswap_max, buf, sfs_help_hot_swap_profile);
+    }
+    else
+    {
+	// Get parameters
+	parsedargs = sscanf(buf, "%d %d", &ownerid, &profile_id);
+//	  printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], profile_id_int[%d]\n",
+//			len, parsedargs, ownerid, profile_id);
+
+	if (parsedargs != numparms)
+	{
+	    printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+	}
+	else
+	{
+	    if ((rc = _tpm_hot_swap_profile(ownerid,
+					  profile_id)) == TPM_RC_OK)
+	    {
+		printk(KERN_INFO "OK\n");
+	    }
+	    else
+	    {
+		printk(KERN_INFO "%s: tpm_hot_swap_profile failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+	    }
+	}
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_port_hwf_admin_bounce(uint32_t	   owner_id,
+							  tpm_gmacs_enum_t port,
+							  uint8_t	   txp,
+							  uint8_t	   enable)
+{
+    tpm_ioctl_set_port_hwf_admin_t *tpm_set_port_hwf_admin_param = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_set_port_hwf_admin_param;
+
+    tpm_sfs_2_ioctl_command.cmd              = MV_TPM_IOCTL_SET_PORT_HWF_ADMIN_SECTION;
+    tpm_set_port_hwf_admin_param->owner_id   = owner_id;
+    tpm_set_port_hwf_admin_param->port       = port;
+    tpm_set_port_hwf_admin_param->txp        = txp;
+    tpm_set_port_hwf_admin_param->enable     = enable;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_port_hwf_admin tpm_set_port_hwf_admin_bounce
+#else
+ #define _tpm_set_port_hwf_admin tpm_proc_hwf_admin_set
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_set_port_hwf_admin
+*
+* DESCRIPTION:
+*           This function set port hwf enable/disable
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_port_hwf_admin  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+	setporthwfadmin_owner=0, setporthwfadmin_port, setporthwfadmin_txp,
+	setporthwfadmin_enable, setporthwfadmin_max
+    } setporthwfadmin_parm_indx_t;
+    // shell line parsing
+    int 		     parsedargs;
+    int 		     numparms;
+    //Used in API call
+    tpm_error_code_t	   rc;
+    uint32_t               ownerid;
+    tpm_gmacs_enum_t       port;
+    uint32_t               txp;
+    uint32_t               enable;
+
+    numparms = count_parameters(buf);
+    if (numparms != setporthwfadmin_max)
+    {
+	parm_error_completion(numparms, setporthwfadmin_max, buf, sfs_help_set_port_hwf_admin);
+    }
+    else
+    {
+	// Get parameters
+	parsedargs = sscanf(buf, "%d %d %d %d", &ownerid, &port, &txp, &enable);
+//	  printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], port[%d], txp[%d], enable[%d]\n",
+//			len, parsedargs, ownerid, port, txp, enable);
+
+	if (parsedargs != numparms)
+	{
+	    printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+	}
+	else
+	{
+	    if ((rc = _tpm_set_port_hwf_admin(port, txp, enable)) == TPM_RC_OK)
+	    {
+		printk(KERN_INFO "OK\n");
+	    }
+	    else
+	    {
+		printk(KERN_INFO "%s: tpm_set_port_hwf_admin failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+	    }
+	}
+    }
+}
+
 /*******************************************************************************
 * sfs_tpm_cfg_set_erase_section
 *
@@ -6413,3 +6930,192 @@
 	}
 }
 
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ds_load_balance_rule_bounce(uint32_t                owner_id,
+                                        uint32_t                rule_num,
+                                        uint32_t               *rule_idx,
+                                        tpm_parse_fields_t      parse_rule_bm,
+					tpm_parse_flags_t	parse_flags_bm,
+                                        tpm_l2_acl_key_t       *l2_key,
+                                        tpm_ds_load_balance_tgrt_t tgrt_port)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_DS_LOAD_BALANCE_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    tpm_add_acl_rule->rule_num                      = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                 = parse_rule_bm;
+    tpm_add_acl_rule->ds_load_balance_acl_rule.parse_flags_bm = parse_flags_bm;
+    tpm_add_acl_rule->ds_load_balance_acl_rule.tgrt = tgrt_port;
+    memcpy(&(tpm_add_acl_rule->ds_load_balance_acl_rule.l2_key),         (void*)l2_key,      sizeof(tpm_l2_acl_key_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ds_load_balance_rule tpm_add_ds_load_balance_rule_bounce
+#else
+ #define _tpm_add_ds_load_balance_rule tpm_add_ds_load_balance_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ds_load_balance_rule_add
+*
+* DESCRIPTION:
+*           This function creates a ds_load_balance rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ds_load_balance_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ds_load_blnc_ruleadd_owner=0, ds_load_blnc_ruleadd_rulenum,
+	ds_load_blnc_ruleadd_parserulebm, ds_load_blnc_ruleadd_parseflagsbm,
+	ds_load_blnc_ruleadd_l2keyname,
+        ds_load_blnc_ruleadd_trgt, ds_load_blnc_ruleadd_max
+    } ds_load_blnc_ruleadd_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rulenum;
+    uint32_t                 parserulebm;
+    uint32_t                 parseflagsbm;
+    uint32_t                 trgt;
+    char                     l2keyname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_l2_key_entry_t    *pdbl2keyentry = 0;
+    //Used in API call
+    tpm_l2_acl_key_t         l2_acl;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ds_load_blnc_ruleadd_max)
+    {
+        parm_error_completion(numparms, ds_load_blnc_ruleadd_max, buf, sfs_help_ds_load_balance_rule);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d 0x%x 0x%x %s %d",  &ownerid, &rulenum, &parserulebm,
+                                 &parseflagsbm, l2keyname, &trgt);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], "
+			"l2keyname[%s], trgt[%d]\n",
+               len, parsedargs, ownerid, rulenum, parserulebm, parseflagsbm, l2keyname, trgt);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (((pdbl2keyentry = find_tpm_l2_key_entry_by_name(l2keyname)) == 0) && strcmp(l2keyname, l2_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "L2 key entry [%s] not found\n", l2keyname);
+        }
+        else
+        {
+
+            if (pdbl2keyentry != 0)  memcpy(&l2_acl, &pdbl2keyentry->l2_acl, sizeof(tpm_l2_acl_key_t));
+            else                     memset(&l2_acl, 0,                      sizeof(tpm_l2_acl_key_t));
+
+            if ((rc = _tpm_add_ds_load_balance_rule(ownerid,
+                                       rulenum,
+                                       &rule_idx,
+                                       parserulebm,
+                                       parseflagsbm,
+                                       &l2_acl,
+                                       trgt)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ds_load_balance_rule failed, rc[%d] - %s\n",
+			__FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ds_load_balance_rule_bounce(uint32_t        owner_id,
+                                        uint32_t        rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_DS_LOAD_BALANCE_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ds_load_balance_rule tpm_del_ds_load_balance_rule_bounce
+#else
+ #define _tpm_del_ds_load_balance_rule tpm_del_ds_load_balance_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ds_load_balance
+*
+* DESCRIPTION:
+*           This function deletes a ds_load_balance HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ds_load_balance  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+	noruleadd_owner=0,  noruleadd_ruleidx,	noruleadd_max
+    } noruleadd_parm_indx_t;
+    // shell line parsing
+    uint32_t		     ownerid;
+    uint32_t		     rule_idx;
+    int 		     parsedargs;
+    int 		     numparms;
+    //Used in API call
+    tpm_error_code_t	     rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noruleadd_max)
+    {
+	parm_error_completion(numparms, noruleadd_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+	// Get parameters
+	parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+	//printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+	//	 len, parsedargs, ownerid, rule_idx);
+
+
+	if (parsedargs != numparms)
+	{
+	    printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+	}
+	else
+	{
+	    if ((rc = _tpm_del_ds_load_balance_rule(ownerid, rule_idx)) == TPM_RC_OK)
+	    {
+		printk(KERN_INFO "OK\n");
+	    }
+	    else
+	    {
+		printk(KERN_INFO "%s: tpm_del_ds_load_balance_rule failed, rc[%d] - %s\n",
+			__FUNCTION__, rc, get_tpm_err_str(rc));
+	    }
+	}
+    }
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h
index 62d755b..74037d7 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h
@@ -88,8 +88,10 @@
 extern void sfs_tpm_cfg_set_ipv4_rule_add                (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_ipv6_gen_rule_add            (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mc_ipv4_stream_add           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv4_stream_set_queue_add           (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mc_ipv4_stream_update        (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mc_ipv6_stream_add           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv6_stream_set_queue_add           (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mc_ipv6_stream_update        (const char *buf, size_t len);
 
 extern void sfs_tpm_cfg_set_igmp_port_forward_mode_cfg   (const char *buf, size_t len);
@@ -107,6 +109,9 @@
 extern void sfs_tpm_cfg_set_no_omci_channel              (const char *buf, size_t len);
 extern void sfs_tpm_cfg_setup                            (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mib_reset                    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_active_wan                   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_port_hwf_admin        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_hot_swap_profile            (const char *buf, size_t len);
 extern void sfs_tpm_cfg_add_cpu_lpbk                     (const char *buf, size_t len);
 extern void sfs_tpm_cfg_del_cpu_lpbk                     (const char *buf, size_t len);
 extern void sfs_tpm_cfg_dump_cpu_lpbk                    (const char *buf, size_t len);
@@ -166,6 +171,8 @@
 extern void sfs_tpm_cfg_set_no_rule_add_mac_learn        (const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_mac_learn_default_rule_action(const char *buf, size_t len);
 extern void sfs_tpm_cfg_set_gmac0_ingr_rate_limit        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ds_load_balance_rule_add     (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ds_load_balance  (const char *buf, size_t len);
 
 /* KostaP */
 extern void sfs_tpm_cfg_set_fc(const char *buf, size_t len);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c
index fbaa8ab..d96c532 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c
@@ -2558,7 +2558,7 @@
         else {
             if ((pentry = find_tpm_ipv6_l4_ports_key_entry_by_name(name)) == 0)
                 pentry = find_free_tpm_ipv6_l4_ports_key_entry();
-			
+
             if (pentry == 0)
                 printk(KERN_INFO "IPV6 L4 ports key DB full\n");
             else {
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c
index c815087..32c3056 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c
@@ -115,9 +115,11 @@
     {"ipv4_rule_add",                      sfs_tpm_cfg_set_ipv4_rule_add},
     {"ipv6_gen_rule_add",                  sfs_tpm_cfg_set_ipv6_gen_rule_add},
     {"mc_ipv4_stream_add",                 sfs_tpm_cfg_set_mc_ipv4_stream_add},
+    {"mc_ipv4_stream_set_queue_add",	   sfs_tpm_cfg_set_mc_ipv4_stream_set_queue_add},
     {"mc_ipv4_stream_update",              sfs_tpm_cfg_set_mc_ipv4_stream_update},
-	{"mc_ipv6_stream_add",				   sfs_tpm_cfg_set_mc_ipv6_stream_add},
-	{"mc_ipv6_stream_update",			   sfs_tpm_cfg_set_mc_ipv6_stream_update},
+    {"mc_ipv6_stream_add",		   sfs_tpm_cfg_set_mc_ipv6_stream_add},
+    {"mc_ipv6_stream_set_queue_add",	   sfs_tpm_cfg_set_mc_ipv6_stream_set_queue_add},
+    {"mc_ipv6_stream_update",		   sfs_tpm_cfg_set_mc_ipv6_stream_update},
     {"igmp_port_forward_mode_cfg",         sfs_tpm_cfg_set_igmp_port_forward_mode_cfg},
     {"mc_vid_key_reset",                   sfs_tpm_cfg_set_mc_vid_key_reset},
     {"mc_vid_key_set",                     sfs_tpm_cfg_set_mc_vid_key_set},
@@ -135,6 +137,9 @@
     {"no_omci_channel",                    sfs_tpm_cfg_set_no_omci_channel},
     {"tpm_setup",                          sfs_tpm_cfg_setup},
     {"mib_reset",                          sfs_tpm_cfg_set_mib_reset},
+    {"set_active_wan",                     sfs_tpm_cfg_set_active_wan},
+    {"hot_swap_profile",		   sfs_tpm_cfg_hot_swap_profile},
+    {"set_port_hwf_admin",		   sfs_tpm_cfg_set_port_hwf_admin},
     {"erase_section",                      sfs_tpm_cfg_set_erase_section},
     {"add_cpu_lpbk",                       sfs_tpm_cfg_add_cpu_lpbk},
     {"del_cpu_lpbk",                       sfs_tpm_cfg_del_cpu_lpbk},
@@ -176,6 +181,8 @@
     {"no_rule_add_ipv6_dip_5t",            sfs_tpm_cfg_set_no_rule_add_ipv6_dip_5t},
     {"ipv6_l4_ports_5t_rule_add",          sfs_tpm_cfg_set_ipv6_l4_ports_5t_rule_add},
     {"no_rule_add_ipv6_l4_ports_5t",       sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_5t},
+    {"add_ds_load_balance",	           sfs_tpm_cfg_set_ds_load_balance_rule_add},
+    {"del_ds_load_balance",		   sfs_tpm_cfg_set_no_rule_add_ds_load_balance},
 
     // zeev
     {"ipv6_nh_acl_rule_add",               sfs_tpm_cfg_set_ipv6_nh_acl_rule_add},
@@ -280,7 +287,11 @@
     {"help_no_oam_omci_channel",     sfs_help_no_oam_omci_channel},
     {"help_tpm_setup",               sfs_help_setup},
     {"help_mib_reset",               sfs_help_mib_reset},
+    {"help_set_active_wan",          sfs_help_set_active_wan},
+    {"help_hot_swap_profile",	     sfs_help_hot_swap_profile},
+    {"help_set_port_hwf_admin",	     sfs_help_set_port_hwf_admin},
     {"help_cfg_cpu_lpbk",            sfs_help_cfg_cpu_lpbk},
+    {"help_ds_load_balance_rule",    sfs_help_ds_load_balance_rule},
     {"help_cfg_age_count",           sfs_help_cfg_age_count},
     {"help_rate_limit",              sfs_help_rate_limit},
     {"help_pkt_mod_add",             sfs_help_pkt_mod_add},
@@ -397,7 +408,11 @@
 static DEVICE_ATTR(help_no_oam_omci_channel,                        S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_tpm_setup,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_mib_reset,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_set_active_wan,                             S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_hot_swap_profile,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_set_port_hwf_admin,                         S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_cfg_cpu_lpbk,                               S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ds_load_balance_rule,                       S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_cfg_age_count,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_rate_limit,                                 S_IRUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(help_pkt_mod_add,                                S_IRUSR, tpm_cfg_show, tpm_cfg_store);
@@ -473,8 +488,10 @@
 static DEVICE_ATTR(ipv6_gen_rule_add,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(ipv6_dip_rule_add,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(mc_ipv4_stream_add,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv4_stream_set_queue_add,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(mc_ipv4_stream_update,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(mc_ipv6_stream_add,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv6_stream_set_queue_add,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(mc_ipv6_stream_update,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(ipv6_nh_acl_rule_add,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(ipv6_l4_ports_acl_rule_add,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
@@ -518,6 +535,9 @@
 static DEVICE_ATTR(no_omci_channel,                                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(tpm_setup,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(mib_reset,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_active_wan,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(hot_swap_profile,                                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_port_hwf_admin,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(add_cpu_lpbk,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(del_cpu_lpbk,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(dump_cpu_lpbk,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
@@ -544,6 +564,8 @@
 static DEVICE_ATTR(tpm_self_check,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(flush_atu,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(flush_vtu,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(add_ds_load_balance,                             S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(del_ds_load_balance,                             S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 
 static DEVICE_ATTR(fc_config_set,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
 static DEVICE_ATTR(fc_us_period_set,                                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
@@ -919,6 +941,7 @@
 #endif /* CONFIG_MV_TPM_SYSFS_HELP */
 
     &dev_attr_mc_ipv4_stream_add.attr,
+    &dev_attr_mc_ipv4_stream_set_queue_add.attr,
     &dev_attr_igmp_port_forward_mode_cfg.attr,
     &dev_attr_igmp_cpu_queue_cfg.attr,
     &dev_attr_igmp_proxy_sa_mac.attr,
@@ -930,6 +953,7 @@
     &dev_attr_mc_vid_cfg_set.attr,
 
     &dev_attr_mc_ipv6_stream_add.attr,
+    &dev_attr_mc_ipv6_stream_set_queue_add.attr,
     &dev_attr_no_mc_stream_add_ipv6.attr,
     &dev_attr_mc_ipv6_stream_update.attr,
 
@@ -953,6 +977,9 @@
 #ifdef CONFIG_MV_TPM_SYSFS_HELP
     &dev_attr_help_tpm_setup.attr,
     &dev_attr_help_mib_reset.attr,
+    &dev_attr_help_set_active_wan.attr,
+    &dev_attr_help_hot_swap_profile.attr,
+    &dev_attr_help_set_port_hwf_admin.attr,
     &dev_attr_help_erase_section.attr,
     &dev_attr_help_send_genquery_to_uni.attr,
     &dev_attr_help_tpm_self_check.attr,
@@ -965,6 +992,9 @@
     &dev_attr_send_genquery_to_uni.attr,
 
     &dev_attr_mib_reset.attr,
+    &dev_attr_set_active_wan.attr,
+    &dev_attr_hot_swap_profile.attr,
+    &dev_attr_set_port_hwf_admin.attr,
     &dev_attr_erase_section.attr,
     &dev_attr_tpm_self_check.attr,
     &dev_attr_flush_vtu.attr,
@@ -1001,6 +1031,26 @@
     .attrs = tpm_cfg_cpu_lpbk_sw_attrs
 };
 
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_ds_load_balance SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_ds_load_balance_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_ds_load_balance_rule.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+    &dev_attr_add_ds_load_balance.attr,
+    &dev_attr_del_ds_load_balance.attr,
+    NULL
+};
+
+static struct attribute_group tpm_cfg_ds_load_balance_sw_group =
+{
+    .name = "cfg_ds_load_balance",
+    .attrs = tpm_cfg_ds_load_balance_sw_attrs
+};
 
 /******************************************************************************/
 /* ========================================================================== */
@@ -1097,6 +1147,10 @@
     &dev_attr_help_no_oam_omci_channel.attr,
     &dev_attr_help_tpm_setup.attr,
     &dev_attr_help_mib_reset.attr,
+    &dev_attr_help_set_active_wan.attr,
+    &dev_attr_help_hot_swap_profile.attr,
+    &dev_attr_help_set_port_hwf_admin.attr,
+    &dev_attr_help_ds_load_balance_rule.attr,
     &dev_attr_help_cfg_cpu_lpbk.attr,
     &dev_attr_help_rate_limit.attr,
     &dev_attr_help_pkt_mod_add.attr,
@@ -1146,8 +1200,10 @@
     &dev_attr_ipv6_gen_rule_add.attr,
     &dev_attr_ipv6_dip_rule_add.attr,
     &dev_attr_mc_ipv4_stream_add.attr,
+    &dev_attr_mc_ipv4_stream_set_queue_add.attr,
     &dev_attr_mc_ipv4_stream_update.attr,
     &dev_attr_mc_ipv6_stream_add.attr,
+    &dev_attr_mc_ipv6_stream_set_queue_add.attr,
     &dev_attr_mc_ipv6_stream_update.attr,
     &dev_attr_ipv6_nh_acl_rule_add.attr,
     &dev_attr_ipv6_l4_ports_acl_rule_add.attr,
@@ -1180,6 +1236,9 @@
 
     &dev_attr_tpm_setup.attr,
     &dev_attr_mib_reset.attr,
+    &dev_attr_set_active_wan.attr,
+    &dev_attr_hot_swap_profile.attr,
+    &dev_attr_set_port_hwf_admin.attr,
 
     &dev_attr_rate_limit_queue_set.attr,
     &dev_attr_scheduling_mode_queue_set.attr,
@@ -1189,7 +1248,6 @@
     &dev_attr_pkt_mod_eng_entry_del.attr,
     &dev_attr_pkt_mod_eng_purge.attr,
 
-
     NULL
 };
 
@@ -1228,6 +1286,7 @@
     {"cfg_traffic",            &tpm_cfg_traffic_sw_group},
     {"cfg_misc",               &tpm_cfg_misc_sw_group},
     {"cfg_cpu_lpbk",           &tpm_cfg_cpu_lpbk_sw_group},
+    {"cfg_ds_load_balance",    &tpm_cfg_ds_load_balance_sw_group},
     {"cfg_age_count",          &tpm_cfg_age_count_sw_group},
     {"cfg_flat",               &tpm_cfg_flat_sw_group},
     {"cfg_mtu",                &tpm_cfg_mtu_sw_group},
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c
index 4928ca4..1778205 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c
@@ -564,6 +564,7 @@
     {ERR_MC_STREAM_INVALID,             "ERR_MC_STREAM_INVALID"},
     {ERR_MC_STREAM_EXISTS ,             "ERR_MC_STREAM_EXISTS "},
     {ERR_MC_DST_PORT_INVALID,           "ERR_MC_DST_PORT_INVALID"},
+    {ERR_MC_DST_QUEUE_INVALID,		"ERR_MC_DST_QUEUE_INVALID"},
     {ERR_IPV4_MC_DST_IP_INVALID,        "ERR_IPV4_MC_DST_IP_INVALID"},
     {ERR_IPV6_MC_DST_IP_INVALID,        "ERR_IPV6_MC_DST_IP_INVALID"},
     {ERR_OMCI_TCONT_INVALID,            "ERR_OMCI_TCONT_INVALID"},
@@ -1782,7 +1783,7 @@
     int indx;
 
     for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
-        if (strcmp(pentry->name, name) == 0) 
+        if (strcmp(pentry->name, name) == 0)
 			return pentry;
     }
     return 0;
@@ -1794,7 +1795,7 @@
     int indx;
 
     for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
-        if (pentry->name[0] == 0) 
+        if (pentry->name[0] == 0)
 			return pentry;
     }
     return 0;
@@ -1826,7 +1827,7 @@
         if (pentry->name[0] != 0) {
             off += sprintf(buf+off, "%s: \n", pentry->name);
 
-            off += sprintf(buf+off, "\tsrc_port %d, dst_port %d\n", 
+            off += sprintf(buf+off, "\tsrc_port %d, dst_port %d\n",
 						pentry->l4_ports.l4_src_port, pentry->l4_ports.l4_dst_port);
 
             printk(KERN_INFO "%s\n", buf);
@@ -1839,14 +1840,14 @@
 void tpm_reset_mc_vid_key(void)
 {
     tpm_src_port_type_t                 src_port;
-    
+
     memset(&mc_vid_key, 0, sizeof(mc_vid_key));
-    
+
     for ( src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_UNI_VIRT; src_port++)
     {
         mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].tpm_src_port = src_port;
     }
-    
+
     return;
 }
 
@@ -1861,11 +1862,11 @@
         printk(KERN_INFO "illegal input src port(%d)\n", src_port);
         return GT_FALSE;
     }
-    
+
     mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].mc_uni_port_mode = mc_uni_xlate_mode;
     mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].tpm_src_port = src_port;
     mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].uni_port_vid = mc_uni_xlate_vid;
-    
+
     return GT_TRUE;
 }
 
@@ -1874,7 +1875,7 @@
 )
 {
     tpm_error_code_t ret;
-    
+
     ret = tpm_proc_set_mc_vid_port_vids (0, mc_vid, &mc_vid_key);
     return ret;
 }
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c
index c38ab83..b54523a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c
@@ -792,7 +792,7 @@
 
     tpm_phy_get_port_speed_mode(owner_id, (tpm_src_port_type_t)lport, &speed);
 
-    printk(KERN_INFO "The speed status of lport[%d] is [%d]('0'-10M, '1'-100M, '2'-1000M)\n", lport, speed);
+    printk(KERN_INFO "The speed status of lport[%d] is [%d]('0'-10M, '1'-100M, '2'-1000M, '3'-UNKOWN)\n", lport, speed);
 
     return;
 
@@ -3441,6 +3441,145 @@
     tpm_sw_set_port_mirror(owner_id, src_port, dst_port, mirror_mode, mirror_state);
 }
 
+
+/*******************************************************************************
+* sfs_tpm_sw_set_trunk_ports
+*
+* DESCRIPTION:
+*       This function set port mirror.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       trunk_id    - valid from 0x0 to 0xf
+*       ports_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_trunk_ports
+(
+    IN  uint32_t  owner_id,
+    IN  uint32_t  trunk_id,
+    IN  uint32_t  ports_mask
+)
+{
+    tpm_sw_set_trunk_ports(owner_id, trunk_id, ports_mask);
+}
+/*******************************************************************************
+* sfs_tpm_sw_set_trunk_mask
+*
+* DESCRIPTION:
+*       This function set port mirror.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       mask_num    - trunk mask number, valid from 0 to 7.
+*       trunk_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_trunk_mask
+(
+    IN	uint32_t  owner_id,
+    IN	uint32_t  mask_num,
+    IN	uint32_t  trunk_mask
+)
+{
+    tpm_sw_set_trunk_mask(owner_id, mask_num, trunk_mask);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_speed_duplex
+*
+* DESCRIPTION:
+*       This function set the port speed and duplex together
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       speed_mode    - speed mode, '0'-10M, '1'-100M, '2'-1000M.
+*       mode          - duplex mode, 1:enable, 0:disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_speed_duplex
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               speed_mode,
+    MV_U32               mode
+)
+{
+    tpm_phy_speed_t speed;
+    bool duplex_mode;
+
+    if((tpm_phy_speed_t)speed_mode > TPM_PHY_SPEED_1000_MBPS)
+        speed = (tpm_phy_speed_t)TPM_PHY_SPEED_1000_MBPS;
+    else
+        speed = (tpm_phy_speed_t)speed_mode;
+
+    duplex_mode = ((1 == mode) ? true: false);
+
+    tpm_phy_set_port_speed_duplex_mode(owner_id, (tpm_src_port_type_t)lport, speed, duplex_mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of allowed VIDs per lport,
+*       and set the port's egress mode.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport    -  lport for adding the vid.
+*       vid      - VLAN id.
+*       eMode    - port egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_port_add_vid_set_egrs_mode
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    vid,
+    MV_U8     eMode
+)
+{
+    tpm_sw_port_add_vid_set_egrs_mode(owner_id,(tpm_src_port_type_t)lport,vid,eMode);
+
+    return;
+}
+
 #ifdef CONFIG_MV_TPM_SYSFS_HELP
 /*******************************************************************************
 **
@@ -3483,9 +3622,10 @@
     off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_flood ('1'-permit,'0'-not)]                 > set_port_flooding           - permit flooding of unknown DA\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
     off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_flood ('1'-permit,'0'-not)]                 > set_port_mc_flooding        - permit flooding of unknown multicast\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
     off += sprintf(buf+off, "echo [owner_id] [always_on ('1'-permit,'0'-use mc rules)]                         > set_bc_flooding             - permit flooding of broadcast\n");
-    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_tagged('1'-drop,  '0'-not)]                 > set_port_tagged             - allows or drops tagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
-    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_untagged('1'-drop,'0'-not)]                 > set_port_untagged           - allows or drops untagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [drop_tagged('1'-drop,  '0'-not)]                  > set_port_tagged             - allows or drops tagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [drop_untagged('1'-drop,'0'-not)]                  > set_port_untagged           - allows or drops untagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
     off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid_filter('1'-Drop,'0'-not)]                     > set_vid_filter_per_port     - set the filtering mod VID\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [speed('0'-10M,'1'-100M,'2'-1000M)] [duplex('1'-enable,'0'-disable)]  > set_port_speed_duplex - set port speed and duplex mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
     off += sprintf(buf+off, "====================================================================================================================================================\n");
 
     return(off);
@@ -3531,6 +3671,9 @@
     off += sprintf(buf+off, "echo [owner_id] [dscp 0-63] [q 0-3]                                               > set_ip_pri_mapping          - map ip pri to queue\n");
     off += sprintf(buf+off, "echo [owner_id] [gmac('0'-GMAC0, '1'-GMAC1, '2'-PMAC, '3'-switch)] [mtu]          > set_gmac_mtu                - set GMAC MTU\n");
     off += sprintf(buf+off, "echo [owner_id] [src port] [dst port] [mode('0'-ingress), '1'-egress] [state]     > set_port_mirror             - set port mirror, src/dst port is UNI port(1-4), state('1'-enable,'0'-disable)\n");
+    off += sprintf(buf+off, "echo [owner_id] [trunk_id] [port mask]                                            > set_trunk_ports             - set trunk ID and port mask\n");
+    off += sprintf(buf+off, "echo [owner_id] [mask num] [trunk mask]                                           > set_trunk_mask              - set trunk mask\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid(1-4094)] [egr_mode]                           > add_port_vid_set_egr_mode   - add a VID to lport and set the egress mode('0'-AS_IS, '2'-RM_TAG, '3'-ADD_TAG)\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
     off += sprintf(buf+off, "====================================================================================================================================================\n");
 
     return(off);
@@ -3666,15 +3809,15 @@
 {
     const char* name = attr->attr.name;
 //     unsigned long flags  = 0;
-    unsigned int  param1 = 0;
-    unsigned int  param2 = 0;
-    unsigned int  param3 = 0;
-    unsigned int  param4 = 0;
-    unsigned int  param5 = 0;
-    unsigned int  param6 = 0;
-    unsigned int  param7 = 0;
-    unsigned int  param8 = 0;
-    unsigned int  param9 = 0;
+    int  param1 = 0;
+    int  param2 = 0;
+    int  param3 = 0;
+    int  param4 = 0;
+    int  param5 = 0;
+    int  param6 = 0;
+    int  param7 = 0;
+    int  param8 = 0;
+    int  param9 = 0;
     MV_U8         static_mac[6] = {0,0,0,0,0,0};
     MV_U32        memPorts[6];
 
@@ -3787,6 +3930,18 @@
     printk(KERN_INFO "param1[%d],param2[%d],param3[%d],param4[%d],param5[%d],param6[%d],param7[%d],param8[%d] param9[%d] \n",
           param1,param2,param3,param4,
           param5,param6,param7,param8,param9);
+    if (param1 < 0 ||
+        param2 < 0 ||
+        param3 < 0 ||
+        param4 < 0 ||
+        param5 < 0 ||
+        param6 < 0 ||
+        param7 < 0 ||
+        param8 < 0 ||
+        param9 < 0) {
+            printk("ERROR %s: illegal negative parameter <%s>\n", __FUNCTION__, attr->attr.name);
+            return (len);
+    }
 
 //     raw_local_irq_save(flags);
 
@@ -3917,6 +4072,18 @@
     else if
         (!strcmp(name, "set_port_mirror"))
                 sfs_tpm_sw_set_port_mirror((MV_U32)param1,(MV_U32)param2,(MV_U32)param3,(MV_U32)param4,(MV_U32)param5);
+    else if
+        (!strcmp(name, "set_trunk_mask"))
+                sfs_tpm_sw_set_trunk_mask((MV_U32)param1,(MV_U32)param2,(MV_U32)param3);
+    else if
+        (!strcmp(name, "set_trunk_ports"))
+                sfs_tpm_sw_set_trunk_ports((MV_U32)param1,(MV_U32)param2,(MV_U32)param3);
+    else if
+        (!strcmp(name, "set_port_speed_duplex"))
+                sfs_tpm_sw_set_port_speed_duplex((MV_U32)param1,(MV_U32)param2, (MV_U32)param3, (MV_U32)param4);
+    else if
+        (!strcmp(name, "add_port_vid_set_egr_mode"))
+                sfs_tpm_sw_port_add_vid_set_egrs_mode((MV_U32)param1,(MV_U32)param2, (MV_U16)param3, (MV_U8)param4);
     else
         printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
 
@@ -4099,6 +4266,8 @@
 static DEVICE_ATTR(set_ip_pri_mapping,              S_IWUSR, set_sw_show, set_sw_store);
 static DEVICE_ATTR(set_gmac_mtu,                    S_IWUSR, set_sw_show, set_sw_store);
 static DEVICE_ATTR(set_port_mirror,                 S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_trunk_mask,                  S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_trunk_ports,                 S_IWUSR, set_sw_show, set_sw_store);
 #ifdef CONFIG_MV_TPM_SYSFS_HELP
 static DEVICE_ATTR(help_sw_set_cfg_1,               S_IRUSR, set_sw_show, set_sw_store);
 static DEVICE_ATTR(help_sw_set_cfg_2,               S_IRUSR, set_sw_show, set_sw_store);
@@ -4106,7 +4275,8 @@
 static DEVICE_ATTR(rate_limit_menu,                 S_IRUSR, set_sw_show, set_sw_store);
 static DEVICE_ATTR(egr_rate_limit_menu,             S_IRUSR, set_sw_show, set_sw_store);
 static DEVICE_ATTR(init_pri_menu,                   S_IRUSR, set_sw_show, set_sw_store);
-
+static DEVICE_ATTR(set_port_speed_duplex,           S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(add_port_vid_set_egr_mode,       S_IWUSR, set_sw_show, set_sw_store);
 
 static struct attribute *set_sw_attrs[] = {
     &dev_attr_set_port_admin.attr,
@@ -4149,6 +4319,9 @@
     &dev_attr_set_ip_pri_mapping.attr,
     &dev_attr_set_gmac_mtu.attr,
     &dev_attr_set_port_mirror.attr,
+    &dev_attr_set_trunk_mask.attr,
+    &dev_attr_set_trunk_ports.attr,
+    &dev_attr_set_port_speed_duplex.attr,
 #ifdef CONFIG_MV_TPM_SYSFS_HELP
     &dev_attr_help_sw_set_cfg_1.attr,
     &dev_attr_help_sw_set_cfg_2.attr,
@@ -4156,6 +4329,7 @@
     &dev_attr_rate_limit_menu.attr,
     &dev_attr_egr_rate_limit_menu.attr,
     &dev_attr_init_pri_menu.attr,
+    &dev_attr_add_port_vid_set_egr_mode.attr,
     NULL
 };
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c
index c93c182..3dd1dec 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c
@@ -1239,6 +1239,7 @@
         entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
         if (main_chain_id != TPM_MOD2_INVALID_CHAIN_ID)
         {
+            tpm_db_mod2_rollback_chain_entry(gmac_port, TPM_CHAIN_TYPE_MH, pattern_data->main_chain_id, false);
             pattern_data->main_chain_id = main_chain_id;
         }
     }
@@ -1741,7 +1742,7 @@
 		else
 			eth_type_sel = TPM_MOD2_TP_FROM_VLAN_2;
 	}
-	
+
 	*conf_data = eth_type_sel;
 	return TPM_OK;
 }
@@ -2328,7 +2329,8 @@
 	tpm_chain_type_t    subr_chain = TPM_CHAIN_TYPE_PPPOE;
     tpm_mod2_entry_t    *tmp_pattern = ipv4_pattern;
 	uint32_t            entry_num = TPM_MOD2_PPPOE_ADD_CMD_ENTRIES;
-	
+    uint32_t  gmac_mh_en;
+
 
     memset(ipv4_pattern, 0, sizeof(ipv4_pattern));
     memset(ipv6_pattern, 0, sizeof(ipv6_pattern));
@@ -2344,12 +2346,15 @@
 		tmp_pattern = ipv6_pattern;
 		entry_num = TPM_MOD2_IPV6_PPPOE_ADD_CMD_ENTRIES;
 	}
-	
+
     /* Build pattern entries */
 	if (bm & TPM_IPV6_UPDATE) {
 	    memcpy(tmp_pattern, tpm_mod2_ipv6_pppoe_pattern.entry,
 	           entry_num * sizeof(tpm_mod2_entry_t));
 	    tmp_pattern[2].data = mod_data->pppoe_mod.ppp_session;
+	    tpm_db_gmac_mh_en_conf_get(gmac_port, &gmac_mh_en);
+	    if (!gmac_mh_en)
+	        tmp_pattern[3].data = TPM_MOD2_DEFAULT_PPPOE_LEN_MH_DIS;
 	} else {
 	    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry,
 	           entry_num * sizeof(tpm_mod2_entry_t));
@@ -3409,7 +3414,7 @@
             max_sz = tpm_db_mod2_get_chain_max_size(entry_p->chain_type);
             if (entry_p->line_num > max_sz)
             {
-                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "chain(%d) PMT entry number(%d) exceeds the maximum chain size(%d)\n", 
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "chain(%d) PMT entry number(%d) exceeds the maximum chain size(%d)\n",
                              entry_p->chain_type, entry_p->line_num, max_sz);
                 return TPM_FAIL;
             }
@@ -3585,7 +3590,7 @@
 {
     uint16_t set_id;
     tpm_pattern_entry_t *pattern_set = NULL;
-    
+
     if (pattern_data == NULL)
     {
         TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
@@ -3604,7 +3609,7 @@
 	    }
 	    spin_unlock_bh(&tpmMod2JumpEntryLock);
 	}
-	
+
 	if (pattern_data->main_chain_type != TPM_CHAIN_TYPE_NONE) {
 	    for (set_id = 1; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++)
 	    {
@@ -3622,7 +3627,7 @@
 	        }
 	    }
 	}
-	
+
     return TPM_OK;
 }
 
@@ -4365,15 +4370,27 @@
 *******************************************************************************/
 int32_t    tpm_mod2_registers_init  (tpm_gmacs_enum_t   gmac_port, uint16_t  txp)
 {
+    uint32_t gmac_mh_en;
 
     TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "\n");
 
     /* Init PPPOE registers*/
     MV_REG_WRITE (NETA_TX_PMT_PPPOE_TYPE_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_ETY);
     MV_REG_WRITE (NETA_TX_PMT_PPPOE_DATA_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_DATA);
-    MV_REG_WRITE (NETA_TX_PMT_PPPOE_LEN_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_LEN);
     MV_REG_WRITE (NETA_TX_PMT_PPPOE_PROTO_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_PROTO);
 
+    if ((TPM_ENUM_GMAC_0 == gmac_port) || (TPM_ENUM_GMAC_1 == gmac_port))
+        tpm_db_gmac_mh_en_conf_get(gmac_port, &gmac_mh_en);
+    else
+        gmac_mh_en = 1;
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "GMAC: (%d), mh_en: (%d)\n", gmac_port, gmac_mh_en);
+
+    if (gmac_mh_en)
+        MV_REG_WRITE (NETA_TX_PMT_PPPOE_LEN_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_LEN_MH_EN);
+    else
+        MV_REG_WRITE (NETA_TX_PMT_PPPOE_LEN_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_LEN_MH_DIS);
+
     return TPM_OK;
 }
 
@@ -4518,7 +4535,7 @@
 		tpm_db_mod2_split_mod_increase_vlan_user_num(port, mod_data);
 		return(TPM_OK);
 	}
-	
+
 	db_ret = tpm_db_mod2_split_mod_insert_vlan(port, mod_data);
 	if (TPM_DB_OK != db_ret)
 	{
@@ -4567,7 +4584,7 @@
 {
 	int32_t	    tpm_ret;
 	tpm_pkt_mod_t mod_data;
-	
+
 	if (TPM_SPLIT_MOD_DISABLED == tpm_db_split_mod_get_enable())
 	{
 		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED\n");
@@ -4601,16 +4618,51 @@
 	return TPM_OK;
 }
 
-int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section, 
+void tpm_mod2_split_mod_entry_del(tpm_gmacs_enum_t     gmac_port,
+                                  uint32_t             mod_entry,
+                                  uint32_t             vlan_index)
+{
+	int32_t  tpm_ret;
+	uint32_t i = 0;
+	uint32_t num_pbits;
+	uint32_t user_num = 0;
+
+	/* decrease user number of this vlan */
+	tpm_ret = tpm_db_mod2_split_mod_decrease_vlan_user_num(gmac_port, vlan_index, &user_num);
+	if (TPM_DB_OK != tpm_ret)
+	{
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to decrease vlan user num, index: %d\n", vlan_index);
+		return;
+	}
+
+	/* still other usr, do not remove */
+	if (user_num != 0)
+	{
+		TPM_OS_INFO(TPM_MODZ2_HM_MOD, "still other usr, do not remove, usr num: %d\n", user_num);
+		return;
+	}
+
+	/* remove all the PMT entry for this VLAN */
+	num_pbits = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+	for(i = 0; i <= num_pbits; i++) {
+		tpm_ret = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, gmac_port, (vlan_index * 16 + i));
+		if (TPM_DB_OK != tpm_ret)
+		{
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to del split mod, index: %d\n", (vlan_index * 16 + i));
+			return;
+		}
+	}
+
+	return;
+}
+int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section,
                                   tpm_gmacs_enum_t     gmac_port,
                                   uint32_t             mod_entry)
 {
 	uint32_t num_vlans;
-	uint32_t num_pbits;
 	uint32_t vlan_index;
-	uint32_t user_num = 0;
-	int32_t  tpm_ret;
-	uint32_t i = 0;
+	tpm_gmacs_enum_t duplicate_gmac;
+	tpm_db_ds_mac_based_trunk_enable_t ds_mac_based_trunk_enable;
 
 	if (!mod_entry) {
 		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "mod_entry is zero, PMT do not need to be removed\n");
@@ -4621,13 +4673,16 @@
 		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED, PMT need to be removed\n");
 		return(TPM_FAIL);
 	}
-	
-	if (	(TPM_IPV4_ACL == api_section)
-		 && (mod_entry <= TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX)) {
-		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "IPv4 split mod, PMT do not need to be removed\n");
+
+	if (	(    (TPM_IPV4_ACL == api_section)
+		  || (TPM_L4_ACL == api_section)
+		  || (TPM_IPV6_GEN_ACL == api_section)
+		  || (TPM_IPV6_DIP_ACL == api_section))
+	     && (mod_entry <= TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX)) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "IPv4/6 split mod, PMT do not need to be removed\n");
 		return(TPM_OK);
 	}
-	
+
 	if (TPM_L2_PRIM_ACL != api_section) {
 		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Not L2 ACL, PMT need to be removed\n");
 		return(TPM_FAIL);
@@ -4651,32 +4706,22 @@
 		return(TPM_OK);
 	}
 
-	/* decrease user number of this vlan */
-	tpm_ret = tpm_db_mod2_split_mod_decrease_vlan_user_num(gmac_port, vlan_index, &user_num);
-	if (TPM_DB_OK != tpm_ret)
-	{
-		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to decrease vlan user num, index: %d\n", vlan_index);
-		return(TPM_OK);
-	}
+	tpm_mod2_split_mod_entry_del(gmac_port, mod_entry, vlan_index);
 
-	/* still other usr, do not remove */
-	if (user_num != 0)
-	{
-		TPM_OS_INFO(TPM_MODZ2_HM_MOD, "still other usr, do not remove, usr num: %d\n", user_num);
-		return(TPM_OK);
+	/* when ds load balance on G0 and G1 is enabled, need to duplicate DS PMT on G0/1 */
+	tpm_db_ds_mac_based_trunk_enable_get(&ds_mac_based_trunk_enable);
+	if (	(TPM_DS_MAC_BASED_TRUNK_ENABLED == ds_mac_based_trunk_enable)
+	     && (TPM_ENUM_GMAC_0 == gmac_port || TPM_ENUM_GMAC_1 == gmac_port)) {
+
+		/* if this is DS and DS_MAC_BASED_TRUNK is ENABLED */
+		if (gmac_port == TPM_ENUM_GMAC_0)
+			duplicate_gmac = TPM_ENUM_GMAC_1;
+		else
+			duplicate_gmac = TPM_ENUM_GMAC_0;
+
+		tpm_mod2_split_mod_entry_del(duplicate_gmac, mod_entry, vlan_index);
 	}
-	
-	/* remove all the PMT entry for this VLAN */
-	num_pbits = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
-	for(i = 0; i <= num_pbits; i++) {
-		tpm_ret = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, gmac_port, (vlan_index * 16 + i));
-		if (TPM_DB_OK != tpm_ret)
-		{
-			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to del split mod, index: %d\n", (vlan_index * 16 + i));
-			return(TPM_OK);
-		}
-	}
-    return TPM_OK;
+	return TPM_OK;
 }
 
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h
index 60af2b1..672227a 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h
@@ -112,11 +112,14 @@
 #define TPM_MOD2_DEFAULT_ETY                (0x8100)
 #define TPM_MOD2_DEFAULT_PPPOE_ETY          (0x8864)
 #define TPM_MOD2_DEFAULT_PPPOE_DATA         (0x1100)
-#define TPM_MOD2_DEFAULT_PPPOE_LEN          (0x7000)
+#define TPM_MOD2_DEFAULT_PPPOE_LEN_MH_EN    (0x7000)
+#define TPM_MOD2_DEFAULT_PPPOE_LEN_MH_DIS   (0x7202)
 #define TPM_MOD2_DEFAULT_PPPOE_PROTO        (0x0021)
 
 /* Self-defined Ethernet type for CPU loopback frames*/
 #define TPM_MOD2_CPU_LOOPBACK_ETY           (0xAABB)
+/* Self-defined Marvell header for MAC learning frames on Media Convert*/
+#define TPM_MOD2_MAC_LEARN_MH               (0xAACC)
 
 /* Max number of modification entries per command */
 #define TPM_MOD2_MAX_CMD_ENTRIES            (5)
@@ -287,7 +290,7 @@
 int32_t    tpm_mod2_init(void);
 int32_t tpm_mod2_split_mod_init(tpm_gmacs_enum_t port);
 int32_t tpm_mod2_split_mod_create_l2_pmts(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, bool init_flag);
-int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section, 
+int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section,
                                   tpm_gmacs_enum_t     gmac_port,
                                   uint32_t             mod_entry);
 
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c
index ede6176..e62bce4 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c
@@ -79,6 +79,7 @@
 
 #include "tpm_common.h"
 #include "tpm_header.h"
+#include "../../mv_mac_learn/mv_mac_learn_header.h"
 
 uint32_t trace_sw_dbg_flag = 0;
 
@@ -91,7 +92,7 @@
 #define SWITCH_INIT_CHECK()\
     int32_t ret_init_check;\
     ret_init_check = tpm_sw_init_check();\
-    IF_ERROR(ret_init_check);
+    IF_ERROR(ret_init_check)
 
 /*******************************************************************************
 * tpm_sw_init_check
@@ -126,6 +127,113 @@
 }
 
 /*******************************************************************************
+* tpm_phy_access_check
+*
+* DESCRIPTION:
+*       This function check the PHY access path, direct or through switch.
+*
+* INPUTS:
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       phy_ctrl    - the PHY SMI master indication
+*       phy_direct_addr - PHY address if PHY accessed directly
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_access_check(tpm_src_port_type_t src_port,
+                                      tpm_phy_ctrl_t *phy_access_way,
+                                      uint32_t *phy_direct_addr)
+{
+    tpm_init_gmac_conn_conf_t gmac_conn_info;
+    uint32_t i;
+    tpm_db_chip_conn_t chip_con;
+    tpm_db_int_conn_t int_con;
+    uint32_t switch_port;
+
+    /* Para check*/
+    if ((NULL == phy_access_way) || (NULL == phy_direct_addr)) {
+        printk(KERN_ERR "ERROR: Invalid pointer\n");
+        return ERR_GENERAL;
+    }
+
+    /* Check gmac port connection info */
+    for (i = 0; i < TPM_MAX_NUM_GMACS; i++) {
+        if (TPM_DB_OK != tpm_db_gmac_conn_conf_get(i, &gmac_conn_info)) {
+            printk(KERN_ERR "ERROR: (%s:%d) Gmac port(%d) connection info get failed\n", __FUNCTION__, __LINE__, i);
+            return ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+        if (TPM_TRUE == gmac_conn_info.valid && src_port == gmac_conn_info.port_src) {
+            /* PHY access directly */
+            *phy_access_way = PHY_SMI_MASTER_CPU;
+            /*get PHY addr on GMAC*/
+            *phy_direct_addr = mvBoardPhyAddrGet(i);
+
+            if (trace_sw_dbg_flag)
+                printk(KERN_INFO "Port%d PHY access directly, phyaddr %d\n", src_port, *phy_direct_addr);
+
+            return TPM_RC_OK;
+        }
+    }
+
+    /* Check eth port connection info */
+    if (TPM_DB_OK != tpm_db_eth_port_conf_get(src_port, &chip_con, &int_con, &switch_port)) {
+        printk(KERN_ERR "ERROR: (%s:%d) Eth port(%d) connection info get failed\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_PHY_SRC_PORT_CONN_INVALID;
+    }
+    /* Check QSGMII */
+    if (TPM_CONN_QSGMII == chip_con && TPM_INTCON_SWITCH == int_con) {
+        /* Check MPP register, if value of MPP29 and MPP30 are both 4, then access PHY directly */
+        if ((mvBoardMppGet(3) & DB_88F6535_MPP24_31) == DB_88F6535_MPP24_31) {
+            /* PHY access directly */
+            *phy_access_way = PHY_SMI_MASTER_CPU;
+            /*get PHY addr on GMAC*/
+            *phy_direct_addr = (uint32_t)src_port;
+            if (trace_sw_dbg_flag)
+                printk(KERN_INFO "Port%d QSGMII PHY access directly, phyaddr %d\n", src_port, *phy_direct_addr);
+            return TPM_RC_OK;
+        }
+    }
+
+    *phy_access_way = PHY_SMI_MASTER_SWT;
+    if (trace_sw_dbg_flag)
+        printk(KERN_INFO "Port%d PHY access through switch\n", src_port);
+
+    return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_src_port_mac_map(tpm_src_port_type_t src_port,
+                                      tpm_gmacs_enum_t *gmac)
+{
+    tpm_init_gmac_conn_conf_t gmac_conn_info;
+    uint32_t i;
+
+    /* Check gmac port connection info */
+    for (i = 0; i < TPM_MAX_NUM_GMACS; i++) {
+        if (TPM_DB_OK != tpm_db_gmac_conn_conf_get(i, &gmac_conn_info)) {
+	    printk(KERN_ERR "ERROR: (%s:%d) Gmac port(%d) connection info get failed\n", __FUNCTION__, __LINE__, i);
+	    return ERR_GENERAL;
+        }
+        if (TPM_TRUE == gmac_conn_info.valid && src_port == gmac_conn_info.port_src) {
+            *gmac = i;
+            return TPM_RC_OK;
+        }
+    }
+    if (i == TPM_MAX_NUM_GMACS) {
+        printk(KERN_ERR "ERROR: (%s:%d) src port(%d) map to MAC failed\n", __FUNCTION__, __LINE__, src_port);
+	return ERR_SRC_PORT_INVALID;
+    }
+
+    return TPM_RC_OK;
+}
+
+/*******************************************************************************
 * tpm_sw_set_debug_trace_flag
 *
 * DESCRIPTION:
@@ -185,8 +293,7 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -196,14 +303,30 @@
               __FUNCTION__,owner_id,src_port, static_mac[0],static_mac[1],static_mac[2],static_mac[3],static_mac[4],static_mac[5]);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_static_entry_add(&(static_mac[0]));
+	else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) MAC learn not supported\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_add_static_mac(lPort, &(static_mac[0]));
+        retVal = mv_switch_add_static_mac(lPort, &(static_mac[0]));
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -247,9 +370,7 @@
     uint8_t  static_mac[6]
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = TPM_RC_OK;
 
     if (trace_sw_dbg_flag)
     {
@@ -259,7 +380,19 @@
                  __FUNCTION__,owner_id,static_mac[0],static_mac[1],static_mac[2],static_mac[3],static_mac[4],static_mac[5]);
     }
 
-    retVal = mv_switch_del_static_mac(&(static_mac[0]));
+    if (tpm_sw_init_check()) {
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_static_entry_del(&(static_mac[0]));
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) MAC learn not supported\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        retVal = mv_switch_del_static_mac(&(static_mac[0]));
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -305,7 +438,10 @@
     uint8_t  static_mac[6]
 )
 {
-    tpm_error_code_t retVal;
+    tpm_error_code_t retVal = TPM_RC_OK;
+#ifdef CONFIG_MV_MAC_LEARN
+    static uint32_t mask_check = 1;
+#endif
 
     SWITCH_INIT_CHECK();
 
@@ -324,7 +460,20 @@
                static_mac[5]);
     }
 
-    retVal = mv_switch_mac_addr_set(&(static_mac[0]), 0, ports_mask, 1);
+    if (tpm_sw_init_check()) {
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+	if (tpm_db_gmac1_lpbk_en_get()) {
+            if (ports_mask & mask_check)
+                retVal = mv_mac_learn_static_entry_add(&(static_mac[0]));
+        } else {
+            printk(KERN_ERR "ERROR: (%s:%d) MAC learn not supported\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        retVal = mv_switch_mac_addr_set(&(static_mac[0]), 0, ports_mask, 1);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -341,6 +490,203 @@
 }
 
 /*******************************************************************************
+* tpm_sw_set_trunk_ports
+*
+* DESCRIPTION:
+*       This function creates trunk ports and trunk id
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       trunk_id    - valid from 0x0 to 0xf
+*       ports_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_trunk_ports
+(
+    uint32_t owner_id,
+    uint32_t trunk_id,
+    uint32_t ports_mask
+)
+{
+    tpm_error_code_t ret;
+    uint16_t  reg_tmp = 0;
+    uint32_t  switch_port = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d], trunk_id[0x%x], ports_mask[0x%x]\n\r",
+               __FUNCTION__, owner_id, trunk_id, ports_mask);
+    }
+
+    if (trunk_id > SW_TRUNK_ID_MAX)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: trunk_id[0x%x] is bigger than [0x%x]\n\r",
+               __FUNCTION__,trunk_id, SW_TRUNK_ID_MAX);
+    }
+
+    for (switch_port = 0; switch_port <= TPM_SWITCH_NUM_PORTS; switch_port++)
+    {
+        if(0 == (ports_mask & (1 << switch_port)))
+        {
+	    continue;
+        }
+
+	/* get trunk reg from HW */
+	ret = mv_switch_reg_read(switch_port, SW_TRUNK_ID_REG, MV_SWITCH_PORT_ACCESS, &reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get trunk reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+
+	/* set bits 8, 9 to 11, as trunk_id */
+	SW_CLEAR_REG_BIT(reg_tmp, SW_TRUNK_ID_BIT_OFF, SW_TRUNK_ID_BIT_LEN);
+	reg_tmp |= (trunk_id << SW_TRUNK_ID_BIT_OFF);
+	/* set bit 14, as trunk bit */
+	reg_tmp |= (1 << SW_TRUNK_BIT_OFF);
+	ret = mv_switch_reg_write(switch_port, SW_TRUNK_ID_REG, MV_SWITCH_PORT_ACCESS, reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set trunk reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+    }
+
+    /* get trunk mapping reg from HW */
+    ret = mv_switch_reg_read(0, SW_TRUNK_MAPPING_REG, MV_SWITCH_GLOBAL2_ACCESS, &reg_tmp);
+    if (0 != ret) {
+	    TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get trunk mapping reg, ret(%d)\n", ret);
+	    return (TPM_FAIL);
+    }
+
+    /* set bits 11 to 14, as trunk_id */
+    SW_CLEAR_REG_BIT(reg_tmp, SW_TRUNK_MAPPING_ID_BIT_OFF, SW_TRUNK_ID_BIT_LEN);
+    reg_tmp |= (trunk_id << SW_TRUNK_MAPPING_ID_BIT_OFF);
+
+    /* set bits 0 to 6, as trunk map */
+    SW_CLEAR_REG_BIT(reg_tmp, SW_TRUNK_MAPPING_BIT_OFF, SW_TRUNK_MAPPING_BIT_LEN);
+    reg_tmp |= (ports_mask << SW_TRUNK_MAPPING_BIT_OFF);
+
+    /* set bits 15, as udpate bit */
+    reg_tmp |= (1 << SW_REG_UPDATE_BIT_OFF);
+
+    ret = mv_switch_reg_write(0, SW_TRUNK_MAPPING_REG, MV_SWITCH_GLOBAL2_ACCESS, reg_tmp);
+    if (0 != ret) {
+	    TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set trunk mapping reg, ret(%d)\n", ret);
+	    return (TPM_FAIL);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return ret;
+}
+
+
+/*******************************************************************************
+* tpm_sw_set_trunk_mask
+*
+* DESCRIPTION:
+*       This function sets trunk mask
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       mask_num    - trunk mask number, valid from 0 to 7.
+*       trunk_mask  - mask for real switch port, not logical port like TPM_SRC_PORT_UNI_0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_trunk_mask
+(
+    uint32_t owner_id,
+    uint32_t mask_num,
+    uint32_t trunk_mask
+)
+{
+    tpm_error_code_t ret;
+    uint16_t  reg_tmp = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],mask_num[0x%x],trunk_mask[0x%x]\n\r",
+               __FUNCTION__, owner_id, mask_num, trunk_mask);
+    }
+
+    if (mask_num > SW_TRUNK_MASK_NUM_MAX)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: mask_num[0x%x] is bigger than [0x%x]\n\r",
+               __FUNCTION__,mask_num, SW_TRUNK_MASK_NUM_MAX);
+    }
+
+    if (trunk_mask > SW_TRUNK_MASK_MAX)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: trunk_mask[0x%x] is bigger than [0x%x]\n\r",
+               __FUNCTION__,trunk_mask, SW_TRUNK_MASK_MAX);
+    }
+
+    /* get trunk mask reg from HW */
+    ret = mv_switch_reg_read(0, SW_TRUNK_MASK_REG, MV_SWITCH_GLOBAL2_ACCESS, &reg_tmp);
+    if (0 != ret) {
+	    TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get trunk mask reg, ret(%d)\n", ret);
+	    return (TPM_FAIL);
+    }
+
+    /* set bits 11 to 14, as mask_num */
+    SW_CLEAR_REG_BIT(reg_tmp, SW_TRUNK_MASK_NUM_BIT_OFF, SW_TRUNK_MASK_NUM_BIT_LEN);
+    reg_tmp |= (mask_num << SW_TRUNK_MASK_NUM_BIT_OFF);
+
+    /* set bits 0 to 6, as trunk_mask */
+    SW_CLEAR_REG_BIT(reg_tmp, SW_TRUNK_MASK_BIT_OFF, SW_TRUNK_MASK_BIT_LEN);
+    reg_tmp |= (trunk_mask << SW_TRUNK_MASK_BIT_OFF);
+
+    /* set bits 15, as udpate bit */
+    reg_tmp |= (1 << SW_REG_UPDATE_BIT_OFF);
+
+    ret = mv_switch_reg_write(0, SW_TRUNK_MASK_REG, MV_SWITCH_GLOBAL2_ACCESS, reg_tmp);
+    if (0 != ret) {
+	    TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set trunk mask reg, ret(%d)\n", ret);
+	    return (TPM_FAIL);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return ret;
+}
+
+/*******************************************************************************
 * tpm_sw_clear_dynamic_mac
 *
 * DESCRIPTION:
@@ -422,7 +768,7 @@
     tpm_error_code_t retVal;
     GT_BOOL  state;
     uint32_t  sw_sport;
-    uint32_t  sw_dport; 
+    uint32_t  sw_dport;
 
     SWITCH_INIT_CHECK();
 
@@ -440,7 +786,7 @@
         state = GT_FALSE;
 
     sw_sport = tpm_db_eth_port_switch_port_get(sport);
-    sw_dport = tpm_db_eth_port_switch_port_get(dport); 
+    sw_dport = tpm_db_eth_port_switch_port_get(dport);
 
     if (TPM_DB_ERR_PORT_NUM == sw_sport || TPM_DB_ERR_PORT_NUM == sw_dport){
             TPM_OS_ERROR(TPM_INIT_MOD, "invalid port (sw_sport %d, sw_dport %d)\n", sw_sport, sw_dport);
@@ -590,29 +936,23 @@
 
     for (i=TPM_SRC_PORT_UNI_0; i<TPM_MAX_NUM_UNI_PORTS; i++)
     {
-	sw_port_num = tpm_db_eth_port_switch_port_get(i);
+        sw_port_num = tpm_db_eth_port_switch_port_get(i);
 
-	if (TPM_DB_ERR_PORT_NUM == sw_port_num)
-		continue;
+        if (TPM_DB_ERR_PORT_NUM == sw_port_num)
+            continue;
 
-	if (sw_port_num >= MEM_PORTS_NR) {
-		TPM_OS_ERROR(TPM_INIT_MOD, "sw_port_num too big! (%d >= MEM_PORTS_NR) \n", sw_port_num);
-		return ERR_SRC_PORT_INVALID;
-	}
+        if (sw_port_num >= MEM_PORTS_NR) {
+            TPM_OS_ERROR(TPM_INIT_MOD, "sw_port_num too big! (%d >= MEM_PORTS_NR) \n", sw_port_num);
+            return ERR_SRC_PORT_INVALID;
+        }
 
         if(port_vector & (1 << i))
         {
             memPorts[sw_port_num] = sw_port_num;
-            printk(KERN_INFO
-               "==ENTER==%s: 1  i[%d] sw_port_num[%d]\n\r",
-               __FUNCTION__,  i, sw_port_num);
         }
         else
         {
             memPorts[sw_port_num] = 0x80;
-            printk(KERN_INFO
-               "==ENTER==%s: 2  i[%d] sw_port_num[%d]\n\r",
-               __FUNCTION__,  i, sw_port_num);
         }
     }
 
@@ -744,8 +1084,7 @@
 )
 {
     tpm_error_code_t retVal = TPM_RC_OK;
-
-    SWITCH_INIT_CHECK();
+    uint32_t switch_init = 0;
 
     if (trace_sw_dbg_flag)
     {
@@ -770,8 +1109,10 @@
             retVal = mv_eth_set_mtu(2, mtu);
             break;
         case TPM_NETA_MTU_SWITCH:
-            /*Set switch MTU*/
-            retVal = mv_switch_set_mtu(mtu);
+            /*Set switch MTU if exist*/
+            tpm_db_switch_init_get(&switch_init);
+	    if (switch_init)
+                retVal = mv_switch_set_mtu(mtu);
             break;
         default:
             break;
@@ -822,8 +1163,6 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
 
-    SWITCH_INIT_CHECK();
-
     if (trace_sw_dbg_flag)
     {
        printk(KERN_INFO
@@ -847,8 +1186,11 @@
             retVal = mv_eth_get_mtu(2, mtu);
             break;
         case TPM_NETA_MTU_SWITCH:
-            /*Get switch MTU*/
-            retVal = mv_switch_get_mtu(mtu);
+            /*Get switch MTU if exist*/
+            if (!tpm_sw_init_check())
+                retVal = mv_switch_get_mtu(mtu);
+            else
+                retVal = ERR_GENERAL;
             break;
         default:
             break;
@@ -904,8 +1246,7 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -914,14 +1255,30 @@
                 __FUNCTION__, owner_id, src_port, mac_per_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+#ifdef CONFIG_MV_MAC_LEARN
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_max_count_set(mac_per_port);
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) MAC learn not supported\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_set_port_max_macs(lPort, mac_per_port);
+        retVal = mv_switch_set_port_max_macs(lPort, mac_per_port);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -983,8 +1340,8 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
+    tpm_db_pnc_range_conf_t range_conf;
 
     if (trace_sw_dbg_flag)
     {
@@ -993,14 +1350,34 @@
                 __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Check GMAC1 lpk status */
+        if (tpm_db_gmac1_lpbk_en_get()) {
+            if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)) {
+                printk(KERN_ERR "ERROR: (%s:%d) tpm_db_pnc_rng_conf_get failed\n", __FUNCTION__, __LINE__);
+                return ERR_GENERAL;
+            }
+            *limit = range_conf.api_end - range_conf.api_start + 1;
+            if (*limit > MAC_LEARN_FDB_MAX_COUNT)
+                *limit = MAC_LEARN_FDB_MAX_COUNT;
+        } else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) MAC learn not supported\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_get_port_max_macs(lPort, limit);
+        retVal = mv_switch_get_port_max_macs(lPort, limit);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -1026,7 +1403,7 @@
 * INPUTS:
 *       owner_id     - APP owner id - should be used for all API calls.
 *       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       allow_tagged - set to 1 = discard tagged packets per UNI port
+*       drop_tagged - set to 1 = drop tagged packets per UNI port
 *                      set to 0 = allow tagged packets per UNI port.
 *
 * OUTPUTS:
@@ -1044,7 +1421,7 @@
 (
     uint32_t            owner_id,
     tpm_src_port_type_t src_port,
-    uint8_t             allow_tagged
+    uint8_t             drop_tagged
 )
 {
     tpm_error_code_t retVal = TPM_RC_OK;
@@ -1056,8 +1433,8 @@
     if (trace_sw_dbg_flag)
     {
        printk(KERN_INFO
-              "==ENTER==%s: owner_id[%d],src_port[%d],allow_tagged[%d]\r\n",
-              __FUNCTION__,owner_id,src_port,allow_tagged);
+              "==ENTER==%s: owner_id[%d],src_port[%d],drop_tagged[%d]\r\n",
+              __FUNCTION__,owner_id,src_port,drop_tagged);
 
     }
 
@@ -1068,7 +1445,7 @@
         return ERR_SRC_PORT_INVALID;
     }
 
-    if (allow_tagged == 1)
+    if (drop_tagged == 1)
     {
         mode = 1/*GT_TRUE*/;
     }
@@ -1165,7 +1542,7 @@
 * INPUTS:
 *       owner_id       - APP owner id - should be used for all API calls.
 *       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       allow_untagged - set to 1 = discard untagged packets per UNI port
+*       drop_untagged - set to 1 = drop untagged packets per UNI port
 *                        set to 0 = alow untagged packets per UNI port.
 *
 * OUTPUTS:
@@ -1183,7 +1560,7 @@
 (
     uint32_t            owner_id,
     tpm_src_port_type_t src_port,
-    uint8_t             allow_untagged
+    uint8_t             drop_untagged
 )
 {
     tpm_error_code_t retVal = TPM_RC_OK;
@@ -1195,11 +1572,11 @@
     if (trace_sw_dbg_flag)
     {
         printk(KERN_INFO
-                "==ENTER==%s: owner_id[%d],src_port[%d],allow_untagged[%d]\r\n",
-                __FUNCTION__,owner_id,src_port,allow_untagged);
+                "==ENTER==%s: owner_id[%d],src_port[%d],drop_untagged[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,drop_untagged);
     }
 
-    if (allow_untagged == 1)
+    if (drop_untagged == 1)
     {
         mode = 1/*GT_TRUE*/;
     }
@@ -2467,9 +2844,9 @@
     uint8_t  weight
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = GT_OK;
+    tpm_gmacs_enum_t gmac_i;
+    tpm_db_gmac_func_t gmac_func;
 
     if (trace_sw_dbg_flag)
     {
@@ -2478,15 +2855,24 @@
                 __FUNCTION__,owner_id,queue_id,weight);
     }
 
-    if ((queue_id == 0) ||
-        (queue_id > SW_QOS_NUM_OF_QUEUES))
-    {
-        printk(KERN_INFO
-               "%s:%d:==ERROR== invalid queue[%d]\r\n", __FUNCTION__,__LINE__,queue_id);
-        return ERR_SW_TM_QUEUE_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+            tpm_db_gmac_func_get(gmac_i, &gmac_func);
+            if (TPM_GMAC_FUNC_LAN_UNI == gmac_func ||
+                TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI == gmac_func)
+                retVal |= mvNetaTxqWrrPrioSet(gmac_i, 0, queue_id, weight);
+        }
+    } else {
+        if ((queue_id == 0) ||
+            (queue_id > SW_QOS_NUM_OF_QUEUES))
+        {
+            printk(KERN_INFO
+                   "%s:%d:==ERROR== invalid queue[%d]\r\n", __FUNCTION__,__LINE__,queue_id);
+            return ERR_SW_TM_QUEUE_INVALID;
+        }
 
-    retVal = mv_switch_set_uni_q_weight(queue_id, weight);
+        retVal = mv_switch_set_uni_q_weight(queue_id, weight);
+    }
     if (retVal != GT_OK)
     {
         printk(KERN_ERR
@@ -2543,8 +2929,8 @@
     tpm_error_code_t    retVal = TPM_RC_OK;
     int32_t             lPort  = 0;
     GT_PIRL2_COUNT_MODE mode;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t    gmac_i;
+    tpm_db_gmac_lpk_uni_ingr_rate_limit_t rate_limit;
 
     if (trace_sw_dbg_flag)
     {
@@ -2553,16 +2939,38 @@
                 __FUNCTION__,owner_id,src_port,count_mode, cir, cbs,ebs);
     }
 
-    mode = (GT_PIRL2_COUNT_MODE)count_mode;
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Check GMAC1 lpk status, if no lpk, no ingress rate for ingress */
+        if (tpm_db_gmac1_lpbk_en_get()) {
+            retVal = tpm_tm_set_gmac0_ingr_rate_lim(owner_id, cir, cbs);
+            if (retVal == TPM_RC_OK) {
+                rate_limit.count_mode = count_mode;
+                rate_limit.cir = cir;
+                rate_limit.cbs = cbs;
+                rate_limit.ebs = ebs;
+                retVal = tpm_db_gmac_lpk_uni_ingr_rate_limit_set(src_port, rate_limit);
+            }
+        } else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) ingr rate limit not support\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+    } else {
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+        mode = (GT_PIRL2_COUNT_MODE)count_mode;
+
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_set_uni_ingr_police_rate(lPort, (GT_PIRL2_COUNT_MODE)mode, cir, cbs, ebs);
     }
-
-    retVal = mv_switch_set_uni_ingr_police_rate(lPort, (GT_PIRL2_COUNT_MODE)mode, cir, cbs, ebs);
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -2620,8 +3028,8 @@
     tpm_error_code_t    retVal = TPM_RC_OK;
     int32_t             lPort  = 0;
     GT_PIRL2_COUNT_MODE mode;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t    gmac_i;
+    tpm_db_gmac_lpk_uni_ingr_rate_limit_t rate_limit;
 
     if (trace_sw_dbg_flag)
     {
@@ -2630,14 +3038,34 @@
                 __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Check GMAC1 lpk status, if no lpk, no ingress rate for ingress */
+        if (tpm_db_gmac1_lpbk_en_get()) {
+            retVal = tpm_db_gmac_lpk_uni_ingr_rate_limit_get(src_port, &rate_limit);
+            if (retVal == TPM_RC_OK) {
+                mode = (GT_PIRL2_COUNT_MODE)rate_limit.count_mode;
+                *cir = rate_limit.cir;
+                *cbs = rate_limit.cbs;
+                *ebs = rate_limit.ebs;
+            }
+        } else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) ingr rate limit not support\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_get_uni_ingr_police_rate(lPort, &mode, cir, cbs, ebs);
+        retVal = mv_switch_get_uni_ingr_police_rate(lPort, &mode, cir, cbs, ebs);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -2836,8 +3264,7 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -2846,14 +3273,27 @@
                 __FUNCTION__,owner_id,src_port,mode,frame_rate_limit_val);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Set tx port rate limit on gmac_i */
+        retVal = tpm_tm_set_tx_port_rate_lim(owner_id, gmac_i, frame_rate_limit_val, 0);
+        if (retVal == TPM_RC_OK) {
+            retVal = tpm_db_gmac_uni_egr_rate_limit_set(src_port, frame_rate_limit_val);
+        }
+    } else {
 
-    retVal = mv_switch_set_uni_egr_rate_limit(lPort, (GT_PIRL_ELIMIT_MODE)mode, frame_rate_limit_val);
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_set_uni_egr_rate_limit(lPort, (GT_PIRL_ELIMIT_MODE)mode, frame_rate_limit_val);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -2905,8 +3345,7 @@
     tpm_error_code_t    retVal = TPM_RC_OK;
     int32_t             lPort  = 0;
     GT_PIRL_ELIMIT_MODE limit_mode;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t    gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -2915,14 +3354,24 @@
                 __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Set tx port rate limit on gmac_i */
+        retVal = tpm_db_gmac_uni_egr_rate_limit_get(src_port, frame_rate_limit_val);
+        limit_mode = GT_PIRL_ELIMIT_FRAME;
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_get_uni_egr_rate_limit(lPort, &limit_mode, frame_rate_limit_val);
+        retVal = mv_switch_get_uni_egr_rate_limit(lPort, &limit_mode, frame_rate_limit_val);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -3033,9 +3482,7 @@
     uint32_t time_out
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = TPM_RC_OK;
 
     if (trace_sw_dbg_flag)
     {
@@ -3044,7 +3491,19 @@
                __FUNCTION__,owner_id,time_out);
     }
 
-    retVal = mv_switch_set_age_time(time_out);
+    if (tpm_sw_init_check()) {
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_expire_time_set(time_out);
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) MAC learn not supported\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        retVal = mv_switch_set_age_time(time_out);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -3086,9 +3545,7 @@
      uint32_t *time_out
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = TPM_RC_OK;
 
     if (trace_sw_dbg_flag)
     {
@@ -3097,7 +3554,19 @@
                __FUNCTION__,owner_id);
     }
 
-    retVal = mv_switch_get_age_time(time_out);
+    if (tpm_sw_init_check()) {
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_expire_time_get(time_out);
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) MAC learn not supported\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        retVal = mv_switch_get_age_time(time_out);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -3147,8 +3616,7 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -3162,14 +3630,30 @@
     else
         state = GT_FALSE;
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+#ifdef CONFIG_MV_MAC_LEARN
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_enable_set(state);
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) MAC learn not supported\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_set_mac_learn(lPort, state);
+        retVal = mv_switch_set_mac_learn(lPort, state);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -3218,8 +3702,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
+    bool             mac_learn_enable = false;
 
     if (trace_sw_dbg_flag)
     {
@@ -3228,14 +3712,34 @@
                __FUNCTION__,owner_id, src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            retVal = mv_mac_learn_enable_get(&mac_learn_enable);
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) src port(%d) MAC learn not supported\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_GENERAL;
+        }
+        if(mac_learn_enable)
+            state = GT_TRUE;
+        else
+            state = GT_FALSE;
+#endif
+    } else {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_get_mac_learn(lPort, &state);
+        retVal = mv_switch_get_mac_learn(lPort, &state);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -4302,8 +4806,7 @@
                                              tpm_src_port_type_t *extern_port)
 {
     tpm_error_code_t retVal = TPM_RC_OK;
-
-    SWITCH_INIT_CHECK();
+    tpm_init_gmac_conn_conf_t gmac_conn_info;
 
     if (trace_sw_dbg_flag)
     {
@@ -4312,8 +4815,19 @@
                __FUNCTION__, owner_id, switch_port);
     }
 
-    *extern_port = tpm_db_phy_convert_port_index(switch_port);
-    if (*extern_port == TPM_DB_ERR_PORT_NUM)
+    if (tpm_sw_init_check()) {
+        if (tpm_db_gmac_conn_conf_get((tpm_gmacs_enum_t)switch_port, &gmac_conn_info)) {
+            printk(KERN_ERR "ERROR: (%s:%d) switch_port(%d) invalid\n", __FUNCTION__, __LINE__, switch_port);
+            return ERR_GENERAL;
+        }
+        if (TPM_TRUE == gmac_conn_info.valid)
+            *extern_port = gmac_conn_info.port_src;
+        else
+            *extern_port = TPM_DB_ERR_PORT_NUM;
+    } else {
+        *extern_port = tpm_db_phy_convert_port_index(switch_port);
+    }
+    if (*extern_port == (tpm_src_port_type_t)TPM_DB_ERR_PORT_NUM)
     {
         printk(KERN_ERR "ERROR: (%s:%d) switch_port(%d) is invalid\n", __FUNCTION__, __LINE__, switch_port);
         return ERR_SRC_PORT_INVALID;
@@ -4374,8 +4888,12 @@
     int32_t          lPort  = 0;
     GT_BOOL  state, prev_state;
     GT_PHY_AUTO_MODE prev_mode;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    uint16_t         lsp_mode = PHY_AUTO_NEGO_MODE_HALF_10 |
+                                PHY_AUTO_NEGO_MODE_FULL_10 |
+                                PHY_AUTO_NEGO_MODE_HALF_100 |
+                                PHY_AUTO_NEGO_MODE_FULL_100;
 
     if (trace_sw_dbg_flag)
     {
@@ -4389,26 +4907,102 @@
     else
         state = GT_FALSE;
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    switch (autoneg_mode) {
+    case TPM_SPEED_AUTO_DUPLEX_AUTO:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_10 |
+                   PHY_AUTO_NEGO_MODE_FULL_10 |
+                   PHY_AUTO_NEGO_MODE_HALF_100 |
+                   PHY_AUTO_NEGO_MODE_FULL_100 |
+                   PHY_AUTO_NEGO_MODE_HALF_1000 |
+                   PHY_AUTO_NEGO_MODE_FULL_1000;
+        break;
+    case TPM_SPEED_1000_DUPLEX_AUTO:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_1000 |
+                   PHY_AUTO_NEGO_MODE_FULL_1000;
+        break;
+    case TPM_SPEED_100_DUPLEX_AUTO:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_100 |
+                   PHY_AUTO_NEGO_MODE_HALF_100;
+        break;
+    case TPM_SPEED_10_DUPLEX_AUTO:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_10 |
+                   PHY_AUTO_NEGO_MODE_HALF_10;
+        break;
+    case TPM_SPEED_AUTO_DUPLEX_FULL:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_10 |
+		   PHY_AUTO_NEGO_MODE_FULL_100 |
+		    PHY_AUTO_NEGO_MODE_FULL_1000;
+        break;
+    case TPM_SPEED_AUTO_DUPLEX_HALF:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_1000 |
+                   PHY_AUTO_NEGO_MODE_HALF_100 |
+                   PHY_AUTO_NEGO_MODE_HALF_10;
+        break;
+    case TPM_SPEED_1000_DUPLEX_FULL:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_1000;
+        break;
+    case TPM_SPEED_1000_DUPLEX_HALF:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_1000;
+        break;
+    case TPM_SPEED_100_DUPLEX_FULL:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_100;
+        break;
+    case TPM_SPEED_100_DUPLEX_HALF:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_100;
+        break;
+    case TPM_SPEED_10_DUPLEX_FULL:
+        lsp_mode = PHY_AUTO_NEGO_MODE_FULL_10;
+        break;
+    case TPM_SPEED_10_DUPLEX_HALF:
+        lsp_mode = PHY_AUTO_NEGO_MODE_HALF_10;
+        break;
+    default:
+        printk(KERN_ERR "ERROR: (%s:%d) invalid autoneg_mode\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
     }
-
-    if (TPM_RC_OK == (retVal = mv_switch_get_port_autoneg_mode(lPort, &prev_state, &prev_mode)))
-    {
-        if (prev_state != state || prev_mode != (GT_PHY_AUTO_MODE)autoneg_mode)
-        {
-            retVal = mv_switch_set_port_autoneg_mode(lPort, state, (GT_PHY_AUTO_MODE)autoneg_mode);
-            if (retVal != TPM_RC_OK)
-            {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
+        printk(KERN_ERR
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyAutoNegoSet(phy_direct_addr, state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+        if (state && (retVal == TPM_RC_OK)) {
+            if (mvEthPhyAdvertiseSet(phy_direct_addr, lsp_mode)) {
                 printk(KERN_ERR
-                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        if (TPM_RC_OK == (retVal = mv_switch_get_port_autoneg_mode(lPort, &prev_state, &prev_mode)))
+        {
+            if (prev_state != state || prev_mode != (GT_PHY_AUTO_MODE)autoneg_mode)
+            {
+                retVal = mv_switch_set_port_autoneg_mode(lPort, state, (GT_PHY_AUTO_MODE)autoneg_mode);
+                if (retVal != TPM_RC_OK)
+                {
+                    printk(KERN_ERR
+                           "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                }
             }
         }
     }
-
     if (trace_sw_dbg_flag)
     {
         printk(KERN_INFO
@@ -4465,8 +5059,9 @@
     int32_t          lPort  = 0;
     GT_BOOL          state;
     GT_PHY_AUTO_MODE mode;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    uint16_t         lsp_mode;
 
     if (trace_sw_dbg_flag)
     {
@@ -4475,18 +5070,97 @@
                __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_autoneg_mode(lPort, &state, &mode);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyAutoNegoGet(phy_direct_addr, (int *)&state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+        if (state && (retVal == TPM_RC_OK)) {
+            if (mvEthPhyAdvertiseGet(phy_direct_addr, &lsp_mode)) {
+                printk(KERN_ERR
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+            switch (lsp_mode) {
+            case (PHY_AUTO_NEGO_MODE_HALF_10 |
+                  PHY_AUTO_NEGO_MODE_FULL_10 |
+                  PHY_AUTO_NEGO_MODE_HALF_100 |
+                  PHY_AUTO_NEGO_MODE_FULL_100 |
+                  PHY_AUTO_NEGO_MODE_HALF_1000 |
+                  PHY_AUTO_NEGO_MODE_FULL_1000):
+                mode = TPM_SPEED_AUTO_DUPLEX_AUTO;
+                break;
+            case (PHY_AUTO_NEGO_MODE_HALF_1000 |
+                  PHY_AUTO_NEGO_MODE_FULL_1000):
+                mode = TPM_SPEED_1000_DUPLEX_AUTO;
+                break;
+            case (PHY_AUTO_NEGO_MODE_FULL_100 |
+                  PHY_AUTO_NEGO_MODE_HALF_100):
+                mode = TPM_SPEED_100_DUPLEX_AUTO;
+                break;
+            case (PHY_AUTO_NEGO_MODE_FULL_10 |
+                  PHY_AUTO_NEGO_MODE_HALF_10):
+                mode = TPM_SPEED_10_DUPLEX_AUTO;
+                break;
+            case (PHY_AUTO_NEGO_MODE_FULL_10 |
+                  PHY_AUTO_NEGO_MODE_FULL_100 |
+                  PHY_AUTO_NEGO_MODE_FULL_1000):
+                mode = TPM_SPEED_AUTO_DUPLEX_FULL;
+                break;
+            case (PHY_AUTO_NEGO_MODE_HALF_1000 |
+                  PHY_AUTO_NEGO_MODE_HALF_100 |
+                  PHY_AUTO_NEGO_MODE_HALF_10):
+                mode = TPM_SPEED_AUTO_DUPLEX_HALF;
+                break;
+            case PHY_AUTO_NEGO_MODE_FULL_1000:
+                mode = TPM_SPEED_1000_DUPLEX_FULL;
+                break;
+            case PHY_AUTO_NEGO_MODE_HALF_1000:
+                mode = TPM_SPEED_1000_DUPLEX_HALF;
+                break;
+            case PHY_AUTO_NEGO_MODE_FULL_100:
+                mode = TPM_SPEED_100_DUPLEX_FULL;
+                break;
+            case PHY_AUTO_NEGO_MODE_HALF_100:
+                mode = TPM_SPEED_100_DUPLEX_HALF;
+                break;
+            case PHY_AUTO_NEGO_MODE_FULL_10:
+                mode = TPM_SPEED_10_DUPLEX_FULL;
+                break;
+            case PHY_AUTO_NEGO_MODE_HALF_10:
+                mode = TPM_SPEED_10_DUPLEX_HALF;
+                break;
+            default:
+                mode = TPM_SPEED_AUTO_DUPLEX_AUTO;
+                break;
+            }
+        } else {
+            mode = TPM_SPEED_AUTO_DUPLEX_AUTO;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_port_autoneg_mode(lPort, &state, &mode);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(GT_TRUE == state)
@@ -4510,6 +5184,8 @@
 *
 * DESCRIPTION:
 *       The API restart the auto negotiation of an Ethernet  UNI port.
+*	If AutoNegotiation is not enabled, it'll enable it.
+*	Loopback and Power Down will be disabled by this routine.
 * INPUTS:
 *       owner_id    - APP owner id  should be used for all API calls.
 *       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
@@ -4535,8 +5211,9 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    
 
     if (trace_sw_dbg_flag)
     {
@@ -4545,18 +5222,35 @@
                __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_restart_port_autoneg(lPort);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyRestartAN(phy_direct_addr, 0)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_restart_port_autoneg(lPort);
+        if (retVal != TPM_RC_OK)
+        {
+             printk(KERN_ERR
+                    "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if (trace_sw_dbg_flag)
@@ -4601,8 +5295,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL  state, prev_state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -4616,22 +5310,39 @@
     else
         state = GT_FALSE;
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
+        printk(KERN_ERR
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
     }
-
-    if (TPM_RC_OK == (retVal = mv_switch_get_phy_port_state(lPort, &prev_state)))
-    {
-        if (prev_state != state)
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhySetAdminState(phy_direct_addr, (int)state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
         {
-            retVal = mv_switch_set_phy_port_state(lPort, state);
-            if (retVal != TPM_RC_OK)
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        if (TPM_RC_OK == (retVal = mv_switch_get_phy_port_state(lPort, &prev_state)))
+        {
+            if (prev_state != state)
             {
-                printk(KERN_ERR
-                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                retVal = mv_switch_set_phy_port_state(lPort, state);
+                if (retVal != TPM_RC_OK)
+                {
+                    printk(KERN_ERR
+                           "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                }
             }
         }
     }
@@ -4677,8 +5388,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -4686,19 +5397,35 @@
                "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
                __FUNCTION__,owner_id,src_port);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_phy_port_state(lPort, &state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyGetAdminState(phy_direct_addr, (int *)&state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_phy_port_state(lPort, &state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(state == GT_TRUE)
@@ -4747,8 +5474,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -4756,19 +5483,31 @@
                "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
                __FUNCTION__,owner_id,src_port);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_link_status(lPort, &state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        state = (GT_BOOL)mvEthPhyCheckLink(phy_direct_addr);
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_port_link_status(lPort, &state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(state == GT_TRUE)
@@ -4804,7 +5543,11 @@
 *       On error different types are returned according to the case, see tpm_error_code_t.
 *
 * COMMENTS:
-*
+* This function is different from tpm_phy_get_port_duplex_mode, it reflects the real duplex status happening
+* in PHY now. If there is a switch, through PPU function, switch can get the duplex info from PHY and
+* store it in switch port register, so duplex info can be got from switch port register. It is a
+* "get_xxx_oper" function. If there is no switch, this info can be read from PHY spec status register,
+* offset 17
 *
 *******************************************************************************/
 tpm_error_code_t tpm_phy_get_port_duplex_status
@@ -4816,9 +5559,9 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-    GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    GT_BOOL          state, status_valid;
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -4826,19 +5569,41 @@
                "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
                __FUNCTION__,owner_id,src_port);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_duplex_status(lPort, &state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyDuplexOperGet(phy_direct_addr, (int *)&status_valid, (int *)&state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+
+        if (status_valid == GT_FALSE) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY duplex status is not valid on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_STATUS_UNKNOWN;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_port_duplex_status(lPort, &state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(state == GT_TRUE)
@@ -4875,8 +5640,11 @@
 *       On error different types are returned according to the case, see tpm_error_code_t.
 *
 * COMMENTS:
-*
-*
+* This function is different from "tpm_phy_get_port_speed ", it reflects what really happens
+* in PHY. If there is a switch, this function will get the stats info from switch register,
+* because the PPU function will make the switch get the PHY status info and store it in port
+* register. If there is no switch, speed mode info can be got from PHY register spec status
+* register, offset is 17.
 *******************************************************************************/
 tpm_error_code_t tpm_phy_get_port_speed_mode
 (
@@ -4888,8 +5656,8 @@
     tpm_error_code_t   retVal = TPM_RC_OK;
     int32_t            lPort  = 0;
     GT_PORT_SPEED_MODE tmpSpeed;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t     phy_access_way;
+    uint32_t           phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -4897,19 +5665,41 @@
                "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
                __FUNCTION__,owner_id,src_port);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_speed_mode(lPort, &tmpSpeed);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhySpeedOperGet(phy_direct_addr, (uint32_t *)&tmpSpeed)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+
+        if (tmpSpeed == PORT_SPEED_UNKNOWN) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY speed status is not valid on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_STATUS_UNKNOWN;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_port_speed_mode(lPort, &tmpSpeed);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     *speed = (uint32_t)tmpSpeed;
@@ -4943,7 +5733,8 @@
 *       On success - TPM_RC_OK.
 *       On error different types are returned according to the case - see tpm_error_code_t.
 * COMMENTS:
-* data sheet register 4.10 Autonegotiation Advertisement Register
+* This function reflect flow control configuration info, it only access PHY register,
+* that is data sheet register 4.10 Autonegotiation Advertisement Register.
 *******************************************************************************/
 
 tpm_error_code_t tpm_phy_set_port_flow_control_support
@@ -4956,8 +5747,10 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_PHY_PAUSE_MODE pause_state, prev_state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    uint32_t         switch_init;
+    tpm_gmacs_enum_t gmac_port;
 
     if (trace_sw_dbg_flag)
     {
@@ -4971,33 +5764,100 @@
     else
         pause_state = GT_PHY_NO_PAUSE;
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
+        printk(KERN_ERR
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
     }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (tpm_db_switch_init_get(&switch_init) != TPM_DB_OK) {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_db_switch_init_get Failed\n", __FUNCTION__, __LINE__);
+            retVal = ERR_GENERAL;
+            return retVal;
+        }
+        /* Only PHY connected to GMAC, need write GMAC register */
+        if (!switch_init) {
+            for (gmac_port = TPM_ENUM_GMAC_0; gmac_port < TPM_MAX_NUM_GMACS; gmac_port++) {
+                if (phy_direct_addr == mvBoardPhyAddrGet(gmac_port))
+                break;
+            }
+            if (gmac_port == TPM_MAX_NUM_GMACS) {
+                printk(KERN_ERR "ERROR: (%s:%d) Can not find gmac port\n", __FUNCTION__, __LINE__);
+                retVal = ERR_GENERAL;
+                return retVal;
+            }
 
-    if (TPM_RC_OK == (retVal = mv_switch_get_port_pause(lPort, &prev_state)))
-    {
-        if (prev_state != pause_state)
-        {
-            retVal = mv_switch_set_port_pause(lPort, pause_state);
-            if (retVal != TPM_RC_OK)
+            /* Write Flow Control reg on GMAC port */
+            switch(pause_state) {
+            case GT_PHY_NO_PAUSE:
+                if (mvNetaFlowCtrlSet((int)gmac_port, MV_ETH_FC_DISABLE) != MV_OK) {
+                    printk(KERN_ERR "ERROR: (%s:%d) mvNetaFlowCtrlSet Failed\n", __FUNCTION__, __LINE__);
+                    retVal = ERR_GENERAL;
+                    return retVal;
+                }
+                break;
+            case GT_PHY_PAUSE:
+                if (mvNetaFlowCtrlSet((int)gmac_port, MV_ETH_FC_ENABLE) != MV_OK) {
+                    printk(KERN_ERR "ERROR: (%s:%d) mvNetaFlowCtrlSet Failed\n", __FUNCTION__, __LINE__);
+                    retVal = ERR_GENERAL;
+                    return retVal;
+                }
+                break;
+            default:
+                printk(KERN_ERR "ERROR: (%s:%d)Invalid flow control mode%d\n", __FUNCTION__, __LINE__, pause_state);
+                retVal = ERR_GENERAL;
+                return retVal;
+            }
+        } else {
+            /* Flow control info can not be got from linkpartner through QSGMII auto negitiation, so manual needed */
+            lPort = tpm_db_eth_port_switch_port_get(src_port);
+            if (lPort == TPM_DB_ERR_PORT_NUM)
             {
-                printk(KERN_ERR
-                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+                return ERR_SRC_PORT_INVALID;
+            }
+            /* Set force FC value */
+            if ((retVal = mv_switch_set_port_forced_fc_value(lPort, state)) != TPM_RC_OK) {
+                printk(KERN_ERR "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                return retVal;
+            }
+            /* Set force FC */
+            if ((retVal = mv_switch_set_port_forced_flow_control(lPort, state)) != TPM_RC_OK) {
+                printk(KERN_ERR "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                return retVal;
+            }
+        }
+        if (mvEthPhyPauseSet(phy_direct_addr, (uint32_t)pause_state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        if (TPM_RC_OK == (retVal = mv_switch_get_port_pause(lPort, &prev_state)))
+        {
+            if (prev_state != pause_state)
+            {
+                retVal = mv_switch_set_port_pause(lPort, pause_state);
+                if (retVal != TPM_RC_OK)
+                {
+                    printk(KERN_ERR
+                           "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                }
             }
         }
     }
 
-    //retVal = mv_switch_restart_port_autoneg(port);
-    // if (retVal != TPM_RC_OK)
-    // {
-    //     printk(KERN_ERR
-    //            "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-    // }
-
     if (trace_sw_dbg_flag)
     {
         printk(KERN_INFO
@@ -5037,8 +5897,8 @@
     tpm_error_code_t  retVal = TPM_RC_OK;
     int32_t           lPort  = 0;
     GT_PHY_PAUSE_MODE pause_state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5046,19 +5906,35 @@
                "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
                __FUNCTION__,owner_id,src_port);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_pause(lPort, &pause_state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyPauseAdminGet(phy_direct_addr, (uint32_t *)&pause_state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_get_port_pause(lPort, &pause_state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(pause_state == GT_PHY_NO_PAUSE)
@@ -5096,7 +5972,11 @@
 *       On success - TPM_RC_OK.
 *       On error different types are returned according to the case, see tpm_error_code_t.
 * COMMENTS:
-*       None.
+* This function is different from function tpm_phy_set_port_flow_control_support(),
+* it reflects the flow control info on MAC of PHY, so this info can only be got from
+* MAC, PHY connected to. If there is a switch, this info can be got from switch port register,
+* if there is no switch connected to PHY, this info can be got from the MAC connected to it,
+* such as GMAC0.
 *******************************************************************************/
 tpm_error_code_t tpm_phy_get_port_flow_control_state
 (
@@ -5108,8 +5988,11 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          fc_state;
-
-    SWITCH_INIT_CHECK();
+    uint32_t         switch_init;
+    tpm_gmacs_enum_t gmac_port;
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    uint32_t         fc_mode;
 
     if (trace_sw_dbg_flag)
     {
@@ -5118,25 +6001,61 @@
                __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* Check swicth init or not */
+    if (tpm_db_switch_init_get(&switch_init) != TPM_DB_OK) {
+        printk(KERN_ERR "ERROR: (%s:%d) tpm_db_switch_init_get failed\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
     }
+    if (switch_init) {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    retVal = mv_switch_get_port_pause_state(lPort, &fc_state);
-    if (retVal != TPM_RC_OK)
-    {
-        printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        retVal = mv_switch_get_port_pause_state(lPort, &fc_state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        if(fc_state == GT_FALSE)
+            *state = false;
+        else
+            *state = true;
+    } else {
+        /* check PHY access way */
+        retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+        if (retVal != TPM_RC_OK) {
+            printk(KERN_ERR
+                   "Port%d PHY access way check failed\n", src_port);
+            return retVal;
+        }
+        for (gmac_port = TPM_ENUM_GMAC_0; gmac_port < TPM_MAX_NUM_GMACS; gmac_port++) {
+            if (phy_direct_addr == mvBoardPhyAddrGet(gmac_port))
+                break;
+        }
+        if (gmac_port == TPM_MAX_NUM_GMACS) {
+            printk(KERN_ERR "ERROR: (%s:%d) Can not find gmac port\n", __FUNCTION__, __LINE__);
+            retVal = ERR_GENERAL;
+            return retVal;
+        }
+
+        /* Get GMAC Flow Control state */
+        if (mvNetaFlowCtrlGet((int)gmac_port, &fc_mode) != MV_OK) {
+            printk(KERN_ERR "ERROR: (%s:%d) Can not find gmac port\n", __FUNCTION__, __LINE__);
+            retVal = ERR_GENERAL;
+            return retVal;
+        }
+
+        if (fc_mode == MV_ETH_FC_DISABLE)
+            *state = false;
+        else
+            *state = true;
     }
 
-    if(fc_state == GT_FALSE)
-        *state = false;
-    else
-        *state = true;
-
     if (trace_sw_dbg_flag)
     {
         printk(KERN_INFO
@@ -5179,8 +6098,10 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state, link_forced;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    uint32_t         switch_init;
+    uint32_t         gmac_idx;
 
     if (trace_sw_dbg_flag)
     {
@@ -5197,25 +6118,40 @@
     {
         state = GT_FALSE;
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
+        printk(KERN_ERR
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
     }
-
-    switch((GT_PHY_LOOPBACK_MODE)mode)
-    {
-        case PHY_INTERNAL_LOOPBACK:
-            if (lPort == INT_GE_PHY_SWITCH_PORT)
-            {
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (PHY_INTERNAL_LOOPBACK == (GT_PHY_LOOPBACK_MODE)mode) {
+            if (mvEthPhyLoopbackSet(phy_direct_addr, state)) {
+                printk(KERN_ERR
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+            /* Force switch port link up if QSGMII mode with switch */
+            retVal = tpm_db_switch_init_get(&switch_init);
+            if (retVal) {
+                printk(KERN_ERR "ERROR: (%s:%d)switch init get failed\n", __FUNCTION__, __LINE__);
+                return retVal;
+            }
+            if (switch_init) {
+                lPort = tpm_db_eth_port_switch_port_get(src_port);
+                if (lPort == TPM_DB_ERR_PORT_NUM)
+                {
+                    printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+                    return ERR_SRC_PORT_INVALID;
+                }
                 retVal = mv_switch_get_port_forced_link(lPort, &link_forced);
                 if (retVal != TPM_RC_OK)
                 {
                     printk(KERN_ERR
                            "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-                    break;
+                    return retVal;
                 }
                 if (((state == GT_TRUE) && (link_forced == GT_FALSE)) ||
                     ((state == GT_FALSE)&& (link_forced == GT_TRUE)))
@@ -5225,30 +6161,101 @@
                     {
                         printk(KERN_ERR
                                "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-                        break;
+                        return retVal;
                     }
                     retVal = mv_switch_set_port_link_value(lPort, state);
                     if (retVal != TPM_RC_OK)
                     {
                         printk(KERN_ERR
                                "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-                        break;
+                        return retVal;
                     }
                 }
+            } else {
+                /* get GMAC with Phyaddr */
+                for (gmac_idx = TPM_ENUM_GMAC_0; gmac_idx < TPM_MAX_NUM_GMACS; gmac_idx++) {
+                    if (phy_direct_addr == mvBoardPhyAddrGet(gmac_idx))
+                        break;
+                }
+                if (gmac_idx == TPM_MAX_NUM_GMACS) {
+                    printk(KERN_ERR
+                           "%s:%d: GMAC get with phyaddr invalid\r\n", __FUNCTION__,__LINE__);
+                    retVal = ERR_GENERAL;
+                    return retVal;
+                }
+                /* Force gmac link or disable it */
+                if (mvNetaForceLinkModeSet(gmac_idx, state, 0)) {
+                    printk(KERN_ERR
+                           "%s:%d: GMAC force link set failed\r\n", __FUNCTION__,__LINE__);
+                    retVal = ERR_GENERAL;
+                    return retVal;
+                }
             }
-            retVal = mv_switch_set_port_loopback(lPort, state);
-            break;
-        case PHY_EXTERNAL_LOOPBACK:
-            retVal = mv_switch_set_port_line_loopback(lPort, state);
-            break;
-        default:
-            break;
+        } else if (PHY_EXTERNAL_LOOPBACK == (GT_PHY_LOOPBACK_MODE)mode) {
+            if (mvEthPhyLineLoopbackSet(phy_direct_addr, state)) {
+                printk(KERN_ERR
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+        } else {
+            printk(KERN_INFO
+                   "==ENTER==%s: mode[%d] invalid\n\r", __FUNCTION__,mode);
+            retVal = ERR_GENERAL;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    }
-    if (retVal != TPM_RC_OK)
-    {
-        printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        switch((GT_PHY_LOOPBACK_MODE)mode)
+        {
+            case PHY_INTERNAL_LOOPBACK:
+                if (lPort == INT_GE_PHY_SWITCH_PORT)
+                {
+                    retVal = mv_switch_get_port_forced_link(lPort, &link_forced);
+                    if (retVal != TPM_RC_OK)
+                    {
+                        printk(KERN_ERR
+                               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                        break;
+                    }
+                    if (((state == GT_TRUE) && (link_forced == GT_FALSE)) ||
+                        ((state == GT_FALSE)&& (link_forced == GT_TRUE)))
+                    {
+                        retVal = mv_switch_set_port_forced_link(lPort, state);
+                        if (retVal != TPM_RC_OK)
+                        {
+                            printk(KERN_ERR
+                                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                            break;
+                        }
+                        retVal = mv_switch_set_port_link_value(lPort, state);
+                        if (retVal != TPM_RC_OK)
+                        {
+                            printk(KERN_ERR
+                                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                            break;
+                        }
+                    }
+                }
+                retVal = mv_switch_set_port_loopback(lPort, state);
+                break;
+            case PHY_EXTERNAL_LOOPBACK:
+                retVal = mv_switch_set_port_line_loopback(lPort, state);
+                break;
+            default:
+                break;
+
+        }
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if (trace_sw_dbg_flag)
@@ -5291,8 +6298,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5300,29 +6307,57 @@
                "==ENTER==%s: owner_id[%d],src_port[%d], mode[%d]\n\r",
                __FUNCTION__,owner_id,src_port, mode);
     }
-
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    switch((GT_PHY_LOOPBACK_MODE)mode)
-    {
-        case PHY_INTERNAL_LOOPBACK:
-           retVal = mv_switch_get_port_loopback(lPort, &state);
-            break;
-        case PHY_EXTERNAL_LOOPBACK:
-            retVal = mv_switch_get_port_line_loopback(lPort, &state);
-            break;
-        default:
-            break;
-    }
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (PHY_INTERNAL_LOOPBACK == (GT_PHY_LOOPBACK_MODE)mode) {
+            if (mvEthPhyLoopbackGet(phy_direct_addr, (int *)&state)) {
+                printk(KERN_ERR
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+        } else if (PHY_EXTERNAL_LOOPBACK == (GT_PHY_LOOPBACK_MODE)mode) {
+            if (mvEthPhyLineLoopbackGet(phy_direct_addr, (int *)&state)) {
+                printk(KERN_ERR
+                       "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+                retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+            }
+        } else {
+            printk(KERN_INFO
+                   "==ENTER==%s: mode[%d] invalid\n\r", __FUNCTION__,mode);
+            retVal = ERR_GENERAL;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        switch((GT_PHY_LOOPBACK_MODE)mode)
+        {
+            case PHY_INTERNAL_LOOPBACK:
+                retVal = mv_switch_get_port_loopback(lPort, &state);
+                break;
+            case PHY_EXTERNAL_LOOPBACK:
+                retVal = mv_switch_get_port_line_loopback(lPort, &state);
+                break;
+            default:
+                break;
+        }
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if(state == GT_TRUE)
@@ -5377,8 +6412,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5396,18 +6431,35 @@
         state = GT_FALSE;
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_set_port_duplex_mode(lPort, state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyDuplexModeSet(phy_direct_addr, state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_set_port_duplex_mode(lPort, state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if (trace_sw_dbg_flag)
@@ -5438,7 +6490,8 @@
 *       On error different types are returned according to the case , see tpm_error_code_t.
 *
 * COMMENTS:
-*         data sheet register 0.8 - Duplex Mode
+*         This function will get the duplex configuration info just from PHY's control register
+* that is data sheet register 0.8 - Duplex Mode. It is a "get_xxx_admin" function.
 *
 *******************************************************************************/
 tpm_error_code_t tpm_phy_get_port_duplex_mode
@@ -5451,8 +6504,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_BOOL          state;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5461,27 +6514,43 @@
                __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_duplex_mode(lPort, &state);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
     }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhyDuplexModeAdminGet(phy_direct_addr, (int *)&state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    if (trace_sw_dbg_flag)
-    {
-        printk(KERN_INFO
-                "==EXIT== %s:enable[%d]\n\r",__FUNCTION__,  *enable);
+        retVal = mv_switch_get_port_duplex_mode(lPort, &state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        if (trace_sw_dbg_flag)
+        {
+            printk(KERN_INFO
+                    "==EXIT== %s:enable[%d]\n\r",__FUNCTION__,  *enable);
+        }
     }
 
-
     if(state == GT_TRUE)
     {
         *enable = true;
@@ -5527,8 +6596,8 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5537,18 +6606,35 @@
                __FUNCTION__,owner_id,src_port, (uint32_t)speed);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_set_port_speed(lPort, (GT_PHY_SPEED)speed);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhySpeedSet(phy_direct_addr, speed)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_set_port_speed(lPort, (GT_PHY_SPEED)speed);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
     }
 
     if (trace_sw_dbg_flag)
@@ -5581,6 +6667,8 @@
 *       On success - TPM_RC_OK.
 *       On error different types are returned according to the case - see tpm_error_code_t.
 * COMMENTS:
+* This function get the PHY config information from PHY controlregister, it is a
+* "get_xxx_admin" function, it reflect the configuration to PHY and it only access PHY register.
 *
 *******************************************************************************/
 tpm_error_code_t tpm_phy_get_port_speed
@@ -5593,8 +6681,8 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_PHY_SPEED     lSpeed;
-
-    SWITCH_INIT_CHECK();
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
 
     if (trace_sw_dbg_flag)
     {
@@ -5603,21 +6691,38 @@
                __FUNCTION__,owner_id,src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
-
-    retVal = mv_switch_get_port_speed(lPort, &lSpeed);
-    if (retVal != TPM_RC_OK)
-    {
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
         printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
     }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhySpeedAdminGet(phy_direct_addr, speed)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    *speed = (tpm_phy_speed_t)lSpeed;
+        retVal = mv_switch_get_port_speed(lPort, &lSpeed);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        *speed = (tpm_phy_speed_t)lSpeed;
+    }
 
     if (trace_sw_dbg_flag)
     {
@@ -5658,9 +6763,9 @@
     void
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = TPM_RC_OK;
+    tpm_gmacs_enum_t gmac_i;
+    tpm_db_gmac_func_t gfunc;
 
     if (trace_sw_dbg_flag)
     {
@@ -5668,7 +6773,17 @@
                 "==ENTER==%s:\n\r",__FUNCTION__);
     }
 
-    retVal = mv_switch_clear_port_counters();
+    if (tpm_sw_init_check()) {
+        for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+            tpm_db_gmac_func_get(gmac_i, &gfunc);
+            if (gfunc == TPM_GMAC_FUNC_LAN_UNI ||
+                gfunc == TPM_GMAC_FUNC_US_MAC_LEARN_DS_LAN_UNI) {
+                MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(gmac_i);
+                mvNetaMibCountersClear(gmac_i, pPortCtrl->txpNum);
+            }
+        }
+    } else
+        retVal = mv_switch_clear_port_counters();
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -5938,8 +7053,7 @@
 )
 {
     tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_gmacs_enum_t gmac_i;
 
     if (trace_sw_dbg_flag)
     {
@@ -5948,7 +7062,14 @@
                 __FUNCTION__,owner_id,lport);
     }
 
-    retVal = mv_switch_print_port_counters(lport);
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(lport, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, lport);
+            return ERR_SRC_PORT_INVALID;
+        }
+        retVal = tpm_sw_pm_print_from_gmac(gmac_i);
+    } else
+        retVal = mv_switch_print_port_counters(lport);
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_INFO
@@ -5994,6 +7115,8 @@
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
+    tpm_gmacs_enum_t gmac_i;
+    MV_NETA_PORT_CTRL *pPortCtrl;
 
     SWITCH_INIT_CHECK();
 
@@ -6003,14 +7126,24 @@
                 "==ENTER==%s:\n\r",__FUNCTION__);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
-    }
+    if (tpm_sw_init_check()) {
+        if (tpm_src_port_mac_map(src_port, &gmac_i)) {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) map to mac failed\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+        pPortCtrl = mvNetaPortHndlGet(gmac_i);
+        mvNetaMibCountersClear(gmac_i, pPortCtrl->txpNum);
+    } else {
 
-    retVal = mv_switch_clean_port_counters(lPort);
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_clean_port_counters(lPort);
+    }
     if (retVal != TPM_RC_OK)
     {
         printk(KERN_ERR
@@ -6027,6 +7160,205 @@
 }
 
 /*******************************************************************************
+* tpm_sw_pm_from_gmac
+*
+*
+* INPUTS:
+*       port        - GMAC port.
+* OUTPUTS:
+*       tpm_swport_pm_1 - Holds PM data1
+*       tpm_swport_pm_3 - Holds PM data all
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_from_gmac(int port,
+				     tpm_swport_pm_1_t   *tpm_swport_pm_1,
+				     tpm_swport_pm_3_all_t *tpm_swport_pm_3)
+{
+    uint32_t         regVaLo, regValHi = 0;
+    int32_t          mib = 0;
+
+    /* Check Input */
+    if (tpm_swport_pm_1 == NULL || tpm_swport_pm_3 == NULL) {
+        printk(KERN_ERR "ERROR: (%s:%d) Invalid Input\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
+    }
+
+    /* Check GMAC Port */
+    if (mvNetaTxpCheck(port, mib)) {
+        printk(KERN_ERR "ERROR: (%s:%d) mvNetaTxpCheck failed\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
+    }
+    if (!mvNetaPortHndlGet(port)) {
+        printk(KERN_ERR "ERROR: (%s:%d) mvNetaPortHndlGet failed\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
+    }
+
+    /* Initialize tpm_swport_pm_3 as Zero */
+    memset(tpm_swport_pm_1, 0, sizeof(tpm_swport_pm_1_t));
+    memset(tpm_swport_pm_3, 0, sizeof(tpm_swport_pm_3_all_t));
+
+    /* Read counter */
+    tpm_swport_pm_3->dropEvents = MV_REG_READ(ETH_RX_DISCARD_PKTS_CNTR_REG(port));
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, &regValHi);
+    tpm_swport_pm_3->InGoodOctetsLo = regVaLo;
+    tpm_swport_pm_3->InGoodOctetsHi = regValHi;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_BAD_OCTETS_RECEIVED, &regValHi);
+    tpm_swport_pm_3->InBadOctets = regVaLo;
+
+    tpm_swport_pm_3->Deferred = MV_REG_READ(ETH_RX_OVERRUN_PKTS_CNTR_REG(port));
+    tpm_swport_pm_1->deferredTransmissionCounter = tpm_swport_pm_3->Deferred;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_BROADCAST_FRAMES_RECEIVED, &regValHi);
+    tpm_swport_pm_3->InBroadcasts = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_MULTICAST_FRAMES_RECEIVED, &regValHi);
+    tpm_swport_pm_3->InMulticasts = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_64_OCTETS, &regValHi);
+    tpm_swport_pm_3->Octets64 = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_65_TO_127_OCTETS, &regValHi);
+    tpm_swport_pm_3->Octets127 = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_128_TO_255_OCTETS, &regValHi);
+    tpm_swport_pm_3->Octets255 = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_256_TO_511_OCTETS, &regValHi);
+    tpm_swport_pm_3->Octets511 = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_512_TO_1023_OCTETS, &regValHi);
+    tpm_swport_pm_3->Octets1023 = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAMES_1024_TO_MAX_OCTETS, &regValHi);
+    tpm_swport_pm_3->OctetsMax = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_GOOD_OCTETS_SENT_LOW, &regValHi);
+    tpm_swport_pm_3->OutOctetsLo = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_GOOD_OCTETS_SENT_HIGH, &regValHi);
+    tpm_swport_pm_3->OutOctetsHi = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_EXCESSIVE_COLLISION, &regValHi);
+    tpm_swport_pm_1->excessiveCollisionCounter = regVaLo;
+    tpm_swport_pm_3->Excessive = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_MULTICAST_FRAMES_SENT, &regValHi);
+    tpm_swport_pm_3->OutMulticasts = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_BROADCAST_FRAMES_SENT, &regValHi);
+    tpm_swport_pm_3->OutBroadcasts = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FC_SENT, &regValHi);
+    tpm_swport_pm_3->OutPause = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_GOOD_FC_RECEIVED, &regValHi);
+    tpm_swport_pm_3->InPause = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_UNDERSIZE_RECEIVED, &regValHi);
+    tpm_swport_pm_3->Undersize = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_FRAGMENTS_RECEIVED, &regValHi);
+    tpm_swport_pm_3->Fragments = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_OVERSIZE_RECEIVED, &regValHi);
+    tpm_swport_pm_1->frameTooLongs = regVaLo;
+    tpm_swport_pm_3->Oversize = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_JABBER_RECEIVED, &regValHi);
+    tpm_swport_pm_3->Jabber = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_MAC_RECEIVE_ERROR, &regValHi);
+    tpm_swport_pm_3->InMACRcvErr = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_BAD_CRC_EVENT, &regValHi);
+    tpm_swport_pm_3->InFCSErr = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_COLLISION, &regValHi);
+    tpm_swport_pm_3->Collisions = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_LATE_COLLISION, &regValHi);
+    tpm_swport_pm_3->Late = regVaLo;
+
+    regVaLo = mvNetaMibCounterRead(port, mib, ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR, &regValHi);
+    tpm_swport_pm_1->internalMacTransmitErrorCounter = regVaLo;
+
+    return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_sw_pm_print_from_gmac
+*
+*
+* INPUTS:
+*       port        - GMAC port.
+* OUTPUTS:
+*       tpm_swport_pm_1 - Holds PM data1
+*       tpm_swport_pm_3 - Holds PM data all
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_print_from_gmac(int port)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    tpm_swport_pm_3_all_t tpm_swport_pm_3;
+    tpm_swport_pm_1_t     tpm_swport_pm_1;
+    MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+
+    retVal = tpm_sw_pm_from_gmac(port, &tpm_swport_pm_1, &tpm_swport_pm_3);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        return retVal;
+    }
+    printk("=======Counters from port[%d]=======\n",port);
+    printk("InGoodOctetsLo  %08d    ", tpm_swport_pm_3.InGoodOctetsLo);
+    printk("InGoodOctetsHi  %08d   \n", tpm_swport_pm_3.InGoodOctetsHi);
+    printk("InBadOctets     %08d    ", tpm_swport_pm_3.InBadOctets);
+    printk("OutFCSErr       %08d   \n", tpm_swport_pm_3.OutFCSErr);
+    printk("InUnicasts      %08d    ", tpm_swport_pm_3.InUnicasts);
+    printk("Deferred        %08d   \n", tpm_swport_pm_3.Deferred);
+    printk("InBroadcasts    %08d    ", tpm_swport_pm_3.InBroadcasts);
+    printk("InMulticasts    %08d   \n", tpm_swport_pm_3.InMulticasts);
+    printk("64Octets        %08d    ", tpm_swport_pm_3.Octets64);
+    printk("127Octets       %08d   \n", tpm_swport_pm_3.Octets127);
+    printk("255Octets       %08d    ", tpm_swport_pm_3.Octets255);
+    printk("511Octets       %08d   \n", tpm_swport_pm_3.Octets511);
+    printk("1023Octets      %08d    ", tpm_swport_pm_3.Octets1023);
+    printk("MaxOctets       %08d   \n", tpm_swport_pm_3.OctetsMax);
+    printk("OutOctetsLo     %08d    ", tpm_swport_pm_3.OutOctetsLo);
+    printk("OutOctetsHi     %08d   \n", tpm_swport_pm_3.OutOctetsHi);
+    printk("OutUnicasts     %08d    ", tpm_swport_pm_3.OutUnicasts);
+    printk("Excessive       %08d   \n", tpm_swport_pm_3.Excessive);
+    printk("OutMulticasts   %08d    ", tpm_swport_pm_3.OutMulticasts);
+    printk("OutBroadcasts   %08d   \n", tpm_swport_pm_3.OutBroadcasts);
+    printk("Single          %08d    ", tpm_swport_pm_3.Single);
+    printk("OutPause        %08d   \n", tpm_swport_pm_3.OutPause);
+    printk("InPause         %08d    ", tpm_swport_pm_3.InPause);
+    printk("Multiple        %08d   \n", tpm_swport_pm_3.Multiple);
+    printk("Undersize       %08d    ", tpm_swport_pm_3.Undersize);
+    printk("Fragments       %08d   \n", tpm_swport_pm_3.Fragments);
+    printk("Oversize        %08d    ", tpm_swport_pm_3.Oversize);
+    printk("Jabber          %08d   \n", tpm_swport_pm_3.Jabber);
+    printk("InMACRcvErr     %08d    ", tpm_swport_pm_3.InMACRcvErr);
+    printk("InFCSErr        %08d   \n", tpm_swport_pm_3.InFCSErr);
+    printk("Collisions      %08d    ", tpm_swport_pm_3.Collisions);
+    printk("Late            %08d   \n", tpm_swport_pm_3.Late);
+
+    /* Flush all counters */
+    mvNetaMibCountersClear(port, pPortCtrl->txpNum);
+
+    return retVal;
+}
+
+/*******************************************************************************
 * tpm_sw_pm_1_read
 *
 *
@@ -6052,8 +7384,11 @@
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_STATS_COUNTER_SET3 statsCounterSet;
-
-    SWITCH_INIT_CHECK();
+    uint32_t         switch_init;
+    tpm_gmacs_enum_t gmac_port;
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    tpm_swport_pm_3_all_t tpm_swport_pm_3;
 
     if (trace_sw_dbg_flag)
     {
@@ -6062,34 +7397,65 @@
                __FUNCTION__,owner_id, src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* Check swicth init or not */
+    if (tpm_db_switch_init_get(&switch_init) != TPM_DB_OK) {
+        printk(KERN_ERR "ERROR: (%s:%d) tpm_db_switch_init_get failed\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
     }
 
-    retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
-    if (retVal != TPM_RC_OK)
-    {
-        printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-    }
+    if (switch_init) {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    tpm_swport_pm_1->fcsErrors                       = statsCounterSet.InFCSErr;
-    tpm_swport_pm_1->excessiveCollisionCounter       = statsCounterSet.Excessive;
-    tpm_swport_pm_1->lateCollisionCounter            = statsCounterSet.Late;
-    tpm_swport_pm_1->frameTooLongs                   = statsCounterSet.Oversize;
-    tpm_swport_pm_1->bufferOverflowsOnReceive        = 0;
-    tpm_swport_pm_1->bufferOverflowsOnTransmit       = 0;
-    tpm_swport_pm_1->singleCollisionFrameCounter     = statsCounterSet.Single;
-    tpm_swport_pm_1->multipleCollisionsFrameCounter  = statsCounterSet.Multiple;
-    tpm_swport_pm_1->sqeCounter                      = 0;
-    tpm_swport_pm_1->deferredTransmissionCounter     = statsCounterSet.Deferred;
-    tpm_swport_pm_1->internalMacTransmitErrorCounter = 0;
-    tpm_swport_pm_1->carrierSenseErrorCounter        = 0;
-    tpm_swport_pm_1->alignmentErrorCounter           = 0;
-    tpm_swport_pm_1->internalMacReceiveErrorCounter  = statsCounterSet.InMACRcvErr;
+        retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        tpm_swport_pm_1->fcsErrors                       = statsCounterSet.InFCSErr;
+        tpm_swport_pm_1->excessiveCollisionCounter       = statsCounterSet.Excessive;
+        tpm_swport_pm_1->lateCollisionCounter            = statsCounterSet.Late;
+        tpm_swport_pm_1->frameTooLongs                   = statsCounterSet.Oversize;
+        tpm_swport_pm_1->bufferOverflowsOnReceive        = 0;
+        tpm_swport_pm_1->bufferOverflowsOnTransmit       = 0;
+        tpm_swport_pm_1->singleCollisionFrameCounter     = statsCounterSet.Single;
+        tpm_swport_pm_1->multipleCollisionsFrameCounter  = statsCounterSet.Multiple;
+        tpm_swport_pm_1->sqeCounter                      = 0;
+        tpm_swport_pm_1->deferredTransmissionCounter     = statsCounterSet.Deferred;
+        tpm_swport_pm_1->internalMacTransmitErrorCounter = 0;
+        tpm_swport_pm_1->carrierSenseErrorCounter        = 0;
+        tpm_swport_pm_1->alignmentErrorCounter           = 0;
+        tpm_swport_pm_1->internalMacReceiveErrorCounter  = statsCounterSet.InMACRcvErr;
+    } else {
+        /* check PHY access way */
+        retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+        if (retVal != TPM_RC_OK) {
+            printk(KERN_ERR
+                   "Port%d PHY access way check failed\n", src_port);
+            return retVal;
+        }
+        for (gmac_port = TPM_ENUM_GMAC_0; gmac_port < TPM_MAX_NUM_GMACS; gmac_port++) {
+            if (phy_direct_addr == mvBoardPhyAddrGet(gmac_port))
+                break;
+        }
+        if (gmac_port == TPM_MAX_NUM_GMACS) {
+            printk(KERN_ERR "ERROR: (%s:%d) Can not find gmac port\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+
+        /* Read counter from GMAC */
+        retVal = tpm_sw_pm_from_gmac((int)gmac_port, tpm_swport_pm_1, &tpm_swport_pm_3);
+        if (retVal != TPM_RC_OK) {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_sw_pm_3_from_gmac failed\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+    }
 
     if (trace_sw_dbg_flag)
     {
@@ -6107,7 +7473,7 @@
 * INPUTS:
 *       owner_id        - APP owner id  should be used for all API calls.
 *       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       tpm_swport_pm_3 - Holds PM data
+*       tpm_swport_pm_3_all_t - Holds PM data
 *
 * OUTPUTS:
 *       PM data is supplied structure.
@@ -6120,14 +7486,18 @@
 (
     uint32_t            owner_id,
     tpm_src_port_type_t src_port,
-    tpm_swport_pm_3_t  *tpm_swport_pm_3
+    tpm_swport_pm_3_all_t *tpm_swport_pm_3
 )
 {
     tpm_error_code_t retVal = TPM_RC_OK;
     int32_t          lPort  = 0;
     GT_STATS_COUNTER_SET3 statsCounterSet;
-
-    SWITCH_INIT_CHECK();
+    GT_PORT_STAT2         ctr;
+    uint32_t         switch_init;
+    tpm_gmacs_enum_t gmac_port;
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    tpm_swport_pm_1_t   tpm_swport_pm_1;
 
     if (trace_sw_dbg_flag)
     {
@@ -6136,34 +7506,95 @@
                __FUNCTION__,owner_id, src_port);
     }
 
-    lPort = tpm_db_eth_port_switch_port_get(src_port);
-    if (lPort == TPM_DB_ERR_PORT_NUM)
-    {
-        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
-        return ERR_SRC_PORT_INVALID;
+    /* Initialize statsCounterSet and ctr as zero */
+    memset(&statsCounterSet, 0, sizeof(GT_STATS_COUNTER_SET3));
+    memset(&ctr, 0, sizeof(GT_PORT_STAT2));
+
+    /* Check swicth init or not */
+    if (tpm_db_switch_init_get(&switch_init) != TPM_DB_OK) {
+        printk(KERN_ERR "ERROR: (%s:%d) tpm_db_switch_init_get failed\n", __FUNCTION__, __LINE__);
+        return ERR_GENERAL;
     }
 
-    retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
-    if (retVal != TPM_RC_OK)
-    {
-        printk(KERN_ERR
-               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
-    }
+    if (switch_init) {
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
 
-    tpm_swport_pm_3->dropEvents              = 0;
-    tpm_swport_pm_3->octets                  = statsCounterSet.InGoodOctetsLo;
-    tpm_swport_pm_3->packets                 = statsCounterSet.InUnicasts;
-    tpm_swport_pm_3->broadcastPackets        = statsCounterSet.InBroadcasts;
-    tpm_swport_pm_3->multicastPackets        = statsCounterSet.InMulticasts;
-    tpm_swport_pm_3->undersizePackets        = 0;
-    tpm_swport_pm_3->fragments               = statsCounterSet.Fragments;
-    tpm_swport_pm_3->jabbers                 = statsCounterSet.Jabber;
-    tpm_swport_pm_3->packets_64Octets        = statsCounterSet.Octets64;
-    tpm_swport_pm_3->packets_65_127Octets    = statsCounterSet.Octets127;
-    tpm_swport_pm_3->packets_128_255Octets   = statsCounterSet.Octets255;
-    tpm_swport_pm_3->packets_256_511Octets   = statsCounterSet.Octets511;
-    tpm_swport_pm_3->packets_512_1023Octets  = statsCounterSet.Octets1023;
-    tpm_swport_pm_3->packets_1024_1518Octets = statsCounterSet.OctetsMax;
+        retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function mv_switch_get_port_counters failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        retVal = mv_switch_get_port_drop_counters(lPort, &ctr);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function mv_switch_get_port_drop_counters failed\r\n", __FUNCTION__,__LINE__);
+        }
+
+        tpm_swport_pm_3->dropEvents	  = (ctr.inDiscardHi<<16) + ctr.inDiscardLo;
+        tpm_swport_pm_3->InGoodOctetsLo   = statsCounterSet.InGoodOctetsLo;
+        tpm_swport_pm_3->InGoodOctetsHi   = statsCounterSet.InGoodOctetsHi;
+        tpm_swport_pm_3->InBadOctets	  = statsCounterSet.InBadOctets;
+        tpm_swport_pm_3->OutFCSErr	  = statsCounterSet.OutFCSErr;
+        tpm_swport_pm_3->InUnicasts	  = statsCounterSet.InUnicasts;
+        tpm_swport_pm_3->Deferred	  = statsCounterSet.Deferred;
+        tpm_swport_pm_3->InBroadcasts	  = statsCounterSet.InBroadcasts;
+        tpm_swport_pm_3->InMulticasts	  = statsCounterSet.InMulticasts;
+        tpm_swport_pm_3->Octets64	  = statsCounterSet.Octets64;
+        tpm_swport_pm_3->Octets127	  = statsCounterSet.Octets127;
+        tpm_swport_pm_3->Octets255	  = statsCounterSet.Octets255;
+        tpm_swport_pm_3->Octets511	  = statsCounterSet.Octets511;
+        tpm_swport_pm_3->Octets1023	  = statsCounterSet.Octets1023;
+        tpm_swport_pm_3->OctetsMax	  = statsCounterSet.OctetsMax;
+        tpm_swport_pm_3->OutOctetsLo	  = statsCounterSet.OutOctetsLo;
+        tpm_swport_pm_3->OutOctetsHi	  = statsCounterSet.OutOctetsHi;
+        tpm_swport_pm_3->OutUnicasts	  = statsCounterSet.OutUnicasts;
+        tpm_swport_pm_3->Excessive	  = statsCounterSet.Excessive;
+        tpm_swport_pm_3->OutMulticasts	  = statsCounterSet.OutMulticasts;
+        tpm_swport_pm_3->OutBroadcasts	  = statsCounterSet.OutBroadcasts;
+        tpm_swport_pm_3->Single 	  = statsCounterSet.Single;
+        tpm_swport_pm_3->OutPause	  = statsCounterSet.OutPause;
+        tpm_swport_pm_3->InPause	  = statsCounterSet.InPause;
+        tpm_swport_pm_3->Multiple	  = statsCounterSet.Multiple;
+        tpm_swport_pm_3->Undersize	  = statsCounterSet.Undersize;
+        tpm_swport_pm_3->Fragments	  = statsCounterSet.Fragments;
+        tpm_swport_pm_3->Oversize	  = statsCounterSet.Oversize;
+        tpm_swport_pm_3->Jabber 	  = statsCounterSet.Jabber;
+        tpm_swport_pm_3->InMACRcvErr	  = statsCounterSet.InMACRcvErr;
+        tpm_swport_pm_3->InFCSErr	  = statsCounterSet.InFCSErr;
+        tpm_swport_pm_3->Collisions	  = statsCounterSet.Collisions;
+        tpm_swport_pm_3->Late		  = statsCounterSet.Late;
+    } else {
+        /* check PHY access way */
+        retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+        if (retVal != TPM_RC_OK) {
+            printk(KERN_ERR
+                   "Port%d PHY access way check failed\n", src_port);
+            return retVal;
+        }
+        for (gmac_port = TPM_ENUM_GMAC_0; gmac_port < TPM_MAX_NUM_GMACS; gmac_port++) {
+            if (phy_direct_addr == mvBoardPhyAddrGet(gmac_port))
+                break;
+        }
+        if (gmac_port == TPM_MAX_NUM_GMACS) {
+            printk(KERN_ERR "ERROR: (%s:%d) Can not find gmac port\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+
+        /* Read counter from GMAC */
+        retVal = tpm_sw_pm_from_gmac((int)gmac_port, &tpm_swport_pm_1, tpm_swport_pm_3);
+        if (retVal != TPM_RC_OK) {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_sw_pm_3_from_gmac failed\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+    }
 
     if (trace_sw_dbg_flag)
     {
@@ -6265,9 +7696,7 @@
      uint16_t db_num
 )
 {
-    tpm_error_code_t retVal;
-
-    SWITCH_INIT_CHECK();
+    tpm_error_code_t retVal = TPM_RC_OK;
 
     if (trace_sw_dbg_flag)
     {
@@ -6276,7 +7705,19 @@
                 __FUNCTION__,owner_id,db_num);
     }
 
-    retVal =  mv_switch_print_fdb(db_num);
+    if (tpm_sw_init_check()) {
+        /* Check GMAC1 lpk status, if no lpk, no way to add static MAC */
+#ifdef CONFIG_MV_MAC_LEARN
+        if (tpm_db_gmac1_lpbk_en_get())
+            mac_learn_db_valid_print();
+        else {
+            printk(KERN_ERR "ERROR: (%s:%d) MAC learn not supported\n", __FUNCTION__, __LINE__);
+            return ERR_GENERAL;
+        }
+#endif
+    } else {
+        retVal =  mv_switch_print_fdb(db_num);
+    }
     if ((retVal != TPM_RC_OK) && (retVal != GT_NO_SUCH))
     {
         printk(KERN_INFO
@@ -6377,6 +7818,176 @@
 }
 
 /*******************************************************************************
+* tpm_phy_set_port_speed_duplex_mode
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed and duplex mode.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       speed       -    PHY_SPEED_10_MBPS   - 10Mbps
+*                        PHY_SPEED_100_MBPS  - 100Mbps
+*                        PHY_SPEED_1000_MBPS - 1000Mbps.
+*       enable      - Enable/Disable full dulpex mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_speed_duplex_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_phy_speed_t     speed,
+    bool                enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    tpm_phy_ctrl_t   phy_access_way;
+    uint32_t         phy_direct_addr;
+    GT_BOOL          state;
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],speed[%d]\n\r",
+               __FUNCTION__,owner_id,src_port, (uint32_t)speed);
+    }
+
+    if(enable == true)
+    {
+        state = GT_TRUE;
+    }
+    else
+    {
+        state = GT_FALSE;
+    }
+
+    /* check PHY access way */
+    retVal = tpm_phy_access_check(src_port, &phy_access_way, &phy_direct_addr);
+    if (retVal != TPM_RC_OK) {
+        printk(KERN_ERR
+               "Port%d PHY access way check failed\n", src_port);
+        return retVal;
+    }
+    /* PHY accessed directly, call lsp API */
+    if (PHY_SMI_MASTER_CPU == phy_access_way) {
+        if (mvEthPhySpeedDuplexModeSet(phy_direct_addr, speed, state)) {
+            printk(KERN_ERR
+                   "ERROR: (%s:%d) PHY LSP API call failed on port(%d)\n", __FUNCTION__, __LINE__, src_port);
+            retVal = ERR_PHY_SRC_PORT_CONN_INVALID;
+        }
+    } else {
+        /* PHY accessed through switch, as original do */
+        lPort = tpm_db_eth_port_switch_port_get(src_port);
+        if (lPort == TPM_DB_ERR_PORT_NUM)
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+            return ERR_SRC_PORT_INVALID;
+        }
+
+        retVal = mv_switch_set_port_speed_duplex_mode(lPort, (GT_PHY_SPEED)speed, state);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per UNI port,
+*       and sets the egress mode for the port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - vlan id
+*       eMode      - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid_set_egrs_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid,
+    uint8_t             eMode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t lPort = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],vid[%d],egress mode[%d]\n",
+               __FUNCTION__,owner_id,src_port,vid,eMode);
+    }
+
+    if (vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+           "%s:%d:==ERROR== invalid VID[%d]\r\n", __FUNCTION__,__LINE__,vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_port_add_vid_set_egrs_mode(lPort, vid, TPM_GMAC0_AMBER_PORT_NUM, eMode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+           "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+            "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
 * tpm_sw_init
 *
 * DESCRIPTION:
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h
index 2026e27..0f6141c 100755
--- a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h
@@ -89,6 +89,35 @@
 
 #define INT_GE_PHY_SWITCH_PORT   (0)
 
+#define SW_TRUNK_ID_MAX          (0xf)
+#define SW_TRUNK_MASK_NUM_MAX    (0x7)
+#define SW_TRUNK_MASK_MAX        (0x7f)
+
+#define SW_TRUNK_ID_REG          (5)
+#define SW_TRUNK_ID_BIT_OFF      (8)
+#define SW_TRUNK_BIT_OFF         (14)
+#define SW_TRUNK_ID_BIT_LEN      (4)
+
+#define SW_TRUNK_MAPPING_REG     (8)
+#define SW_TRUNK_MAPPING_BIT_OFF (0)
+#define SW_TRUNK_MAPPING_BIT_LEN (7)
+#define SW_TRUNK_MAPPING_ID_BIT_OFF     (11)
+#define SW_REG_UPDATE_BIT_OFF    (15)
+
+#define SW_TRUNK_MASK_REG         (7)
+#define SW_TRUNK_MASK_NUM_BIT_OFF (12)
+#define SW_TRUNK_MASK_NUM_BIT_LEN (3)
+#define SW_TRUNK_MASK_BIT_OFF     (0)
+#define SW_TRUNK_MASK_BIT_LEN     (7)
+
+#define SW_CLEAR_REG_BIT(REG, OFF, LEN) (REG) = (~((0xFFFF >> (16 - (LEN))) << OFF) & (REG))
+
+/* enum of PHY access way */
+typedef enum {
+        PHY_SMI_MASTER_CPU,/*Phy directly accessed through LSP function*/
+        PHY_SMI_MASTER_SWT,/*Phy accessed through switch*/
+} tpm_phy_ctrl_t;
+
 /*******************************************************************************
 * tpm_sw_set_static_mac_w_ports_mask
 *
@@ -897,7 +926,7 @@
 * INPUTS:
 *       owner_id        - APP owner id should be used for all API calls.
 *       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
-*       tpm_swport_pm_3 - Holds PM data
+*       tpm_swport_pm_3_all_t - Holds PM data
 *
 * OUTPUTS:
 *       PM data is supplied structure.
@@ -910,7 +939,7 @@
 (
     uint32_t            owner_id,
     tpm_src_port_type_t src_port,
-    tpm_swport_pm_3_t  *tpm_swport_pm_3
+    tpm_swport_pm_3_all_t  *tpm_swport_pm_3
 );
 
 /*******************************************************************************
@@ -1014,6 +1043,72 @@
 tpm_error_code_t tpm_sw_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num);
 
 /*******************************************************************************
+* tpm_phy_set_port_speed_duplex_mode
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed and duplex mode.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       speed       -    PHY_SPEED_10_MBPS   - 10Mbps
+*                        PHY_SPEED_100_MBPS  - 100Mbps
+*                        PHY_SPEED_1000_MBPS - 1000Mbps.
+*       enable      - Enable/Disable full dulpex mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_speed_duplex_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_phy_speed_t     speed,
+    bool                enable
+);
+
+/*******************************************************************************
+* tpm_sw_port_add_vid_set_egrs_mode
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per UNI port,
+*       and sets the egress mode for the port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - vlan id
+*       eMode      - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid_set_egrs_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid,
+    uint8_t             eMode
+);
+
+/*******************************************************************************
 * tpm_sw_init
 *
 * DESCRIPTION:
@@ -1061,5 +1156,20 @@
      uint32_t            enDis
 );
 
+/*******************************************************************************
+* tpm_sw_pm_print_from_gmac
+*
+*
+* INPUTS:
+*       port        - GMAC port.
+* OUTPUTS:
+*       tpm_swport_pm_1 - Holds PM data1
+*       tpm_swport_pm_3 - Holds PM data all
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_print_from_gmac(int port);
 
 #endif
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c
index 52c5a33..7371cdb 100755
--- a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c
@@ -69,6 +69,8 @@
 #include "mvSysEthPhyConfig.h"
 #include "mvEthPhyRegs.h"
 #include "mvEthPhy.h"
+#include "gbe/mvNeta.h"
+#include "boardEnv/mvBoardEnvLib.h"
 
 static 	MV_VOID	mvEthPhyPower(MV_U32 ethPortNum, MV_BOOL enable);
 
@@ -441,6 +443,7 @@
 *
 * INPUT:
 *       phyAddr - Phy address.
+*	data    - PHY control register value want to be, if 0xFFFF, use original value
 *       timeout - in millisec
 *
 * OUTPUT:
@@ -450,17 +453,30 @@
 *           MV_TIMEOUT  - Timeout
 *
 *******************************************************************************/
-MV_STATUS mvEthPhyReset(MV_U32 phyAddr, int timeout)
+MV_STATUS mvEthPhyReset(MV_U32 phyAddr, MV_U16 data, int timeout)
 {
-	MV_U16  phyRegData;
+	MV_U16  phyRegData, temp;
+	MV_BOOL power_down = 0;
 
 	/* Reset the PHY */
-	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &temp) != MV_OK)
 		return MV_FAIL;
 
-	/* Set bit 15 to reset the PHY */
-	phyRegData |= ETH_PHY_CTRL_RESET_MASK;
-	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);
+	if (temp & ETH_PHY_CTRL_POWER_DOWN_MASK)
+		power_down = 1;
+
+	if (data != 0xFFFF)
+		temp = data;
+
+	if (power_down)
+		temp |= ETH_PHY_CTRL_POWER_DOWN_MASK;
+	else
+		temp |= ETH_PHY_CTRL_RESET_MASK;
+
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, temp);
+
+	if (power_down)
+		return MV_OK;
 
 	/* Wait untill Reset completed */
 	while (timeout > 0) {
@@ -482,6 +498,8 @@
 *
 * DESCRIPTION:
 *       This function resets a given ethernet Phy.
+*	If AutoNegotiation is not enabled, it'll enable it.
+*	Loopback and Power Down will be disabled by this routine
 *
 * INPUT:
 *       phyAddr - Phy address.
@@ -498,10 +516,17 @@
 {
 	MV_U16  phyRegData;
 
-	/* Reset the PHY */
+	/* Disable internal loopback first, in order to restore value of related register */
+	if (mvEthPhyLoopbackSet(phyAddr, MV_FALSE) != MV_OK)
+		return MV_FAIL;
+
+	/* Read Control reg of the PHY */
 	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
 		return MV_FAIL;
 
+	/* disable loopback and power down */
+	phyRegData &= (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_SPEED_LSB_MASK | ETH_PHY_CTRL_SPEED_MSB_MASK);
+
 	/* Set bit 12 to Enable autonegotiation of the PHY */
 	phyRegData |= ETH_PHY_CTRL_AN_ENABLE_MASK;
 
@@ -624,7 +649,7 @@
 		regVal &= ~(BIT5 | BIT6 | BIT8 | BIT9);
 		mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL_REG, regVal);
 
-		status = mvEthPhyReset(phyAddr, 1000);
+		status = mvEthPhyReset(phyAddr, 0xFFFF, MV_PHY_RESET_EXPIRE_COUNT);
 		if (status != MV_OK) {
 			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
 			return status;
@@ -636,9 +661,8 @@
 	} else {
 		/* Cancel Loopback */
 		ctrlVal &= ~ETH_PHY_CTRL_LOOPBACK_MASK;
-		mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, ctrlVal);
 
-		status = mvEthPhyReset(phyAddr, 1000);
+		status = mvEthPhyReset(phyAddr, ctrlVal, MV_PHY_RESET_EXPIRE_COUNT);
 		if (status != MV_OK) {
 			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
 			return status;
@@ -650,7 +674,7 @@
 		regVal |= (BIT5 | BIT6 | BIT8 | BIT9);
 		mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL_REG, regVal);
 
-		status = mvEthPhyReset(phyAddr, 1000);
+		status = mvEthPhyReset(phyAddr, 0xFFFF, MV_PHY_RESET_EXPIRE_COUNT);
 		if (status != MV_OK) {
 			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
 			return status;
@@ -808,6 +832,14 @@
 	regVal = regVal & (~ETH_PHY_1000BASE_ADVERTISE_MASK);
 	regVal = regVal | (tmp << ETH_PHY_1000BASE_ADVERTISE_OFFSET);
 	mvEthPhyRegWrite(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, regVal);
+
+	/* Reset PHY */
+	mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &tmp);
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, tmp | ETH_PHY_CTRL_RESET_MASK);
+	mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &tmp);
+	while(tmp & ETH_PHY_CTRL_RESET_MASK)
+		mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &tmp);
+
 	return MV_OK;
 }
 
@@ -2046,3 +2078,879 @@
 	}
 }
 
+/* Check GEPHY or FEPHY through Reg1.8 */
+static MV_STATUS mvEthPhyIsFe(MV_U32 phyAddr, MV_BOOL *Is_Fe_PHY)
+{
+	MV_U16  phyRegData;
+	MV_BOOL isfe = 0;
+
+	/* Check PHY exist or not */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_ID2_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	if (phyRegData == ETH_PHY_SMI_DATA_MASK)
+		return MV_FAIL;
+
+	/* Judge PHY is FE or GE through reg1.8 */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	if (ETH_PHY_STATUS_EXTEND_MASK & phyRegData)
+		isfe = 0;
+	else
+		isfe = 1;
+
+	*Is_Fe_PHY = isfe;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhySetAdminState - Set phy power down state.
+*
+* DESCRIPTION:
+*       The API Configures the PHY state on the eth port.
+* INPUTS:
+*       phyAddr - Phy address.
+*       phy_state  - PHY port  state to set.
+*                         0:power down
+*                         1:power up
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+
+MV_STATUS mvEthPhySetAdminState(MV_U32 phyAddr, MV_BOOL phy_state)
+{
+	MV_U16  phyRegData;
+	MV_BOOL pre_state;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	pre_state = (phyRegData & ETH_PHY_CTRL_POWER_DOWN_MASK) ? 0 : 1;
+
+	if (pre_state != phy_state) {
+		if (!phy_state) {
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData | ETH_PHY_CTRL_POWER_DOWN_MASK) != MV_OK)
+				return MV_FAIL;
+		} else {
+			/* from down to normal, 0.11 and 16.2 must be set 0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData & (~ETH_PHY_CTRL_POWER_DOWN_MASK)) != MV_OK)
+				return MV_FAIL;
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL_REG, &phyRegData) != MV_OK)
+				return MV_FAIL;
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL_REG, phyRegData & (~ETH_PHY_SPEC_CTRL_POWER_DOWN_MASK)) != MV_OK)
+				return MV_FAIL;
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyGetAdminState - Get PHY power down dtate.
+*
+* DESCRIPTION:
+*       The API get the PHY state on the eth port.
+* INPUTS:
+*       phyAddr - Phy address.
+*       phy_state  - PHY port  state to set.
+*                         0:power down
+*                         1:power up
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyGetAdminState(MV_U32 phyAddr, MV_BOOL *phy_state)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	*phy_state = (phyRegData & ETH_PHY_CTRL_POWER_DOWN_MASK) ? 0 : 1;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyGetLinkStatus - Get PHY link state.
+*
+* DESCRIPTION:
+*       The API get the PHY  link state on the eth port.
+* INPUTS:
+*       phyAddr - Phy address.
+*       link_state  - PHY link state to set.
+*                         0:link down
+*                         1:link up
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyGetLinkStatus(MV_U32 phyAddr, MV_BOOL *link_state)
+{
+	MV_U16  phyRegData;
+
+	/* Check if the PHY exist */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_ID2_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	if (phyRegData == ETH_PHY_SMI_DATA_MASK)
+		return MV_FAIL;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_STATUS_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	/* Check status valid or not */
+	if (!(phyRegData & ETH_PHY_SPEC_STATUS_RESOLVE_MASK))
+		return MV_FAIL;
+
+	*link_state = (phyRegData & ETH_PHY_SPEC_STATUS_LINK_MASK) ? 1 : 0;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyDuplexOperGet - Get PHYduplex info.
+*
+* DESCRIPTION:
+*       The API get the PHY duplex status on the eth port. It reflects the real
+*       configuration happened in PHY.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       state_valid   - indicates PHY state is valid or not
+*                         0: invalid
+*                         1: valid
+*       duplex_state  - PHY link state to set.
+*                         0:half duplex
+*                         1:full duplex
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+* COMMENT: Reg17.13
+*******************************************************************************/
+MV_STATUS mvEthPhyDuplexOperGet(MV_U32 phyAddr, MV_BOOL *state_valid, MV_BOOL *duplex_state)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_STATUS_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	/* Check status valid or not */
+	if (!(phyRegData & ETH_PHY_SPEC_STATUS_RESOLVE_MASK)) {
+		*state_valid = MV_FALSE;
+		return MV_OK;
+	}
+	*state_valid = MV_TRUE;
+
+	*duplex_state = (phyRegData & ETH_PHY_SPEC_STATUS_DUPLEX_MASK) ? 1 : 0;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyPauseSet - Set pause of PHY.
+*
+* DESCRIPTION:
+*       The API set pause state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       pause_state   - pause state set to
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyPauseSet(MV_U32 phyAddr, MV_U32 pause_state)
+{
+	MV_U16  phyRegData;
+	MV_U32 pre_state = MV_ETHPHY_NO_PAUSE;
+
+	/* read current pause state */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_AUTONEGO_AD_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	if (phyRegData & ETH_PHY_SPEC_CTRL_PAUSE_MASK)
+		pre_state |= MV_ETHPHY_PAUSE;
+	if (phyRegData & ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK)
+		pre_state |= MV_ETHPHY_ASYMMETRIC_PAUSE;
+
+	if (pause_state == pre_state)
+		return MV_OK;
+
+	/*set expected PAUSE state*/
+	phyRegData &= ((~ETH_PHY_SPEC_CTRL_PAUSE_MASK) & (~ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK));
+	switch (pause_state) {
+	case MV_ETHPHY_NO_PAUSE:
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_AUTONEGO_AD_REG, phyRegData) != MV_OK)
+			return MV_FAIL;
+		break;
+	case MV_ETHPHY_PAUSE:
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_AUTONEGO_AD_REG, phyRegData |
+								       ETH_PHY_SPEC_CTRL_PAUSE_MASK) != MV_OK)
+			return MV_FAIL;
+		break;
+	case MV_ETHPHY_ASYMMETRIC_PAUSE:
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_AUTONEGO_AD_REG, phyRegData |
+								       ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK) != MV_OK)
+			return MV_FAIL;
+		break;
+	case MV_ETHPHY_BOTH_PAUSE:
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_AUTONEGO_AD_REG, phyRegData |
+								       ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK |
+								       ETH_PHY_SPEC_CTRL_PAUSE_MASK) != MV_OK)
+			return MV_FAIL;
+		break;
+	default:
+		return MV_FAIL;
+	}
+
+	/*restart auto-nego, let set above take effect*/
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	phyRegData = phyRegData | ETH_PHY_CTRL_AN_RESTART_MASK;
+
+	if (mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyPauseAdminGet - Get pause state of PHY.
+*
+* DESCRIPTION:
+*       The API get pause state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       pause_state   - pause state set to
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+* COMMENT: Reg4.10 4.11
+*******************************************************************************/
+MV_STATUS mvEthPhyPauseAdminGet(MV_U32 phyAddr, MV_U32 *pause_state)
+{
+	MV_U16  phyRegData;
+	MV_U32 pre_state = MV_ETHPHY_NO_PAUSE;
+
+	/* read current pause state */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_AUTONEGO_AD_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	if (phyRegData & ETH_PHY_SPEC_CTRL_PAUSE_MASK)
+		pre_state |= MV_ETHPHY_PAUSE;
+	if (phyRegData & ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK)
+		pre_state |= MV_ETHPHY_ASYMMETRIC_PAUSE;
+
+	*pause_state = pre_state;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyLoopbackSet - Set loopback state of PHY.
+*
+* DESCRIPTION:
+*       The API set loopback state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       isEnable      - loopback state.
+*                     0--disable
+*                     1--enabled
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyLoopbackSet(MV_U32 phyAddr, MV_BOOL isEnable)
+{
+	MV_U16	phyRegData, ctrlVal;
+	MV_BOOL isfe = 0;
+
+	if (mvEthPhyIsFe(phyAddr, &isfe))
+		return MV_FAIL;
+
+	/* Set loopback speed and duplex accordingly with current */
+	/* Bits: 6, 8, 13 */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &ctrlVal) != MV_OK)
+		return MV_FAIL;
+
+	if (isEnable) {
+		if (!isfe) {
+			/* select page 2 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 2) != MV_OK)
+				return MV_FAIL;
+
+			/* Set register 21_2 */
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, &phyRegData) != MV_OK)
+				return MV_FAIL;
+			phyRegData &= ~(ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_SPEED_LSB_MASK |
+					ETH_PHY_CTRL_SPEED_MSB_MASK | ETH_PHY_CTRL_AN_ENABLE_MASK);
+			phyRegData |= (ctrlVal & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_SPEED_LSB_MASK |
+						  ETH_PHY_CTRL_SPEED_MSB_MASK | ETH_PHY_CTRL_AN_ENABLE_MASK));
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, phyRegData) != MV_OK)
+				return MV_FAIL;
+
+			/* restore page0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+				return MV_FAIL;
+
+			/* Force master */
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, &phyRegData) != MV_OK)
+				return MV_FAIL;
+			phyRegData |= ETH_PHY_1000BASE_MASTER_ENABLE_MASK;
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, phyRegData) != MV_OK)
+				return MV_FAIL;
+
+			/*reset PHY */
+			if (mvEthPhyReset(phyAddr, 0xFFFF, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+				return MV_FAIL;
+			/* When auto-nego is disabled, 2 PHY reset is needed */
+			if (mvEthPhyReset(phyAddr, 0xFFFF, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+				return MV_FAIL;
+
+			/* Select page 0x00FA, there is no description in reference */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0x00FA) != MV_OK)
+				return MV_FAIL;
+
+			/* write register 7, force 1000M link, dfault is 0x200*/
+			if (mvEthPhyRegWrite(phyAddr, 7, 0x020c) != MV_OK)
+				return MV_FAIL;
+
+			/* restore page0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+				return MV_FAIL;
+		}
+
+		/* Set loopback */
+		ctrlVal |= ETH_PHY_CTRL_LOOPBACK_MASK;
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, ctrlVal) != MV_OK)
+			return MV_FAIL;
+	} else {
+		if (!isfe) {
+			/*restore original setting*/
+			/* Select page 0x00FA */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0x00FA) != MV_OK)
+				return MV_FAIL;
+
+			/* write register 7, restore default is 0x200*/
+			if (mvEthPhyRegWrite(phyAddr, 7, 0x0200) != MV_OK)
+				return MV_FAIL;
+
+			/* restore page0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+				return MV_FAIL;
+
+			/* Cancel  Force master */
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, &phyRegData) != MV_OK)
+				return MV_FAIL;
+			phyRegData &= (~ETH_PHY_1000BASE_MASTER_ENABLE_MASK);
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, phyRegData) != MV_OK)
+				return MV_FAIL;
+		}
+		/*disable loopback*/
+		ctrlVal &= (~ETH_PHY_CTRL_LOOPBACK_MASK);
+		if (mvEthPhyReset(phyAddr, ctrlVal, MV_PHY_RESET_EXPIRE_COUNT) !=MV_OK)
+			return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyLoopbackGet - Get loopback state of PHY.
+*
+* DESCRIPTION:
+*       The API get loopback state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*
+* OUTPUT:
+*       isEnable      - loopback state.
+*                     0--disable
+*                     1--enabled
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyLoopbackGet(MV_U32 phyAddr, MV_BOOL *isEnable)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	*isEnable = (phyRegData & ETH_PHY_CTRL_LOOPBACK_MASK) ? 1 : 0;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyLineLoopbackSet - Set line loopback state of PHY.
+*
+* DESCRIPTION:
+*       The API set loopback state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       isEnable      - loopback state.
+*                     0--disable
+*                     1--enabled
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyLineLoopbackSet(MV_U32 phyAddr, MV_BOOL isEnable)
+{
+	MV_U16  phyRegData;
+	MV_BOOL isfe = 0;
+
+	if (mvEthPhyIsFe(phyAddr, &isfe))
+		return MV_FAIL;
+
+	if (isEnable) {
+		if (!isfe) {
+			/* select page 2 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 2) != MV_OK)
+				return MV_FAIL;
+			/* set speed to 1000Mbps */
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, &phyRegData) != MV_OK)
+				return MV_FAIL;
+			phyRegData &= 0xFFFFFFF8;
+			phyRegData |= ETH_PHY_SPEC_CTRL2_PAGE2_MAC_SPEED_1000M;
+			phyRegData |= ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_MASK;
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, phyRegData) != MV_OK)
+				return MV_FAIL;
+			/* restore page0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+				return MV_FAIL;
+		} else {
+
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_FE_SPEC_CTRL2, &phyRegData) != MV_OK)
+				return MV_FAIL;
+
+			phyRegData |= ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_MASK;
+
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_FE_SPEC_CTRL2, phyRegData) != MV_OK)
+				return MV_FAIL;
+		}
+	} else {
+		if (!isfe) {
+			/* select page 2 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 2) != MV_OK)
+				return MV_FAIL;
+			phyRegData &= (~ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_MASK);
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, phyRegData) != MV_OK)
+				return MV_FAIL;
+			/* restore page0 */
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+				return MV_FAIL;
+		} else {
+
+			if (mvEthPhyRegRead(phyAddr, ETH_PHY_FE_SPEC_CTRL2, &phyRegData) != MV_OK)
+				return MV_FAIL;
+
+			phyRegData &= (~ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_MASK);
+
+			if (mvEthPhyRegWrite(phyAddr, ETH_PHY_FE_SPEC_CTRL2, phyRegData) != MV_OK)
+				return MV_FAIL;
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyLineLoopbackGet - Get line loopback state of PHY, external loopback
+*
+* DESCRIPTION:
+*       The API get loopback state.
+* INPUTS:
+*       phyAddr       - Phy address.
+*
+* OUTPUT:
+*       isEnable      - loopback state.
+*                     0--disable
+*                     1--enabled
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyLineLoopbackGet(MV_U32 phyAddr, MV_BOOL *isEnable)
+{
+	MV_U16  phyRegData;
+	MV_BOOL isfe = 0;
+
+	if (mvEthPhyIsFe(phyAddr, &isfe))
+		return MV_FAIL;
+
+	if (!isfe) {
+		/* select page 2 */
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 2) != MV_OK)
+			return MV_FAIL;
+
+		if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL2_PAGE2, &phyRegData) != MV_OK)
+			return MV_FAIL;
+		/* restore page0 */
+		if (mvEthPhyRegWrite(phyAddr, ETH_PHY_PAGE_ADDR, 0) != MV_OK)
+			return MV_FAIL;
+
+		*isEnable = (phyRegData & ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_MASK) ? 1 : 0;
+	} else {
+		if (mvEthPhyRegRead(phyAddr, ETH_PHY_FE_SPEC_CTRL2, &phyRegData) != MV_OK)
+			return MV_FAIL;
+		*isEnable = (phyRegData & ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_MASK) ? 1 : 0;
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvEthPhyDuplexModeSet - Set duplex mode of PHY.
+*
+* DESCRIPTION:
+*		This function will keep the speed and loopback mode to the
+*		previous value, but disable others, such as Autonegotiation.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       isEnable      - duplex state
+*                     0--half duplex
+*                     1--full duplex
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyDuplexModeSet(MV_U32 phyAddr, MV_BOOL isEnable)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	if (isEnable)
+		phyRegData = phyRegData | ETH_PHY_CTRL_DUPLEX_MASK;
+	else
+		phyRegData = phyRegData & (~ETH_PHY_CTRL_DUPLEX_MASK);
+
+	phyRegData = phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK |
+				   ETH_PHY_CTRL_LOOPBACK_MASK |
+				   ETH_PHY_CTRL_SPEED_LSB_MASK |
+				   ETH_PHY_CTRL_SPEED_MSB_MASK);
+	/* Write Control reg and reset PHY */
+	if (mvEthPhyReset(phyAddr, phyRegData, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyDuplexModeAdminGet - Get configured duplex mode of PHY.
+*
+* DESCRIPTION:
+*       The API get duplex mode.
+* INPUTS:
+*       phyAddr       - Phy address.
+*
+* OUTPUT:
+*       isEnable      - duplex state
+*                     0--half duplex
+*                     1--full duplex
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+* Comment: reg0.8
+*******************************************************************************/
+MV_STATUS mvEthPhyDuplexModeAdminGet(MV_U32 phyAddr, MV_BOOL *isEnable)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	*isEnable = (phyRegData & ETH_PHY_CTRL_DUPLEX_MASK) ? 1 : 0;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhySpeedSet - Set speed of PHY.
+*
+* DESCRIPTION:
+*		This function will keep the duplex mode and loopback mode to the
+*		previous value, but disable others, such as Autonegotiation.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       speed         - PHY speed
+*                     0--10 Mbps
+*                     1--100 Mbps
+*                     2--1000 Mbps
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhySpeedSet(MV_U32 phyAddr, MV_U32 speed)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	phyRegData = phyRegData & ((~ETH_PHY_CTRL_SPEED_LSB_MASK) & (~ETH_PHY_CTRL_SPEED_MSB_MASK));
+
+	switch (speed) {
+	case MV_ETHPHY_SPEED_10_MBPS:
+		phyRegData = phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK);
+		break;
+	case MV_ETHPHY_SPEED_100_MBPS:
+		phyRegData = (phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK)) |
+			     ETH_PHY_CTRL_SPEED_LSB_MASK;
+		break;
+	case MV_ETHPHY_SPEED_1000_MBPS:
+		phyRegData = (phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK)) |
+			     ETH_PHY_CTRL_SPEED_MSB_MASK;
+		break;
+	default:
+		return MV_FAIL;
+	}
+
+	if (mvEthPhyReset(phyAddr, phyRegData, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhySpeedOperGet - Get PHYduplex info.
+*
+* DESCRIPTION:
+*       The API get the PHY speed status on the eth port. It reflects the real
+*       configuration happened in PHY.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       speed         - PHY connection speed.
+*                         0--10 Mbps
+*                         1--100 Mbps
+*                         2--1000 Mbps
+*                         3--Unknown
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+* COMMENT: Reg17.14 and 17.15
+*******************************************************************************/
+MV_STATUS mvEthPhySpeedOperGet(MV_U32 phyAddr, MV_U32 *speed)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_STATUS_REG, &phyRegData) != MV_OK)
+		return MV_ERROR;
+	/* Check status valid or not */
+	if (!(phyRegData & ETH_PHY_SPEC_STATUS_RESOLVE_MASK)) {
+		*speed = MV_ETHPHY_SPEED_UNKNOWN;
+		return MV_OK;
+	}
+
+	switch (phyRegData & ETH_PHY_SPEC_STATUS_SPEED_MASK) {
+	case ETH_PHY_SPEC_STATUS_SPEED_1000MBPS:
+		*speed = MV_ETHPHY_SPEED_1000_MBPS;
+		break;
+	case ETH_PHY_SPEC_STATUS_SPEED_100MBPS:
+		*speed = MV_ETHPHY_SPEED_100_MBPS;
+		break;
+	case ETH_PHY_SPEC_STATUS_SPEED_10MBPS:
+		*speed = MV_ETHPHY_SPEED_10_MBPS;
+		break;
+	default:
+		return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhySpeedAdminGet - Get Configured speed of PHY.
+*
+* DESCRIPTION:
+*       The API get speed.
+* INPUTS:
+*       phyAddr       - Phy address.
+*
+* OUTPUT:
+*       speed         - duplex state
+*                     0--10 Mbps
+*                     1--100 Mbps
+*                     2--1000 Mbps
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+* Comment: Reg0.6, 0.13
+*******************************************************************************/
+MV_STATUS mvEthPhySpeedAdminGet(MV_U32 phyAddr, MV_U32 *speed)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_ERROR;
+
+	/* MSB = 1, LSB = 0, 1000M */
+	if ((phyRegData & ETH_PHY_CTRL_SPEED_MSB_MASK) && (!(phyRegData & ETH_PHY_CTRL_SPEED_LSB_MASK)))
+		*speed = MV_ETHPHY_SPEED_1000_MBPS;
+	/* MSB = 0, LSB = 1, 100M */
+	else if ((phyRegData & ETH_PHY_CTRL_SPEED_LSB_MASK) && (!(phyRegData & ETH_PHY_CTRL_SPEED_MSB_MASK)))
+		*speed = MV_ETHPHY_SPEED_100_MBPS;
+	/* MSB = 0, LSB = 0, 10M */
+	else if ((!(phyRegData & ETH_PHY_CTRL_SPEED_LSB_MASK)) && (!(phyRegData & ETH_PHY_CTRL_SPEED_MSB_MASK)))
+		*speed = MV_ETHPHY_SPEED_10_MBPS;
+	else
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhySpeedDuplexModeSet - Set Speed and duplex mode of PHY.
+*
+* DESCRIPTION:
+*		This function will keep the loopback mode to the
+*		previous value, but disable others, such as Autonegotiation.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       speed         - PHY speed
+*                     0--10 Mbps
+*                     1--100 Mbps
+*                     2--1000 Mbps
+*       isEnable      - duplex state
+*                     0--half duplex
+*                     1--full duplex
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhySpeedDuplexModeSet(MV_U32 phyAddr, MV_U32 speed, MV_BOOL isEnable)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	if (isEnable)
+		phyRegData = phyRegData | ETH_PHY_CTRL_DUPLEX_MASK;
+	else
+		phyRegData = phyRegData & (~ETH_PHY_CTRL_DUPLEX_MASK);
+
+	phyRegData = phyRegData & ((~ETH_PHY_CTRL_SPEED_LSB_MASK) & (~ETH_PHY_CTRL_SPEED_MSB_MASK));
+
+	switch (speed) {
+	case MV_ETHPHY_SPEED_10_MBPS:
+		phyRegData = phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK);
+		break;
+	case MV_ETHPHY_SPEED_100_MBPS:
+		phyRegData = (phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK)) |
+			     ETH_PHY_CTRL_SPEED_LSB_MASK;
+		break;
+	case MV_ETHPHY_SPEED_1000_MBPS:
+		phyRegData = (phyRegData & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_LOOPBACK_MASK)) |
+			     ETH_PHY_CTRL_SPEED_MSB_MASK;
+		break;
+	default:
+		return MV_FAIL;
+	}
+
+	if (mvEthPhyReset(phyAddr, phyRegData, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyAutoNegoSet - Set auto nego of PHY.
+*
+* DESCRIPTION:
+*       The API set auto nego.
+* INPUTS:
+*       phyAddr       - Phy address.
+*       isEnable      - auto nego state
+*                     0--disable auto nego
+*                     1--enable auto nego
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyAutoNegoSet(MV_U32 phyAddr, MV_BOOL isEnable)
+{
+	MV_U16  phyRegData;
+	MV_BOOL pre_state;
+
+	/* Disable internal loopback first if enable auto-nego, in order to restore value of related register */
+	if (isEnable) {
+		if (mvEthPhyLoopbackSet(phyAddr, MV_FALSE) != MV_OK)
+			return MV_FAIL;
+	}
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	pre_state = (phyRegData & ETH_PHY_CTRL_AN_ENABLE_MASK) ? 1 : 0;
+	if (isEnable == pre_state)
+		return MV_OK;
+	if (isEnable)
+		phyRegData |= ETH_PHY_CTRL_AN_ENABLE_MASK;
+	else
+		phyRegData &= (~ETH_PHY_CTRL_AN_ENABLE_MASK);
+
+	/*reset PHY, let set above take effect*/
+	if (mvEthPhyReset(phyAddr, phyRegData, MV_PHY_RESET_EXPIRE_COUNT) != MV_OK)
+		return MV_FAIL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyAutoNegoGet - Get auto nego of PHY.
+*
+* DESCRIPTION:
+*       The API get duplex mode.
+* INPUTS:
+*       phyAddr       - Phy address.
+*
+* OUTPUT:
+*       isEnable      - auto nego state
+*                     0--disable
+*                     1--enable
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*******************************************************************************/
+MV_STATUS mvEthPhyAutoNegoGet(MV_U32 phyAddr, MV_BOOL *isEnable)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+	*isEnable = (phyRegData & ETH_PHY_CTRL_AN_ENABLE_MASK) ? 1 : 0;
+
+	return MV_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h
index d621d81..69a581b 100755
--- a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h
@@ -103,6 +103,17 @@
 #define MV_IS_MARVELL_OUI(_reg2, _reg3)		\
 	(((_reg2) == 0x0141) && (((_reg3)&0xFC00) == 0x0C00))
 
+/* PHY nego mode macro */
+#define PHY_AUTO_NEGO_MODE_HALF_10 0x1
+#define PHY_AUTO_NEGO_MODE_FULL_10 0x2
+#define PHY_AUTO_NEGO_MODE_HALF_100 0x4
+#define PHY_AUTO_NEGO_MODE_FULL_100 0x8
+#define PHY_AUTO_NEGO_MODE_HALF_1000 0x10
+#define PHY_AUTO_NEGO_MODE_FULL_1000 0x20
+
+/* PHY reset expire time */
+#define MV_PHY_RESET_EXPIRE_COUNT 1000
+
 typedef struct {
 	MV_U8		ctrlRevId;
 	MV_U32		phyAddr[MV_ETH_MAX_PORTS];
@@ -119,11 +130,50 @@
 	MV_STATUS	(*mvExtPhyReadFunc)(MV_U32 phyAddr, MV_U32 regAddr, MV_U16 *data);
 } MV_ETHPHY_HAL_DATA;
 
+/*
+* typedef: enum MV_ETHPHY_PAUSE_MODE
+*
+* Description: Enumeration of Pause Mode in the Phy.
+*
+* Enumerations:
+*	MV_ETHPHY_NO_PAUSE		- disable pause
+*	MV_ETHPHY_PAUSE		- support pause
+*	MV_ETHPHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*	MV_ETHPHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*/
+typedef enum
+{
+	MV_ETHPHY_NO_PAUSE = 0,
+	MV_ETHPHY_PAUSE,
+	MV_ETHPHY_ASYMMETRIC_PAUSE,
+	MV_ETHPHY_BOTH_PAUSE
+} MV_ETHPHY_PAUSE_MODE;
+
+/*
+* typedef: enum MV_ETHPHY_SPEED
+*
+* Description: Enumeration of Phy Speed
+*
+* Enumerations:
+*	MV_ETHPHY_SPEED_10_MBPS   - 10Mbps
+*	MV_ETHPHY_SPEED_100_MBPS  - 100Mbps
+*	MV_ETHPHY_SPEED_1000_MBPS - 1000Mbps
+*	MV_ETHPHY_SPEED_UNKNOWN   - Unknown speed
+*/
+typedef enum
+{
+	MV_ETHPHY_SPEED_10_MBPS,
+	MV_ETHPHY_SPEED_100_MBPS,
+	MV_ETHPHY_SPEED_1000_MBPS,
+	MV_ETHPHY_SPEED_UNKNOWN
+} MV_ETHPHY_SPEED;
+
+
 MV_STATUS 	mvEthPhyHalInit(MV_ETHPHY_HAL_DATA *halData);
 MV_STATUS	mvEthPhyInit(MV_U32 ethPortNum, MV_BOOL eeeEnable);
 MV_STATUS	mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data);
 MV_STATUS 	mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data);
-MV_STATUS 	mvEthPhyReset(MV_U32 phyAddr, int timeout);
+MV_STATUS 	mvEthPhyReset(MV_U32 phyAddr, MV_U16 data, int timeout);
 MV_STATUS 	mvEthPhyRestartAN(MV_U32 phyAddr, int timeout);
 MV_STATUS 	mvEthPhyDisableAN(MV_U32 phyAddr, int speed, int duplex);
 MV_STATUS   	mvEthPhyLoopback(MV_U32 phyAddr, MV_BOOL isEnable);
@@ -149,6 +199,24 @@
 MV_VOID		mvEth131xPhyBasicInit(MV_U32 phyAddr);
 MV_VOID 	mvEthE1512PhyBasicInit(MV_U32 ethPortNum, MV_BOOL eeeEnable);
 /* MV_VOID		mvEthInternal3FEPhyBasicInit(MV_U32 port); */
+MV_STATUS	mvEthPhySetAdminState(MV_U32 phyAddr, MV_BOOL phy_state);
+MV_STATUS	mvEthPhyGetAdminState(MV_U32 phyAddr, MV_BOOL *phy_state);
+MV_STATUS	mvEthPhyGetLinkStatus(MV_U32 phyAddr, MV_BOOL *link_state);
+MV_STATUS	mvEthPhyDuplexOperGet(MV_U32 phyAddr, MV_BOOL *state_valid, MV_BOOL *duplex_state);
+MV_STATUS	mvEthPhyPauseSet(MV_U32 phyAddr, MV_U32 pause_state);
+MV_STATUS	mvEthPhyPauseAdminGet(MV_U32 phyAddr, MV_U32 *pause_state);
+MV_STATUS	mvEthPhyLoopbackSet(MV_U32 phyAddr, MV_BOOL isEnable);
+MV_STATUS	mvEthPhyLoopbackGet(MV_U32 phyAddr, MV_BOOL *isEnable);
+MV_STATUS	mvEthPhyLineLoopbackSet(MV_U32 phyAddr, MV_BOOL isEnable);
+MV_STATUS	mvEthPhyLineLoopbackGet(MV_U32 phyAddr, MV_BOOL *isEnable);
+MV_STATUS	mvEthPhyDuplexModeSet(MV_U32 phyAddr, MV_BOOL isEnable);
+MV_STATUS	mvEthPhyDuplexModeAdminGet(MV_U32 phyAddr, MV_BOOL *isEnable);
+MV_STATUS	mvEthPhySpeedSet(MV_U32 phyAddr, MV_U32 speed);
+MV_STATUS	mvEthPhySpeedOperGet(MV_U32 phyAddr, MV_U32 *speed);
+MV_STATUS	mvEthPhySpeedAdminGet(MV_U32 phyAddr, MV_U32 *speed);
+MV_STATUS	mvEthPhySpeedDuplexModeSet(MV_U32 phyAddr, MV_U32 speed, MV_BOOL isEnable);
+MV_STATUS	mvEthPhyAutoNegoSet(MV_U32 phyAddr, MV_BOOL isEnable);
+MV_STATUS	mvEthPhyAutoNegoGet(MV_U32 phyAddr, MV_BOOL *isEnable);
 
 #ifdef __cplusplus
 }
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h
index c91984d..e3b58b5 100755
--- a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h
@@ -99,10 +99,14 @@
 /* PHY registers and bits */
 #define ETH_PHY_CTRL_REG                0
 #define ETH_PHY_STATUS_REG              1
-#define ETH_PHY_AUTONEGO_AD_REG		    4
-#define ETH_PHY_1000BASE_T_CTRL_REG	    9
+#define ETH_PHY_ID2_REG                 3
+#define ETH_PHY_AUTONEGO_AD_REG		4
+#define ETH_PHY_1000BASE_T_CTRL_REG	9
 #define ETH_PHY_SPEC_CTRL_REG           16
 #define ETH_PHY_SPEC_STATUS_REG         17
+#define ETH_PHY_SPEC_CTRL2_PAGE2        21
+#define ETH_PHY_PAGE_ADDR               22
+#define ETH_PHY_FE_SPEC_CTRL2           28
 
 /* ETH_PHY_CTRL_REG bits */
 #define ETH_PHY_CTRL_SPEED_MSB_BIT      6
@@ -139,13 +143,28 @@
 #define ETH_PHY_STATUS_AN_DONE_BIT      5
 #define ETH_PHY_STATUS_AN_DONE_MASK     (1 << ETH_PHY_STATUS_AN_DONE_BIT)
 
+#define ETH_PHY_STATUS_EXTEND_BIT       8
+#define ETH_PHY_STATUS_EXTEND_MASK      (1 << ETH_PHY_STATUS_EXTEND_BIT)
+
 /* ETH_PHY_AUTONEGO_AD_REG bits */
 #define ETH_PHY_10_100_BASE_ADVERTISE_OFFSET	5
 #define ETH_PHY_10_100_BASE_ADVERTISE_MASK	(0xf << ETH_PHY_10_100_BASE_ADVERTISE_OFFSET)
 
+#define ETH_PHY_SPEC_CTRL_PAUSE_BIT		10
+#define  ETH_PHY_SPEC_CTRL_PAUSE_MASK		(1 << ETH_PHY_SPEC_CTRL_PAUSE_BIT)
+
+#define ETH_PHY_SPEC_CTRL_ASY_PAUSE_BIT		11
+#define  ETH_PHY_SPEC_CTRL_ASY_PAUSE_MASK	(1 << ETH_PHY_SPEC_CTRL_ASY_PAUSE_BIT)
+
 /* ETH_PHY_1000BASE_T_CTRL_REG bits */
 #define ETH_PHY_1000BASE_ADVERTISE_OFFSET	8
 #define ETH_PHY_1000BASE_ADVERTISE_MASK		(0x3 << ETH_PHY_1000BASE_ADVERTISE_OFFSET)
+#define ETH_PHY_1000BASE_MASTER_ENABLE_OFFSET	12
+#define ETH_PHY_1000BASE_MASTER_ENABLE_MASK	(1 << ETH_PHY_1000BASE_MASTER_ENABLE_OFFSET)
+
+/*ETH_PHY_SPEC_CTRL_REG bits */
+#define ETH_PHY_SPEC_CTRL_POWER_DOWN_BIT	2
+#define ETH_PHY_SPEC_CTRL_POWER_DOWN_MASK	(1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
 
 /* ETH_PHY_SPEC_STATUS_REG bits */
 #define ETH_PHY_SPEC_STATUS_SPEED_OFFS		14
@@ -155,16 +174,31 @@
 #define ETH_PHY_SPEC_STATUS_SPEED_100MBPS	(0x1 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
 #define ETH_PHY_SPEC_STATUS_SPEED_1000MBPS	(0x2 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
 
-
 #define ETH_PHY_SPEC_STATUS_DUPLEX_BIT		13
 #define ETH_PHY_SPEC_STATUS_DUPLEX_MASK		(0x1 << ETH_PHY_SPEC_STATUS_DUPLEX_BIT)
 
+#define ETH_PHY_SPEC_STATUS_RESOLVE_BIT		11
+#define ETH_PHY_SPEC_STATUS_RESOLVE_MASK	(0x1 << ETH_PHY_SPEC_STATUS_RESOLVE_BIT)
+
 #define ETH_PHY_SPEC_STATUS_LINK_BIT		10
 #define ETH_PHY_SPEC_STATUS_LINK_MASK		(0x1 << ETH_PHY_SPEC_STATUS_LINK_BIT)
 
 /* ETH_PHY_SPEC_STATUS_REG bits */
 #define ETH_PHY_LED_ACT_LNK_DV              0x4109
 
+/* ETH_PHY_SPEC_CTRL2_PAGE2 bits*/
+#define ETH_PHY_SPEC_CTRL2_PAGE2_MAC_SPEED_OFFS		0
+#define ETH_PHY_SPEC_CTRL2_PAGE2_MAC_SPEED_10M		4
+#define ETH_PHY_SPEC_CTRL2_PAGE2_MAC_SPEED_100M		5
+#define ETH_PHY_SPEC_CTRL2_PAGE2_MAC_SPEED_1000M	6
+
+#define ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_BIT		14
+#define ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_MASK		(0x1 << ETH_PHY_SPEC_CTRL2_PAGE2_LINE_LPK_BIT)
+
+/* ETH_PHY_FE_SPEC_CTRL2 bits*/
+#define ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_BIT		4
+#define ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_MASK		(0x1 << ETH_PHY_SPEC_CTRL2_FE_LINE_LPK_BIT)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c
index e57702c..69b6a4c 100755
--- a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c
@@ -235,6 +235,19 @@
 	return MV_OK;
 }
 
+MV_STATUS mvNetaHwfTxqNextIndexGet(int port, int tx_port, int txp, int txq, int *val)
+{
+	MV_U32				regVal;
+
+	regVal = NETA_HWF_TX_PORT_MASK(tx_port + txp) | NETA_HWF_TXQ_MASK(txq) | NETA_HWF_REG_MASK(3);
+	MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+
+	regVal = MV_REG_READ(NETA_HWF_MEMORY_REG(port));
+	if (val)
+		*val = (int)((regVal >> 16) & 0x3fff);
+
+	return MV_OK;
+}
 
 /*******************************************************************************
  * mvNetaHwfTxqEnable - Enable / Disable HWF from the rx_port to tx_port/txp/txq
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h
index ad3679c..5a9ac64 100755
--- a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h
@@ -474,6 +474,30 @@
 	return sent_desc;
 }
 
+/* Invalidate TXQ descriptor - buffer will not be sent, buffer will not be returned */
+static INLINE void mvNetaTxqDescInv(NETA_TX_DESC *pTxDesc)
+{
+	pTxDesc->command |= NETA_TX_HWF_MASK;
+	pTxDesc->command &= ~NETA_TX_BM_ENABLE_MASK;
+	pTxDesc->hw_cmd |= NETA_TX_ES_MASK;
+}
+
+/* Return: 1 - TX descriptor is valid, 0 - TX descriptor is invalid */
+static INLINE int mvNetaTxqDescIsValid(NETA_TX_DESC *pTxDesc)
+{
+	return ((pTxDesc->hw_cmd & NETA_TX_ES_MASK) == 0);
+}
+
+/* Get index of descripotor to be processed next in the specific TXQ */
+static INLINE int mvNetaTxqNextIndexGet(int port, int txp, int txq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_TXQ_INDEX_REG(port, txp, txq));
+
+	return (regVal & NETA_TXQ_NEXT_DESC_INDEX_MASK) >> NETA_TXQ_NEXT_DESC_INDEX_OFFS;
+}
+
 /* Get number of TX descriptors didn't send by HW yet and waiting for TX */
 static INLINE int mvNetaTxqPendDescNumGet(int port, int txp, int txq)
 {
@@ -755,6 +779,8 @@
 MV_STATUS mvNetaHwfTxqDropSet(int port, int p, int txp, int txq, int thresh, int bits);
 MV_STATUS mvNetaHwfMhSrcSet(int port, MV_NETA_HWF_MH_SRC src);
 MV_STATUS mvNetaHwfMhSelSet(int port, MV_U8 mhSel);
+MV_STATUS mvNetaHwfTxqNextIndexGet(int port, int tx_port, int txp, int txq, int *val);
+
 
 void mvNetaHwfRxpRegs(int port);
 void mvNetaHwfTxpRegs(int port, int p, int txp);
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c
index 2a487d0..4db75e3 100755
--- a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c
@@ -599,16 +599,20 @@
 	mvEthMibPrint(port, mib, ETH_MIB_BAD_CRC_EVENT, "BAD_CRC_EVENT");
 	mvEthRegPrint0(ETH_RX_DISCARD_PKTS_CNTR_REG(port), "RX_DISCARD_PKTS_CNTR_REG");
 	mvEthRegPrint0(ETH_RX_OVERRUN_PKTS_CNTR_REG(port), "RX_OVERRUN_PKTS_CNTR_REG");
+
 	mvOsPrintf("\n[Tx]\n");
 	mvEthMibPrint(port, mib, ETH_MIB_GOOD_FRAMES_SENT, "GOOD_FRAMES_SENT");
 	mvEthMibPrint(port, mib, ETH_MIB_BROADCAST_FRAMES_SENT, "BROADCAST_FRAMES_SENT");
 	mvEthMibPrint(port, mib, ETH_MIB_MULTICAST_FRAMES_SENT, "MULTICAST_FRAMES_SENT");
 	mvEthMibPrint(port, mib, ETH_MIB_GOOD_OCTETS_SENT_LOW, "GOOD_OCTETS_SENT");
+
 	mvOsPrintf("\n[Tx Errors]\n");
 	mvEthMibPrint(port, mib, ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR, "INTERNAL_MAC_TRANSMIT_ERR");
 	mvEthMibPrint(port, mib, ETH_MIB_EXCESSIVE_COLLISION, "EXCESSIVE_COLLISION");
 	mvEthMibPrint(port, mib, ETH_MIB_COLLISION, "COLLISION");
 	mvEthMibPrint(port, mib, ETH_MIB_LATE_COLLISION, "LATE_COLLISION");
+	mvEthRegPrint0(NETA_TX_BAD_FCS_CNTR_REG(port, mib), "NETA_TX_BAD_FCS_CNTR_REG");
+	mvEthRegPrint0(NETA_TX_DROP_CNTR_REG(port, mib), "NETA_TX_DROP_CNTR_REG");
 
 	mvOsPrintf("\n[FC control]\n");
 	mvEthMibPrint(port, mib, ETH_MIB_UNREC_MAC_CONTROL_RECEIVED, "UNREC_MAC_CONTROL_RECEIVED");
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h
index 7b0d73b..435ce51 100755
--- a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h
@@ -313,6 +313,10 @@
 #define NETA_HWF_TXQ_OFFS                   8
 #define NETA_HWF_TXQ_ALL_MASK               (0x7 << NETA_HWF_TXQ_OFFS)
 #define NETA_HWF_TXQ_MASK(txq)              ((txq) << NETA_HWF_TXQ_OFFS)
+
+#define NETA_HWF_REG_OFFS                   0
+#define NETA_HWF_REG_ALL_MASK               (0x7 << NETA_HWF_REG_OFFS)
+#define NETA_HWF_REG_MASK(reg)              ((reg) << NETA_HWF_REG_OFFS)
 /*-----------------------------------------------------------------------------------*/
 
 #define NETA_HWF_DROP_TH_REG(p)             (NETA_REG_BASE(p) + 0x1d40)
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c
index 85741ef..3d4d2d0 100755
--- a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c
@@ -239,6 +239,29 @@
 
 /*******************************************************************************
 **
+**  mvOnuGponMacRxFecHysteresisSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx PSA FEC Hysteresis config register
+**
+**  PARAMETERS:  MV_U32 fecHyst
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecHysteresisSet(MV_U32 fecHyst)
+{
+    MV_STATUS status;
+
+    status = asicOntGlbRegWrite(mvAsicReg_GPON_RX_PSA_CONFIG_FHM1, fecHyst, 0); 
+
+    return(status);
+}
+
+/*******************************************************************************
+**
 **  mvOnuGponMacRxFecConfigSet
 **  ____________________________________________________________________________
 **
@@ -1449,6 +1472,68 @@
   return(status);
 }
 
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmActiveTxBitmapSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the active TX bitmap
+**
+**  PARAMETERS:  MV_U32 bitmap
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapSet(MV_U32 bitmap)
+{
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP, bitmap, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmActiveTxBitmapValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the active TX bitmap valid
+**
+**  PARAMETERS:  MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapValidSet(MV_U32 valid)
+{
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP_VALID, valid, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmActiveTxBitmapConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the active TX bitmap configuration
+**
+**  PARAMETERS:  MV_U32 *bitmap
+**               MV_U32 *valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapConfigGet(MV_U32 *bitmap, MV_U32 *valid)
+{
+	MV_STATUS status;
+
+	status  = asicOntGlbRegRead(mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP,       bitmap, 0);
+	status |= asicOntGlbRegRead(mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP_VALID, valid, 0);
+
+	return(status);
+}
 
 /******************************************************************************/
 /* ========================================================================== */
@@ -2436,7 +2521,7 @@
 					    MV_U8  dataPattern1,
 					    MV_U8  dataPattern2)
 {
-	MV_U32    reg = 0;
+	MV_U32 reg = 0;
 
 	if (busrtMode != GPON_TX_AC_COUPL_BUST_MODE_0)
 		reg = 1 << 30;
@@ -4305,6 +4390,52 @@
 
 /*******************************************************************************
 **
+**  mvOnuEponMacPcsRxEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets PcsRxEnable register
+**
+**  PARAMETERS:  MV_U32 rxEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsRxEnableSet(MV_U32 rxEnable)
+{
+    MV_STATUS status;
+
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE, rxEnable, 0);
+
+    return (status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsTxEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets PcsTxEnable register
+**
+**  PARAMETERS:  MV_U32 txEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsTxEnableSet(MV_U32 txEnable)
+{
+    MV_STATUS status;
+
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION_TX_ENABLE, txEnable, 0);
+
+    return (status);
+}
+
+/*******************************************************************************
+**
 **  mvOnuEponMacOnuEnableSet
 **  ____________________________________________________________________________
 **
@@ -4320,12 +4451,15 @@
 *******************************************************************************/
 MV_STATUS mvOnuEponMacOnuEnableSet(MV_U32 rxEnable, MV_U32 txEnable)
 {
-  MV_STATUS status;
+    MV_STATUS status;
 
-  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
-  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_TX_ENABLE, txEnable, 0);
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE, rxEnable, 0);
+    status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
 
-  return(status);
+    status |= asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION_TX_ENABLE, txEnable, 0);
+    status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_TX_ENABLE, txEnable, 0);
+
+    return (status);
 }
 
 /*******************************************************************************
@@ -4333,7 +4467,7 @@
 **  mvOnuEponMacOnuRxEnableSet
 **  ____________________________________________________________________________
 **
-**  DESCRIPTION: The function set onu Rx & Tx enable
+**  DESCRIPTION: The function set onu Rx enable
 **
 **  PARAMETERS:  MV_U32 rxEnable
 **
@@ -4344,11 +4478,13 @@
 *******************************************************************************/
 MV_STATUS mvOnuEponMacOnuRxEnableSet(MV_U32 rxEnable)
 {
-  MV_STATUS status;
+    MV_STATUS status;
 
-  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE, rxEnable, 0);
 
-  return(status);
+    status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
+
+    return (status);
 }
 
 /*******************************************************************************
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h
index 7c1f720..41c62b8 100755
--- a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h
@@ -200,10 +200,19 @@
 /*AC coupling burst mode*/
 #define GPON_TX_AC_COUPL_BUST_MODE_0        (0)
 #define GPON_TX_AC_COUPL_BUST_MODE_1        (1)
-#define GPON_TX_AC_COUPL_PREACT_BURST_TIME  (0x0)
-#define GPON_TX_AC_COUPL_DATA_PATTERN_1     (0x0)
+#define GPON_TX_AC_COUPL_PREACT_BURST_TIME  (0x30)
+#define GPON_TX_AC_COUPL_DATA_PATTERN_1     (0x66)
 #define GPON_TX_AC_COUPL_DATA_PATTERN_2     (0x0)
 
+/*UTM Active TX Bitmap*/
+#define GPON_UTM_ACTIVE_TX_BITMAP           (0xFFFF)
+#define GPON_UTM_ACTIVE_TX_BITMAP_VALID     (1)
+
+/*GSE Transmit threshold*/
+#define GPON_GST_TX_DATA_SHIFT              (12)
+#define GPON_GST_TX_DATA_THRESHOLD          (0x30)
+#define GPON_GST_TX_IDLE_THRESHOLD          (0x10)
+
 /* Typedefs
 ------------------------------------------------------------------------------*/
 typedef MV_STATUS (*MACTXPLOAMCTRFUNC)(MV_U8 msgId, MV_BOOL status);
@@ -272,6 +281,7 @@
 MV_STATUS mvOnuGponMacRxConfigSet(MV_BOOL enable);
 MV_STATUS mvOnuGponMacRxConfigBitOrderSet(MV_U32 value);
 MV_STATUS mvOnuGponMacRxPsaConfigSet(MV_U32 syncFsmM1, MV_U32 syncFsmM2, MV_U32 syncFsmM3, MV_U32 fecHyst);
+MV_STATUS mvOnuGponMacRxFecHysteresisSet(MV_U32 fecHyst);
 MV_STATUS mvOnuGponMacRxFecConfigSet(MV_BOOL swIndication, MV_BOOL forceSw, MV_BOOL ignoreParity);
 MV_STATUS mvOnuGponMacRxFecStatusGet(MV_U32 *fecStatus);
 MV_STATUS mvOnuGponMacRxPloamDataGet(MV_U32  *ploamData);
@@ -333,6 +343,9 @@
 MV_STATUS mvOnuGponMacUtmTcPeriodSet(MV_U32 period );
 MV_STATUS mvOnuGponMacUtmTcValidSet(MV_U32 valid);
 MV_STATUS mvOnuGponMacUtmTcConfigGet(MV_U32 *period, MV_U32 *valid);
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapSet(MV_U32 bitmap);
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapValidSet(MV_U32 valid);
+MV_STATUS mvOnuGponMacUtmActiveTxBitmapConfigGet(MV_U32 *bitmap, MV_U32 *valid);
 /* ========================================================================== */
 /*                        Interrupt Functions Section                         */
 /* ========================================================================== */
@@ -480,6 +493,21 @@
 #define EPON_DDM_TX_XVR_POL_DEFAULT          (0)
 #define EPON_DDM_TX_BURST_ENA_DEFAULT        (0)
 
+/* PCS RX */
+#define EPON_PCS_CONFIG_RX_ENABLE            (1)
+#define EPON_PCS_CONFIG_RX_DISABLE           (0)
+
+/* EPON 2K packet supported */
+#define EPON_MAC_RXP_DATA_FIFO_THRESHOLD_2K_SUPP      (0x800)
+#define EPON_MAC_PCS_FRAME_SIZE_LIMIT_SIZE_2K_SUPP    (0x800)
+#define EPON_MAC_PCS_FRAME_SIZE_LIMIT_LATENCY_2K_SUPP (0x1324)
+
+/* Default value of these registers */
+#define EPON_MAC_RXP_DATA_FIFO_THRESHOLD_DEF      (0x780)
+#define EPON_MAC_PCS_FRAME_SIZE_LIMIT_SIZE_DEF    (0x640)
+#define EPON_MAC_PCS_FRAME_SIZE_LIMIT_LATENCY_DEF (0xED8)
+
+
 /* Global functions
 ------------------------------------------------------------------------------*/
 
@@ -494,6 +522,8 @@
 /*                        General Functions Section                           */
 /* ========================================================================== */
 MV_STATUS mvOnuEponMacVersionGet(MV_U32 *version);
+MV_STATUS mvOnuEponMacPcsRxEnableSet(MV_U32 rxEnable);
+MV_STATUS mvOnuEponMacPcsTxEnableSet(MV_U32 txEnable);
 MV_STATUS mvOnuEponMacOnuEnableSet(MV_U32 rxEnable, MV_U32 txEnable);
 MV_STATUS mvOnuEponMacOnuRxEnableSet(MV_U32 rxEnable);
 MV_STATUS mvOnuEponMacOnuTxEnableSet(MV_U32 txEnable, MV_U32 macId);
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c
index 497a288..8ce83f0 100755
--- a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c
@@ -256,7 +256,7 @@
   [mvAsicReg_GPON_TX_STAT_GEM_IDLE]                 = {mvAsicReg_GPON_TX_STAT_GEM_IDLE,                 MV_ASIC_ONT_GLB_ADDR + 0x1034,   0x1034,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of trans idle gem frames"},
   [mvAsicReg_GPON_TX_STAT_TX_EN_CNT]                = {mvAsicReg_GPON_TX_STAT_TX_EN_CNT,                MV_ASIC_ONT_GLB_ADDR + 0x1038,   0x1038,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of cycles with tx enable indication asserted"},
   [mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD]           = {mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD,           MV_ASIC_ONT_GLB_ADDR + 0x103C,   0x103C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Saturation threshold for tx enable indication counter"},
-  [mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD]           = {mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD,           MV_ASIC_ONT_GLB_ADDR + 0x1040,   0x1040,   asicRO,     0x00FFFFFF,     0,      0,     0,      0,     "GSE threshold for starting forwarding data to the tx burst fifo"},
+  [mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD]           = {mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD,           MV_ASIC_ONT_GLB_ADDR + 0x1040,   0x1040,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "GSE threshold for starting forwarding data to the tx burst fifo"},
   [mvAsicReg_GPON_TX_CFG_AC_COUPLING]               = {mvAsicReg_GPON_TX_CFG_AC_COUPLING,               MV_ASIC_ONT_GLB_ADDR + 0x104C,   0x104C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Transmit Configuration AC Coupling"},
   [mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES]       = {mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES,       MV_ASIC_ONT_GLB_ADDR + 0x10A0,   0x10A0,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of ethernet frames trans via tcont i"},
   [mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES]        = {mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES,        MV_ASIC_ONT_GLB_ADDR + 0x10C8,   0x10C8,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of ethernet payload bytes trans via tcont i"},
@@ -270,6 +270,8 @@
   [mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID]       = {mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x1404,   0x1404,   asicRW,     0x00000001,     0,      0,     0,      0,     "Omci gem port valid - upstream direction"},
   [mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD]             = {mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD,             MV_ASIC_ONT_GLB_ADDR + 0x1408,   0x1408,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of cycles to pause between two counter gathering sweeps"},
   [mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID]       = {mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x140C,   0x140C,   asicRW,     0x00000001,     0,      0,     0,      0,     "Tc period valid"},
+  [mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP]             = {mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP,             MV_ASIC_ONT_GLB_ADDR + 0x1410,   0x1410,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Active TX bitmap"},
+  [mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP_VALID]       = {mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000001,     0,      0,     0,      0,     "Active TX bitmap valid"},
 
   /* =========================== */
   /*  SGL Registers              */
@@ -494,6 +496,8 @@
   /*  EPON PCS Registers         */
   /* =========================== */
   [mvAsicReg_EPON_PCS_CONFIGURATION]                = {mvAsicReg_EPON_PCS_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000033,     0,      0,     0,      0,     "PCS configuration"},
+  [mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE]      = {mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE,      MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000001,     0,      0,     0,      0,     "PCS configuration Rx enable"},
+  [mvAsicReg_EPON_PCS_CONFIGURATION_TX_ENABLE]      = {mvAsicReg_EPON_PCS_CONFIGURATION_TX_ENABLE,      MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000001,     4,      0,     0,      0,     "PCS configuration Tx enable"},
   [mvAsicReg_EPON_PCS_DELAY_CONFIG]                 = {mvAsicReg_EPON_PCS_DELAY_CONFIG,                 MV_ASIC_ONT_GLB_ADDR + 0x1418,   0x1418,   asicRW,     0x00001FFF,     0,      0,     0,      0,     "PCS delay config"},
   [mvAsicReg_EPON_PCS_STATS_FEC_0]                  = {mvAsicReg_EPON_PCS_STATS_FEC_0,                  MV_ASIC_ONT_GLB_ADDR + 0x141C,   0x141C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats Fec 0"},
   [mvAsicReg_EPON_PCS_STATS_FEC_1]                  = {mvAsicReg_EPON_PCS_STATS_FEC_1,                  MV_ASIC_ONT_GLB_ADDR + 0x1420,   0x1420,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats Fec 1"},
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h
index 6fa151b..96a6ba3 100755
--- a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h
@@ -256,6 +256,8 @@
   mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID     = 134,  /* UtmCfgOmciPvalid                */
   mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD           = 135,  /* UtmCfgTcPeriod                  */
   mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID     = 136,  /* UtmCfgTcPeriodValid             */
+  mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP           = 137,  /* UtmActiveTxBitmap               */
+  mvAsicReg_GPON_UTM_ACTIVE_TX_BITMAP_VALID     = 138,  /* UtmActiveTxBitmapValid          */
 
   /* SGL Registers */
   /* ============= */
@@ -419,52 +421,56 @@
 
   /*  EPON PCS Registers         */
   /* =========================== */
-  mvAsicReg_EPON_PCS_CONFIGURATION                   = 284,
-  mvAsicReg_EPON_PCS_DELAY_CONFIG                    = 285,
-  mvAsicReg_EPON_PCS_STATS_FEC_0                     = 286,
-  mvAsicReg_EPON_PCS_STATS_FEC_1                     = 287,
-  mvAsicReg_EPON_PCS_STATS_FEC_2                     = 288,
-  mvAsicReg_EPON_PCS_STATS_0                         = 290,
-  mvAsicReg_EPON_PCS_STATS_1                         = 291,
-  mvAsicReg_EPON_PCS_STATS_2                         = 292,
-  mvAsicReg_EPON_PCS_STATS_3                         = 293,
-  mvAsicReg_EPON_PCS_STATS_4                         = 294,
-  mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS                 = 295,
+  mvAsicReg_EPON_PCS_CONFIGURATION                   = 284, 
+  
+  mvAsicReg_EPON_PCS_CONFIGURATION_RX_ENABLE         = 285, 
+  mvAsicReg_EPON_PCS_CONFIGURATION_TX_ENABLE         = 286,
+
+  mvAsicReg_EPON_PCS_DELAY_CONFIG                    = 287,
+  mvAsicReg_EPON_PCS_STATS_FEC_0                     = 288,
+  mvAsicReg_EPON_PCS_STATS_FEC_1                     = 289,
+  mvAsicReg_EPON_PCS_STATS_FEC_2                     = 290,
+  mvAsicReg_EPON_PCS_STATS_0                         = 292,
+  mvAsicReg_EPON_PCS_STATS_1                         = 293,
+  mvAsicReg_EPON_PCS_STATS_2                         = 294,
+  mvAsicReg_EPON_PCS_STATS_3                         = 295,
+  mvAsicReg_EPON_PCS_STATS_4                         = 296,
+  mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS                 = 297,
 
   /*  EPON DDM Registers         */
   /* =========================== */
-  mvAsicReg_EPON_DDM_DELAY_CONFIG                    = 296,
-  mvAsicReg_EPON_DDM_TX_POLARITY                     = 297,
+  mvAsicReg_EPON_DDM_DELAY_CONFIG                    = 298,
+  mvAsicReg_EPON_DDM_TX_POLARITY                     = 299,
   /* statistics */
-  mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT              = 298,
-  mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT            = 299,
-  mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT             = 300,
-  mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT            = 301,
-  mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT            = 302,
-  mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT          = 303,
-  mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT            = 304,
-  mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT    = 305,
-  mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT    = 306,
-  mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT     = 307,
-  mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT            = 308,
-  mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT        = 309,
+  mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT              = 300,
+  mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT            = 301,
+  mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT             = 302,
+  mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT            = 303,
+  mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT            = 304,
+  mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT          = 305,
+  mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT            = 306,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT    = 307,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT    = 308,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT     = 309,
+  mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT            = 310,
+  mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT        = 311,
 
   /*  EPON Control Packet queue Registers   */
   /* =====================================  */
-  mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ                  = 310,
-  mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED                  = 311,
-  mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ                  = 312,
-  mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED                  = 313,
-  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L               = 314,
-  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H               = 315,
-  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED                 = 316,
-  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L               = 317,
-  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H               = 318,
-  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED                 = 319,
-  mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE                 = 320,
-  mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE                  = 321,
-  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE                = 322,
-  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE                 = 323,
+  mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ                  = 312,
+  mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED                  = 313,
+  mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ                  = 314,
+  mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED                  = 315,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L               = 316,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H               = 317,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED                 = 318,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L               = 319,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H               = 320,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED                 = 321,
+  mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE                 = 322,
+  mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE                  = 323,
+  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE                = 324,
+  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE                 = 325,
 
 
   /*  P2P Registers                         */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h
index c5c0f4b..76f69cc 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h
@@ -723,6 +723,8 @@
 #define DEV_IP_MAPPING_TABLE		( DEV_88E6351_FAMILY )
 #define DEV_EEPROM					( DEV_88E6351_FAMILY )
 
+/*PIRL Alpha factor macro for 6510 internal switch*/
+#define PIRL_ALPHA 6250000
 
 /* Macros to utilize Device Group */
 
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h
index 6e238e6..4b41fef 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h
@@ -3895,6 +3895,63 @@
 
 };
 
+/*
+ * typedef: struct PIRL_PARA_TBL_T
+ *
+ * Description: PIRL parameter table structure
+ *
+ * Fields:
+ *      BI     - bucket increment 
+ *      BRF    - bucket rate factor
+ *      CBS    - Committed Burst Size
+ *      EBS    - Excess Burst Size
+ */
+typedef struct {
+	GT_U32 BI;
+	GT_U32 BRF;
+	GT_U32 CBS;
+	GT_U32 EBS;
+} PIRL_PARA_TBL_T;
+
+/*special rate which can not be calculated by formula*/
+typedef enum {
+	PIRL_RATE_NO_LIMIT = 0,
+	PIRL_RATE_64K,
+	PIRL_RATE_128K,
+	PIRL_RATE_192K,
+	PIRL_RATE_256K,
+	PIRL_RATE_320K,
+	PIRL_RATE_384K,
+	PIRL_RATE_448K,
+	PIRL_RATE_512K,
+	PIRL_RATE_576K,
+	PIRL_RATE_640K,
+	PIRL_RATE_704K,
+	PIRL_RATE_768K,
+	PIRL_RATE_832K,
+	PIRL_RATE_896K,
+	PIRL_RATE_960K,
+	PIRL_RATE_1M,
+	PIRL_RATE_2M,
+	PIRL_RATE_3M,
+	PIRL_RATE_4M,
+	PIRL_RATE_5M,
+	PIRL_RATE_6M,
+	PIRL_RATE_7M,
+	PIRL_RATE_8M,
+	PIRL_RATE_9M,
+	PIRL_RATE_10M,
+	PIRL_RATE_11M,
+	PIRL_RATE_12M,
+	PIRL_RATE_13M,
+	PIRL_RATE_14M,
+	PIRL_RATE_15M,
+	PIRL_RATE_16M,
+	PIRL_RATE_17M,
+	PIRL_RATE_18M,
+	PIRL_RATE_19M,
+	PIRL_RATE_20M
+} PIRL_SPECIAL_RATE_ENUM_T;
 
 #ifdef __cplusplus
 }
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h
index f02972e..d2828e7 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h
@@ -3199,6 +3199,42 @@
     IN  GT_BOOL  mode
 );
 
+/*******************************************************************************
+* gprtSetPortSpeedDuplexMode
+*
+* DESCRIPTION:
+* 		Sets speed and duplex mode for a specific logical port. This function
+*		will keep the loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*		dMode - Duplex mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+* data sheet register 0.8  - Duplex mode
+*******************************************************************************/
+GT_STATUS gprtSetPortSpeedDuplexMode
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_SPEED speed,
+IN GT_BOOL dMode
+);
 
 /*******************************************************************************
 * gqosSetPortDefaultTc
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c
index efe1f05..4b14c5b 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c
@@ -515,9 +515,6 @@
     GT_STATUS       	retVal;
     GT_U8       	port; 
     GT_LPORT       	lport; 
-    GT_VTU_ENTRY 	tmpVtuEntry;
-	GT_BOOL		 	found;
-	int				count = 5000;
     GT_VTU_ENTRY    	entry;
 
     DBG_INFO(("gvtuAddEntry Called.\n"));
@@ -611,25 +608,6 @@
         return retVal;
     }
 
-	/* verify that the given entry has been added */
-	tmpVtuEntry.vid = vtuEntry->vid;
-	tmpVtuEntry.DBNum = vtuEntry->DBNum;
-
-	if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&found)) != GT_OK)
-	{
-		while(count--);
-		if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&found)) != GT_OK)
-		{
-			DBG_INFO(("Added entry cannot be found\n"));
-			return retVal;
-		}
-	}
-	if(found == GT_FALSE)
-	{
-		DBG_INFO(("Added entry cannot be found\n"));
-		return GT_FAIL;
-	}
-
     DBG_INFO(("OK.\n"));
     return GT_OK;
 }
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c
index f5b2193..28717e0 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c
@@ -20,6 +20,46 @@
 #include <linux/init.h>
 #include <linux/string.h>
 
+/* special ingress rate limit para */
+static PIRL_PARA_TBL_T pirl2RateLimitParaTbl[] = {
+	/* BI----BRF-----CBS-------EBS--------------------*/
+	{0x000, 0x00, 0x000000, 0x000000},/*No rate limit*/
+	{0x186, 0x04, 0xD06470, 0xFFFFF0},/*PIRL_RATE_64K*/
+	{0x30D, 0x10, 0x415370, 0xFFFFF0},/*PIRL_RATE_128K*/
+	{0x186, 0x0C, 0x712D70, 0xFFFFF0},/*PIRL_RATE_192K*/
+	{0x186, 0x10, 0xA0C8F0, 0xFFFFF0},/*PIRL_RATE_256K*/
+	{0x138, 0x10, 0x4191F0, 0xFFFFF0},/*PIRL_RATE_320K*/
+	{0x0C3, 0x0C, 0x712D70, 0xFFFFF0},/*PIRL_RATE_384K*/
+	{0x0C3, 0x0E, 0x595FB0, 0xFFFFF0},/*PIRL_RATE_448K*/
+	{0x0C3, 0x10, 0x4191F0, 0xFFFFF0},/*PIRL_RATE_512K*/
+	{0x0C3, 0x12, 0x29C430, 0xFFFFF0},/*PIRL_RATE_576K*/
+	{0x09C, 0x10, 0x4191F0, 0xFFFFF0},/*PIRL_RATE_640K*/
+	{0x07C, 0x0E, 0x597EF0, 0xFFFFF0},/*PIRL_RATE_704K*/
+	{0x082, 0x10, 0x71E8F0, 0xFFFFF0},/*PIRL_RATE_768K*/
+	{0x078, 0x10, 0x4191F0, 0xFFFFF0},/*PIRL_RATE_832K*/
+	{0x084, 0x13, 0x1E69F0, 0xFFFFF0},/*PIRL_RATE_896K*/
+	{0x027, 0x06, 0xB896B0, 0xFFFFF0},/*PIRL_RATE_960K*/
+	{0x031, 0x08, 0xA28A28, 0xFFFFF0},/*PIRL_RATE_1M*/
+	{0x031, 0x10, 0x451460, 0xFFFFF0},/*PIRL_RATE_2M*/
+	{0x021, 0x10, 0x432C18, 0xFFFFF0},/*PIRL_RATE_3M*/
+	{0x01C, 0x12, 0x2A6070, 0xFFFFF0},/*PIRL_RATE_4M*/
+	{0x065, 0x51, 0x029810, 0xFFFFF0},/*PIRL_RATE_5M*/
+	{0x037, 0x35, 0x0186A0, 0xFFFFF0},/*PIRL_RATE_6M*/
+	{0x051, 0x5B, 0x0222E0, 0xFFFFF0},/*PIRL_RATE_7M*/
+	{0x035, 0x44, 0x0186A0, 0xFFFFF0},/*PIRL_RATE_8M*/
+	{0x03B, 0x55, 0x0186A0, 0xFFFFF0},/*PIRL_RATE_9M*/
+	{0x030, 0x4D, 0x015F90, 0xFFFFF0},/*PIRL_RATE_10M*/
+	{0x033, 0x5A, 0x0186A0, 0xFFFFF0},/*PIRL_RATE_11M*/
+	{0x033, 0x62, 0x015F90, 0xFFFFF0},/*PIRL_RATE_12M*/
+	{0x02F, 0x62, 0x015F90, 0xFFFFF0},/*PIRL_RATE_13M*/
+	{0x02D, 0x65, 0x013880, 0xFFFFF0},/*PIRL_RATE_14M*/
+	{0x02A, 0x65, 0x013880, 0xFFFFF0},/*PIRL_RATE_15M*/
+	{0x030, 0x7B, 0x015F90, 0xFFFFF0},/*PIRL_RATE_16M*/
+	{0x02F, 0x80, 0x015F90, 0xFFFFF0},/*PIRL_RATE_17M*/
+	{0x02A, 0x79, 0x013880, 0xFFFFF0},/*PIRL_RATE_18M*/
+	{0x02D, 0x89, 0x013880, 0xFFFFF0},/*PIRL_RATE_19M*/
+	{0x02C, 0x8D, 0x013880, 0xFFFFF0},/*PIRL_RATE_20M*/
+};
 
 /****************************************************************************/
 /* PIRL operation function declaration.                                    */
@@ -989,6 +1029,37 @@
 	return GT_OK;	
 }
 
+/*find the greatest common divisor for two interger
+*used to calculate BRF and BI
+*/
+static GT_U32 pirl2GetGCD
+(	IN GT_U32 data1,
+	IN GT_U32 data2
+)
+{
+	GT_U32 temp1, temp2, temp;
+
+	if (data1 == 0 || data2 == 0)
+		return 1;
+
+	temp1 = data1;
+	temp2 = data2;
+
+	if (temp1 < temp2) {
+		temp = temp1;
+		temp1 = temp2;
+		temp2 = temp;
+	}
+	temp = temp1 % temp2;
+	while(temp) {
+		temp1 = temp2;
+		temp2 = temp;
+		temp = temp1 % temp2;
+	}
+
+	return temp2;
+}
+
 /*
  * convert PIRL Data structure to PIRL Resource structure.
  * if PIRL Data is not valid, return GT_BAD_PARARM;
@@ -1002,8 +1073,9 @@
 {
 	GT_U32 typeMask;
 	GT_U32 data;
-    GT_U32 bktIncrementFactor = 1;
-    
+	GT_U32 burst_allocation;
+	GT_U32 pirl2_cir;
+	GT_U32 pirl_gcd = 1;
 
 	gtMemSet((void*)res,0,sizeof(GT_PIRL2_RESOURCE));
 
@@ -1086,60 +1158,55 @@
 			return GT_BAD_PARAM;
 		}
 
-		if(pirlData->ingressRate < 1000)	/* less than 1Mbps */
-		{
+		if (pirlData->ingressRate < 1000) { /* less than 1Mbps */
 			/* it should be divided by 64 */
 			if(pirlData->ingressRate % 64)
 			{
 				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
 				return GT_BAD_PARAM;
 			}
-			res->bktRateFactor = pirlData->ingressRate/64 * 32;
-		}
-		else if(pirlData->ingressRate < 10000)	/* less than or equal to 10Mbps */
-		{
+			/* Less than 1Mbps, use special value */
+			res->bktIncrement = pirl2RateLimitParaTbl[pirlData->ingressRate / 64].BI;
+			res->bktRateFactor = pirl2RateLimitParaTbl[pirlData->ingressRate / 64].BRF;
+			res->cbsLimit = pirl2RateLimitParaTbl[pirlData->ingressRate / 64].CBS;
+			res->ebsLimit = pirl2RateLimitParaTbl[pirlData->ingressRate / 64].EBS;
+		} else if(pirlData->ingressRate <= 20000) {/* greater or equal to 1Mbps, and less than or equal to 20Mbps */
 			/* it should be divided by 1000 */
 			if(pirlData->ingressRate % 1000)
 			{
 				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
 				return GT_BAD_PARAM;
 			}
-            res->bktRateFactor = pirlData->ingressRate/1000 * 4;
-		}
-		else /* greater than or equal to 10Mbps */
-		{
-			/* it should be divided by 1000 */
-			if(pirlData->ingressRate % 1000)
-			{
-				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
-				return GT_BAD_PARAM;
+			res->bktIncrement = pirl2RateLimitParaTbl[PIRL_RATE_960K + pirlData->ingressRate / 1000].BI;
+			res->bktRateFactor = pirl2RateLimitParaTbl[PIRL_RATE_960K + pirlData->ingressRate / 1000].BRF;
+			res->cbsLimit = pirl2RateLimitParaTbl[PIRL_RATE_960K + pirlData->ingressRate / 1000].CBS;
+			res->ebsLimit = pirl2RateLimitParaTbl[PIRL_RATE_960K + pirlData->ingressRate / 1000].EBS;
+		} else {/* greater than 20Mbps */
+			if (pirlData->ingressRate < 100000) {
+				/* it should be divided by 1000, if less than 100Mbps*/
+				if(pirlData->ingressRate % 1000)
+				{
+					DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+					return GT_BAD_PARAM;
+				}
+			} else {
+				/* it should be divided by 10000, if more or equal than 100Mbps */
+				if(pirlData->ingressRate % 10000)
+				{
+					DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+					return GT_BAD_PARAM;
+				}
 			}
-            res->bktRateFactor = pirlData->ingressRate/1000 * 8;
-            bktIncrementFactor = 10;
-           
-		}
-	
-		/*If custom ebslimit exists, use the custom value, otherwize use recommended value*/
-		if(pirlData->customSetup.ebsLimit)
-		{
-           res->ebsLimit = pirlData->customSetup.ebsLimit;
-		}
-		else
-		{
-		res->ebsLimit = RECOMMENDED_ESB_LIMIT(dev, pirlData->ingressRate);
-		}
+			pirl2_cir = pirlData->ingressRate * 1000;
 
-		/*If custom cbslimit exists, use the custom value, otherwize use recommended value*/
-		if(pirlData->customSetup.cbsLimit)
-		{
-           res->cbsLimit = pirlData->customSetup.cbsLimit;
+			burst_allocation = pirl2_cir;
+
+			pirl_gcd = pirl2GetGCD(pirl2_cir, PIRL_ALPHA);
+			res->bktRateFactor = pirl2_cir / pirl_gcd;
+			res->bktIncrement = PIRL_ALPHA  / pirl_gcd;
+			res->ebsLimit = RECOMMENDED_ESB_LIMIT(dev, pirlData->ingressRate);
+			res->cbsLimit = RECOMMENDED_CBS_LIMIT(dev, pirlData->ingressRate);
 		}
-		else
-		{
-		res->cbsLimit = RECOMMENDED_CBS_LIMIT(dev, pirlData->ingressRate);
-		}
-	
-		res->bktIncrement = RECOMMENDED_BUCKET_INCREMENT(dev, pirlData->ingressRate)*bktIncrementFactor;
 	}
 
 	switch(pirlData->bktRateType)
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c
index edec2c3..bff23d3 100755
--- a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c
@@ -406,12 +406,12 @@
 	IN GT_PHY_AUTO_MODE mode
 )
 {
-    GT_U16 		u16Data;
+	GT_U16 		u16Data;
 	GT_STATUS	status;
-	GT_BOOL			autoOn;
-	GT_U16			pageReg;
+	GT_BOOL		autoOn;
+	GT_U16		pageReg;
 
-    DBG_INFO(("phySetAutoMode Called.\n"));
+	DBG_INFO(("phySetAutoMode Called.\n"));
 
 	if (!(phyInfo->flag & GT_PHY_GIGABIT))
 	{
@@ -420,10 +420,13 @@
    		    return status;
 		}
 
-		u16Data = QD_PHY_SPEED | QD_PHY_DUPLEX | QD_PHY_AUTONEGO;
+		if (hwReadPhyReg(dev, hwPort, QD_PHY_CONTROL_REG, &u16Data) != GT_OK)
+			return GT_FAIL;
 
-    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
-        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+		u16Data = (u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
+
+		DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+			 hwPort,QD_PHY_CONTROL_REG,u16Data));
 
 		/* soft reset */
 		return hwPhyReset(dev,hwPort,u16Data);
@@ -434,6 +437,10 @@
 		return GT_FAIL;
 	}
 
+	/* Read to Phy Control Register.  */
+	if(hwReadPagedPhyReg(dev, hwPort, 0, QD_PHY_CONTROL_REG, phyInfo->anyPage, &u16Data) != GT_OK)
+		return GT_FAIL;
+
 	if(phyInfo->flag & GT_PHY_COPPER)
 	{
 		if((status=gigCopperSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
@@ -441,14 +448,14 @@
    		    return status;
 		}
 
-		u16Data = QD_PHY_AUTONEGO;
+		u16Data = (u16Data & (QD_PHY_SPEED_MSB | QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
 
-    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
-        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+		DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+			 hwPort,QD_PHY_CONTROL_REG,u16Data));
 
-	    /* Write to Phy Control Register.  */
-	    if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
-    		return GT_FAIL;
+		/* Write to Phy Control Register.  */
+		if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
+			return GT_FAIL;
 	}
 	else if(phyInfo->flag & GT_PHY_FIBER)
 	{
@@ -456,14 +463,14 @@
 		{
    		    return status;
 		}
-		u16Data = QD_PHY_AUTONEGO;
+		u16Data = (u16Data & (QD_PHY_SPEED_MSB | QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
 
-    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
-        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+		DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+			 hwPort,QD_PHY_CONTROL_REG,u16Data));
 
-	    /* Write to Phy Control Register.  */
-	    if(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
-    		return GT_FAIL;
+		/* Write to Phy Control Register.  */
+		if(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
+			return GT_FAIL;
 	}
 
 	if(driverPagedAccessStop(dev,hwPort,phyInfo->pageType,autoOn,pageReg) != GT_OK)
@@ -1037,15 +1044,15 @@
 IN GT_PHY_SPEED speed
 )
 {
-    GT_U8           hwPort;         /* the physical port number     */
-    GT_U16 			u16Data;
-	GT_PHY_INFO		phyInfo;
-	GT_STATUS		retVal;
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 		u16Data;
+	GT_PHY_INFO	phyInfo;
+	GT_STATUS	retVal;
 
-    DBG_INFO(("gprtSetPortSpeed Called.\n"));
-    
-    /* translate LPORT to hardware port */
-    hwPort = GT_LPORT_2_PHY(port);
+	DBG_INFO(("gprtSetPortSpeed Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
 
 	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
 
@@ -1063,11 +1070,11 @@
 		return GT_FAIL;
 	}
 
-    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
 	{
-        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
 		gtSemGive(dev,dev->phyRegsSem);
-        return GT_FAIL;
+        	return GT_FAIL;
 	}
 
 	switch(speed)
@@ -1078,10 +1085,10 @@
 				gtSemGive(dev,dev->phyRegsSem);
 				return GT_BAD_PARAM;
 			}
-			u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX);
+			u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX);
 			break;
 		case PHY_SPEED_100_MBPS:
-			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX)) | QD_PHY_SPEED;
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED;
 			break;
 		case PHY_SPEED_1000_MBPS:
 			if (!(phyInfo.flag & GT_PHY_GIGABIT))
@@ -1089,15 +1096,15 @@
 				gtSemGive(dev,dev->phyRegsSem);
 				return GT_BAD_PARAM;
 			}
-			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX)) | QD_PHY_SPEED_MSB;
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED_MSB;
 			break;
 		default:
 			gtSemGive(dev,dev->phyRegsSem);
 			return GT_FAIL;
 	}
 
-    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
-              hwPort,QD_PHY_CONTROL_REG,u16Data));
+	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+		 hwPort,QD_PHY_CONTROL_REG,u16Data));
 
 	retVal = hwPhyReset(dev,hwPort,u16Data);
   	gtSemGive(dev,dev->phyRegsSem);
@@ -1258,11 +1265,11 @@
 
 	if(state)
 	{
-		u16Data = (u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
+		u16Data = (u16Data & (QD_PHY_SPEED_MSB | QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
 	}
 	else
 	{
-		u16Data = u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX);
+		u16Data = u16Data & (QD_PHY_SPEED_MSB |QD_PHY_SPEED | QD_PHY_DUPLEX | QD_PHY_LOOPBACK);
 	}
 
 
@@ -1519,7 +1526,7 @@
         return GT_FAIL;
 	}
 
-	u16Data &= (QD_PHY_DUPLEX | QD_PHY_SPEED);
+	u16Data &= (QD_PHY_DUPLEX | QD_PHY_SPEED | QD_PHY_SPEED_MSB);
 	u16Data |= (QD_PHY_RESTART_AUTONEGO | QD_PHY_AUTONEGO);
 
     DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
@@ -1678,6 +1685,116 @@
 }
 
 /*******************************************************************************
+* gprtSetPortSpeedDuplexMode
+*
+* DESCRIPTION:
+* 		Sets speed and duplex mode for a specific logical port. This function
+*		will keep the loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*		dMode - Duplex mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+* data sheet register 0.8  - Duplex mode
+*******************************************************************************/
+GT_STATUS gprtSetPortSpeedDuplexMode
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_SPEED speed,
+IN GT_BOOL dMode
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 		u16Data;
+	GT_PHY_INFO	phyInfo;
+	GT_STATUS	retVal;
+
+	DBG_INFO(("gprtSetPortSpeed Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+		DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/* Set Duplex mode */
+	if (dMode)
+		u16Data = u16Data | QD_PHY_DUPLEX;
+	else
+		u16Data = u16Data & (~QD_PHY_DUPLEX);
+
+	switch(speed)
+	{
+		case PHY_SPEED_10_MBPS:
+			if ((phyInfo.flag & GT_PHY_GIGABIT) && !(phyInfo.flag & GT_PHY_COPPER))
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+			}
+			u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX);
+			break;
+		case PHY_SPEED_100_MBPS:
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED;
+			break;
+		case PHY_SPEED_1000_MBPS:
+			if (!(phyInfo.flag & GT_PHY_GIGABIT))
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+			}
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED_MSB;
+			break;
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+	}
+
+	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+		 hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+	retVal = hwPhyReset(dev,hwPort,u16Data);
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+/*******************************************************************************
 * gprtSetPortAutoMode
 *
 * DESCRIPTION:
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c
index 8d382d0..3217041 100755
--- a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c
@@ -851,7 +851,7 @@
 }
 
 /* Low level TDM interrupt service routine */
-MV_VOID mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo)
+MV_32 mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo)
 {
 	MV_U32 causeReg, maskReg, causeAndMask;
 	MV_U32 intAckBits = 0, currDesc;
@@ -895,7 +895,7 @@
 	if (tdmEnable == MV_FALSE) {
 		MV_TRC_REC("TDM is disabled - quit low level ISR\n");
 		MV_REG_WRITE(TDM_CAUSE_REG, ~intAckBits);
-		return;
+		return 0;
 	}
 
 	/* Handle TDM Error/s */
@@ -943,7 +943,7 @@
 	MV_REG_WRITE(TDM_CAUSE_REG, ~intAckBits);
 
 	TRC_REC("<-%s\n", __func__);
-	return;
+	return 0;
 }
 
 static MV_VOID mvCommUnitDescChainBuild(MV_VOID)
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h
index 620e458..966027d 100755
--- a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h
@@ -188,7 +188,7 @@
 /* CommUnit APIs */
 	MV_STATUS mvCommUnitHalInit(MV_TDM_PARAMS *pTdmParams, MV_TDM_HAL_DATA *halData);
 	MV_STATUS mvCommUnitWinInit(MV_UNIT_WIN_INFO *pAddrWinMap);
-	MV_VOID mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo);
+	MV_32 mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo);
 	MV_VOID mvCommUnitPcmStart(MV_VOID);
 	MV_VOID mvCommUnitPcmStop(MV_VOID);
 	MV_STATUS mvCommUnitTx(MV_U8 *pTdmTxBuff);
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c
index eb76460..55bf2d9 100755
--- a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c
@@ -107,6 +107,19 @@
 static MV_BAND_MODE tdmBandMode;
 static MV_TDM_CH_INFO *tdmChInfo[MV_TDM_TOTAL_CHANNELS] = { NULL, NULL };
 
+static MV_U8 intLock;
+static MV_U32 intRxCount;
+static MV_U32 intTxCount;
+static MV_U32 intRx0Count;
+static MV_U32 intTx0Count;
+static MV_U32 intRx1Count;
+static MV_U32 intTx1Count;
+static MV_U32 intRx0Miss;
+static MV_U32 intTx0Miss;
+static MV_U32 intRx1Miss;
+static MV_U32 intTx1Miss;
+static MV_U32 pcmRestartCount;
+
 MV_STATUS mvTdmHalInit(MV_TDM_PARAMS *tdmParams, MV_TDM_HAL_DATA *halData)
 {
 	MV_U8 ch;
@@ -119,9 +132,15 @@
 	/* Init globals */
 	rxInt = txInt = 0;
 	rxFull = txEmpty = BUFF_INVALID;
-	tdmEnable = 0;
+	tdmEnable = 0, intLock = 0;
 	spiMode = halData->spiMode;
 	pcmFormat = tdmParams->pcmFormat;
+	intRxCount = 0, intTxCount = 0;
+	intRx0Count = 0, intTx0Count = 0;
+	intRx1Count = 0, intTx1Count = 0;
+	intRx0Miss = 0, intTx0Miss = 0;
+	intRx1Miss = 0, intTx1Miss = 0;
+	pcmRestartCount = 0;
 
 	if (tdmParams->samplingPeriod > MV_TDM_MAX_SAMPLING_PERIOD)
 		factor = 1;	/* use base sample period(10ms) */
@@ -160,8 +179,8 @@
 	}
 
 	/* Config TDM */
-	MV_REG_BIT_RESET(TDM_SPI_MUX_REG, 1);	/* enable TDM/SPI interface */
-	MV_REG_BIT_SET(TDM_MISC_REG, BIT0);	/* sw reset to TDM for 5181L-A1 & up */
+	MV_REG_BIT_RESET(TDM_SPI_MUX_REG, BIT0);	/* enable TDM/SPI interface */
+	MV_REG_BIT_SET(TDM_MISC_REG, BIT0);		/* sw reset to TDM for 5181L-A1 & up */
 	MV_REG_WRITE(INT_RESET_SELECT_REG, CLEAR_ON_ZERO);	/* int cause is not clear on read */
 	MV_REG_WRITE(INT_EVENT_MASK_REG, 0x3ffff);	/* all interrupt bits latched in status */
 	MV_REG_WRITE(INT_STATUS_MASK_REG, 0);	/* disable interrupts */
@@ -344,6 +363,7 @@
 	MV_TRC_REC("->%s\n", __func__);
 
 	tdmEnable = 1;		/* TDM is enabled  */
+	intLock = 0;
 	mvTdmReset();
 
 	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
@@ -471,9 +491,12 @@
 }
 
 /* Low level TDM interrupt service routine */
-MV_VOID mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo)
+MV_32 mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo)
 {
 	MV_U32 statusReg, maskReg, statusAndMask;
+	MV_32 ret = 0;
+	MV_32 intTxMiss = -1;
+	MV_32 intRxMiss = -1;
 	MV_U8 ch;
 
 	MV_TRC_REC("->%s\n", __func__);
@@ -512,68 +535,107 @@
 	}
 
 	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
-		if (statusAndMask & TDM_INT_TX(ch)) {
-			/* Give next buff to TDM and set curr buff as empty */
-			if ((statusAndMask & TX_BIT(ch)) && tdmEnable) {
-				MV_TRC_REC("Tx interrupt(ch%d) !!!\n", ch);
 
-				/* MV_OK -> Tx is done for both channels */
-				if (mvTdmChTxLow(ch) == MV_OK) {
-					MV_TRC_REC("Assign Tx aggregate buffer for further processing\n");
-					tdmIntInfo->tdmTxBuff = txAggrBuffVirt;
-					tdmIntInfo->intType |= MV_TX_INT;
+		/* Give next buff to TDM and set curr buff as empty */
+		if ((statusAndMask & TX_BIT(ch)) && tdmEnable && !intLock) {
+			MV_TRC_REC("Tx interrupt(ch%d) !!!\n", ch);
+
+			intTxCount++;
+			if (ch == 0) {
+				intTx0Count++;
+				if (intTx0Count <= intTx1Count) {
+					intTxMiss = 0;
+					intTx0Miss++;
+				}
+			} else {
+				intTx1Count++;
+				if (intTx1Count < intTx0Count) {
+					intTxMiss = 1;
+					intTx1Miss++;
 				}
 			}
 
-			if (statusAndMask & TX_UNDERFLOW_BIT(ch)) {
-				MV_TRC_REC("Tx underflow(ch%d) - checking for root cause...\n", ch);
-				if (tdmEnable) {
-					MV_TRC_REC("Tx underflow ERROR\n");
-					tdmIntInfo->intType |= MV_TX_ERROR_INT;
-					if (!(statusAndMask & TX_BIT(ch))) {
-						MV_TRC_REC("Trying to recover for ch(%d)\n", ch);
-						/* Set HW ownership */
-						MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + TX_OWN_BYTE_OFFS, OWN_BY_HW);
-						/* Enable Tx */
-						MV_REG_BYTE_WRITE(CH_ENABLE_REG(ch) + TX_ENABLE_BYTE_OFFS, CH_ENABLE);
+			/* MV_OK -> Tx is done for both channels */
+			if (mvTdmChTxLow(ch) == MV_OK) {
+				MV_TRC_REC("Assign Tx aggregate buffer for further processing\n");
+				tdmIntInfo->tdmTxBuff = txAggrBuffVirt;
+				tdmIntInfo->intType |= MV_TX_INT;
+			}
+		}
+	}
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+
+		if ((statusAndMask & RX_BIT(ch)) && tdmEnable && !intLock) {
+			MV_TRC_REC("Rx interrupt(ch%d) !!!\n", ch);
+
+			intRxCount++;
+			if (ch == 0) {
+				intRx0Count++;
+				if (intRx0Count <= intRx1Count) {
+					intRxMiss = 0;
+					intRx0Miss++;
+				}
+			} else {
+				intRx1Count++;
+				if (intRx1Count < intRx0Count) {
+					intRxMiss = 1;
+					intRx1Miss++;
+				}
+			}
+
+			/* MV_OK -> Rx is done for both channels */
+			if (mvTdmChRxLow(ch) == MV_OK) {
+				MV_TRC_REC("Assign Rx aggregate buffer for further processing\n");
+				tdmIntInfo->tdmRxBuff = rxAggrBuffVirt;
+				tdmIntInfo->intType |= MV_RX_INT;
+			}
+		}
+	}
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+
+		if (statusAndMask & TX_UNDERFLOW_BIT(ch)) {
+
+			MV_TRC_REC("Tx underflow(ch%d) - checking for root cause...\n", ch);
+			if (tdmEnable) {
+				MV_TRC_REC("Tx underflow ERROR\n");
+				tdmIntInfo->intType |= MV_TX_ERROR_INT;
+				if (!(statusAndMask & TX_BIT(ch))) {
+					ret = -1;
+					/* MV_OK -> Tx is done for both channels */
+					if (mvTdmChTxLow(ch) == MV_OK) {
+						MV_TRC_REC("Assign Tx aggregate buffer for further processing\n");
+						tdmIntInfo->tdmTxBuff = txAggrBuffVirt;
+						tdmIntInfo->intType |= MV_TX_INT;
 					}
-				} else {
-					MV_TRC_REC("Expected Tx underflow(not an error)\n");
+				}
+			} else {
+				MV_TRC_REC("Expected Tx underflow(not an error)\n");
 					MV_REG_WRITE(INT_STATUS_MASK_REG,
 						     MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_TX(ch))));
-				}
 			}
 		}
 
-		if (statusAndMask & TDM_INT_RX(ch)) {
-			if ((statusAndMask & RX_BIT(ch)) && tdmEnable) {
-				MV_TRC_REC("Rx interrupt(ch%d) !!!\n", ch);
 
-				/* MV_OK -> Rx is done for both channels */
-				if (mvTdmChRxLow(ch) == MV_OK) {
-					MV_TRC_REC("Assign Rx aggregate buffer for further processing\n");
-					tdmIntInfo->tdmRxBuff = rxAggrBuffVirt;
-					tdmIntInfo->intType |= MV_RX_INT;
-				}
-			}
-
-			if (statusAndMask & RX_OVERFLOW_BIT(ch)) {
-				MV_TRC_REC("Rx overflow(ch%d) - checking for root cause...\n", ch);
-				if (tdmEnable) {
-					MV_TRC_REC("Rx overflow ERROR\n");
-					tdmIntInfo->intType |= MV_RX_ERROR_INT;
-					if (!(statusAndMask & RX_BIT(ch))) {
-						MV_TRC_REC("Trying to recover for ch(%d)\n", ch);
-						/* Set HW ownership */
-						MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + RX_OWN_BYTE_OFFS, OWN_BY_HW);
-						/* Enable Rx */
-						MV_REG_BYTE_WRITE(CH_ENABLE_REG(ch) + RX_ENABLE_BYTE_OFFS, CH_ENABLE);
+		if (statusAndMask & RX_OVERFLOW_BIT(ch)) {
+			MV_TRC_REC("Rx overflow(ch%d) - checking for root cause...\n", ch);
+			if (tdmEnable) {
+				MV_TRC_REC("Rx overflow ERROR\n");
+				tdmIntInfo->intType |= MV_RX_ERROR_INT;
+				if (!(statusAndMask & RX_BIT(ch))) {
+					ret = -1;
+					/* MV_OK -> Rx is done for both channels */
+					if (mvTdmChRxLow(ch) == MV_OK) {
+						MV_TRC_REC("Assign Rx aggregate buffer for further processing\n");
+						tdmIntInfo->tdmRxBuff = rxAggrBuffVirt;
+						tdmIntInfo->intType |= MV_RX_INT;
 					}
-				} else {
-					MV_TRC_REC("Expected Rx overflow(not an error)\n");
-					MV_REG_WRITE(INT_STATUS_MASK_REG,
-						     MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_RX(ch))));
 				}
+			} else {
+				MV_TRC_REC("Expected Rx overflow(not an error)\n");
+				MV_REG_WRITE(INT_STATUS_MASK_REG,
+					     MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_RX(ch))));
 			}
 		}
 	}
@@ -581,8 +643,32 @@
 	/* clear TDM interrupts */
 	MV_REG_WRITE(INT_STATUS_REG, ~statusReg);
 
+	/* Check if interrupt was missed -> restart */
+	if  (intTxMiss != -1)  {
+		MV_TRC_REC("Missing Tx Interrupt Detected ch%d!!!\n", intTxMiss);
+		if (intTxMiss)
+			intTx1Count = intTx0Count;
+		else
+			intTx0Count  = (intTx1Count + 1);
+		ret = -1;
+	}
+
+	if  (intRxMiss != -1)  {
+		MV_TRC_REC("Missing Rx Interrupt Detected ch%d!!!\n", intRxMiss);
+		if (intRxMiss)
+			intRx1Count = intRx0Count;
+		else
+			intRx0Count  = (intRx1Count + 1);
+		ret = -1;
+	}
+
+	if (ret == -1) {
+		intLock = 1;
+		pcmRestartCount++;
+	}
+
 	MV_TRC_REC("<-%s\n", __func__);
-	return;
+	return ret;
 }
 
 static INLINE MV_STATUS mvTdmChTxLow(MV_U8 ch)
@@ -933,3 +1019,39 @@
 
 	MV_TRC_REC("<-%s\n", __func__);
 }
+
+MV_VOID mvTdmPcmIfReset(MV_VOID)
+{
+	MV_TRC_REC("->%s\n", __func__);
+
+	MV_REG_BIT_RESET(PCM_CTRL_REG, BIT0);
+
+	/* Wait a bit - might be fine tuned */
+	mvOsDelay(10);
+
+	MV_REG_WRITE(TDM_MISC_REG, 0);
+
+	/* Wait a bit more - might be fine tuned */
+	mvOsDelay(100);
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+#ifdef MV_TDM_EXT_STATS
+MV_VOID mvTdmExtStatsGet(MV_TDM_EXTENDED_STATS* tdmExtStats)
+{
+	tdmExtStats->intRxCount = intRxCount;
+	tdmExtStats->intTxCount = intTxCount;
+	tdmExtStats->intRx0Count = intRx0Count;
+	tdmExtStats->intTx0Count = intTx0Count;
+	tdmExtStats->intRx1Count = intRx1Count;
+	tdmExtStats->intTx1Count = intTx1Count;
+	tdmExtStats->intRx0Miss = intRx0Miss;
+	tdmExtStats->intTx0Miss = intTx0Miss;
+	tdmExtStats->intRx1Miss = intRx1Miss;
+	tdmExtStats->intTx1Miss = intTx1Miss;
+	tdmExtStats->pcmRestartCount = pcmRestartCount;
+
+	return;
+}
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h
index 3909a7f..1240739 100755
--- a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h
@@ -164,11 +164,27 @@
 	MV_FRAME_TS frameTs;
 } MV_TDM_HAL_DATA;
 
+#ifdef MV_TDM_EXT_STATS
+typedef struct {
+	MV_U32 intRxCount;
+	MV_U32 intTxCount;
+	MV_U32 intRx0Count;
+	MV_U32 intTx0Count;
+	MV_U32 intRx1Count;
+	MV_U32 intTx1Count;
+	MV_U32 intRx0Miss;
+	MV_U32 intTx0Miss;
+	MV_U32 intRx1Miss;
+	MV_U32 intTx1Miss;
+	MV_U32 pcmRestartCount;
+} MV_TDM_EXTENDED_STATS;
+#endif
+
 /* APIs */
 MV_STATUS mvTdmHalInit(MV_TDM_PARAMS *tdmParams, MV_TDM_HAL_DATA *halData);
 MV_STATUS mvTdmWinInit(MV_UNIT_WIN_INFO *addrWinMap);
 MV_VOID mvTdmRelease(MV_VOID);
-MV_VOID mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo);
+MV_32 mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo);
 MV_VOID mvTdmPcmStart(MV_VOID);
 MV_VOID mvTdmPcmStop(MV_VOID);
 MV_STATUS mvTdmTx(MV_U8 *tdmTxBuff);
@@ -180,4 +196,9 @@
 MV_U8 currTxSampleGet(MV_U8 ch);
 MV_VOID mvTdmIntEnable(MV_VOID);
 MV_VOID mvTdmIntDisable(MV_VOID);
+MV_VOID mvTdmPcmIfReset(MV_VOID);
+#ifdef MV_TDM_EXT_STATS
+MV_VOID mvTdmExtStatsGet(MV_TDM_EXTENDED_STATS* tdmExtStats);
+#endif
+
 #endif /* __INCmvTdmh */
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
deleted file mode 100644
index f02382a..0000000
--- a/arch/sh/boot/compressed/vmlinux.scr
+++ /dev/null
@@ -1,10 +0,0 @@
-SECTIONS
-{
-  .rodata.compressed : {
-	input_len = .;
-	LONG(input_data_end - input_data) input_data = .;
-	*(.data)
-	output_len = . - 4;
-	input_data_end = .;
-	}
-}
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
deleted file mode 100644
index 287c08f..0000000
--- a/arch/sh/boot/romimage/vmlinux.scr
+++ /dev/null
@@ -1,6 +0,0 @@
-SECTIONS
-{
-  .text : {
-	*(.data)
-	}
-}
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
deleted file mode 100644
index f7e2fa0..0000000
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* iptables module for the IPv4 and TCP ECN bits, Version 1.5
- *
- * (C) 2002 by Harald Welte <laforge@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <net/ip.h>
-#include <linux/tcp.h>
-#include <net/checksum.h>
-
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_ECN.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag modification");
-
-/* set ECT codepoint from IP header.
- * 	return false if there was an error. */
-static inline bool
-set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
-{
-	struct iphdr *iph = ip_hdr(skb);
-
-	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
-		__u8 oldtos;
-		if (!skb_make_writable(skb, sizeof(struct iphdr)))
-			return false;
-		iph = ip_hdr(skb);
-		oldtos = iph->tos;
-		iph->tos &= ~IPT_ECN_IP_MASK;
-		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
-		csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
-	}
-	return true;
-}
-
-/* Return false if there was an error. */
-static inline bool
-set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
-{
-	struct tcphdr _tcph, *tcph;
-	__be16 oldval;
-
-	/* Not enought header? */
-	tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
-	if (!tcph)
-		return false;
-
-	if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
-	     tcph->ece == einfo->proto.tcp.ece) &&
-	    (!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
-	     tcph->cwr == einfo->proto.tcp.cwr))
-		return true;
-
-	if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
-		return false;
-	tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb);
-
-	oldval = ((__be16 *)tcph)[6];
-	if (einfo->operation & IPT_ECN_OP_SET_ECE)
-		tcph->ece = einfo->proto.tcp.ece;
-	if (einfo->operation & IPT_ECN_OP_SET_CWR)
-		tcph->cwr = einfo->proto.tcp.cwr;
-
-	inet_proto_csum_replace2(&tcph->check, skb,
-				 oldval, ((__be16 *)tcph)[6], 0);
-	return true;
-}
-
-static unsigned int
-ecn_tg(struct sk_buff *skb, const struct xt_target_param *par)
-{
-	const struct ipt_ECN_info *einfo = par->targinfo;
-
-	if (einfo->operation & IPT_ECN_OP_SET_IP)
-		if (!set_ect_ip(skb, einfo))
-			return NF_DROP;
-
-	if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
-	    && ip_hdr(skb)->protocol == IPPROTO_TCP)
-		if (!set_ect_tcp(skb, einfo))
-			return NF_DROP;
-
-	return XT_CONTINUE;
-}
-
-static bool ecn_tg_check(const struct xt_tgchk_param *par)
-{
-	const struct ipt_ECN_info *einfo = par->targinfo;
-	const struct ipt_entry *e = par->entryinfo;
-
-	if (einfo->operation & IPT_ECN_OP_MASK) {
-		printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
-			einfo->operation);
-		return false;
-	}
-	if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
-		printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n",
-			einfo->ip_ect);
-		return false;
-	}
-	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
-	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
-		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
-		       "non-tcp rule\n");
-		return false;
-	}
-	return true;
-}
-
-static struct xt_target ecn_tg_reg __read_mostly = {
-	.name		= "ECN",
-	.family		= NFPROTO_IPV4,
-	.target		= ecn_tg,
-	.targetsize	= sizeof(struct ipt_ECN_info),
-	.table		= "mangle",
-	.checkentry	= ecn_tg_check,
-	.me		= THIS_MODULE,
-};
-
-static int __init ecn_tg_init(void)
-{
-	return xt_register_target(&ecn_tg_reg);
-}
-
-static void __exit ecn_tg_exit(void)
-{
-	xt_unregister_target(&ecn_tg_reg);
-}
-
-module_init(ecn_tg_init);
-module_exit(ecn_tg_exit);