Skip to content

Commit 95540ad

Browse files
danish-tikuba-moo
authored andcommitted
net: ti: icssg-prueth: Add support for HSR frame forward offload
Add support for offloading HSR port-to-port frame forward to hardware. When the slave interfaces are added to the HSR interface, the PRU cores will be stopped and ICSSG HSR firmwares will be loaded to them. Similarly, when HSR interface is deleted, the PRU cores will be restarted and the last used firmwares will be reloaded. PRUeth interfaces will be back to the last used mode. This commit also renames some APIs that are common between switch and hsr mode with '_fw_offload' suffix. Signed-off-by: MD Danish Anwar <[email protected]> Reviewed-by: Roger Quadros <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4ebe059 commit 95540ad

File tree

4 files changed

+119
-12
lines changed

4 files changed

+119
-12
lines changed

drivers/net/ethernet/ti/icssg/icssg_classifier.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
290290
mac[2] << 16 | mac[3] << 24));
291291
regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
292292
}
293+
EXPORT_SYMBOL_GPL(icssg_class_set_host_mac_addr);
293294

294295
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
295296
{

drivers/net/ethernet/ti/icssg/icssg_config.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
107107
},
108108
};
109109

110-
static void icssg_config_mii_init_switch(struct prueth_emac *emac)
110+
static void icssg_config_mii_init_fw_offload(struct prueth_emac *emac)
111111
{
112112
struct prueth *prueth = emac->prueth;
113113
int mii = prueth_emac_slice(emac);
@@ -278,7 +278,7 @@ static int emac_r30_is_done(struct prueth_emac *emac)
278278
return 1;
279279
}
280280

281-
static int prueth_switch_buffer_setup(struct prueth_emac *emac)
281+
static int prueth_fw_offload_buffer_setup(struct prueth_emac *emac)
282282
{
283283
struct icssg_buffer_pool_cfg __iomem *bpool_cfg;
284284
struct icssg_rxq_ctx __iomem *rxq_ctx;
@@ -424,7 +424,7 @@ static void icssg_init_emac_mode(struct prueth *prueth)
424424
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
425425
}
426426

427-
static void icssg_init_switch_mode(struct prueth *prueth)
427+
static void icssg_init_fw_offload_mode(struct prueth *prueth)
428428
{
429429
u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
430430
int i;
@@ -455,8 +455,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
455455
struct icssg_flow_cfg __iomem *flow_cfg;
456456
int ret;
457457

458-
if (prueth->is_switch_mode)
459-
icssg_init_switch_mode(prueth);
458+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
459+
icssg_init_fw_offload_mode(prueth);
460460
else
461461
icssg_init_emac_mode(prueth);
462462

@@ -472,8 +472,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
472472
regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET,
473473
ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
474474
icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
475-
if (prueth->is_switch_mode)
476-
icssg_config_mii_init_switch(emac);
475+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
476+
icssg_config_mii_init_fw_offload(emac);
477477
else
478478
icssg_config_mii_init(emac);
479479
icssg_config_ipg(emac);
@@ -498,8 +498,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
498498
writeb(0, config + SPL_PKT_DEFAULT_PRIORITY);
499499
writeb(0, config + QUEUE_NUM_UNTAGGED);
500500

501-
if (prueth->is_switch_mode)
502-
ret = prueth_switch_buffer_setup(emac);
501+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
502+
ret = prueth_fw_offload_buffer_setup(emac);
503503
else
504504
ret = prueth_emac_buffer_setup(emac);
505505
if (ret)

drivers/net/ethernet/ti/icssg/icssg_prueth.c

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/dma/ti-cppi5.h>
1414
#include <linux/etherdevice.h>
1515
#include <linux/genalloc.h>
16+
#include <linux/if_hsr.h>
1617
#include <linux/if_vlan.h>
1718
#include <linux/interrupt.h>
1819
#include <linux/kernel.h>
@@ -40,6 +41,8 @@
4041
#define DEFAULT_PORT_MASK 1
4142
#define DEFAULT_UNTAG_MASK 1
4243

44+
#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD
45+
4346
/* CTRLMMR_ICSSG_RGMII_CTRL register bits */
4447
#define ICSSG_CTRL_RGMII_ID_MODE BIT(24)
4548

@@ -118,6 +121,19 @@ static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id)
118121
return IRQ_HANDLED;
119122
}
120123

