From 7eecd672747b222d8ba1d1fdc4b2f9046aa629b8 Mon Sep 17 00:00:00 2001
From: "Ho, Nghia Duc" <nghia.duc.ho@intel.com>
Date: Tue, 23 Jan 2018 09:54:23 +0100
Subject: [PATCH] Merge pull request #227 in SW_PON/linux from
 bugfix/UGW_SW-20393-pp-subsystem-integration-problems-with-ugw8.x to xrx500

* commit '15e8e69c20afe76bd8085ecd949b099b1befc051':
  UGW_SW-20393: add new fields to the end of the atm_trafprm structure
  UGW_SW-20393: fix identation, ATM_DELBACKENDIF, remove unused CONFIG
  UGW_SW-20393: modify ATM_DELBACKENDIF to avoid conflict
  UGW_SW-20393: remove unused CONFIG_LTQ_ATM
  UGW_SW-20393: modify ATM_DELBACKENDIF
  UGW_SW-20393: remove DEBUG in aca.c
  UGW_SW-20393: ATM and 518 EP
---
 drivers/net/ethernet/intel/Kconfig       |  10 +
 drivers/net/ethernet/intel/vrx518/aca.c  | 236 +++++++++++++++++++----
 drivers/net/ethernet/intel/vrx518/aca.h  |  99 ++++++++--
 drivers/net/ethernet/intel/vrx518/ep.c   |  57 +++++-
 drivers/net/ethernet/intel/vrx518/ep.h   |   7 +-
 drivers/net/ethernet/intel/vrx518/misc.c |  10 +
 drivers/net/ethernet/intel/vrx518/misc.h |   2 +
 drivers/net/ppp/ppp_generic.c            |  46 +++--
 include/linux/ppp_channel.h              |   3 +
 include/net/dc_ep.h                      |  39 +++-
 include/uapi/linux/atm.h                 |   9 +
 include/uapi/linux/atmdev.h              |   2 +
 include/uapi/linux/if.h                  |   1 +
 net/atm/br2684.c                         |  48 +++++
 net/atm/common.c                         |   5 +
 net/atm/common.h                         |   5 +
 net/atm/mpc.c                            |   7 +-
 net/atm/pppoatm.c                        |   6 +
 18 files changed, 526 insertions(+), 66 deletions(-)

diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 92b4aba3c..8a6a34a99 100755
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -285,6 +285,16 @@ config VRX518
 	  will be called vrx518.  MSI interrupt support is required for
 	  this driver to work correctly.
 
+config VRX518_TC
+	tristate "Intel(R) VRX518 SmartPHY DSL PCIe Endpoint support"
+	depends on VRX518
+        default n
+	---help---
+	  This driver supports Intel(R) VRX518 TC functions. 
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called vrx518_tc.
+
 config VRX518_PCIE_SWITCH_BONDING
 	bool "Intel(R) VRX518 SmartPHY DSL bonding with PCIe Switch"
 	depends on VRX518
diff --git a/drivers/net/ethernet/intel/vrx518/aca.c b/drivers/net/ethernet/intel/vrx518/aca.c
index 52d9480b9..3fcf45488 100755
--- a/drivers/net/ethernet/intel/vrx518/aca.c
+++ b/drivers/net/ethernet/intel/vrx518/aca.c
@@ -21,7 +21,6 @@
 
 *******************************************************************************/
 #define DEBUG
-
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/delay.h>
@@ -89,38 +88,33 @@ static const char *fw_id_to_str(u32 fw_id)
 	}
 }
 
+static const char * const sec_id_str[] = {
+	"Unknown", "HIF", "GenRisc", "MAC_HT", "TXIN", "TXIN_PDRING", "TXOUT",
+	"TXOUT_PDRING", "RXIN", "RXIN_PDRING", "RXOUT", "RXOUT_PDRING", "DMA",
+	"FW_INIT",
+};
 static const char *sec_id_to_str(u32 sec_id)
 {
 	switch (sec_id) {
 	case ACA_SEC_HIF:
-		return "HIF";
-
 	case ACA_SEC_GNR:
-		return "GenRisc";
-
 	case ACA_SEC_MAC_HT:
-		return "MAC_HT";
-
 	case ACA_SEC_MEM_TXIN:
-		return "TXIN";
-
+	case ACA_SEC_MEM_TXIN_PDRING:
 	case ACA_SEC_MEM_TXOUT:
-		return "TXOUT";
-
+	case ACA_SEC_MEM_TXOUT_PDRING:
 	case ACA_SEC_MEM_RXIN:
-		return "RXIN";
-
+	case ACA_SEC_MEM_RXIN_PDRING:
 	case ACA_SEC_MEM_RXOUT:
-		return "RXOUT";
-
+	case ACA_SEC_MEM_RXOUT_PDRING:
 	case ACA_SEC_DMA:
-		return "DMA";
-
+	case ACA_SEC_FW_INIT:
+		return sec_id_str[sec_id];
 	case ACA_SEC_FW:
 		return "ACA FW";
 
 	default:
-		return "unknow";
+		return "unknown";
 	}
 }
 
@@ -139,6 +133,16 @@ static inline struct aca_mem_layout *to_mem_layout(struct dc_ep_priv *priv)
 	return &priv->aca.fw_info.mem_layout;
 }
 
