Skip to content

Commit 2934db9

Browse files
r-vigneshdavem330
authored andcommitted
net: ti: am65-cpsw-nuss: Add netdevice notifiers
Register netdevice notifiers in order to receive notification when individual MAC ports are added to the HW bridge. Signed-off-by: Vignesh Raghavendra <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 58356eb commit 2934db9

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

drivers/net/ethernet/ti/am65-cpsw-nuss.c

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,126 @@ static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
20362036
}
20372037
}
20382038

2039+
static void am65_cpsw_port_offload_fwd_mark_update(struct am65_cpsw_common *common)
2040+
{
2041+
int set_val = 0;
2042+
int i;
2043+
2044+
if (common->br_members == (GENMASK(common->port_num, 1) & ~common->disabled_ports_mask))
2045+
set_val = 1;
2046+
2047+
dev_dbg(common->dev, "set offload_fwd_mark %d\n", set_val);
2048+
2049+
for (i = 1; i <= common->port_num; i++) {
2050+
struct am65_cpsw_port *port = am65_common_get_port(common, i);
2051+
struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(port->ndev);
2052+
2053+
priv->offload_fwd_mark = set_val;
2054+
}
2055+
}
2056+
2057+
bool am65_cpsw_port_dev_check(const struct net_device *ndev)
2058+
{
2059+
if (ndev->netdev_ops == &am65_cpsw_nuss_netdev_ops) {
2060+
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
2061+
2062+
return !common->is_emac_mode;
2063+
}
2064+
2065+
return false;
2066+
}
2067+
2068+
static int am65_cpsw_netdevice_port_link(struct net_device *ndev, struct net_device *br_ndev)
2069+
{
2070+
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
2071+
struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
2072+
2073+
if (!common->br_members) {
2074+
common->hw_bridge_dev = br_ndev;
2075+
} else {
2076+
/* This is adding the port to a second bridge, this is
2077+
* unsupported
2078+
*/
2079+
if (common->hw_bridge_dev != br_ndev)
2080+
return -EOPNOTSUPP;
2081+
}
2082+
2083+
common->br_members |= BIT(priv->port->port_id);
2084+
2085+
am65_cpsw_port_offload_fwd_mark_update(common);
2086+
2087+
return NOTIFY_DONE;
2088+
}
2089+
2090+
static void am65_cpsw_netdevice_port_unlink(struct net_device *ndev)
2091+
{
2092+
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
2093+
struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
2094+
2095+
common->br_members &= ~BIT(priv->port->port_id);
2096+
2097+
am65_cpsw_port_offload_fwd_mark_update(common);
2098+
2099+
if (!common->br_members)
2100+
common->hw_bridge_dev = NULL;
2101+
}
2102+
2103+
/* netdev notifier */
2104+
static int am65_cpsw_netdevice_event(struct notifier_block *unused,
2105+
unsigned long event, void *ptr)
2106+
{
2107+
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
2108+
struct netdev_notifier_changeupper_info *info;
2109+
int ret = NOTIFY_DONE;
2110+
2111+
if (!am65_cpsw_port_dev_check(ndev))
2112+
return NOTIFY_DONE;
2113+
2114+
switch (event) {
2115+
case NETDEV_CHANGEUPPER:
2116+
info = ptr;
2117+
2118+
if (netif_is_bridge_master(info->upper_dev)) {
2119+
if (info->linking)
2120+
ret = am65_cpsw_netdevice_port_link(ndev, info->upper_dev);
2121+
else
2122+
am65_cpsw_netdevice_port_unlink(ndev);
2123+
}
2124+
break;
2125+
default:
2126+
return NOTIFY_DONE;
2127+
}
2128+
2129+
return notifier_from_errno(ret);
2130+
}
2131+
2132+
static int am65_cpsw_register_notifiers(struct am65_cpsw_common *cpsw)
2133+
{
2134+
int ret = 0;
2135+
2136+
if (AM65_CPSW_IS_CPSW2G(cpsw) ||
2137+
!IS_REACHABLE(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV))
2138+
return 0;
2139+
2140+
cpsw->am65_cpsw_netdevice_nb.notifier_call = &am65_cpsw_netdevice_event;
2141+
ret = register_netdevice_notifier(&cpsw->am65_cpsw_netdevice_nb);
2142+
if (ret) {
2143+
dev_err(cpsw->dev, "can't register netdevice notifier\n");
2144+
return ret;
2145+
}
2146+
2147+
return ret;
2148+
}
2149+
2150+
static void am65_cpsw_unregister_notifiers(struct am65_cpsw_common *cpsw)
2151+
{
2152+
if (AM65_CPSW_IS_CPSW2G(cpsw) ||
2153+
!IS_REACHABLE(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV))
2154+
return;
2155+
2156+
unregister_netdevice_notifier(&cpsw->am65_cpsw_netdevice_nb);
2157+
}
2158+
20392159
static const struct devlink_ops am65_cpsw_devlink_ops = {};
20402160

20412161
static void am65_cpsw_init_stp_ale_entry(struct am65_cpsw_common *cpsw)
@@ -2379,17 +2499,24 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
23792499
}
23802500
}
23812501

2382-
ret = am65_cpsw_nuss_register_devlink(common);
2502+
ret = am65_cpsw_register_notifiers(common);
23832503
if (ret)
23842504
goto err_cleanup_ndev;
23852505

2506+
ret = am65_cpsw_nuss_register_devlink(common);
2507+
if (ret)
2508+
goto clean_unregister_notifiers;
2509+
23862510
/* can't auto unregister ndev using devm_add_action() due to
23872511
* devres release sequence in DD core for DMA
23882512
*/
23892513

23902514
return 0;
2515+
clean_unregister_notifiers:
2516+
am65_cpsw_unregister_notifiers(common);
23912517
err_cleanup_ndev:
23922518
am65_cpsw_nuss_cleanup_ndev(common);
2519+
23932520
return ret;
23942521
}
23952522

@@ -2621,6 +2748,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
26212748
}
26222749

26232750
am65_cpsw_unregister_devlink(common);
2751+
am65_cpsw_unregister_notifiers(common);
26242752

26252753
/* must unregister ndevs here because DD release_driver routine calls
26262754
* dma_deconfigure(dev) before devres_release_all(dev)

drivers/net/ethernet/ti/am65-cpsw-nuss.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ struct am65_cpsw_common {
137137
u16 br_members;
138138
int default_vlan;
139139
struct devlink *devlink;
140+
struct net_device *hw_bridge_dev;
141+
struct notifier_block am65_cpsw_netdevice_nb;
140142
unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
141143
};
142144

@@ -180,4 +182,6 @@ void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common);
180182
void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common);
181183
int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx);
182184

185+
bool am65_cpsw_port_dev_check(const struct net_device *dev);
186+
183187
#endif /* AM65_CPSW_NUSS_H_ */

0 commit comments

Comments
 (0)