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, ¶m->aca_rxout); aca_rxin_init(priv, ¶m->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