+static inline struct aca_pdmem_layout *to_pdmem_layout(struct dc_ep_priv *priv)
+{
+	return &priv->aca.fw_info.pdmem_layout;
+}
+
+static inline struct aca_fw_param *to_aca_fw_param(struct dc_ep_priv *priv)
+{
+	return &priv->aca.fw_info.fw_param;
+}
+
 static inline struct aca_hif_params *to_hif_params(struct dc_ep_priv *priv)
 {
 	return priv->aca.hif_params;
@@ -199,38 +203,77 @@ static void aca_dma_parse(struct dc_ep_priv *priv, const char *data, int chn)
 static void aca_sram_desc_parse(struct dc_ep_priv *priv, const char *data,
 	u32 sid)
 {
-	u32 dbase;
+	u32 dbase, dnum;
 	struct aca_sram_desc *desc_base;
 	struct aca_mem_layout *mem_layout = to_mem_layout(priv);
+	struct aca_pdmem_layout *pdmem = to_pdmem_layout(priv);
 
 	desc_base = (struct aca_sram_desc *)data;
 	dbase = be32_to_cpu(desc_base->dbase);
+	dnum = be32_to_cpu(desc_base->dnum);
 
-	dev_dbg(priv->dev, "Sec %s desc base 0x%08x\n",
-		sec_id_to_str(sid), dbase);
+	dev_dbg(priv->dev, "Sec %s desc base 0x%08x, des_num: %d\n",
+		sec_id_to_str(sid), dbase, dnum);
 
 	switch (sid) {
 	case ACA_SEC_MEM_TXIN:
 		mem_layout->txin_host_desc_base = dbase;
+		mem_layout->txin_host_dnum = dnum;
 		break;
 
 	case ACA_SEC_MEM_TXOUT:
 		mem_layout->txout_host_desc_base = dbase;
+		mem_layout->txout_host_dnum = dnum;
 		break;
 
 	case ACA_SEC_MEM_RXIN:
 		mem_layout->rxin_host_desc_base = dbase;
+		mem_layout->rxin_host_dnum = dnum;
 		break;
 
 	case ACA_SEC_MEM_RXOUT:
 		mem_layout->rxout_host_desc_base = dbase;
+		mem_layout->rxout_host_dnum = dnum;
+		break;
+	case ACA_SEC_MEM_TXIN_PDRING:
+		pdmem->txin_pd_desc_base = dbase;
+		pdmem->txin_pd_dnum = dnum;
+		break;
+	case ACA_SEC_MEM_TXOUT_PDRING:
+		pdmem->txout_pd_desc_base = dbase;
+		pdmem->txout_pd_dnum = dnum;
+		break;
+	case ACA_SEC_MEM_RXIN_PDRING:
+		pdmem->rxin_pd_desc_base = dbase;
+		pdmem->rxin_pd_dnum = dnum;
+		break;
+	case ACA_SEC_MEM_RXOUT_PDRING:
+		pdmem->rxin_pd_desc_base = dbase;
+		pdmem->rxin_pd_dnum = dnum;
 		break;
 	default:
-		dev_err(priv->dev, "Unknow aca sram seciontion %d\n", sid);
+		dev_err(priv->dev, "Unknow aca sram section %d\n", sid);
 		break;
 	}
 }
 
+static void aca_init_parse(struct dc_ep_priv *priv, const char *data,
+	u32 sid)
+{
+	struct aca_fw_param *fw_param = to_aca_fw_param(priv);
+	struct aca_fw_param *param;
+	u32 hdr_sz, hdr_addr;
+
+	param = (struct aca_fw_param *)data;
+	hdr_sz = be32_to_cpu(param->st_sz);
+	hdr_addr = be32_to_cpu(param->init_addr);
+
+	fw_param->init_addr = hdr_addr;
+	fw_param->st_sz = hdr_sz;
+	dev_dbg(priv->dev, "init st size: %d, addr: 0x%x\n",
+		hdr_sz, hdr_addr);
+}
+
 static void aca_fw_parse(struct dc_ep_priv *priv, const char *data,
 	const char *fw_base, int fw_num)
 {
@@ -315,12 +358,17 @@ static int aca_section_parse(struct dc_ep_priv *priv, const char *fw_data)
 			ie_dlen = ie_len * sizeof(struct aca_fw_reg);
 			data += ie_dlen;
 			var_hlen -= ie_dlen;
+
 			break;
 
 		case ACA_SEC_MEM_TXIN:
 		case ACA_SEC_MEM_TXOUT:
 		case ACA_SEC_MEM_RXIN:
 		case ACA_SEC_MEM_RXOUT:
+		case ACA_SEC_MEM_TXIN_PDRING:
+		case ACA_SEC_MEM_TXOUT_PDRING:
+		case ACA_SEC_MEM_RXIN_PDRING:
+		case ACA_SEC_MEM_RXOUT_PDRING:
 			aca_sram_desc_parse(priv, data, ie_id);
 			ie_dlen = ie_len * sizeof(struct aca_sram_desc);
 			data += ie_dlen;
@@ -340,6 +388,13 @@ static int aca_section_parse(struct dc_ep_priv *priv, const char *fw_data)
 			var_hlen -= ie_dlen;
 			break;
 
+		case ACA_SEC_FW_INIT:
+			aca_init_parse(priv, data, ie_id);
+			ie_dlen = ie_len * sizeof(struct aca_fw_param);
+			data += ie_dlen;
+			var_hlen -= ie_dlen;
+			break;
+
 		case ACA_SEC_FW:
 			if (ie_len > ACA_FW_MAX) {
 				dev_err(dev, "Too many aca fws %d\n", ie_len);
@@ -693,10 +748,13 @@ static void aca_hif_param_init_done(struct dc_ep_priv *priv)
 {
 	u32 addr;
 	struct aca_hif_params *hif_params = to_hif_params(priv);
+	struct aca_fw_param *fw_param = to_aca_fw_param(priv);
 
-	wr32(ACA_HIF_PARAM_ADDR, ACA_HIF_LOC_POS);
+	/* wr32(ACA_HIF_PARAM_ADDR, ACA_HIF_LOC_POS);*/
+	/* addr = rd32(ACA_HIF_LOC_POS);*/
 
-	addr = rd32(ACA_HIF_LOC_POS);
+	addr = fw_param->init_addr;
+	dev_dbg(priv->dev, "init_addr: %x\n", addr);
 	memcpy_toio(priv->mem + addr, hif_params, sizeof(*hif_params));
 	kzfree(hif_params);
 	dev_dbg(priv->dev, "%s\n", __func__);
@@ -707,16 +765,18 @@ static bool aca_hif_param_init_check(struct dc_ep_priv *priv)
 	u32 addr;
 	int timeout = ACA_LOOP_CNT;
 	u32 offset = offsetof(struct aca_hif_params, magic);
+	struct aca_fw_param *fw_param = to_aca_fw_param(priv);
 
-	addr = rd32(ACA_HIF_LOC_POS);
-
+	/* addr = rd32(ACA_HIF_LOC_POS);*/
+	addr = fw_param->init_addr;
 	while (--timeout && (rd32(addr + offset) != ACA_MAGIC))
 		udelay(1);
 
-	if (timeout < 0) {
+	if (timeout <= 0) {
 		dev_err(priv->dev, "aca hif params init failed\n");
 		return false;
 	}
+
 	return true;
 }
 
@@ -735,6 +795,10 @@ static void aca_txin_init(struct dc_ep_priv *priv,
 		| SM((aca_txin->pd_size_in_dw - 1), PD_DESC_IN_DW);
 	wr32(val, TXIN_CONV_CFG);
 
+	/* SoC cumulative counter address */
+	wr32(aca_txin->soc_cmlt_cnt_addr, GNRC_TXIN_CMLT_CNT_ADDR);
+
+
 	/* SoC descriptors */
 	txin_param->soc_desc_base = aca_txin->soc_desc_base;
 	txin_param->soc_desc_num = aca_txin->soc_desc_num;
@@ -743,7 +807,7 @@ static void aca_txin_init(struct dc_ep_priv *priv,
 	txin_param->pp_buf_base = priv->phymem
 		+ mem_layout->txin_host_desc_base;
 
-	txin_param->pp_buf_num = aca_txin->pp_buf_desc_num;
+	txin_param->pp_buf_num = mem_layout->txin_host_dnum;
 
 	/* PD ring */
 	txin_param->pd_desc_base = priv->phymem
@@ -768,6 +832,12 @@ static void aca_txout_init(struct dc_ep_priv *priv,
 		| SM((aca_txout->pd_size_in_dw - 1), PD_DESC_IN_DW);
 	wr32(val, TXOUT_CONV_CFG);
 
+	/* SoC Ring size */
+	val = aca_txout->soc_desc_num;
+	wr32(val, TXOUT_RING_CFG);
+
+	/* SoC cumulative counter address */
+	wr32(aca_txout->soc_cmlt_cnt_addr, GNRC_TXOUT_CMLT_CNT_ADDR);
 	/* SoC descriptors */
 	txout_param->soc_desc_base = aca_txout->soc_desc_base;
 	txout_param->soc_desc_num = aca_txout->soc_desc_num;
@@ -776,7 +846,7 @@ static void aca_txout_init(struct dc_ep_priv *priv,
 	txout_param->pp_buf_base = priv->phymem
 		+mem_layout->txout_host_desc_base;
 
-	txout_param->pp_buf_num = aca_txout->pp_buf_desc_num;
+	txout_param->pp_buf_num = mem_layout->txout_host_dnum;
 
 	/* PD ring */
 	txout_param->pd_desc_base = priv->phymem
@@ -791,6 +861,42 @@ static void aca_txout_init(struct dc_ep_priv *priv,
 static void aca_rxin_init(struct dc_ep_priv *priv,
 	struct aca_cfg_param *aca_rxin)
 {
+	u32 val = 0;
+	struct aca_mem_layout *mem_layout = to_mem_layout(priv);
+	struct aca_hif_params *hif_params = to_hif_params(priv);
+	struct aca_hif_param *rxin_param = &hif_params->rxin;
+
+	if (aca_rxin->byteswap)
+		val = BYTE_SWAP_EN;
+
+	val |= (aca_rxin->hd_size_in_dw - 1)
+		| SM((aca_rxin->pd_size_in_dw - 1), PD_DESC_IN_DW);
+	wr32(val, RXIN_CONV_CFG);
+
+	/* SoC cumulative counter address */
+	wr32(aca_rxin->soc_cmlt_cnt_addr, GNRC_RXIN_CMLT_CNT_ADDR);
+
+    /* RXIN may not be used */
+	if (!(aca_rxin->soc_desc_base))
+		goto __RXIN_DONE;
+	/* SoC descriptors */
+	rxin_param->soc_desc_base = aca_rxin->soc_desc_base;
+	rxin_param->soc_desc_num = aca_rxin->soc_desc_num;
+
+	/* Ping/pong buffer */
+	rxin_param->pp_buf_base = (u32)priv->phymem
+		+ mem_layout->rxin_host_desc_base;
+
+	rxin_param->pp_buf_num = mem_layout->rxin_host_dnum;
+
+	/* PD ring */
+	rxin_param->pd_desc_base = (u32)priv->phymem
+		+ aca_rxin->pd_desc_base;
+	rxin_param->pd_desc_num = aca_rxin->pd_desc_num;
+
+	rxin_param->pd_desc_threshold = aca_rxin->pp_buf_desc_num;
+
+__RXIN_DONE:
 	dev_dbg(priv->dev, "aca rxin init done\n");
 }
 
@@ -809,6 +915,12 @@ static void aca_rxout_init(struct dc_ep_priv *priv,
 		| SM((aca_rxout->pd_size_in_dw - 1), PD_DESC_IN_DW);
 	wr32(val, RXOUT_CONV_CFG);
 
+	/* SoC Ring size */
+	val = aca_rxout->soc_desc_num;
+	wr32(val, RXOUT_RING_CFG);
+
+	/* SoC cumulative counter address */
+	wr32(aca_rxout->soc_cmlt_cnt_addr, GNRC_RXOUT_CMLT_CNT_ADDR);
 	/* SoC descriptors */
 	rxout_param->soc_desc_base = aca_rxout->soc_desc_base;
 	rxout_param->soc_desc_num = aca_rxout->soc_desc_num;
@@ -817,7 +929,7 @@ static void aca_rxout_init(struct dc_ep_priv *priv,
 	rxout_param->pp_buf_base = (u32)priv->phymem
 		+ mem_layout->rxout_host_desc_base;
 
-	rxout_param->pp_buf_num = aca_rxout->pp_buf_desc_num;
+	rxout_param->pp_buf_num = mem_layout->rxout_host_dnum;
 
 	/* PD ring */
 	rxout_param->pd_desc_base = (u32)priv->phymem
@@ -934,6 +1046,7 @@ int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset)
 			}
 		}
 
+
 		if (val & ACA_RXIN_EN) {
 			reg = rd32(RXIN_COUNTERS);
 			if (MS(reg, ACA_PENDING_JOB)
@@ -964,6 +1077,41 @@ int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset)
 	return 0;
 }
 
+#ifdef CONFIG_SOC_TYPE_XWAY
+static void aca_grx330_init(struct dc_ep_priv *priv)
+{
+	wr32(0x0044001E, TXIN_CFG1);
+	wr32(0x0040041F, TXIN_CFG2);
+	wr32(0x007FE020, TXIN_CFG3);
+
+	wr32(0x0044001F, TXOUT_CFG1);
+	wr32(0x0040041F, TXOUT_CFG2);
+	wr32(0x007BE020, TXOUT_CFG3);
+
+	wr32(0x0044001F, RXOUT_CFG1);
+	wr32(0x0040041F, RXOUT_CFG2);
+	wr32(0x007BE020, RXOUT_CFG3);
+
+	wr32(0x0044001E, RXIN_CFG1);
+	wr32(0x0040041F, RXIN_CFG2);
+	wr32(0x007FE020, RXIN_CFG3);
+
+	wr32(0x1, TXIN_DST_OWWBIT_CFG4);
+	wr32(0x1, TXOUT_DST_OWWBIT_CFG4);
+	wr32(0x1, RXOUT_SRC_OWNBIT_CFG3);
+	wr32(0x1, RXIN_SRC_OWNBIT_CFG3);
+
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x4);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x8);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0xc);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x10);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x14);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x18);
+	wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x1c);
+}
+#endif
+
 int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *param,
 	struct aca_modem_param *mdm)
 {
@@ -991,9 +1139,10 @@ int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *param,
 	aca_rxout_init(priv, &param->aca_rxout);
 	aca_rxin_init(priv, &param->aca_rxin);
 	aca_hif_param_init_done(priv);
-
 	aca_mdm_init(priv, mdm);
-
+#ifdef CONFIG_SOC_TYPE_XWAY
+	aca_grx330_init(priv);
+#endif
 	aca->initialized = true;
 	dev_info(priv->dev, "aca init done\n");
 	return 0;
@@ -1015,9 +1164,28 @@ void dc_aca_info_init(struct dc_ep_priv *priv)
 	aca->max_gpio = aca_max_gpio(priv);
 }
 
