@@ -26,13 +26,20 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = {
2626
2727struct mlxsw_m_port ;
2828
29+ struct mlxsw_m_line_card {
30+ bool active ;
31+ int module_to_port [];
32+ };
33+
2934struct mlxsw_m {
3035 struct mlxsw_m_port * * ports ;
31- int * module_to_port ;
3236 struct mlxsw_core * core ;
3337 const struct mlxsw_bus_info * bus_info ;
3438 u8 base_mac [ETH_ALEN ];
3539 u8 max_ports ;
40+ u8 max_modules_per_slot ; /* Maximum number of modules per-slot. */
41+ u8 num_of_slots ; /* Including the main board. */
42+ struct mlxsw_m_line_card * * line_cards ;
3643};
3744
3845struct mlxsw_m_port {
@@ -191,7 +198,7 @@ static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
191198
192199static int
193200mlxsw_m_port_module_info_get (struct mlxsw_m * mlxsw_m , u16 local_port ,
194- u8 * p_module , u8 * p_width )
201+ u8 * p_module , u8 * p_width , u8 * p_slot_index )
195202{
196203 char pmlp_pl [MLXSW_REG_PMLP_LEN ];
197204 int err ;
@@ -202,6 +209,7 @@ mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port,
202209 return err ;
203210 * p_module = mlxsw_reg_pmlp_module_get (pmlp_pl , 0 );
204211 * p_width = mlxsw_reg_pmlp_width_get (pmlp_pl );
212+ * p_slot_index = mlxsw_reg_pmlp_slot_index_get (pmlp_pl , 0 );
205213
206214 return 0 ;
207215}
@@ -223,6 +231,11 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
223231 return 0 ;
224232}
225233
234+ static bool mlxsw_m_port_created (struct mlxsw_m * mlxsw_m , u16 local_port )
235+ {
236+ return mlxsw_m -> ports [local_port ];
237+ }
238+
226239static int
227240mlxsw_m_port_create (struct mlxsw_m * mlxsw_m , u16 local_port , u8 slot_index ,
228241 u8 module )
@@ -300,16 +313,23 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port)
300313 mlxsw_core_port_fini (mlxsw_m -> core , local_port );
301314}
302315
316+ static int *
317+ mlxsw_m_port_mapping_get (struct mlxsw_m * mlxsw_m , u8 slot_index , u8 module )
318+ {
319+ return & mlxsw_m -> line_cards [slot_index ]-> module_to_port [module ];
320+ }
321+
303322static int mlxsw_m_port_module_map (struct mlxsw_m * mlxsw_m , u16 local_port ,
304323 u8 * last_module )
305324{
306325 unsigned int max_ports = mlxsw_core_max_ports (mlxsw_m -> core );
307- u8 module , width ;
326+ u8 module , width , slot_index ;
327+ int * module_to_port ;
308328 int err ;
309329
310330 /* Fill out to local port mapping array */
311331 err = mlxsw_m_port_module_info_get (mlxsw_m , local_port , & module ,
312- & width );
332+ & width , & slot_index );
313333 if (err )
314334 return err ;
315335
@@ -322,107 +342,198 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port,
322342
323343 if (WARN_ON_ONCE (module >= max_ports ))
324344 return - EINVAL ;
325- mlxsw_env_module_port_map (mlxsw_m -> core , 0 , module );
326- mlxsw_m -> module_to_port [module ] = ++ mlxsw_m -> max_ports ;
345+ mlxsw_env_module_port_map (mlxsw_m -> core , slot_index , module );
346+ module_to_port = mlxsw_m_port_mapping_get (mlxsw_m , slot_index , module );
347+ * module_to_port = local_port ;
327348
328349 return 0 ;
329350}
330351
331352static void
332353mlxsw_m_port_module_unmap (struct mlxsw_m * mlxsw_m , u8 slot_index , u8 module )
333354{
334- mlxsw_m -> module_to_port [module ] = -1 ;
355+ int * module_to_port = mlxsw_m_port_mapping_get (mlxsw_m , slot_index ,
356+ module );
357+ * module_to_port = -1 ;
335358 mlxsw_env_module_port_unmap (mlxsw_m -> core , slot_index , module );
336359}
337360
338361static int mlxsw_m_linecards_init (struct mlxsw_m * mlxsw_m )
339362{
340363 unsigned int max_ports = mlxsw_core_max_ports (mlxsw_m -> core );
341- int i , err ;
364+ char mgpir_pl [MLXSW_REG_MGPIR_LEN ];
365+ u8 num_of_modules ;
366+ int i , j , err ;
367+
368+ mlxsw_reg_mgpir_pack (mgpir_pl , 0 );
369+ err = mlxsw_reg_query (mlxsw_m -> core , MLXSW_REG (mgpir ), mgpir_pl );
370+ if (err )
371+ return err ;
372+
373+ mlxsw_reg_mgpir_unpack (mgpir_pl , NULL , NULL , NULL , & num_of_modules ,
374+ & mlxsw_m -> num_of_slots );
375+ /* If the system is modular, get the maximum number of modules per-slot.
376+ * Otherwise, get the maximum number of modules on the main board.
377+ */
378+ if (mlxsw_m -> num_of_slots )
379+ mlxsw_m -> max_modules_per_slot =
380+ mlxsw_reg_mgpir_max_modules_per_slot_get (mgpir_pl );
381+ else
382+ mlxsw_m -> max_modules_per_slot = num_of_modules ;
383+ /* Add slot for main board. */
384+ mlxsw_m -> num_of_slots += 1 ;
342385
343386 mlxsw_m -> ports = kcalloc (max_ports , sizeof (* mlxsw_m -> ports ),
344387 GFP_KERNEL );
345388 if (!mlxsw_m -> ports )
346389 return - ENOMEM ;
347390
348- mlxsw_m -> module_to_port = kmalloc_array (max_ports , sizeof (int ),
349- GFP_KERNEL );
350- if (!mlxsw_m -> module_to_port ) {
351- err = - ENOMEM ;
352- goto err_module_to_port_alloc ;
391+ mlxsw_m -> line_cards = kcalloc (mlxsw_m -> num_of_slots ,
392+ sizeof (* mlxsw_m -> line_cards ),
393+ GFP_KERNEL );
394+ if (!mlxsw_m -> line_cards )
395+ goto err_kcalloc ;
396+
397+ for (i = 0 ; i < mlxsw_m -> num_of_slots ; i ++ ) {
398+ mlxsw_m -> line_cards [i ] =
399+ kzalloc (struct_size (mlxsw_m -> line_cards [i ],
400+ module_to_port ,
401+ mlxsw_m -> max_modules_per_slot ),
402+ GFP_KERNEL );
403+ if (!mlxsw_m -> line_cards [i ])
404+ goto err_kmalloc_array ;
405+
406+ /* Invalidate the entries of module to local port mapping array. */
407+ for (j = 0 ; j < mlxsw_m -> max_modules_per_slot ; j ++ )
408+ mlxsw_m -> line_cards [i ]-> module_to_port [j ] = -1 ;
353409 }
354410
355- /* Invalidate the entries of module to local port mapping array */
356- for (i = 0 ; i < max_ports ; i ++ )
357- mlxsw_m -> module_to_port [i ] = -1 ;
358-
359411 return 0 ;
360412
361- err_module_to_port_alloc :
413+ err_kmalloc_array :
414+ for (i -- ; i >= 0 ; i -- )
415+ kfree (mlxsw_m -> line_cards [i ]);
416+ err_kcalloc :
362417 kfree (mlxsw_m -> ports );
363418 return err ;
364419}
365420
366421static void mlxsw_m_linecards_fini (struct mlxsw_m * mlxsw_m )
367422{
368- kfree (mlxsw_m -> module_to_port );
423+ int i = mlxsw_m -> num_of_slots ;
424+
425+ for (i -- ; i >= 0 ; i -- )
426+ kfree (mlxsw_m -> line_cards [i ]);
427+ kfree (mlxsw_m -> line_cards );
369428 kfree (mlxsw_m -> ports );
370429}
371430
372- static int mlxsw_m_ports_create (struct mlxsw_m * mlxsw_m )
431+ static void
432+ mlxsw_m_linecard_port_module_unmap (struct mlxsw_m * mlxsw_m , u8 slot_index )
373433{
374- unsigned int max_ports = mlxsw_core_max_ports (mlxsw_m -> core );
375- u8 last_module = max_ports ;
376434 int i ;
377- int err ;
378435
379- /* Fill out module to local port mapping array */
380- for (i = 1 ; i < max_ports ; i ++ ) {
381- err = mlxsw_m_port_module_map (mlxsw_m , i , & last_module );
382- if (err )
383- goto err_module_to_port_map ;
436+ for (i = mlxsw_m -> max_modules_per_slot - 1 ; i >= 0 ; i -- ) {
437+ int * module_to_port ;
438+
439+ module_to_port = mlxsw_m_port_mapping_get (mlxsw_m , slot_index , i );
440+ if (* module_to_port > 0 )
441+ mlxsw_m_port_module_unmap (mlxsw_m , slot_index , i );
384442 }
443+ }
385444
386- /* Create port objects for each valid entry */
387- for (i = 0 ; i < mlxsw_m -> max_ports ; i ++ ) {
388- if (mlxsw_m -> module_to_port [i ] > 0 ) {
389- err = mlxsw_m_port_create (mlxsw_m ,
390- mlxsw_m -> module_to_port [i ],
391- 0 , i );
445+ static int
446+ mlxsw_m_linecard_ports_create (struct mlxsw_m * mlxsw_m , u8 slot_index )
447+ {
448+ int * module_to_port ;
449+ int i , err ;
450+
451+ for (i = 0 ; i < mlxsw_m -> max_modules_per_slot ; i ++ ) {
452+ module_to_port = mlxsw_m_port_mapping_get (mlxsw_m , slot_index , i );
453+ if (* module_to_port > 0 ) {
454+ err = mlxsw_m_port_create (mlxsw_m , * module_to_port ,
455+ slot_index , i );
392456 if (err )
393- goto err_module_to_port_create ;
457+ goto err_port_create ;
458+ /* Mark slot as active */
459+ if (!mlxsw_m -> line_cards [slot_index ]-> active )
460+ mlxsw_m -> line_cards [slot_index ]-> active = true;
394461 }
395462 }
396-
397463 return 0 ;
398464
399- err_module_to_port_create :
465+ err_port_create :
400466 for (i -- ; i >= 0 ; i -- ) {
401- if (mlxsw_m -> module_to_port [i ] > 0 )
402- mlxsw_m_port_remove (mlxsw_m ,
403- mlxsw_m -> module_to_port [i ]);
467+ module_to_port = mlxsw_m_port_mapping_get (mlxsw_m , slot_index , i );
468+ if (* module_to_port > 0 &&
469+ mlxsw_m_port_created (mlxsw_m , * module_to_port )) {
470+ mlxsw_m_port_remove (mlxsw_m , * module_to_port );
471+ /* Mark slot as inactive */
472+ if (mlxsw_m -> line_cards [slot_index ]-> active )
473+ mlxsw_m -> line_cards [slot_index ]-> active = false;
474+ }
404475 }
405- i = max_ports ;
406- err_module_to_port_map :
407- for (i -- ; i > 0 ; i -- )
408- mlxsw_m_port_module_unmap (mlxsw_m , 0 , i );
409476 return err ;
410477}
411478
412- static void mlxsw_m_ports_remove (struct mlxsw_m * mlxsw_m )
479+ static void
480+ mlxsw_m_linecard_ports_remove (struct mlxsw_m * mlxsw_m , u8 slot_index )
413481{
414482 int i ;
415483
416- for (i = 0 ; i < mlxsw_m -> max_ports ; i ++ ) {
417- if (mlxsw_m -> module_to_port [i ] > 0 ) {
418- mlxsw_m_port_remove (mlxsw_m ,
419- mlxsw_m -> module_to_port [i ]);
420- mlxsw_m_port_module_unmap (mlxsw_m , 0 , i );
484+ for (i = 0 ; i < mlxsw_m -> max_modules_per_slot ; i ++ ) {
485+ int * module_to_port = mlxsw_m_port_mapping_get (mlxsw_m ,
486+ slot_index , i );
487+
488+ if (* module_to_port > 0 &&
489+ mlxsw_m_port_created (mlxsw_m , * module_to_port )) {
490+ mlxsw_m_port_remove (mlxsw_m , * module_to_port );
491+ mlxsw_m_port_module_unmap (mlxsw_m , slot_index , i );
421492 }
422493 }
494+ }
423495
424- kfree (mlxsw_m -> module_to_port );
425- kfree (mlxsw_m -> ports );
496+ static int mlxsw_m_ports_module_map (struct mlxsw_m * mlxsw_m )
497+ {
498+ unsigned int max_ports = mlxsw_core_max_ports (mlxsw_m -> core );
499+ u8 last_module = max_ports ;
500+ int i , err ;
501+
502+ for (i = 1 ; i < max_ports ; i ++ ) {
503+ err = mlxsw_m_port_module_map (mlxsw_m , i , & last_module );
504+ if (err )
505+ return err ;
506+ }
507+
508+ return 0 ;
509+ }
510+
511+ static int mlxsw_m_ports_create (struct mlxsw_m * mlxsw_m )
512+ {
513+ int err ;
514+
515+ /* Fill out module to local port mapping array */
516+ err = mlxsw_m_ports_module_map (mlxsw_m );
517+ if (err )
518+ goto err_ports_module_map ;
519+
520+ /* Create port objects for each valid entry */
521+ err = mlxsw_m_linecard_ports_create (mlxsw_m , 0 );
522+ if (err )
523+ goto err_linecard_ports_create ;
524+
525+ return 0 ;
526+
527+ err_linecard_ports_create :
528+ err_ports_module_map :
529+ mlxsw_m_linecard_port_module_unmap (mlxsw_m , 0 );
530+
531+ return err ;
532+ }
533+
534+ static void mlxsw_m_ports_remove (struct mlxsw_m * mlxsw_m )
535+ {
536+ mlxsw_m_linecard_ports_remove (mlxsw_m , 0 );
426537}
427538
428539static int mlxsw_m_fw_rev_validate (struct mlxsw_m * mlxsw_m )
0 commit comments