124+
static struct icssg_firmwares icssg_hsr_firmwares[] = {
125+
{
126+
.pru = "ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf",
127+
.rtu = "ti-pruss/am65x-sr2-rtu0-pruhsr-fw.elf",
128+
.txpru = "ti-pruss/am65x-sr2-txpru0-pruhsr-fw.elf",
129+
},
130+
{
131+
.pru = "ti-pruss/am65x-sr2-pru1-pruhsr-fw.elf",
132+
.rtu = "ti-pruss/am65x-sr2-rtu1-pruhsr-fw.elf",
133+
.txpru = "ti-pruss/am65x-sr2-txpru1-pruhsr-fw.elf",
134+
}
135+
};
136+
121137
static struct icssg_firmwares icssg_switch_firmwares[] = {
122138
{
123139
.pru = "ti-pruss/am65x-sr2-pru0-prusw-fw.elf",
@@ -152,6 +168,8 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
152168

153169
if (prueth->is_switch_mode)
154170
firmwares = icssg_switch_firmwares;
171+
else if (prueth->is_hsr_offload_mode)
172+
firmwares = icssg_hsr_firmwares;
155173
else
156174
firmwares = icssg_emac_firmwares;
157175

@@ -865,6 +883,7 @@ static int prueth_netdev_init(struct prueth *prueth,
865883
ndev->ethtool_ops = &icssg_ethtool_ops;
866884
ndev->hw_features = NETIF_F_SG;
867885
ndev->features = ndev->hw_features;
886+
ndev->hw_features |= NETIF_PRUETH_HSR_OFFLOAD_FEATURES;
868887

869888
netif_napi_add(ndev, &emac->napi_rx, icssg_napi_rx_poll);
870889
hrtimer_init(&emac->rx_hrtimer, CLOCK_MONOTONIC,
@@ -953,7 +972,7 @@ static void prueth_emac_restart(struct prueth *prueth)
953972
netif_device_attach(emac1->ndev);
954973
}
955974

956-
static void icssg_enable_switch_mode(struct prueth *prueth)
975+
static void icssg_change_mode(struct prueth *prueth)
957976
{
958977
struct prueth_emac *emac;
959978
int mac;
@@ -973,8 +992,13 @@ static void icssg_enable_switch_mode(struct prueth *prueth)
973992
BIT(emac->port_id) | DEFAULT_PORT_MASK,
974993
BIT(emac->port_id) | DEFAULT_UNTAG_MASK,
975994
true);
995+
if (prueth->is_hsr_offload_mode)
996+
icssg_vtbl_modify(emac, DEFAULT_VID,
997+
DEFAULT_PORT_MASK,
998+
DEFAULT_UNTAG_MASK, true);
976999
icssg_set_pvid(prueth, emac->port_vlan, emac->port_id);
977-
icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
1000+
if (prueth->is_switch_mode)
1001+
icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
9781002
}
9791003
}
9801004
}
@@ -1012,7 +1036,7 @@ static int prueth_netdevice_port_link(struct net_device *ndev,
10121036
prueth->is_switch_mode = true;
10131037
prueth->default_vlan = 1;
10141038
emac->port_vlan = prueth->default_vlan;
1015-
icssg_enable_switch_mode(prueth);
1039+
icssg_change_mode(prueth);
10161040
}
10171041
}
10181042

@@ -1040,13 +1064,70 @@ static void prueth_netdevice_port_unlink(struct net_device *ndev)
10401064
prueth->hw_bridge_dev = NULL;
10411065
}
10421066