-u32 aca_umt_msg_addr(struct dc_ep_priv *priv)
+#define ACA_ENDIAN_ADDR(addr, endian)		\
+{						\
+	if (endian == ACA_BIG_ENDIAN)		\
+		return addr##_BE;		\
+	else					\
+		return addr;			\
+}
+
+u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type)
 {
-	return RXIN_HD_ACCUM_ADD;
+	switch (type) {
+	case ACA_TXIN:
+		ACA_ENDIAN_ADDR(TXIN_HD_ACCUM_ADD, endian);
+	case ACA_RXIN:
+		ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian);
+	case ACA_TXOUT:
+		ACA_ENDIAN_ADDR(TXOUT_HD_ACCUM_SUB, endian);
+	case ACA_RXOUT:
+		ACA_ENDIAN_ADDR(RXOUT_HD_ACCUM_SUB, endian);
+	default:
+		ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian);
+	};
 }
 
 void dc_aca_event_addr_get(struct dc_ep_priv *priv,
diff --git a/drivers/net/ethernet/intel/vrx518/aca.h b/drivers/net/ethernet/intel/vrx518/aca.h
index 17c04d1a4..10f2ecb4c 100755
--- a/drivers/net/ethernet/intel/vrx518/aca.h
+++ b/drivers/net/ethernet/intel/vrx518/aca.h
@@ -43,10 +43,32 @@
 
 /* TODO: change name after karthik explained */
 #define TXIN_DST_OWNBIT		0xC4
-#define RXOUT_SRC_OWNBIT	0xC4
-#define RXOUT_DST_OWNBIT	0xC8
+#define TXOUT_DST_OWNBIT	0x1C4
+#define RXOUT_SRC_OWNBIT	0x3C4
+#define RXIN_DST_OWNBIT		0x2C4
 
 /* Genrisc Internal Host Descriptor(Ping/Pong) decided by ACA fw header */
+/* ACA Core */
+#define ACA_CORE_REG(X)	(ACA_CORE_BASE + (X))
+#define TXIN_CFG1	ACA_CORE_REG(0x0)
+#define TXIN_CFG2	ACA_CORE_REG(0x4)
+#define TXIN_CFG3	ACA_CORE_REG(0x8)
+#define TXIN_DST_OWWBIT_CFG4	ACA_CORE_REG(TXIN_DST_OWNBIT)
+
+#define TXOUT_CFG1	ACA_CORE_REG(0x100)
+#define TXOUT_CFG2	ACA_CORE_REG(0x104)
+#define TXOUT_CFG3	ACA_CORE_REG(0x108)
+#define TXOUT_DST_OWWBIT_CFG4	ACA_CORE_REG(TXOUT_DST_OWNBIT)
+
+#define RXOUT_CFG1	ACA_CORE_REG(0x300)
+#define RXOUT_CFG2	ACA_CORE_REG(0x304)
+#define RXOUT_CFG3	ACA_CORE_REG(0x308)
+#define RXOUT_SRC_OWNBIT_CFG3	ACA_CORE_REG(RXOUT_SRC_OWNBIT)
+
+#define RXIN_CFG1	ACA_CORE_REG(0x200)
+#define RXIN_CFG2	ACA_CORE_REG(0x204)
+#define RXIN_CFG3	ACA_CORE_REG(0x208)
+#define RXIN_SRC_OWNBIT_CFG3	ACA_CORE_REG(RXIN_DST_OWNBIT)
 
 /* Genrisc */
 #define GNRC_REG(X)		(GENRISC_BASE + (X))
@@ -56,14 +78,15 @@
 
 /* HOST Interface Register */
 #define HOST_IF_REG(X)		(HOST_IF_BASE + (X))
-#define TXIN_CONV_CFG		HOST_IF_REG(0x14)
 #define HD_DESC_IN_DW		0x7u
 #define HD_DESC_IN_DW_S		0
 #define PD_DESC_IN_DW		0x70u
 #define PD_DESC_IN_DW_S		4
 #define BYTE_SWAP_EN		BIT(28)
 
+#define TXIN_CONV_CFG		HOST_IF_REG(0x14)
 #define TXOUT_CONV_CFG		HOST_IF_REG(0x18)
+#define RXIN_CONV_CFG		HOST_IF_REG(0x1C)
 #define RXOUT_CONV_CFG		HOST_IF_REG(0x20)
 
 #define TXIN_COUNTERS		HOST_IF_REG(0x44)
@@ -71,6 +94,9 @@
 #define RXIN_COUNTERS		HOST_IF_REG(0x4c)
 #define RXOUT_COUNTERS		HOST_IF_REG(0x50)
 
+#define TXOUT_RING_CFG		HOST_IF_REG(0x98)
+#define RXOUT_RING_CFG		HOST_IF_REG(0x9C)
+
 #define ACA_PENDING_JOB		0x00000300
 #define ACA_PENDING_JOB_S	8
 #define ACA_AVAIL_BUF		0x00030000
@@ -83,15 +109,19 @@
 #define RXIN_HD_ACCUM_ADD	HOST_IF_REG(0xC8) /* UMT Message trigger */
 #define TXIN_HD_ACCUM_ADD	HOST_IF_REG(0xCC) /* UMT Message trigger */
 #define RXOUT_HD_ACCUM_ADD	HOST_IF_REG(0xD0)
-#define RXOUT_HD_ACCUM_SUB	HOST_IF_REG(0xF8)
 #define TXOUT_HD_ACCUM_ADD	HOST_IF_REG(0xD4)
-#define TXOUT_HD_ACCUM_SUB	HOST_IF_REG(0xFC)
 #define RXOUT_ACA_ACCUM_ADD	HOST_IF_REG(0xE0) /* PPE FW tigger */
 #define TXOUT_ACA_ACCUM_ADD	HOST_IF_REG(0xE4) /* PPE FW tigger */
+#define RXOUT_HD_ACCUM_SUB	HOST_IF_REG(0xF8)
+#define TXOUT_HD_ACCUM_SUB	HOST_IF_REG(0xFC)
 #define RXIN_ACA_ACCUM_SUB	HOST_IF_REG(0x100)
 #define TXIN_ACA_ACCUM_SUB	HOST_IF_REG(0x104)
 #define TXIN_ACA_HD_ACC_CNT	HOST_IF_REG(0x11C)
 #define UMT_ORDER_CFG		HOST_IF_REG(0x234)
+#define RXIN_HD_ACCUM_ADD_BE	HOST_IF_REG(0x250)
+#define TXIN_HD_ACCUM_ADD_BE	HOST_IF_REG(0x254)
+#define RXOUT_HD_ACCUM_SUB_BE	HOST_IF_REG(0x268)
+#define TXOUT_HD_ACCUM_SUB_BE	HOST_IF_REG(0x26c)
 
 /* MAC_HT_EXTENSION Register */
 #define MAC_HT_EXT_REG(X)	(MAC_HT_EXT_BASE + (X))
@@ -131,7 +161,26 @@
 #define GNRC_RXOUT_TGT_PD_OFF		GNRC_SPRAM_REG(0x2C)
 #define GNRC_RXOUT_TGT_ACCM_CNT		GNRC_SPRAM_REG(0x30)
 
-#define GNRC_EN_TASK_BITMAP		GNRC_SPRAM_REG(0x34)
+/* 4 Ring 8 UMT case SoC cumulative counter address configuration */
+#define GNRC_TXIN_CMLT_CNT_ADDR		GNRC_SPRAM_REG(0x34)
+#define GNRC_TXOUT_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x38)
+#define GNRC_RXOUT_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x3C)
+#define GNRC_RXIN_CMLT_CNT_ADDR		GNRC_SPRAM_REG(0x40)
+
+
+#define GNRC_SOURCE_TXIN_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x54)
+#define GNRC_SOURCE_TXOUT_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x58)
+#define GNRC_SOURCE_RXOUT_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x5c)
+#define GNRC_SOURCE_RXIN_CMLT_CNT_ADDR	GNRC_SPRAM_REG(0x60)
+
+/* Txin index prefill */
+#define GNRC_TXIN_BUF_PREFILL		GNRC_SPRAM_REG(0x44)
+/* Task enable bitmap */
+#define GNRC_EN_TASK_BITMAP		GNRC_SPRAM_REG(0x64)
+
+#define ACA_SRAM_REG(X)	(ACA_SRAM_BASE + (X))
+#define ACA_TXOUT_PING_BUFFER_START ACA_SRAM_REG(0x1528)
+
 
 /* XBAR SSX0 */
 #define ACA_SSX0_BASE			0x180000
@@ -228,17 +277,22 @@ enum {
 #define POLL_EN			31 /* Polling Enable */
 #define POLL_CNT		4 /* Polling Counter */
 
-#define ACA_DMA_CHAN_MAX	8
+#define ACA_DMA_CHAN_MAX	12
 
 enum aca_sec_id {
 	ACA_SEC_HIF = 0x1,
 	ACA_SEC_GNR = 0x2,
 	ACA_SEC_MAC_HT = 0x3,
 	ACA_SEC_MEM_TXIN = 0x4,
-	ACA_SEC_MEM_TXOUT = 0x5,
-	ACA_SEC_MEM_RXOUT = 0x6,
-	ACA_SEC_MEM_RXIN = 0X7,
-	ACA_SEC_DMA = 0x8,
+	ACA_SEC_MEM_TXIN_PDRING = 0x5,
+	ACA_SEC_MEM_TXOUT = 0x6,
+	ACA_SEC_MEM_TXOUT_PDRING = 0x7,
+	ACA_SEC_MEM_RXOUT = 0x8,
+	ACA_SEC_MEM_RXOUT_PDRING = 0x9,
+	ACA_SEC_MEM_RXIN = 0xa,
+	ACA_SEC_MEM_RXIN_PDRING = 0xb,
+	ACA_SEC_DMA = 0xc,
+	ACA_SEC_FW_INIT = 0xd,
 	ACA_SEC_FW = 0x88,
 };
 
@@ -280,6 +334,7 @@ struct aca_fw_reg {
 } __packed;
 
 struct aca_sram_desc {
+	__be32 dnum;
 	__be32 dbase;
 } __packed;
 
@@ -296,11 +351,31 @@ struct aca_int_hdr {
 	__be32 load_addr;
 } __packed;
 
+struct aca_fw_param {
+	__be32 st_sz;
+	__be32 init_addr;
+} __packed;
+
 struct aca_mem_layout {
 	u32 txin_host_desc_base;
+	u32 txin_host_dnum;
 	u32 txout_host_desc_base;
+	u32 txout_host_dnum;
 	u32 rxin_host_desc_base;
+	u32 rxin_host_dnum;
 	u32 rxout_host_desc_base;
+	u32 rxout_host_dnum;
+};
+
+struct aca_pdmem_layout {
+	u32 txin_pd_desc_base;
+	u32 txin_pd_dnum;
+	u32 txout_pd_desc_base;
+	u32 txout_pd_dnum;
+	u32 rxin_pd_desc_base;
+	u32 rxin_pd_dnum;
+	u32 rxout_pd_desc_base;
+	u32 rxout_pd_dnum;
 };
 
 struct aca_fw_addr_tuple {
@@ -320,6 +395,8 @@ struct aca_fw_info {
 	const void *fw_data;
 	size_t fw_len;
 	struct aca_mem_layout mem_layout;
+	struct aca_pdmem_layout pdmem_layout;
+	struct aca_fw_param fw_param;
 	struct aca_fw_dl_addr fw_dl;
 	u32 chan_num;
 	u32 adma_desc_base[ACA_DMA_CHAN_MAX];
diff --git a/drivers/net/ethernet/intel/vrx518/ep.c b/drivers/net/ethernet/intel/vrx518/ep.c
index 7f15c2950..442be2ae2 100755
--- a/drivers/net/ethernet/intel/vrx518/ep.c
+++ b/drivers/net/ethernet/intel/vrx518/ep.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/pci.h>
 #include <linux/pci_regs.h>
+#include <linux/platform_device.h>
 
 #include "ep.h"
 #include "aca.h"
@@ -40,7 +41,7 @@
 
 #define DC_EP_DBG
 
-#define MAJ	1
+#define MAJ	2
 #define MIN	1
 #define BUILD	0
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
@@ -80,6 +81,26 @@ static inline void reset_deassert_device(struct dc_ep_dev *dev, u32 bits)
 	dc_ep_deassert_device(dev->priv, bits);
 }
 
+static inline void icu_disable_intr(struct dc_ep_dev *dev, u32 bits)
+{
+	if (WARN_ON(!dev))
+		return;
+	if (WARN_ON(!dev->priv))
+		return;
+
+	dc_ep_icu_dis_intr(dev->priv, bits);
+}
+
+static inline void icu_enable_intr(struct dc_ep_dev *dev, u32 bits)
+{
+	if (WARN_ON(!dev))
+		return;
+	if (WARN_ON(!dev->priv))
+		return;
+
+	dc_ep_icu_en_intr(dev->priv, bits);
+}
+
 static inline int reset_device(struct dc_ep_dev *dev, u32 bits)
 {
 	if (WARN_ON(!dev))
@@ -262,14 +283,14 @@ static inline void aca_event_addr_get(struct dc_ep_dev *dev,
 	dc_aca_event_addr_get(dev->priv, regs);
 }
 
-static inline u32 umt_msg_addr(struct dc_ep_dev *dev)
+static inline u32 umt_msg_addr(struct dc_ep_dev *dev, u32 endian, u32 type)
 {
 	if (WARN_ON(!dev))
 		return -EINVAL;
 	if (WARN_ON(!dev->priv))
 		return -EINVAL;
 
-	return aca_umt_msg_addr(dev->priv);
+	return aca_umt_msg_addr(dev->priv, endian, type);
 }
 
 static inline void aca_txin_sub_ack(struct dc_ep_dev *dev, u32 val)
@@ -296,6 +317,8 @@ static const struct aca_hw_ops dc_ep_hw_ops = {
 	.reset_assert = reset_assert_device,
 	.reset_deassert = reset_deassert_device,
 	.reset_device = reset_device,
+	.icu_en = icu_enable_intr,
+	.icu_mask = icu_disable_intr,
 	.clk_on = clk_on,
 	.clk_off = clk_off,
 	.clk_set = clk_set,
@@ -545,6 +568,9 @@ static int dc_ep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	size_t memsize;
 	int msi_mode;
 	static int cards_found;
+#ifndef CONFIG_OF
+	struct pcie_ep_adapter *adapter;
+#endif
 	struct dc_ep_priv *priv;
 
 	ret = pci_enable_device(pdev);
@@ -630,11 +656,30 @@ static int dc_ep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	spin_lock(&dc_ep_lock);
 	priv->irq_base = pdev->irq;
 	spin_unlock(&dc_ep_lock);
+
+#ifndef CONFIG_OF
+	adapter = kmalloc(sizeof(struct pcie_ep_adapter), GFP_KERNEL);
+	if (adapter == NULL)
+		goto err_iomap;
+	pci_set_drvdata(pdev, adapter);
+	adapter->mei_dev = platform_device_register_data(&pdev->dev, "mei_cpe",
+							 PLATFORM_DEVID_AUTO,
+							 NULL, 0);
+	if (IS_ERR(adapter->mei_dev)) {
+		dev_err(&pdev->dev, "can not register mei device, err: %li, ignore this\n",
+			PTR_ERR(adapter->mei_dev));
+		goto err_msi;
+	}
+#endif
 	dc_ep_info_xchange(pdev, cards_found);
 	/* Disable output clock to save power */
 	dc_ep_clkod_disable(priv);
 	dc_aca_info_init(priv);
 	return 0;
+#ifndef CONFIG_OF
+err_msi:
+	kfree(adapter);
+#endif
 err_iomap:
 	pci_iounmap(pdev, mem);
 err_master:
@@ -651,6 +696,12 @@ static void dc_ep_remove(struct pci_dev *pdev)
 {
 	struct dc_ep_priv *priv = pci_get_drvdata(pdev);
 
+#ifndef CONFIG_OF
+	struct pcie_ep_adapter *adapter =
+		(struct pcie_ep_adapter *) pci_get_drvdata(pdev);
+
+	platform_device_unregister(adapter->mei_dev);
+#endif
 	if (priv == NULL)
 		return;
 
diff --git a/drivers/net/ethernet/intel/vrx518/ep.h b/drivers/net/ethernet/intel/vrx518/ep.h
index b65e236bc..2e31008ec 100755
--- a/drivers/net/ethernet/intel/vrx518/ep.h
+++ b/drivers/net/ethernet/intel/vrx518/ep.h
@@ -114,9 +114,14 @@ int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *aca,
 void dc_aca_event_addr_get(struct dc_ep_priv *priv,
 	struct aca_event_reg_addr *regs);
 void dc_aca_txin_sub_ack(struct dc_ep_priv *priv, u32 val);
-u32 aca_umt_msg_addr(struct dc_ep_priv *priv);
+u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type);
 u32 dc_aca_txin_hd_cnt(struct dc_ep_priv *priv);
 void dc_aca_free_fw_file(struct dc_ep_priv *priv);
 
+/* Card specific private data structure */
+struct pcie_ep_adapter {
+	struct platform_device *mei_dev; /* the mei driver */
+};
+
 #endif /* EP_H */
 
diff --git a/drivers/net/ethernet/intel/vrx518/misc.c b/drivers/net/ethernet/intel/vrx518/misc.c
index 4f395e557..9140fe79e 100755
--- a/drivers/net/ethernet/intel/vrx518/misc.c
+++ b/drivers/net/ethernet/intel/vrx518/misc.c
@@ -66,6 +66,16 @@ void dc_ep_icu_disable(struct dc_ep_priv *priv)
 	wr32(0, ICU_IMER);
 }
 
+void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits)
+{
+	wr32_mask(~bits, 0, ICU_IMER);
+}
+
+void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits)
+{
+	wr32_mask(0, bits, ICU_IMER);
+}
+
 void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits)
 {
 	struct dc_aca *aca = to_aca(priv);
diff --git a/drivers/net/ethernet/intel/vrx518/misc.h b/drivers/net/ethernet/intel/vrx518/misc.h
index c64e4aff1..d92ea83e2 100755
--- a/drivers/net/ethernet/intel/vrx518/misc.h
+++ b/drivers/net/ethernet/intel/vrx518/misc.h
@@ -45,5 +45,7 @@ int dc_ep_gpio_pupd_set(struct dc_ep_priv *priv, u32 gpio, u32 val);
 int dc_ep_gpio_od_set(struct dc_ep_priv *priv, u32 gpio, int val);
 int dc_ep_gpio_src_set(struct dc_ep_priv *priv, u32 gpio, int val);
 int dc_ep_gpio_dcc_set(struct dc_ep_priv *priv, u32 gpio, u32 val);
+void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits);
+void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits);
 
 #endif /* MISC_H */
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index bc8d4bf20..b2a8879c6 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -78,7 +78,7 @@
  */
 struct ppp_file {
 	enum {
-		INTERFACE=1, CHANNEL
+		INTERFACE = 1, CHANNEL
 	}		kind;
 	struct sk_buff_head xq;		/* pppd transmit queue */
 	struct sk_buff_head rq;		/* receive queue for pppd */
@@ -371,10 +371,12 @@ static const int npindex_to_ethertype[NUM_NP] = {
 #define ppp_xmit_unlock(ppp)	spin_unlock_bh(&(ppp)->wlock)
 #define ppp_recv_lock(ppp)	spin_lock_bh(&(ppp)->rlock)
 #define ppp_recv_unlock(ppp)	spin_unlock_bh(&(ppp)->rlock)
-#define ppp_lock(ppp)		do { ppp_xmit_lock(ppp); \
-				     ppp_recv_lock(ppp); } while (0)
-#define ppp_unlock(ppp)		do { ppp_recv_unlock(ppp); \
-				     ppp_xmit_unlock(ppp); } while (0)
+#define ppp_lock(ppp)		do { ppp_xmit_lock(ppp);\
+				     ppp_recv_lock(ppp); } \
+					 while (0)
+#define ppp_unlock(ppp)		do { ppp_recv_unlock(ppp);\
+				     ppp_xmit_unlock(ppp); } \
+					 while (0)
 
 #ifdef CONFIG_PPA
 extern int32_t (*ppa_ppp_get_chan_info_fn)
