mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
Merge branch 'net-airoha-add-an7583-ethernet-controller-support'
Lorenzo Bianconi says: ==================== net: airoha: Add AN7583 ethernet controller support Introduce support for AN7583 ethernet controller to airoha-eth dirver. The main differences between EN7581 and AN7583 is the latter runs a single PPE module while EN7581 runs two of them. Moreover PPE SRAM in AN7583 SoC is reduced to 8K (while SRAM is 16K on EN7581). v2: https://lore.kernel.org/r/20251016-an7583-eth-support-v2-0-ea6e7e9acbdb@kernel.org v1: https://lore.kernel.org/r/20251015-an7583-eth-support-v1-0-064855f05923@kernel.org ==================== Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-0-f28319666667@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
d1d7998df9
|
|
@ -17,6 +17,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- airoha,en7581-eth
|
||||
- airoha,an7583-eth
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
|
@ -44,6 +45,7 @@ properties:
|
|||
- description: PDMA irq
|
||||
|
||||
resets:
|
||||
minItems: 7
|
||||
maxItems: 8
|
||||
|
||||
reset-names:
|
||||
|
|
@ -54,8 +56,9 @@ properties:
|
|||
- const: xsi-mac
|
||||
- const: hsi0-mac
|
||||
- const: hsi1-mac
|
||||
- const: hsi-mac
|
||||
- enum: [ hsi-mac, xfp-mac ]
|
||||
- const: xfp-mac
|
||||
minItems: 7
|
||||
|
||||
memory-region:
|
||||
items:
|
||||
|
|
@ -81,6 +84,36 @@ properties:
|
|||
interface to implement hardware flow offloading programming Packet
|
||||
Processor Engine (PPE) flow table.
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- airoha,en7581-eth
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
minItems: 8
|
||||
|
||||
reset-names:
|
||||
minItems: 8
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- airoha,an7583-eth
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
maxItems: 7
|
||||
|
||||
reset-names:
|
||||
maxItems: 7
|
||||
|
||||
patternProperties:
|
||||
"^ethernet@[1-4]$":
|
||||
type: object
|
||||
|
|
|
|||
|
|
@ -297,8 +297,11 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)
|
|||
int q;
|
||||
|
||||
all_rsv = airoha_fe_get_pse_all_rsv(eth);
|
||||
/* hw misses PPE2 oq rsv */
|
||||
all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2];
|
||||
if (airoha_ppe_is_enabled(eth, 1)) {
|
||||
/* hw misses PPE2 oq rsv */
|
||||
all_rsv += PSE_RSV_PAGES *
|
||||
pse_port_num_queues[FE_PSE_PORT_PPE2];
|
||||
}
|
||||
airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv);
|
||||
|
||||
/* CMD1 */
|
||||
|
|
@ -335,13 +338,17 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)
|
|||
for (q = 4; q < pse_port_num_queues[FE_PSE_PORT_CDM4]; q++)
|
||||
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM4, q,
|
||||
PSE_QUEUE_RSV_PAGES);
|
||||
/* PPE2 */
|
||||
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) {
|
||||
if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2)
|
||||
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q,
|
||||
PSE_QUEUE_RSV_PAGES);
|
||||
else
|
||||
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, 0);
|
||||
if (airoha_ppe_is_enabled(eth, 1)) {
|
||||
/* PPE2 */
|
||||
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) {
|
||||
if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2)
|
||||
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2,
|
||||
q,
|
||||
PSE_QUEUE_RSV_PAGES);
|
||||
else
|
||||
airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2,
|
||||
q, 0);
|
||||
}
|
||||
}
|
||||
/* GMD4 */
|
||||
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++)
|
||||
|
|
@ -524,25 +531,6 @@ static int airoha_fe_init(struct airoha_eth *eth)
|
|||
/* disable IFC by default */
|
||||
airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK);
|
||||
|
||||
airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0),
|
||||
FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM1) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM1));
|
||||
airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(1),
|
||||
FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM2) |
|
||||
FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM2));
|
||||
|
||||
/* enable 1:N vlan action, init vlan table */
|
||||
airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK);
|
||||
|
||||
|
|
@ -1387,8 +1375,7 @@ static int airoha_hw_init(struct platform_device *pdev,
|
|||
int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts),
|
||||
eth->xsi_rsts);
|
||||
err = reset_control_bulk_assert(eth->soc->num_xsi_rsts, eth->xsi_rsts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -1695,19 +1682,23 @@ static int airoha_dev_set_macaddr(struct net_device *dev, void *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
|
||||
static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
|
||||
{
|
||||
u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4;
|
||||
struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 chan = port->id == 3 ? 4 : 0;
|
||||
u32 val, pse_port, chan, nbq;
|
||||
int src_port;
|
||||
|
||||
/* Forward the traffic to the proper GDM port */
|
||||
pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
|
||||
: FE_PSE_PORT_GDM4;
|
||||
airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port);
|
||||
airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC);
|
||||
|
||||
/* Enable GDM2 loopback */
|
||||
airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff);
|
||||
airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff);
|
||||
|
||||
chan = port->id == AIROHA_GDM3_IDX ? airoha_is_7581(eth) ? 4 : 3 : 0;
|
||||
airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2),
|
||||
LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK,
|
||||
FIELD_PREP(LPBK_CHAN_MASK, chan) |
|
||||
|
|
@ -1722,36 +1713,36 @@ static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
|
|||
airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2));
|
||||
airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2));
|
||||
|
||||
if (port->id == 3) {
|
||||
/* FIXME: handle XSI_PCE1_PORT */
|
||||
airoha_fe_rmw(eth, REG_FE_WAN_PORT,
|
||||
WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
|
||||
FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT));
|
||||
airoha_fe_rmw(eth,
|
||||
REG_SP_DFT_CPORT(HSGMII_LAN_PCIE0_SRCPORT >> 3),
|
||||
SP_CPORT_PCIE0_MASK,
|
||||
FIELD_PREP(SP_CPORT_PCIE0_MASK,
|
||||
FE_PSE_PORT_CDM2));
|
||||
} else {
|
||||
/* FIXME: handle XSI_USB_PORT */
|
||||
/* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
|
||||
nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
|
||||
src_port = eth->soc->ops.get_src_port_id(port, nbq);
|
||||
if (src_port < 0)
|
||||
return src_port;
|
||||
|
||||
airoha_fe_rmw(eth, REG_FE_WAN_PORT,
|
||||
WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
|
||||
FIELD_PREP(WAN0_MASK, src_port));
|
||||
val = src_port & SP_CPORT_DFT_MASK;
|
||||
airoha_fe_rmw(eth,
|
||||
REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)),
|
||||
SP_CPORT_MASK(val),
|
||||
FE_PSE_PORT_CDM2 << __ffs(SP_CPORT_MASK(val)));
|
||||
|
||||
if (port->id != AIROHA_GDM3_IDX && airoha_is_7581(eth))
|
||||
airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6,
|
||||
FC_ID_OF_SRC_PORT24_MASK,
|
||||
FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2));
|
||||
airoha_fe_rmw(eth, REG_FE_WAN_PORT,
|
||||
WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
|
||||
FIELD_PREP(WAN0_MASK, HSGMII_LAN_ETH_SRCPORT));
|
||||
airoha_fe_rmw(eth,
|
||||
REG_SP_DFT_CPORT(HSGMII_LAN_ETH_SRCPORT >> 3),
|
||||
SP_CPORT_ETH_MASK,
|
||||
FIELD_PREP(SP_CPORT_ETH_MASK, FE_PSE_PORT_CDM2));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int airoha_dev_init(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 pse_port;
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
struct airoha_eth *eth = qdma->eth;
|
||||
u32 pse_port, fe_cpu_port;
|
||||
u8 ppe_id;
|
||||
|
||||
airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
|
|
@ -1759,18 +1750,37 @@ static int airoha_dev_init(struct net_device *dev)
|
|||
case 3:
|
||||
case 4:
|
||||
/* If GDM2 is active we can't enable loopback */
|
||||
if (!eth->ports[1])
|
||||
airhoha_set_gdm2_loopback(port);
|
||||
if (!eth->ports[1]) {
|
||||
int err;
|
||||
|
||||
err = airhoha_set_gdm2_loopback(port);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
fallthrough;
|
||||
case 2:
|
||||
pse_port = FE_PSE_PORT_PPE2;
|
||||
break;
|
||||
default:
|
||||
if (airoha_ppe_is_enabled(eth, 1)) {
|
||||
/* For PPE2 always use secondary cpu port. */
|
||||
fe_cpu_port = FE_PSE_PORT_CDM2;
|
||||
pse_port = FE_PSE_PORT_PPE2;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
default: {
|
||||
u8 qdma_id = qdma - ð->qdma[0];
|
||||
|
||||
/* For PPE1 select cpu port according to the running QDMA. */
|
||||
fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1;
|
||||
pse_port = FE_PSE_PORT_PPE1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port);
|
||||
ppe_id = pse_port == FE_PSE_PORT_PPE2 ? 1 : 0;
|
||||
airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id),
|
||||
DFT_CPORT_MASK(port->id),
|
||||
fe_cpu_port << __ffs(DFT_CPORT_MASK(port->id)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1887,6 +1897,22 @@ static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags)
|
|||
return index >= tail;
|
||||
}
|
||||
|
||||
static int airoha_get_fe_port(struct airoha_gdm_port *port)
|
||||
{
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
struct airoha_eth *eth = qdma->eth;
|
||||
|
||||
switch (eth->soc->version) {
|
||||
case 0x7583:
|
||||
return port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
|
||||
: port->id;
|
||||
case 0x7581:
|
||||
default:
|
||||
return port->id == AIROHA_GDM4_IDX ? FE_PSE_PORT_GDM4
|
||||
: port->id;
|
||||
}
|
||||
}
|
||||
|
||||
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
|
|
@ -1927,7 +1953,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
|||
}
|
||||
}
|
||||
|
||||
fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
|
||||
fport = airoha_get_fe_port(port);
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
|
|
@ -2922,6 +2948,7 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
|
|||
|
||||
static int airoha_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct reset_control_bulk_data *xsi_rsts;
|
||||
struct device_node *np;
|
||||
struct airoha_eth *eth;
|
||||
int i, err;
|
||||
|
|
@ -2930,6 +2957,10 @@ static int airoha_probe(struct platform_device *pdev)
|
|||
if (!eth)
|
||||
return -ENOMEM;
|
||||
|
||||
eth->soc = of_device_get_match_data(&pdev->dev);
|
||||
if (!eth->soc)
|
||||
return -EINVAL;
|
||||
|
||||
eth->dev = &pdev->dev;
|
||||
|
||||
err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32));
|
||||
|
|
@ -2954,13 +2985,18 @@ static int airoha_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
eth->xsi_rsts[0].id = "xsi-mac";
|
||||
eth->xsi_rsts[1].id = "hsi0-mac";
|
||||
eth->xsi_rsts[2].id = "hsi1-mac";
|
||||
eth->xsi_rsts[3].id = "hsi-mac";
|
||||
eth->xsi_rsts[4].id = "xfp-mac";
|
||||
xsi_rsts = devm_kzalloc(eth->dev,
|
||||
eth->soc->num_xsi_rsts * sizeof(*xsi_rsts),
|
||||
GFP_KERNEL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
eth->xsi_rsts = xsi_rsts;
|
||||
for (i = 0; i < eth->soc->num_xsi_rsts; i++)
|
||||
eth->xsi_rsts[i].id = eth->soc->xsi_rsts_names[i];
|
||||
|
||||
err = devm_reset_control_bulk_get_exclusive(eth->dev,
|
||||
ARRAY_SIZE(eth->xsi_rsts),
|
||||
eth->soc->num_xsi_rsts,
|
||||
eth->xsi_rsts);
|
||||
if (err) {
|
||||
dev_err(eth->dev, "failed to get bulk xsi reset lines\n");
|
||||
|
|
@ -3048,8 +3084,90 @@ static void airoha_remove(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const char * const en7581_xsi_rsts_names[] = {
|
||||
"xsi-mac",
|
||||
"hsi0-mac",
|
||||
"hsi1-mac",
|
||||
"hsi-mac",
|
||||
"xfp-mac",
|
||||
};
|
||||
|
||||
static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)
|
||||
{
|
||||
switch (port->id) {
|
||||
case 3:
|
||||
/* 7581 SoC supports PCIe serdes on GDM3 port */
|
||||
if (nbq == 4)
|
||||
return HSGMII_LAN_7581_PCIE0_SRCPORT;
|
||||
if (nbq == 5)
|
||||
return HSGMII_LAN_7581_PCIE1_SRCPORT;
|
||||
break;
|
||||
case 4:
|
||||
/* 7581 SoC supports eth and usb serdes on GDM4 port */
|
||||
if (!nbq)
|
||||
return HSGMII_LAN_7581_ETH_SRCPORT;
|
||||
if (nbq == 1)
|
||||
return HSGMII_LAN_7581_USB_SRCPORT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const char * const an7583_xsi_rsts_names[] = {
|
||||
"xsi-mac",
|
||||
"hsi0-mac",
|
||||
"hsi1-mac",
|
||||
"xfp-mac",
|
||||
};
|
||||
|
||||
static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)
|
||||
{
|
||||
switch (port->id) {
|
||||
case 3:
|
||||
/* 7583 SoC supports eth serdes on GDM3 port */
|
||||
if (!nbq)
|
||||
return HSGMII_LAN_7583_ETH_SRCPORT;
|
||||
break;
|
||||
case 4:
|
||||
/* 7583 SoC supports PCIe and USB serdes on GDM4 port */
|
||||
if (!nbq)
|
||||
return HSGMII_LAN_7583_PCIE_SRCPORT;
|
||||
if (nbq == 1)
|
||||
return HSGMII_LAN_7583_USB_SRCPORT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct airoha_eth_soc_data en7581_soc_data = {
|
||||
.version = 0x7581,
|
||||
.xsi_rsts_names = en7581_xsi_rsts_names,
|
||||
.num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
|
||||
.num_ppe = 2,
|
||||
.ops = {
|
||||
.get_src_port_id = airoha_en7581_get_src_port_id,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct airoha_eth_soc_data an7583_soc_data = {
|
||||
.version = 0x7583,
|
||||
.xsi_rsts_names = an7583_xsi_rsts_names,
|
||||
.num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names),
|
||||
.num_ppe = 1,
|
||||
.ops = {
|
||||
.get_src_port_id = airoha_an7583_get_src_port_id,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id of_airoha_match[] = {
|
||||
{ .compatible = "airoha,en7581-eth" },
|
||||
{ .compatible = "airoha,en7581-eth", .data = &en7581_soc_data },
|
||||
{ .compatible = "airoha,an7583-eth", .data = &an7583_soc_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_airoha_match);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#define AIROHA_MAX_NUM_IRQ_BANKS 4
|
||||
#define AIROHA_MAX_DSA_PORTS 7
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 9216
|
||||
#define AIROHA_MAX_PACKET_SIZE 2048
|
||||
#define AIROHA_NUM_QOS_CHANNELS 4
|
||||
|
|
@ -48,20 +47,9 @@
|
|||
#define QDMA_METER_IDX(_n) ((_n) & 0xff)
|
||||
#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
|
||||
|
||||
#define PPE_NUM 2
|
||||
#define PPE1_SRAM_NUM_ENTRIES (8 * 1024)
|
||||
#define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES)
|
||||
#ifdef CONFIG_NET_AIROHA_FLOW_STATS
|
||||
#define PPE1_STATS_NUM_ENTRIES (4 * 1024)
|
||||
#else
|
||||
#define PPE1_STATS_NUM_ENTRIES 0
|
||||
#endif /* CONFIG_NET_AIROHA_FLOW_STATS */
|
||||
#define PPE_STATS_NUM_ENTRIES (2 * PPE1_STATS_NUM_ENTRIES)
|
||||
#define PPE1_SRAM_NUM_DATA_ENTRIES (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES)
|
||||
#define PPE_SRAM_NUM_DATA_ENTRIES (2 * PPE1_SRAM_NUM_DATA_ENTRIES)
|
||||
#define PPE_SRAM_NUM_ENTRIES (8 * 1024)
|
||||
#define PPE_STATS_NUM_ENTRIES (4 * 1024)
|
||||
#define PPE_DRAM_NUM_ENTRIES (16 * 1024)
|
||||
#define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES)
|
||||
#define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1)
|
||||
#define PPE_ENTRY_SIZE 80
|
||||
#define PPE_RAM_NUM_ENTRIES_SHIFT(_n) (__ffs((_n) >> 10))
|
||||
|
||||
|
|
@ -79,10 +67,16 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
HSGMII_LAN_PCIE0_SRCPORT = 0x16,
|
||||
HSGMII_LAN_PCIE1_SRCPORT,
|
||||
HSGMII_LAN_ETH_SRCPORT,
|
||||
HSGMII_LAN_USB_SRCPORT,
|
||||
HSGMII_LAN_7581_PCIE0_SRCPORT = 0x16,
|
||||
HSGMII_LAN_7581_PCIE1_SRCPORT,
|
||||
HSGMII_LAN_7581_ETH_SRCPORT,
|
||||
HSGMII_LAN_7581_USB_SRCPORT,
|
||||
};
|
||||
|
||||
enum {
|
||||
HSGMII_LAN_7583_ETH_SRCPORT = 0x16,
|
||||
HSGMII_LAN_7583_PCIE_SRCPORT = 0x18,
|
||||
HSGMII_LAN_7583_USB_SRCPORT,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -111,6 +105,13 @@ enum {
|
|||
CRSN_25 = 0x19,
|
||||
};
|
||||
|
||||
enum airoha_gdm_index {
|
||||
AIROHA_GDM1_IDX = 1,
|
||||
AIROHA_GDM2_IDX = 2,
|
||||
AIROHA_GDM3_IDX = 3,
|
||||
AIROHA_GDM4_IDX = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
FE_PSE_PORT_CDM1,
|
||||
FE_PSE_PORT_GDM1,
|
||||
|
|
@ -554,7 +555,7 @@ struct airoha_ppe {
|
|||
struct rhashtable l2_flows;
|
||||
|
||||
struct hlist_head *foe_flow;
|
||||
u16 foe_check_time[PPE_NUM_ENTRIES];
|
||||
u16 *foe_check_time;
|
||||
|
||||
struct airoha_foe_stats *foe_stats;
|
||||
dma_addr_t foe_stats_dma;
|
||||
|
|
@ -562,9 +563,21 @@ struct airoha_ppe {
|
|||
struct dentry *debugfs_dir;
|
||||
};
|
||||
|
||||
struct airoha_eth_soc_data {
|
||||
u16 version;
|
||||
const char * const *xsi_rsts_names;
|
||||
int num_xsi_rsts;
|
||||
int num_ppe;
|
||||
struct {
|
||||
int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq);
|
||||
} ops;
|
||||
};
|
||||
|
||||
struct airoha_eth {
|
||||
struct device *dev;
|
||||
|
||||
const struct airoha_eth_soc_data *soc;
|
||||
|
||||
unsigned long state;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
|
|
@ -574,7 +587,7 @@ struct airoha_eth {
|
|||
struct rhashtable flow_table;
|
||||
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
struct reset_control_bulk_data *xsi_rsts;
|
||||
|
||||
struct net_device *napi_dev;
|
||||
|
||||
|
|
@ -617,15 +630,27 @@ static inline bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)
|
|||
return port->id == 1;
|
||||
}
|
||||
|
||||
static inline bool airoha_is_7581(struct airoha_eth *eth)
|
||||
{
|
||||
return eth->soc->version == 0x7581;
|
||||
}
|
||||
|
||||
static inline bool airoha_is_7583(struct airoha_eth *eth)
|
||||
{
|
||||
return eth->soc->version == 0x7583;
|
||||
}
|
||||
|
||||
bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
|
||||
struct airoha_gdm_port *port);
|
||||
|
||||
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
|
||||
void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
|
||||
u16 hash, bool rx_wlan);
|
||||
int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);
|
||||
int airoha_ppe_init(struct airoha_eth *eth);
|
||||
void airoha_ppe_deinit(struct airoha_eth *eth);
|
||||
void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port);
|
||||
u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);
|
||||
struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
|
||||
u32 hash);
|
||||
void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
|
||||
|
|
|
|||
|
|
@ -32,9 +32,50 @@ static const struct rhashtable_params airoha_l2_flow_table_params = {
|
|||
.automatic_shrinking = true,
|
||||
};
|
||||
|
||||
static bool airoha_ppe2_is_enabled(struct airoha_eth *eth)
|
||||
static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
|
||||
{
|
||||
return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK;
|
||||
if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (airoha_is_7583(ppe->eth))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return PPE_STATS_NUM_ENTRIES;
|
||||
}
|
||||
|
||||
static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe)
|
||||
{
|
||||
int num_stats = airoha_ppe_get_num_stats_entries(ppe);
|
||||
|
||||
if (num_stats > 0) {
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
|
||||
num_stats = num_stats * eth->soc->num_ppe;
|
||||
}
|
||||
|
||||
return num_stats;
|
||||
}
|
||||
|
||||
static u32 airoha_ppe_get_total_sram_num_entries(struct airoha_ppe *ppe)
|
||||
{
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
|
||||
return PPE_SRAM_NUM_ENTRIES * eth->soc->num_ppe;
|
||||
}
|
||||
|
||||
u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe)
|
||||
{
|
||||
u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
|
||||
|
||||
return sram_num_entries + PPE_DRAM_NUM_ENTRIES;
|
||||
}
|
||||
|
||||
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index)
|
||||
{
|
||||
if (index >= eth->soc->num_ppe)
|
||||
return false;
|
||||
|
||||
return airoha_fe_rr(eth, REG_PPE_GLO_CFG(index)) & PPE_GLO_CFG_EN_MASK;
|
||||
}
|
||||
|
||||
static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
|
||||
|
|
@ -46,14 +87,22 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
|
|||
|
||||
static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
|
||||
{
|
||||
u32 sram_tb_size, sram_num_entries, dram_num_entries;
|
||||
u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries;
|
||||
u32 sram_tb_size, dram_num_entries;
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
int i;
|
||||
int i, sram_num_stats_entries;
|
||||
|
||||
sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry);
|
||||
sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
|
||||
sram_tb_size = sram_num_entries * sizeof(struct airoha_foe_entry);
|
||||
dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES);
|
||||
|
||||
for (i = 0; i < PPE_NUM; i++) {
|
||||
sram_num_stats_entries = airoha_ppe_get_num_stats_entries(ppe);
|
||||
if (sram_num_stats_entries > 0)
|
||||
sram_ppe_num_data_entries -= sram_num_stats_entries;
|
||||
sram_ppe_num_data_entries =
|
||||
PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
|
||||
|
||||
for (i = 0; i < eth->soc->num_ppe; i++) {
|
||||
int p;
|
||||
|
||||
airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
|
||||
|
|
@ -85,10 +134,16 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
|
|||
|
||||
airoha_fe_rmw(eth, REG_PPE_TB_CFG(i),
|
||||
PPE_TB_CFG_SEARCH_MISS_MASK |
|
||||
PPE_SRAM_TB_NUM_ENTRY_MASK |
|
||||
PPE_DRAM_TB_NUM_ENTRY_MASK |
|
||||
PPE_TB_CFG_KEEPALIVE_MASK |
|
||||
PPE_TB_ENTRY_SIZE_MASK,
|
||||
FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) |
|
||||
FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0));
|
||||
FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0) |
|
||||
FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
|
||||
sram_ppe_num_data_entries) |
|
||||
FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
dram_num_entries));
|
||||
|
||||
airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED);
|
||||
|
||||
|
|
@ -101,35 +156,6 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
|
|||
FIELD_PREP(FP1_EGRESS_MTU_MASK,
|
||||
AIROHA_MAX_MTU));
|
||||
}
|
||||
|
||||
if (airoha_ppe2_is_enabled(eth)) {
|
||||
sram_num_entries =
|
||||
PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_DATA_ENTRIES);
|
||||
airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
|
||||
PPE_SRAM_TB_NUM_ENTRY_MASK |
|
||||
PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
|
||||
sram_num_entries) |
|
||||
FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
dram_num_entries));
|
||||
airoha_fe_rmw(eth, REG_PPE_TB_CFG(1),
|
||||
PPE_SRAM_TB_NUM_ENTRY_MASK |
|
||||
PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
|
||||
sram_num_entries) |
|
||||
FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
dram_num_entries));
|
||||
} else {
|
||||
sram_num_entries =
|
||||
PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_DATA_ENTRIES);
|
||||
airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
|
||||
PPE_SRAM_TB_NUM_ENTRY_MASK |
|
||||
PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
|
||||
sram_num_entries) |
|
||||
FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
|
||||
dram_num_entries));
|
||||
}
|
||||
}
|
||||
|
||||
static void airoha_ppe_flow_mangle_eth(const struct flow_action_entry *act, void *eth)
|
||||
|
|
@ -428,9 +454,11 @@ static int airoha_ppe_foe_entry_set_ipv6_tuple(struct airoha_foe_entry *hwe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe)
|
||||
static u32 airoha_ppe_foe_get_entry_hash(struct airoha_ppe *ppe,
|
||||
struct airoha_foe_entry *hwe)
|
||||
{
|
||||
int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
|
||||
u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
|
||||
u32 hash, hv1, hv2, hv3;
|
||||
|
||||
switch (type) {
|
||||
|
|
@ -468,25 +496,31 @@ static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe)
|
|||
case PPE_PKT_TYPE_IPV6_6RD:
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return PPE_HASH_MASK;
|
||||
return ppe_hash_mask;
|
||||
}
|
||||
|
||||
hash = (hv1 & hv2) | ((~hv1) & hv3);
|
||||
hash = (hash >> 24) | ((hash & 0xffffff) << 8);
|
||||
hash ^= hv1 ^ hv2 ^ hv3;
|
||||
hash ^= hash >> 16;
|
||||
hash &= PPE_NUM_ENTRIES - 1;
|
||||
hash &= ppe_hash_mask;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static u32 airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, u32 hash)
|
||||
static int airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe,
|
||||
u32 hash, u32 *index)
|
||||
{
|
||||
if (!airoha_ppe2_is_enabled(ppe->eth))
|
||||
return hash;
|
||||
int ppe_num_stats_entries;
|
||||
|
||||
return hash >= PPE_STATS_NUM_ENTRIES ? hash - PPE1_STATS_NUM_ENTRIES
|
||||
: hash;
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries < 0)
|
||||
return ppe_num_stats_entries;
|
||||
|
||||
*index = hash >= ppe_num_stats_entries ? hash - PPE_STATS_NUM_ENTRIES
|
||||
: hash;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe,
|
||||
|
|
@ -500,9 +534,13 @@ static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe,
|
|||
static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
int i;
|
||||
int i, ppe_num_stats_entries;
|
||||
|
||||
for (i = 0; i < PPE_STATS_NUM_ENTRIES; i++)
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries < 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ppe_num_stats_entries; i++)
|
||||
airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i);
|
||||
}
|
||||
|
||||
|
|
@ -513,10 +551,17 @@ static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe,
|
|||
{
|
||||
int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
|
||||
u32 index, pse_port, val, *data, *ib2, *meter;
|
||||
int ppe_num_stats_entries;
|
||||
u8 nbq;
|
||||
|
||||
index = airoha_ppe_foe_get_flow_stats_index(ppe, hash);
|
||||
if (index >= PPE_STATS_NUM_ENTRIES)
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries < 0)
|
||||
return;
|
||||
|
||||
if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
|
||||
return;
|
||||
|
||||
if (index >= ppe_num_stats_entries)
|
||||
return;
|
||||
|
||||
if (type == PPE_PKT_TYPE_BRIDGE) {
|
||||
|
|
@ -557,17 +602,17 @@ static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe,
|
|||
static struct airoha_foe_entry *
|
||||
airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)
|
||||
{
|
||||
u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
|
||||
|
||||
lockdep_assert_held(&ppe_lock);
|
||||
|
||||
if (hash < PPE_SRAM_NUM_ENTRIES) {
|
||||
if (hash < sram_num_entries) {
|
||||
u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
|
||||
bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
bool ppe2;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
ppe2 = airoha_ppe2_is_enabled(ppe->eth) &&
|
||||
hash >= PPE1_SRAM_NUM_ENTRIES;
|
||||
airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
|
||||
FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
|
||||
PPE_SRAM_CTRL_REQ_MASK);
|
||||
|
|
@ -577,7 +622,8 @@ airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)
|
|||
REG_PPE_RAM_CTRL(ppe2)))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < sizeof(struct airoha_foe_entry) / 4; i++)
|
||||
for (i = 0; i < sizeof(struct airoha_foe_entry) / sizeof(*hwe);
|
||||
i++)
|
||||
hwe[i] = airoha_fe_rr(eth,
|
||||
REG_PPE_RAM_ENTRY(ppe2, i));
|
||||
}
|
||||
|
|
@ -614,10 +660,32 @@ static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e,
|
|||
return !memcmp(&e->data.d, &hwe->d, len - sizeof(hwe->ib1));
|
||||
}
|
||||
|
||||
static int airoha_ppe_foe_commit_sram_entry(struct airoha_ppe *ppe, u32 hash)
|
||||
{
|
||||
struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
|
||||
bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
|
||||
u32 *ptr = (u32 *)hwe, val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(*hwe) / sizeof(*ptr); i++)
|
||||
airoha_fe_wr(ppe->eth, REG_PPE_RAM_ENTRY(ppe2, i), ptr[i]);
|
||||
|
||||
wmb();
|
||||
airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
|
||||
FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
|
||||
PPE_SRAM_CTRL_WR_MASK | PPE_SRAM_CTRL_REQ_MASK);
|
||||
|
||||
return read_poll_timeout_atomic(airoha_fe_rr, val,
|
||||
val & PPE_SRAM_CTRL_ACK_MASK,
|
||||
10, 100, false, ppe->eth,
|
||||
REG_PPE_RAM_CTRL(ppe2));
|
||||
}
|
||||
|
||||
static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe,
|
||||
struct airoha_foe_entry *e,
|
||||
u32 hash, bool rx_wlan)
|
||||
{
|
||||
u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
|
||||
struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
|
||||
u32 ts = airoha_ppe_get_timestamp(ppe);
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
|
|
@ -642,14 +710,8 @@ static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe,
|
|||
if (!rx_wlan)
|
||||
airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash);
|
||||
|
||||
if (hash < PPE_SRAM_NUM_ENTRIES) {
|
||||
dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe);
|
||||
bool ppe2 = airoha_ppe2_is_enabled(eth) &&
|
||||
hash >= PPE1_SRAM_NUM_ENTRIES;
|
||||
|
||||
err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
|
||||
hash, ppe2);
|
||||
}
|
||||
if (hash < sram_num_entries)
|
||||
err = airoha_ppe_foe_commit_sram_entry(ppe, hash);
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
@ -772,7 +834,7 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
|
|||
if (state == AIROHA_FOE_STATE_BIND)
|
||||
goto unlock;
|
||||
|
||||
index = airoha_ppe_foe_get_entry_hash(hwe);
|
||||
index = airoha_ppe_foe_get_entry_hash(ppe, hwe);
|
||||
hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) {
|
||||
if (e->type == FLOW_TYPE_L2_SUBFLOW) {
|
||||
state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
|
||||
|
|
@ -832,7 +894,7 @@ static int airoha_ppe_foe_flow_commit_entry(struct airoha_ppe *ppe,
|
|||
if (type == PPE_PKT_TYPE_BRIDGE)
|
||||
return airoha_ppe_foe_l2_flow_commit_entry(ppe, e);
|
||||
|
||||
hash = airoha_ppe_foe_get_entry_hash(&e->data);
|
||||
hash = airoha_ppe_foe_get_entry_hash(ppe, &e->data);
|
||||
e->type = FLOW_TYPE_L4;
|
||||
e->hash = 0xffff;
|
||||
|
||||
|
|
@ -1158,11 +1220,19 @@ static int airoha_ppe_flow_offload_destroy(struct airoha_eth *eth,
|
|||
void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
|
||||
struct airoha_foe_stats64 *stats)
|
||||
{
|
||||
u32 index = airoha_ppe_foe_get_flow_stats_index(ppe, hash);
|
||||
struct airoha_eth *eth = ppe->eth;
|
||||
int ppe_num_stats_entries;
|
||||
struct airoha_npu *npu;
|
||||
u32 index;
|
||||
|
||||
if (index >= PPE_STATS_NUM_ENTRIES)
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries < 0)
|
||||
return;
|
||||
|
||||
if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
|
||||
return;
|
||||
|
||||
if (index >= ppe_num_stats_entries)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
@ -1225,20 +1295,22 @@ static int airoha_ppe_flow_offload_cmd(struct airoha_eth *eth,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe,
|
||||
struct airoha_npu *npu)
|
||||
static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe)
|
||||
{
|
||||
int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES;
|
||||
u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
|
||||
struct airoha_foe_entry *hwe = ppe->foe;
|
||||
int i, err = 0;
|
||||
|
||||
if (airoha_ppe2_is_enabled(ppe->eth))
|
||||
sram_num_entries = sram_num_entries / 2;
|
||||
for (i = 0; i < sram_num_entries; i++) {
|
||||
int err;
|
||||
|
||||
for (i = 0; i < sram_num_entries; i++)
|
||||
memset(&hwe[i], 0, sizeof(*hwe));
|
||||
err = airoha_ppe_foe_commit_sram_entry(ppe, i);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma,
|
||||
PPE_SRAM_NUM_ENTRIES);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
|
||||
|
|
@ -1257,7 +1329,7 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
|
|||
{
|
||||
struct airoha_npu *npu = airoha_ppe_npu_get(eth);
|
||||
struct airoha_ppe *ppe = eth->ppe;
|
||||
int err;
|
||||
int err, ppe_num_stats_entries;
|
||||
|
||||
if (IS_ERR(npu))
|
||||
return PTR_ERR(npu);
|
||||
|
|
@ -1266,18 +1338,15 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
|
|||
if (err)
|
||||
goto error_npu_put;
|
||||
|
||||
if (PPE_STATS_NUM_ENTRIES) {
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries > 0) {
|
||||
err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
|
||||
PPE_STATS_NUM_ENTRIES);
|
||||
ppe_num_stats_entries);
|
||||
if (err)
|
||||
goto error_npu_put;
|
||||
}
|
||||
|
||||
airoha_ppe_hw_init(ppe);
|
||||
err = airoha_ppe_flush_sram_entries(ppe, npu);
|
||||
if (err)
|
||||
goto error_npu_put;
|
||||
|
||||
airoha_ppe_foe_flow_stats_reset(ppe, npu);
|
||||
|
||||
rcu_assign_pointer(eth->npu, npu);
|
||||
|
|
@ -1313,9 +1382,10 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
|
|||
u16 hash, bool rx_wlan)
|
||||
{
|
||||
struct airoha_ppe *ppe = dev->priv;
|
||||
u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
|
||||
u16 now, diff;
|
||||
|
||||
if (hash > PPE_HASH_MASK)
|
||||
if (hash > ppe_hash_mask)
|
||||
return;
|
||||
|
||||
now = (u16)jiffies;
|
||||
|
|
@ -1405,8 +1475,9 @@ EXPORT_SYMBOL_GPL(airoha_ppe_put_dev);
|
|||
|
||||
int airoha_ppe_init(struct airoha_eth *eth)
|
||||
{
|
||||
int foe_size, err, ppe_num_stats_entries;
|
||||
u32 ppe_num_entries;
|
||||
struct airoha_ppe *ppe;
|
||||
int foe_size, err;
|
||||
|
||||
ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL);
|
||||
if (!ppe)
|
||||
|
|
@ -1415,24 +1486,25 @@ int airoha_ppe_init(struct airoha_eth *eth)
|
|||
ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb;
|
||||
ppe->dev.ops.check_skb = airoha_ppe_check_skb;
|
||||
ppe->dev.priv = ppe;
|
||||
ppe->eth = eth;
|
||||
eth->ppe = ppe;
|
||||
|
||||
foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry);
|
||||
ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
|
||||
foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
|
||||
ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma,
|
||||
GFP_KERNEL);
|
||||
if (!ppe->foe)
|
||||
return -ENOMEM;
|
||||
|
||||
ppe->eth = eth;
|
||||
eth->ppe = ppe;
|
||||
|
||||
ppe->foe_flow = devm_kzalloc(eth->dev,
|
||||
PPE_NUM_ENTRIES * sizeof(*ppe->foe_flow),
|
||||
ppe_num_entries * sizeof(*ppe->foe_flow),
|
||||
GFP_KERNEL);
|
||||
if (!ppe->foe_flow)
|
||||
return -ENOMEM;
|
||||
|
||||
foe_size = PPE_STATS_NUM_ENTRIES * sizeof(*ppe->foe_stats);
|
||||
if (foe_size) {
|
||||
ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
|
||||
if (ppe_num_stats_entries > 0) {
|
||||
foe_size = ppe_num_stats_entries * sizeof(*ppe->foe_stats);
|
||||
ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size,
|
||||
&ppe->foe_stats_dma,
|
||||
GFP_KERNEL);
|
||||
|
|
@ -1440,6 +1512,15 @@ int airoha_ppe_init(struct airoha_eth *eth)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries,
|
||||
GFP_KERNEL);
|
||||
if (!ppe->foe_check_time)
|
||||
return -ENOMEM;
|
||||
|
||||
err = airoha_ppe_flush_sram_entries(ppe);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = rhashtable_init(ð->flow_table, &airoha_flow_table_params);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -53,9 +53,10 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
|
|||
[AIROHA_FOE_STATE_FIN] = "FIN",
|
||||
};
|
||||
struct airoha_ppe *ppe = m->private;
|
||||
u32 ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PPE_NUM_ENTRIES; i++) {
|
||||
for (i = 0; i < ppe_num_entries; i++) {
|
||||
const char *state_str, *type_str = "UNKNOWN";
|
||||
void *src_addr = NULL, *dest_addr = NULL;
|
||||
u16 *src_port = NULL, *dest_port = NULL;
|
||||
|
|
|
|||
|
|
@ -383,10 +383,8 @@
|
|||
#define REG_MC_VLAN_DATA 0x2108
|
||||
|
||||
#define REG_SP_DFT_CPORT(_n) (0x20e0 + ((_n) << 2))
|
||||
#define SP_CPORT_PCIE1_MASK GENMASK(31, 28)
|
||||
#define SP_CPORT_PCIE0_MASK GENMASK(27, 24)
|
||||
#define SP_CPORT_USB_MASK GENMASK(7, 4)
|
||||
#define SP_CPORT_ETH_MASK GENMASK(7, 4)
|
||||
#define SP_CPORT_DFT_MASK GENMASK(2, 0)
|
||||
#define SP_CPORT_MASK(_n) GENMASK(3 + ((_n) << 2), ((_n) << 2))
|
||||
|
||||
#define REG_SRC_PORT_FC_MAP6 0x2298
|
||||
#define FC_ID_OF_SRC_PORT27_MASK GENMASK(28, 24)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user