1067+
static int prueth_hsr_port_link(struct net_device *ndev)
1068+
{
1069+
struct prueth_emac *emac = netdev_priv(ndev);
1070+
struct prueth *prueth = emac->prueth;
1071+
struct prueth_emac *emac0;
1072+
struct prueth_emac *emac1;
1073+
1074+
emac0 = prueth->emac[PRUETH_MAC0];
1075+
emac1 = prueth->emac[PRUETH_MAC1];
1076+
1077+
if (prueth->is_switch_mode)
1078+
return -EOPNOTSUPP;
1079+
1080+
prueth->hsr_members |= BIT(emac->port_id);
1081+
if (!prueth->is_hsr_offload_mode) {
1082+
if (prueth->hsr_members & BIT(PRUETH_PORT_MII0) &&
1083+
prueth->hsr_members & BIT(PRUETH_PORT_MII1)) {
1084+
if (!(emac0->ndev->features &
1085+
NETIF_PRUETH_HSR_OFFLOAD_FEATURES) &&
1086+
!(emac1->ndev->features &
1087+
NETIF_PRUETH_HSR_OFFLOAD_FEATURES))
1088+
return -EOPNOTSUPP;
1089+
prueth->is_hsr_offload_mode = true;
1090+
prueth->default_vlan = 1;
1091+
emac0->port_vlan = prueth->default_vlan;
1092+
emac1->port_vlan = prueth->default_vlan;
1093+
icssg_change_mode(prueth);
1094+
netdev_dbg(ndev, "Enabling HSR offload mode\n");
1095+
}
1096+
}
1097+
1098+
return 0;
1099+
}
1100+
1101+
static void prueth_hsr_port_unlink(struct net_device *ndev)
1102+
{
1103+
struct prueth_emac *emac = netdev_priv(ndev);
1104+
struct prueth *prueth = emac->prueth;
1105+
struct prueth_emac *emac0;
1106+
struct prueth_emac *emac1;
1107+
1108+
emac0 = prueth->emac[PRUETH_MAC0];
1109+
emac1 = prueth->emac[PRUETH_MAC1];
1110+
1111+
prueth->hsr_members &= ~BIT(emac->port_id);
1112+
if (prueth->is_hsr_offload_mode) {
1113+
prueth->is_hsr_offload_mode = false;
1114+
emac0->port_vlan = 0;
1115+
emac1->port_vlan = 0;
1116+
prueth->hsr_dev = NULL;
1117+
prueth_emac_restart(prueth);
1118+
netdev_dbg(ndev, "Disabling HSR Offload mode\n");
1119+
}
1120+
}
1121+
10431122
/* netdev notifier */
10441123
static int prueth_netdevice_event(struct notifier_block *unused,
10451124
unsigned long event, void *ptr)
10461125
{
10471126
struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr);
10481127
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
10491128
struct netdev_notifier_changeupper_info *info;
1129+
struct prueth_emac *emac = netdev_priv(ndev);
1130+
struct prueth *prueth = emac->prueth;
10501131
int ret = NOTIFY_DONE;
10511132

10521133
if (ndev->netdev_ops != &emac_netdev_ops)
@@ -1056,6 +1137,25 @@ static int prueth_netdevice_event(struct notifier_block *unused,
10561137
case NETDEV_CHANGEUPPER:
10571138
info = ptr;
10581139

1140+
if ((ndev->features & NETIF_PRUETH_HSR_OFFLOAD_FEATURES) &&
1141+
is_hsr_master(info->upper_dev)) {
1142+
if (info->linking) {
1143+
if (!prueth->hsr_dev) {
1144+
prueth->hsr_dev = info->upper_dev;
1145+
icssg_class_set_host_mac_addr(prueth->miig_rt,
1146+
prueth->hsr_dev->dev_addr);
1147+
} else {
1148+
if (prueth->hsr_dev != info->upper_dev) {
1149+
netdev_dbg(ndev, "Both interfaces must be linked to same upper device\n");
1150+
return -EOPNOTSUPP;
1151+
}
1152+
}
1153+
prueth_hsr_port_link(ndev);
1154+
} else {
1155+
prueth_hsr_port_unlink(ndev);
1156+
}
1157+
}
1158+
10591159
if (netif_is_bridge_master(info->upper_dev)) {
10601160
if (info->linking)
10611161
ret = prueth_netdevice_port_link(ndev, info->upper_dev, extack);

drivers/net/ethernet/ti/icssg/icssg_prueth.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,14 @@ struct icssg_firmwares {
243243
* @iep1: pointer to IEP1 device
244244
* @vlan_tbl: VLAN-FID table pointer
245245
* @hw_bridge_dev: pointer to HW bridge net device
246+
* @hsr_dev: pointer to the HSR net device
246247
* @br_members: bitmask of bridge member ports
248+
* @hsr_members: bitmask of hsr member ports
247249
* @prueth_netdevice_nb: netdevice notifier block
248250
* @prueth_switchdev_nb: switchdev notifier block
249251
* @prueth_switchdev_bl_nb: switchdev blocking notifier block
250252
* @is_switch_mode: flag to indicate if device is in Switch mode
253+
* @is_hsr_offload_mode: flag to indicate if device is in hsr offload mode
251254
* @is_switchmode_supported: indicates platform support for switch mode
252255
* @switch_id: ID for mapping switch ports to bridge
253256
* @default_vlan: Default VLAN for host
@@ -279,11 +282,14 @@ struct prueth {
279282
struct prueth_vlan_tbl *vlan_tbl;
280283

281284
struct net_device *hw_bridge_dev;
285+
struct net_device *hsr_dev;
282286
u8 br_members;
287+
u8 hsr_members;
283288
struct notifier_block prueth_netdevice_nb;
284289
struct notifier_block prueth_switchdev_nb;
285290
struct notifier_block prueth_switchdev_bl_nb;
286291
bool is_switch_mode;
292+
bool is_hsr_offload_mode;
287293
bool is_switchmode_supported;
288294
unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
289295
int default_vlan;

0 commit comments

Comments
 (0)