@@ -2036,6 +2036,126 @@ static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
2036
2036
}
2037
2037
}
2038
2038
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
+
2039
2159
static const struct devlink_ops am65_cpsw_devlink_ops = {};
2040
2160
2041
2161
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)
2379
2499
}
2380
2500
}
2381
2501
2382
- ret = am65_cpsw_nuss_register_devlink (common );
2502
+ ret = am65_cpsw_register_notifiers (common );
2383
2503
if (ret )
2384
2504
goto err_cleanup_ndev ;
2385
2505
2506
+ ret = am65_cpsw_nuss_register_devlink (common );
2507
+ if (ret )
2508
+ goto clean_unregister_notifiers ;
2509
+
2386
2510
/* can't auto unregister ndev using devm_add_action() due to
2387
2511
* devres release sequence in DD core for DMA
2388
2512
*/
2389
2513
2390
2514
return 0 ;
2515
+ clean_unregister_notifiers :
2516
+ am65_cpsw_unregister_notifiers (common );
2391
2517
err_cleanup_ndev :
2392
2518
am65_cpsw_nuss_cleanup_ndev (common );
2519
+
2393
2520
return ret ;
2394
2521
}
2395
2522
@@ -2621,6 +2748,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
2621
2748
}
2622
2749
2623
2750
am65_cpsw_unregister_devlink (common );
2751
+ am65_cpsw_unregister_notifiers (common );
2624
2752
2625
2753
/* must unregister ndevs here because DD release_driver routine calls
2626
2754
* dma_deconfigure(dev) before devres_release_all(dev)
0 commit comments