Commit 01792bc3 authored by MD Danish Anwar's avatar MD Danish Anwar Committed by Paolo Abeni
Browse files

net: ti: icssg-prueth: Fix HSR and switch offload Enablement during firwmare reload.



To enable HSR / Switch offload, certain configurations are needed.
Currently they are done inside icssg_change_mode(). This function only
gets called if we move from one mode to another without bringing the
links up / down.

Once in HSR / Switch mode, if we bring the links down and bring it back
up again. The callback sequence is,

- emac_ndo_stop()
	Firmwares are stopped
- emac_ndo_open()
	Firmwares are loaded

In this path icssg_change_mode() doesn't get called and as a result the
configurations needed for HSR / Switch is not done.

To fix this, put all these configurations in a separate function
icssg_enable_fw_offload() and call this from both icssg_change_mode()
and emac_ndo_open()

Fixes: 56375086 ("net: ti: icssg-prueth: Enable HSR Tx duplication, Tx Tag and Rx Tag offload")
Signed-off-by: default avatarMD Danish Anwar <danishanwar@ti.com>
Link: https://patch.msgid.link/20250814105106.1491871-1-danishanwar@ti.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 0417adf3
Loading
Loading
Loading
Loading
+41 −31
Original line number Diff line number Diff line
@@ -203,6 +203,44 @@ static void prueth_emac_stop(struct prueth *prueth)
	}
}

static void icssg_enable_fw_offload(struct prueth *prueth)
{
	struct prueth_emac *emac;
	int mac;

	for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) {
		emac = prueth->emac[mac];
		if (prueth->is_hsr_offload_mode) {
			if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM)
				icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE);
			else
				icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE);
		}

		if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) {
			if (netif_running(emac->ndev)) {
				icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
						  ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
						  ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
						  ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
						  ICSSG_FDB_ENTRY_BLOCK,
						  true);
				icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID,
						  BIT(emac->port_id) | DEFAULT_PORT_MASK,
						  BIT(emac->port_id) | DEFAULT_UNTAG_MASK,
						  true);
				if (prueth->is_hsr_offload_mode)
					icssg_vtbl_modify(emac, DEFAULT_VID,
							  DEFAULT_PORT_MASK,
							  DEFAULT_UNTAG_MASK, true);
				icssg_set_pvid(prueth, emac->port_vlan, emac->port_id);
				if (prueth->is_switch_mode)
					icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
			}
		}
	}
}

static int prueth_emac_common_start(struct prueth *prueth)
{
	struct prueth_emac *emac;
@@ -753,6 +791,7 @@ static int emac_ndo_open(struct net_device *ndev)
		ret = prueth_emac_common_start(prueth);
		if (ret)
			goto free_rx_irq;
		icssg_enable_fw_offload(prueth);
	}

	flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
@@ -1360,8 +1399,7 @@ static int prueth_emac_restart(struct prueth *prueth)

static void icssg_change_mode(struct prueth *prueth)
{
	struct prueth_emac *emac;
	int mac, ret;
	int ret;

	ret = prueth_emac_restart(prueth);
	if (ret) {
@@ -1369,35 +1407,7 @@ static void icssg_change_mode(struct prueth *prueth)
		return;
	}

	for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) {
		emac = prueth->emac[mac];
		if (prueth->is_hsr_offload_mode) {
			if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM)
				icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE);
			else
				icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE);
		}

		if (netif_running(emac->ndev)) {
			icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
					  ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
					  ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
					  ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
					  ICSSG_FDB_ENTRY_BLOCK,
					  true);
			icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID,
					  BIT(emac->port_id) | DEFAULT_PORT_MASK,
					  BIT(emac->port_id) | DEFAULT_UNTAG_MASK,
					  true);
			if (prueth->is_hsr_offload_mode)
				icssg_vtbl_modify(emac, DEFAULT_VID,
						  DEFAULT_PORT_MASK,
						  DEFAULT_UNTAG_MASK, true);
			icssg_set_pvid(prueth, emac->port_vlan, emac->port_id);
			if (prueth->is_switch_mode)
				icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
		}
	}
	icssg_enable_fw_offload(prueth);
}

static int prueth_netdevice_port_link(struct net_device *ndev,