@@ -481,21 +481,16 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
481481}
482482
483483static int
484- mlxsw_sp_port_module_info_get (struct mlxsw_sp * mlxsw_sp , u16 local_port ,
485- struct mlxsw_sp_port_mapping * port_mapping )
484+ mlxsw_sp_port_module_info_parse (struct mlxsw_sp * mlxsw_sp ,
485+ u16 local_port , char * pmlp_pl ,
486+ struct mlxsw_sp_port_mapping * port_mapping )
486487{
487- char pmlp_pl [MLXSW_REG_PMLP_LEN ];
488488 bool separate_rxtx ;
489489 u8 first_lane ;
490490 u8 module ;
491491 u8 width ;
492- int err ;
493492 int i ;
494493
495- mlxsw_reg_pmlp_pack (pmlp_pl , local_port );
496- err = mlxsw_reg_query (mlxsw_sp -> core , MLXSW_REG (pmlp ), pmlp_pl );
497- if (err )
498- return err ;
499494 module = mlxsw_reg_pmlp_module_get (pmlp_pl , 0 );
500495 width = mlxsw_reg_pmlp_width_get (pmlp_pl );
501496 separate_rxtx = mlxsw_reg_pmlp_rxtx_get (pmlp_pl );
@@ -534,6 +529,21 @@ mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, u16 local_port,
534529 return 0 ;
535530}
536531
532+ static int
533+ mlxsw_sp_port_module_info_get (struct mlxsw_sp * mlxsw_sp , u16 local_port ,
534+ struct mlxsw_sp_port_mapping * port_mapping )
535+ {
536+ char pmlp_pl [MLXSW_REG_PMLP_LEN ];
537+ int err ;
538+
539+ mlxsw_reg_pmlp_pack (pmlp_pl , local_port );
540+ err = mlxsw_reg_query (mlxsw_sp -> core , MLXSW_REG (pmlp ), pmlp_pl );
541+ if (err )
542+ return err ;
543+ return mlxsw_sp_port_module_info_parse (mlxsw_sp , local_port ,
544+ pmlp_pl , port_mapping );
545+ }
546+
537547static int
538548mlxsw_sp_port_module_map (struct mlxsw_sp * mlxsw_sp , u16 local_port ,
539549 const struct mlxsw_sp_port_mapping * port_mapping )
@@ -1861,13 +1871,121 @@ static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u16 local_port)
18611871 return mlxsw_sp -> ports [local_port ] != NULL ;
18621872}
18631873
1874+ static int mlxsw_sp_port_mapping_event_set (struct mlxsw_sp * mlxsw_sp ,
1875+ u16 local_port , bool enable )
1876+ {
1877+ char pmecr_pl [MLXSW_REG_PMECR_LEN ];
1878+
1879+ mlxsw_reg_pmecr_pack (pmecr_pl , local_port ,
1880+ enable ? MLXSW_REG_PMECR_E_GENERATE_EVENT :
1881+ MLXSW_REG_PMECR_E_DO_NOT_GENERATE_EVENT );
1882+ return mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (pmecr ), pmecr_pl );
1883+ }
1884+
1885+ struct mlxsw_sp_port_mapping_event {
1886+ struct list_head list ;
1887+ char pmlp_pl [MLXSW_REG_PMLP_LEN ];
1888+ };
1889+
1890+ static void mlxsw_sp_port_mapping_events_work (struct work_struct * work )
1891+ {
1892+ struct mlxsw_sp_port_mapping_event * event , * next_event ;
1893+ struct mlxsw_sp_port_mapping_events * events ;
1894+ struct mlxsw_sp_port_mapping port_mapping ;
1895+ struct mlxsw_sp * mlxsw_sp ;
1896+ struct devlink * devlink ;
1897+ LIST_HEAD (event_queue );
1898+ u16 local_port ;
1899+ int err ;
1900+
1901+ events = container_of (work , struct mlxsw_sp_port_mapping_events , work );
1902+ mlxsw_sp = container_of (events , struct mlxsw_sp , port_mapping_events );
1903+ devlink = priv_to_devlink (mlxsw_sp -> core );
1904+
1905+ spin_lock_bh (& events -> queue_lock );
1906+ list_splice_init (& events -> queue , & event_queue );
1907+ spin_unlock_bh (& events -> queue_lock );
1908+
1909+ list_for_each_entry_safe (event , next_event , & event_queue , list ) {
1910+ local_port = mlxsw_reg_pmlp_local_port_get (event -> pmlp_pl );
1911+ err = mlxsw_sp_port_module_info_parse (mlxsw_sp , local_port ,
1912+ event -> pmlp_pl , & port_mapping );
1913+ if (err )
1914+ goto out ;
1915+
1916+ if (WARN_ON_ONCE (!port_mapping .width ))
1917+ goto out ;
1918+
1919+ devl_lock (devlink );
1920+
1921+ if (!mlxsw_sp_port_created (mlxsw_sp , local_port ))
1922+ mlxsw_sp_port_create (mlxsw_sp , local_port ,
1923+ false, & port_mapping );
1924+ else
1925+ WARN_ON_ONCE (1 );
1926+
1927+ devl_unlock (devlink );
1928+
1929+ mlxsw_sp -> port_mapping [local_port ] = port_mapping ;
1930+
1931+ out :
1932+ kfree (event );
1933+ }
1934+ }
1935+
1936+ static void
1937+ mlxsw_sp_port_mapping_listener_func (const struct mlxsw_reg_info * reg ,
1938+ char * pmlp_pl , void * priv )
1939+ {
1940+ struct mlxsw_sp_port_mapping_events * events ;
1941+ struct mlxsw_sp_port_mapping_event * event ;
1942+ struct mlxsw_sp * mlxsw_sp = priv ;
1943+ u16 local_port ;
1944+
1945+ local_port = mlxsw_reg_pmlp_local_port_get (pmlp_pl );
1946+ if (WARN_ON_ONCE (!mlxsw_sp_local_port_is_valid (mlxsw_sp , local_port )))
1947+ return ;
1948+
1949+ events = & mlxsw_sp -> port_mapping_events ;
1950+ event = kmalloc (sizeof (* event ), GFP_ATOMIC );
1951+ if (!event )
1952+ return ;
1953+ memcpy (event -> pmlp_pl , pmlp_pl , sizeof (event -> pmlp_pl ));
1954+ spin_lock (& events -> queue_lock );
1955+ list_add_tail (& event -> list , & events -> queue );
1956+ spin_unlock (& events -> queue_lock );
1957+ mlxsw_core_schedule_work (& events -> work );
1958+ }
1959+
1960+ static void
1961+ __mlxsw_sp_port_mapping_events_cancel (struct mlxsw_sp * mlxsw_sp )
1962+ {
1963+ struct mlxsw_sp_port_mapping_event * event , * next_event ;
1964+ struct mlxsw_sp_port_mapping_events * events ;
1965+
1966+ events = & mlxsw_sp -> port_mapping_events ;
1967+
1968+ /* Caller needs to make sure that no new event is going to appear. */
1969+ cancel_work_sync (& events -> work );
1970+ list_for_each_entry_safe (event , next_event , & events -> queue , list ) {
1971+ list_del (& event -> list );
1972+ kfree (event );
1973+ }
1974+ }
1975+
18641976static void mlxsw_sp_ports_remove (struct mlxsw_sp * mlxsw_sp )
18651977{
1978+ unsigned int max_ports = mlxsw_core_max_ports (mlxsw_sp -> core );
18661979 struct devlink * devlink = priv_to_devlink (mlxsw_sp -> core );
18671980 int i ;
18681981
1982+ for (i = 1 ; i < max_ports ; i ++ )
1983+ mlxsw_sp_port_mapping_event_set (mlxsw_sp , i , false);
1984+ /* Make sure all scheduled events are processed */
1985+ __mlxsw_sp_port_mapping_events_cancel (mlxsw_sp );
1986+
18691987 devl_lock (devlink );
1870- for (i = 1 ; i < mlxsw_core_max_ports ( mlxsw_sp -> core ) ; i ++ )
1988+ for (i = 1 ; i < max_ports ; i ++ )
18711989 if (mlxsw_sp_port_created (mlxsw_sp , i ))
18721990 mlxsw_sp_port_remove (mlxsw_sp , i );
18731991 mlxsw_sp_cpu_port_remove (mlxsw_sp );
@@ -1880,6 +1998,7 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
18801998{
18811999 unsigned int max_ports = mlxsw_core_max_ports (mlxsw_sp -> core );
18822000 struct devlink * devlink = priv_to_devlink (mlxsw_sp -> core );
2001+ struct mlxsw_sp_port_mapping_events * events ;
18832002 struct mlxsw_sp_port_mapping * port_mapping ;
18842003 size_t alloc_size ;
18852004 int i ;
@@ -1890,6 +2009,17 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
18902009 if (!mlxsw_sp -> ports )
18912010 return - ENOMEM ;
18922011
2012+ events = & mlxsw_sp -> port_mapping_events ;
2013+ INIT_LIST_HEAD (& events -> queue );
2014+ spin_lock_init (& events -> queue_lock );
2015+ INIT_WORK (& events -> work , mlxsw_sp_port_mapping_events_work );
2016+
2017+ for (i = 1 ; i < max_ports ; i ++ ) {
2018+ err = mlxsw_sp_port_mapping_event_set (mlxsw_sp , i , true);
2019+ if (err )
2020+ goto err_event_enable ;
2021+ }
2022+
18932023 devl_lock (devlink );
18942024 err = mlxsw_sp_cpu_port_create (mlxsw_sp );
18952025 if (err )
@@ -1910,9 +2040,15 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
19102040 for (i -- ; i >= 1 ; i -- )
19112041 if (mlxsw_sp_port_created (mlxsw_sp , i ))
19122042 mlxsw_sp_port_remove (mlxsw_sp , i );
2043+ i = max_ports ;
19132044 mlxsw_sp_cpu_port_remove (mlxsw_sp );
19142045err_cpu_port_create :
19152046 devl_unlock (devlink );
2047+ err_event_enable :
2048+ for (i -- ; i >= 1 ; i -- )
2049+ mlxsw_sp_port_mapping_event_set (mlxsw_sp , i , false);
2050+ /* Make sure all scheduled events are processed */
2051+ __mlxsw_sp_port_mapping_events_cancel (mlxsw_sp );
19162052 kfree (mlxsw_sp -> ports );
19172053 mlxsw_sp -> ports = NULL ;
19182054 return err ;
@@ -2074,6 +2210,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u16 local_port,
20742210
20752211err_port_split_create :
20762212 mlxsw_sp_port_unsplit_create (mlxsw_sp , count , pmtdb_pl );
2213+
20772214 return err ;
20782215}
20792216
@@ -2294,6 +2431,11 @@ static const struct mlxsw_listener mlxsw_sp1_listener[] = {
22942431 MLXSW_EVENTL (mlxsw_sp1_ptp_ing_fifo_event_func , PTP_ING_FIFO , SP_PTP0 ),
22952432};
22962433
2434+ static const struct mlxsw_listener mlxsw_sp2_listener [] = {
2435+ /* Events */
2436+ MLXSW_SP_EVENTL (mlxsw_sp_port_mapping_listener_func , PMLPE ),
2437+ };
2438+
22972439static int mlxsw_sp_cpu_policers_set (struct mlxsw_core * mlxsw_core )
22982440{
22992441 struct mlxsw_sp * mlxsw_sp = mlxsw_core_driver_priv (mlxsw_core );
@@ -3085,6 +3227,8 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
30853227 mlxsw_sp -> trap_ops = & mlxsw_sp2_trap_ops ;
30863228 mlxsw_sp -> mall_ops = & mlxsw_sp2_mall_ops ;
30873229 mlxsw_sp -> router_ops = & mlxsw_sp2_router_ops ;
3230+ mlxsw_sp -> listeners = mlxsw_sp2_listener ;
3231+ mlxsw_sp -> listeners_count = ARRAY_SIZE (mlxsw_sp2_listener );
30883232 mlxsw_sp -> lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2 ;
30893233
30903234 return mlxsw_sp_init (mlxsw_core , mlxsw_bus_info , extack );
@@ -3115,6 +3259,8 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
31153259 mlxsw_sp -> trap_ops = & mlxsw_sp2_trap_ops ;
31163260 mlxsw_sp -> mall_ops = & mlxsw_sp2_mall_ops ;
31173261 mlxsw_sp -> router_ops = & mlxsw_sp2_router_ops ;
3262+ mlxsw_sp -> listeners = mlxsw_sp2_listener ;
3263+ mlxsw_sp -> listeners_count = ARRAY_SIZE (mlxsw_sp2_listener );
31183264 mlxsw_sp -> lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3 ;
31193265
31203266 return mlxsw_sp_init (mlxsw_core , mlxsw_bus_info , extack );
@@ -3145,6 +3291,8 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
31453291 mlxsw_sp -> trap_ops = & mlxsw_sp2_trap_ops ;
31463292 mlxsw_sp -> mall_ops = & mlxsw_sp2_mall_ops ;
31473293 mlxsw_sp -> router_ops = & mlxsw_sp2_router_ops ;
3294+ mlxsw_sp -> listeners = mlxsw_sp2_listener ;
3295+ mlxsw_sp -> listeners_count = ARRAY_SIZE (mlxsw_sp2_listener );
31483296 mlxsw_sp -> lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP4 ;
31493297
31503298 return mlxsw_sp_init (mlxsw_core , mlxsw_bus_info , extack );
0 commit comments