@@ -1750,7 +1752,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 				  *having no queued packets before
 				  *starting the fragmentation*/
 
-	hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+	hdrlen = (ppp->flags & SC_MP_XSHORTSEQ) ? MPHDRLEN_SSN : MPHDRLEN;
 	i = 0;
 	list_for_each_entry(pch, &ppp->channels, clist) {
 		if (pch->chan) {
@@ -2147,8 +2149,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 			skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len);
 			consume_skb(skb);
 			skb = ns;
-		}
-		else
+		} else
 			skb->ip_summed = CHECKSUM_NONE;
 
 		len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
@@ -2276,7 +2277,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
 	if (proto == PPP_COMP) {
 		int obuff_size;
 
-		switch(ppp->rcomp->compress_proto) {
+		switch (ppp->rcomp->compress_proto) {
 		case CI_MPPE:
 			obuff_size = ppp->mru + PPP_HDRLEN + 1;
 			break;
@@ -2335,7 +2336,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
 {
 	u32 mask, seq;
 	struct channel *ch;
-	int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+	int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ) ? MPHDRLEN_SSN : MPHDRLEN;
 
 	if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
 		goto err;		/* no good, throw it away */
@@ -2485,13 +2486,13 @@ ppp_mp_reconstruct(struct ppp *ppp)
 			/* Fragment `seq' is lost, keep going. */
 			lost = 1;
 			oldseq = seq;
-			seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
-				minseq + 1: PPP_MP_CB(p)->sequence;
+			seq = seq_before(minseq, PPP_MP_CB(p)->sequence) ?
+				minseq + 1 : PPP_MP_CB(p)->sequence;
 
 			if (ppp->debug & 1)
 				netdev_printk(KERN_DEBUG, ppp->dev,
 					      "lost frag %u..%u\n",
-					      oldseq, seq-1);
+					      oldseq, seq - 1);
 
 			goto again;
 		}
@@ -2695,6 +2696,22 @@ char *ppp_dev_name(struct ppp_channel *chan)
 	return name;
 }
 
