@@ -26,13 +26,20 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = {
26
26
27
27
struct mlxsw_m_port ;
28
28
29
+ struct mlxsw_m_line_card {
30
+ bool active ;
31
+ int module_to_port [];
32
+ };
33
+
29
34
struct mlxsw_m {
30
35
struct mlxsw_m_port * * ports ;
31
- int * module_to_port ;
32
36
struct mlxsw_core * core ;
33
37
const struct mlxsw_bus_info * bus_info ;
34
38
u8 base_mac [ETH_ALEN ];
35
39
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 ;
36
43
};
37
44
38
45
struct mlxsw_m_port {
@@ -191,7 +198,7 @@ static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
191
198
192
199
static int
193
200
mlxsw_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 )
195
202
{
196
203
char pmlp_pl [MLXSW_REG_PMLP_LEN ];
197
204
int err ;
@@ -202,6 +209,7 @@ mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port,
202
209
return err ;
203
210
* p_module = mlxsw_reg_pmlp_module_get (pmlp_pl , 0 );
204
211
* p_width = mlxsw_reg_pmlp_width_get (pmlp_pl );
212
+ * p_slot_index = mlxsw_reg_pmlp_slot_index_get (pmlp_pl , 0 );
205
213
206
214
return 0 ;
207
215
}
@@ -223,6 +231,11 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
223
231
return 0 ;
224
232
}
225
233
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
+
226
239
static int
227
240
mlxsw_m_port_create (struct mlxsw_m * mlxsw_m , u16 local_port , u8 slot_index ,
228
241
u8 module )
@@ -300,16 +313,23 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port)
300
313
mlxsw_core_port_fini (mlxsw_m -> core , local_port );
301
314
}
302
315
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
+
303
322
static int mlxsw_m_port_module_map (struct mlxsw_m * mlxsw_m , u16 local_port ,
304
323
u8 * last_module )
305
324
{
306
325
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 ;
308
328
int err ;
309
329
310
330
/* Fill out to local port mapping array */
311
331
err = mlxsw_m_port_module_info_get (mlxsw_m , local_port , & module ,
312
- & width );
332
+ & width , & slot_index );
313
333
if (err )
314
334
return err ;
315
335
@@ -322,107 +342,198 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port,
322
342
323
343
if (WARN_ON_ONCE (module >= max_ports ))
324
344
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 ;
327
348
328
349
return 0 ;
329
350
}
330
351
331
352
static void
332
353
mlxsw_m_port_module_unmap (struct mlxsw_m * mlxsw_m , u8 slot_index , u8 module )
333
354
{
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 ;
335
358
mlxsw_env_module_port_unmap (mlxsw_m -> core , slot_index , module );
336
359
}
337
360
338
361
static int mlxsw_m_linecards_init (struct mlxsw_m * mlxsw_m )
339
362
{
340
363
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 ;
342
385
343
386
mlxsw_m -> ports = kcalloc (max_ports , sizeof (* mlxsw_m -> ports ),
344
387
GFP_KERNEL );
345
388
if (!mlxsw_m -> ports )
346
389
return - ENOMEM ;
347
390
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 ;
353
409
}
354
410
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
-
359
411
return 0 ;
360
412
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 :
362
417
kfree (mlxsw_m -> ports );
363
418
return err ;
364
419
}
365
420
366
421
static void mlxsw_m_linecards_fini (struct mlxsw_m * mlxsw_m )
367
422
{
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 );
369
428
kfree (mlxsw_m -> ports );
370
429
}
371
430
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 )
373
433
{
374
- unsigned int max_ports = mlxsw_core_max_ports (mlxsw_m -> core );
375
- u8 last_module = max_ports ;
376
434
int i ;
377
- int err ;
378
435
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 );
384
442
}
443
+ }
385
444
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 );
392
456
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;
394
461
}
395
462
}
396
-
397
463
return 0 ;
398
464
399
- err_module_to_port_create :
465
+ err_port_create :
400
466
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
+ }
404
475
}
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 );
409
476
return err ;
410
477
}
411
478
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 )
413
481
{
414
482
int i ;
415
483
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 );
421
492
}
422
493
}
494
+ }
423
495
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 );
426
537
}
427
538
428
539
static int mlxsw_m_fw_rev_validate (struct mlxsw_m * mlxsw_m )
0 commit comments