diff options
Diffstat (limited to 'drivers/net/ethernet/airoha')
-rw-r--r-- | drivers/net/ethernet/airoha/airoha_eth.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/airoha/airoha_npu.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/airoha/airoha_ppe.c | 35 | ||||
-rw-r--r-- | drivers/net/ethernet/airoha/airoha_regs.h | 3 |
4 files changed, 58 insertions, 45 deletions
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index a7ec609d64de..e6b802e3d844 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -551,9 +551,7 @@ static int airoha_fe_init(struct airoha_eth *eth) static int airoha_qdma_fill_rx_queue(struct airoha_queue *q) { - enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); struct airoha_qdma *qdma = q->qdma; - struct airoha_eth *eth = qdma->eth; int qid = q - &qdma->q_rx[0]; int nframes = 0; @@ -577,9 +575,6 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q) e->dma_addr = page_pool_get_dma_addr(page) + offset; e->dma_len = SKB_WITH_OVERHEAD(q->buf_size); - dma_sync_single_for_device(eth->dev, e->dma_addr, e->dma_len, - dir); - val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); @@ -1065,23 +1060,18 @@ static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) { + int size, index, num_desc = HW_DSCP_NUM; struct airoha_eth *eth = qdma->eth; int id = qdma - ð->qdma[0]; + u32 status, buf_size; dma_addr_t dma_addr; const char *name; - int size, index; - u32 status; - - size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); - if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) - return -ENOMEM; - - airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); if (!name) return -ENOMEM; + buf_size = id ? AIROHA_MAX_PACKET_SIZE / 2 : AIROHA_MAX_PACKET_SIZE; index = of_property_match_string(eth->dev->of_node, "memory-region-names", name); if (index >= 0) { @@ -1099,8 +1089,12 @@ static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) rmem = of_reserved_mem_lookup(np); of_node_put(np); dma_addr = rmem->base; + /* Compute the number of hw descriptors according to the + * reserved memory size and the payload buffer size + */ + num_desc = div_u64(rmem->size, buf_size); } else { - size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; + size = buf_size * num_desc; if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) return -ENOMEM; @@ -1108,15 +1102,21 @@ static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); + size = num_desc * sizeof(struct airoha_qdma_fwd_desc); + if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) + return -ENOMEM; + + airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); + /* QDMA0: 2KB. QDMA1: 1KB */ airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, HW_FWD_DSCP_PAYLOAD_SIZE_MASK, - FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); + FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, !!id)); airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK, FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128)); airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, LMGR_INIT_START | LMGR_SRAM_MODE_MASK | HW_FWD_DESC_NUM_MASK, - FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | + FIELD_PREP(HW_FWD_DESC_NUM_MASK, num_desc) | LMGR_INIT_START | LMGR_SRAM_MODE_MASK); return read_poll_timeout(airoha_qdma_rr, status, @@ -2979,6 +2979,7 @@ static int airoha_probe(struct platform_device *pdev) error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) airoha_qdma_stop_napi(ð->qdma[i]); + airoha_ppe_deinit(eth); error_hw_cleanup: for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) airoha_hw_cleanup(ð->qdma[i]); diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index 0e5b8c21b9aa..9ab964c536e1 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -161,7 +161,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, } static int airoha_npu_run_firmware(struct device *dev, void __iomem *base, - struct reserved_mem *rmem) + struct resource *res) { const struct firmware *fw; void __iomem *addr; @@ -178,9 +178,9 @@ static int airoha_npu_run_firmware(struct device *dev, void __iomem *base, goto out; } - addr = devm_ioremap(dev, rmem->base, rmem->size); - if (!addr) { - ret = -ENOMEM; + addr = devm_ioremap_resource(dev, res); + if (IS_ERR(addr)) { + ret = PTR_ERR(addr); goto out; } @@ -401,12 +401,13 @@ struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) return ERR_PTR(-ENODEV); pdev = of_find_device_by_node(np); - of_node_put(np); if (!pdev) { dev_err(dev, "cannot find device node %s\n", np->name); + of_node_put(np); return ERR_PTR(-ENODEV); } + of_node_put(np); if (!try_module_get(THIS_MODULE)) { dev_err(dev, "failed to get the device driver module\n"); @@ -474,9 +475,8 @@ static const struct regmap_config regmap_config = { static int airoha_npu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct reserved_mem *rmem; struct airoha_npu *npu; - struct device_node *np; + struct resource res; void __iomem *base; int i, irq, err; @@ -498,15 +498,9 @@ static int airoha_npu_probe(struct platform_device *pdev) if (IS_ERR(npu->regmap)) return PTR_ERR(npu->regmap); - np = of_parse_phandle(dev->of_node, "memory-region", 0); - if (!np) - return -ENODEV; - - rmem = of_reserved_mem_lookup(np); - of_node_put(np); - - if (!rmem) - return -ENODEV; + err = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + if (err) + return err; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -539,12 +533,12 @@ static int airoha_npu_probe(struct platform_device *pdev) if (err) return err; - err = airoha_npu_run_firmware(dev, base, rmem); + err = airoha_npu_run_firmware(dev, base, &res); if (err) return dev_err_probe(dev, err, "failed to run npu firmware\n"); regmap_write(npu->regmap, REG_CR_NPU_MIB(10), - rmem->base + NPU_EN7581_FIRMWARE_RV32_MAX_SIZE); + res.start + NPU_EN7581_FIRMWARE_RV32_MAX_SIZE); regmap_write(npu->regmap, REG_CR_NPU_MIB(11), 0x40000); /* SRAM 256K */ regmap_write(npu->regmap, REG_CR_NPU_MIB(12), 0); regmap_write(npu->regmap, REG_CR_NPU_MIB(21), 1); @@ -552,7 +546,7 @@ static int airoha_npu_probe(struct platform_device *pdev) /* setting booting address */ for (i = 0; i < NPU_NUM_CORES; i++) - regmap_write(npu->regmap, REG_CR_BOOT_BASE(i), rmem->base); + regmap_write(npu->regmap, REG_CR_BOOT_BASE(i), res.start); usleep_range(1000, 2000); /* enable NPU cores */ diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 9067d2fc7706..c354d536bc66 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -232,6 +232,7 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, FIELD_PREP(AIROHA_FOE_IB1_BIND_UDP, l4proto == IPPROTO_UDP) | FIELD_PREP(AIROHA_FOE_IB1_BIND_VLAN_LAYER, data->vlan.num) | FIELD_PREP(AIROHA_FOE_IB1_BIND_VPM, data->vlan.num) | + FIELD_PREP(AIROHA_FOE_IB1_BIND_PPPOE, data->pppoe.num) | AIROHA_FOE_IB1_BIND_TTL; hwe->ib1 = val; @@ -281,33 +282,42 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, hwe->ipv6.data = qdata; hwe->ipv6.ib2 = val; l2 = &hwe->ipv6.l2; + l2->etype = ETH_P_IPV6; } else { hwe->ipv4.data = qdata; hwe->ipv4.ib2 = val; l2 = &hwe->ipv4.l2.common; + l2->etype = ETH_P_IP; } l2->dest_mac_hi = get_unaligned_be32(data->eth.h_dest); l2->dest_mac_lo = get_unaligned_be16(data->eth.h_dest + 4); if (type <= PPE_PKT_TYPE_IPV4_DSLITE) { + struct airoha_foe_mac_info *mac_info; + l2->src_mac_hi = get_unaligned_be32(data->eth.h_source); hwe->ipv4.l2.src_mac_lo = get_unaligned_be16(data->eth.h_source + 4); + + mac_info = (struct airoha_foe_mac_info *)l2; + mac_info->pppoe_id = data->pppoe.sid; } else { - l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id); + l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id) | + FIELD_PREP(AIROHA_FOE_MAC_PPPOE_ID, + data->pppoe.sid); } if (data->vlan.num) { - l2->etype = dsa_port >= 0 ? BIT(dsa_port) : 0; l2->vlan1 = data->vlan.hdr[0].id; if (data->vlan.num == 2) l2->vlan2 = data->vlan.hdr[1].id; - } else if (dsa_port >= 0) { - l2->etype = BIT(15) | BIT(dsa_port); - } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { - l2->etype = ETH_P_IPV6; - } else { - l2->etype = ETH_P_IP; + } + + if (dsa_port >= 0) { + l2->etype = BIT(dsa_port); + l2->etype |= !data->vlan.num ? BIT(15) : 0; + } else if (data->pppoe.num) { + l2->etype = ETH_P_PPP_SES; } return 0; @@ -809,8 +819,10 @@ airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe *ppe, int idle; hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); - ib1 = READ_ONCE(hwe->ib1); + if (!hwe) + continue; + ib1 = READ_ONCE(hwe->ib1); state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); if (state != AIROHA_FOE_STATE_BIND) { iter->hash = 0xffff; @@ -957,6 +969,11 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, case FLOW_ACTION_VLAN_POP: break; case FLOW_ACTION_PPPOE_PUSH: + if (data.pppoe.num == 1 || data.vlan.num == 2) + return -EOPNOTSUPP; + + data.pppoe.sid = act->pppoe.sid; + data.pppoe.num++; break; default: return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h index 04187eb40ec6..150c85995cc1 100644 --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -614,8 +614,9 @@ RX19_DONE_INT_MASK | RX18_DONE_INT_MASK | \ RX17_DONE_INT_MASK | RX16_DONE_INT_MASK) -#define RX_DONE_INT_MASK (RX_DONE_HIGH_INT_MASK | RX_DONE_LOW_INT_MASK) #define RX_DONE_HIGH_OFFSET fls(RX_DONE_HIGH_INT_MASK) +#define RX_DONE_INT_MASK \ + ((RX_DONE_HIGH_INT_MASK << RX_DONE_HIGH_OFFSET) | RX_DONE_LOW_INT_MASK) #define INT_RX2_MASK(_n) \ ((RX_NO_CPU_DSCP_HIGH_INT_MASK & (_n)) | \ |