+/*
+ * Return the PPP device interface pointer
+ */
+struct net_device *ppp_device(struct ppp_channel *chan)
+{
+	struct channel *pch = chan->ppp;
+	struct net_device *dev = NULL;
+
+	if (pch) {
+		read_lock_bh(&pch->upl);
+		if (pch->ppp && pch->ppp->dev)
+			dev = pch->ppp->dev;
+		read_unlock_bh(&pch->upl);
+	}
+	return dev;
+}
 
 /*
  * Disconnect a channel from the generic layer.
@@ -2845,7 +2862,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
 		 * Remember:
 		 * A ConfReq indicates what the sender would like to receive
 		 */
-		if(inbound)
+		if (inbound)
 			/* He is proposing what I should send */
 			ppp->xstate &= ~SC_COMP_RUN;
 		else
@@ -3337,6 +3354,7 @@ EXPORT_SYMBOL(ppp_unregister_channel);
 EXPORT_SYMBOL(ppp_channel_index);
 EXPORT_SYMBOL(ppp_unit_number);
 EXPORT_SYMBOL(ppp_dev_name);
+EXPORT_SYMBOL(ppp_device);
 EXPORT_SYMBOL(ppp_input);
 EXPORT_SYMBOL(ppp_input_error);
 EXPORT_SYMBOL(ppp_output_wakeup);
diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h
index 5d87f810a..c0a8a02d3 100644
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -75,6 +75,9 @@ extern int ppp_unit_number(struct ppp_channel *);
 /* Get the device name associated with a channel, or NULL if none */
 extern char *ppp_dev_name(struct ppp_channel *);
 
+/* Get the device pointer associated with a channel, or NULL if none */
+extern struct net_device *ppp_device(struct ppp_channel *);
+
 /*
  * SMP locking notes:
  * The channel code must ensure that when it calls ppp_unregister_channel,
diff --git a/include/net/dc_ep.h b/include/net/dc_ep.h
index c8556d53d..f1142332e 100755
--- a/include/net/dc_ep.h
+++ b/include/net/dc_ep.h
@@ -64,6 +64,23 @@
 #define PMU_PPM2		BIT(23)
 #define PMU_PPE_TOP		BIT(29)
 
+/* IMER bit definition */
+#define PPE2HOST_INT0		BIT(0)
+#define PPE2HOST_INT1		BIT(1)
+#define DYING_GASP_INT		BIT(3)
+#define MEI_IRQ			BIT(8)
+#define ACA_XBAR_INT		BIT(9)
+#define MODEM_XBAR_INT		BIT(12)
+#define LED0_INT		BIT(13)
+#define LED1_INT		BIT(14)
+#define NMI_PLL			BIT(15)
+#define DMA_TX			BIT(16)
+#define DMA_RX			BIT(17)
+#define ACA_HOSTIF_TX		BIT(20)
+#define ACA_HOSTIF_RX		BIT(21)
+#define ACA_RXOUT_PD_RING_FULL	BIT(22)
+#define ACA_TXOUT_PD_RING_FULL	BIT(23)
+
 /*
  * Structure used to specify available pin mux functions for gpio pinx
  * It will be used in pinmux_set() function
@@ -132,6 +149,20 @@ enum {
 	GPIO_DRV_CUR_MAX,
 };
 
+enum {
+	ACA_LITTLE_ENDIAN = 0,
+	ACA_BIG_ENDIAN,
+	ACA_ENDIAN_MAX,
+};
+
+enum {
+	ACA_TXIN = 0,
+	ACA_TXOUT,
+	ACA_RXIN,
+	ACA_RXOUT,
+	ACA_MAX,
+};
+
 /* ACA four major direction functions for start/stop */
 #define ACA_TXIN_EN	BIT(0)
 #define ACA_TXOUT_EN	BIT(1)
@@ -149,12 +180,14 @@ struct dc_ep_dev;
 struct aca_cfg_param {
 	u32 soc_desc_base; /*!< SoC CBM or DDR descriptor base address */
 	u32 soc_desc_num; /*!< SoC and HostIF (same) descriptor number */
+	u32 soc_cmlt_cnt_addr; /*! SoC cumulative counter address */
 	u32 pp_buf_desc_num; /*!< ACA ping pong buffer descriptor number */
 	u32 pd_desc_base; /*!< Packet Descriptor base address in modem */
 	u32 pd_desc_num; /*!< Packet Descriptor number in modem */
 	u32 hd_size_in_dw; /*!< Host(SoC) descriptor size in dwords */
 	u32 pd_size_in_dw; /*!< Packet descriptor size in dwords */
 	u32 byteswap; /*!< Byte swap enabled or not in ACA FW */
+	u32 prefill_cnt; /*!< Prefill counter special required for some platform */
 };
 
 struct aca_param {
@@ -218,6 +251,10 @@ struct aca_hw_ops {
 	int (*gpio_src_set)(struct dc_ep_dev *pdev, u32 gpio, int val);
 	int (*gpio_dcc_set)(struct dc_ep_dev *pdev, u32 gpio, u32 val);
 
+	/* ICU Callbacks */
+	void (*icu_en)(struct dc_ep_dev *pdev, u32 bit);
+	void (*icu_mask)(struct dc_ep_dev *pdev, u32 bit);
+
 	/* ACA related stuff */
 	int (*aca_start)(struct dc_ep_dev *pdev, u32 func, int start);
 	int (*aca_stop)(struct dc_ep_dev *pdev, u32 *func, int reset);
@@ -227,7 +264,7 @@ struct aca_hw_ops {
 	void (*aca_event_addr_get)(struct dc_ep_dev *pdev,
 		struct aca_event_reg_addr *regs);
 	/* UMT address needed for SoC filled in to trigger UMT msg */
-	u32 (*umt_msg_addr)(struct dc_ep_dev *pdev);
+	u32 (*umt_msg_addr)(struct dc_ep_dev *pdev, u32 endian, u32 type);
 	/* TXIN accum sub to ack PPE already processed */
 	void (*aca_txin_ack_sub)(struct dc_ep_dev *pdev, u32 val);
 	u32 (*aca_txin_hd_cnt)(struct dc_ep_dev *pdev);
diff --git a/include/uapi/linux/atm.h b/include/uapi/linux/atm.h
index 88399db60..c5ae98fc0 100644
--- a/include/uapi/linux/atm.h
+++ b/include/uapi/linux/atm.h
@@ -130,8 +130,14 @@
 #define ATM_ABR		4
 #define ATM_ANYCLASS	5		/* compatible with everything */
 
+#define ATM_VBR_NRT     ATM_VBR
+#define ATM_VBR_RT      6
+#define ATM_UBR_PLUS    7
+#define ATM_GFR         8
+
 #define ATM_MAX_PCR	-1		/* maximum available PCR */
 
+
 struct atm_trafprm {
 	unsigned char	traffic_class;	/* traffic class (ATM_UBR, ...) */
 	int		max_pcr;	/* maximum PCR in cells per second */
@@ -154,6 +160,9 @@ struct atm_trafprm {
 	unsigned int adtf      :10;     /* ACR Decrease Time Factor (10-bit) */
 	unsigned int cdf       :3;      /* Cutoff Decrease Factor (3-bit) */
         unsigned int spare     :9;      /* spare bits */ 
+	int		scr;		/* sustained rate in cells per second */
+	int		mbs;		/* maximum burst size (MBS) in cells */
+	int		cdv;		/* Cell delay varition */
 };
 
 struct atm_qos {
diff --git a/include/uapi/linux/atmdev.h b/include/uapi/linux/atmdev.h
index 93e0ec008..3b51063bc 100644
--- a/include/uapi/linux/atmdev.h
+++ b/include/uapi/linux/atmdev.h
@@ -106,6 +106,8 @@ struct atm_dev_stats {
 #endif
 #define ATM_DROPPARTY 	_IOW('a', ATMIOC_SPECIAL+5,int)
 					/* drop party from p2mp call */
+#define ATM_DELBACKENDIF _IOW('a',ATMIOC_SPECIAL+6,atm_backend_t)
+                                       /* set backend to remove if */
 
 /*
  * These are backend handkers that can be set via the ATM_SETBACKEND call
diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
index 1158a0433..b6779614d 100644
--- a/include/uapi/linux/if.h
+++ b/include/uapi/linux/if.h
@@ -130,6 +130,7 @@ enum net_device_flags {
 #define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
 		IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
 
+#define IFF_BR2684     0x80            /* nas RFC2684 interface        */
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
 
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 8e1744e9d..7a2a2b8b3 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -38,7 +38,10 @@ static void skb_debug(const struct sk_buff *skb)
 #endif
 }
 
+#define BR2684_LLC_LEN         3
+#define BR2684_SNAP_LEN        3
 #define BR2684_ETHERTYPE_LEN	2
+#define BR2684_PID_LEN		2
 #define BR2684_PAD_LEN		2
 
 #define LLC		0xaa, 0xaa, 0x03
@@ -596,6 +599,11 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 	atmvcc->push = br2684_push;
 	atmvcc->pop = br2684_pop;
 	atmvcc->release_cb = br2684_release_cb;
+#if IS_ENABLED(CONFIG_VRX518_TC)
+	if (atm_hook_mpoa_setup) /* IPoA or EoA w/o FCS */
+		atm_hook_mpoa_setup(atmvcc, brdev->payload == p_routed ? 3 : 0,
+			brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0, net_dev);
+#endif
 	atmvcc->owner = THIS_MODULE;
 
 	/* initialize netdev carrier state */
@@ -661,6 +669,41 @@ static const struct net_device_ops br2684_netdev_ops_routed = {
 #endif
 };
 
+static int br2684_unregvcc(struct atm_vcc *atmvcc, void __user *arg)
+{
+	int err;
+	struct br2684_vcc *brvcc;
+	struct br2684_dev *brdev;
+	struct net_device *net_dev;
+	struct atm_backend_br2684 be;
+
+	if (copy_from_user(&be, arg, sizeof be))
+		return -EFAULT;
+	/* write_lock_irq(&devs_lock); */
+	net_dev = br2684_find_dev(&be.ifspec);
+	if (net_dev == NULL) {
+		printk(KERN_ERR
+			"br2684: tried to unregister to non-existant device\n");
+		err = -ENXIO;
+		goto error;
+	}
+	brdev = BRPRIV(net_dev);
+	while (!list_empty(&brdev->brvccs)) {
+		brvcc = list_entry_brvcc(brdev->brvccs.next);
+		br2684_close_vcc(brvcc);
+	}
+	list_del(&brdev->br2684_devs);
+	/* write_unlock_irq(&devs_lock); */
+	unregister_netdev(net_dev);
+	free_netdev(net_dev);
+	atmvcc->push = NULL;
+	vcc_release_async(atmvcc, -ETIMEDOUT);
+	return 0;
+error:
+	/* write_unlock_irq(&devs_lock); */
+	return err;
+}
+
 static void br2684_setup(struct net_device *netdev)
 {
 	struct br2684_dev *brdev = BRPRIV(netdev);
@@ -728,6 +771,8 @@ static int br2684_create(void __user *arg)
 		free_netdev(netdev);
 		return err;
 	}
+	/* Mark br2684 device */
+	netdev->priv_flags |= IFF_BR2684;
 
 	write_lock_irq(&devs_lock);
 
@@ -759,6 +804,7 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
 	switch (cmd) {
 	case ATM_SETBACKEND:
 	case ATM_NEWBACKENDIF:
+	case ATM_DELBACKENDIF:
 		err = get_user(b, (atm_backend_t __user *) argp);
 		if (err)
 			return -EFAULT;
@@ -770,6 +816,8 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
 			if (sock->state != SS_CONNECTED)
 				return -EINVAL;
 			return br2684_regvcc(atmvcc, argp);
+		} else if (cmd == ATM_DELBACKENDIF) {
+			return br2684_unregvcc(atmvcc, argp);
 		} else {
 			return br2684_create(argp);
 		}
diff --git a/net/atm/common.c b/net/atm/common.c
index 6dc123057..41ce61519 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -141,6 +141,11 @@ static struct proto vcc_proto = {
 	.release_cb = vcc_release_cb,
 };
 
+#if IS_ENABLED(CONFIG_VRX518_TC)
+void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *) = NULL;
+EXPORT_SYMBOL(atm_hook_mpoa_setup);
+#endif
+
 int vcc_create(struct net *net, struct socket *sock, int protocol, int family, int kern)
 {
 	struct sock *sk;
diff --git a/net/atm/common.h b/net/atm/common.h
index 959436b87..6ac04016c 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -51,5 +51,10 @@ static inline void atm_proc_exit(void)
 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
 
 void atm_dev_release_vccs(struct atm_dev *dev);
+#if IS_ENABLED(CONFIG_VRX318_DATAPATH) || IS_ENABLED(CONFIG_VRX518_TC) \
+	|| IS_ENABLED(CONFIG_LTQ_PPA_A1)
+extern void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *);
+#endif
+
 
 #endif
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 3b3b1a292..e0512cb80 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -30,6 +30,7 @@
 /* Modular too */
 #include <linux/module.h>
 
+#include "common.h"
 #include "lec.h"
 #include "mpc.h"
 #include "resources.h"
@@ -601,7 +602,6 @@ static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
 non_ip:
 	return __netdev_start_xmit(mpc->old_ops, skb, dev, false);
 }
-
 static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
 {
 	int bytes_left;
@@ -644,7 +644,10 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
 
 	vcc->proto_data = mpc->dev;
 	vcc->push = mpc_push;
-
+#if IS_ENABLED(CONFIG_VRX518_TC)
+   if (atm_hook_mpoa_setup) /* IPoA, LLC */
+       atm_hook_mpoa_setup(vcc, 3, 1, mpc->dev);
+#endif
 	return 0;
 }
 
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 230fb9f5b..f3df127d7 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -464,6 +464,12 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
 	atmvcc->user_back = pvcc;
 	atmvcc->push = pppoatm_push;
 	atmvcc->pop = pppoatm_pop;
+#if IS_ENABLED(CONFIG_VRX518_TC)
+	if (atm_hook_mpoa_setup) /* PPPoA */
+		atm_hook_mpoa_setup(atmvcc, 2,
+			pvcc->encaps == e_llc ? 1 : 0,
+			ppp_device(&pvcc->chan));
+#endif
 	atmvcc->release_cb = pppoatm_release_cb;
 	__module_get(THIS_MODULE);
 	atmvcc->owner = THIS_MODULE;
-- 
GitLab