@@ -349,12 +349,18 @@ enum mlx5e_fec_supported_link_mode {
349349 MLX5E_FEC_SUPPORTED_LINK_MODES_50G ,
350350 MLX5E_FEC_SUPPORTED_LINK_MODES_56G ,
351351 MLX5E_FEC_SUPPORTED_LINK_MODES_100G ,
352+ MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X ,
353+ MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X ,
354+ MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X ,
355+ MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X ,
352356 MLX5E_MAX_FEC_SUPPORTED_LINK_MODE ,
353357};
354358
359+ #define MLX5E_FEC_FIRST_50G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X
360+
355361#define MLX5E_FEC_OVERRIDE_ADMIN_POLICY (buf , policy , write , link ) \
356362 do { \
357- u8 *_policy = &(policy); \
363+ u16 *_policy = &(policy); \
358364 u32 *_buf = buf; \
359365 \
360366 if (write) \
@@ -363,8 +369,21 @@ enum mlx5e_fec_supported_link_mode {
363369 *_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \
364370 } while (0)
365371
372+ #define MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY (buf , policy , write , link ) \
373+ do { \
374+ u16 *__policy = &(policy); \
375+ bool _write = (write); \
376+ \
377+ if (_write && *__policy) \
378+ *__policy = find_first_bit((u_long *)__policy, \
379+ sizeof(u16) * BITS_PER_BYTE);\
380+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, *__policy, _write, link); \
381+ if (!_write && *__policy) \
382+ *__policy = 1 << *__policy; \
383+ } while (0)
384+
366385/* get/set FEC admin field for a given speed */
367- static int mlx5e_fec_admin_field (u32 * pplm , u8 * fec_policy , bool write ,
386+ static int mlx5e_fec_admin_field (u32 * pplm , u16 * fec_policy , bool write ,
368387 enum mlx5e_fec_supported_link_mode link_mode )
369388{
370389 switch (link_mode ) {
@@ -383,6 +402,18 @@ static int mlx5e_fec_admin_field(u32 *pplm, u8 *fec_policy, bool write,
383402 case MLX5E_FEC_SUPPORTED_LINK_MODES_100G :
384403 MLX5E_FEC_OVERRIDE_ADMIN_POLICY (pplm , * fec_policy , write , 100 g );
385404 break ;
405+ case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X :
406+ MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY (pplm , * fec_policy , write , 50 g_1x );
407+ break ;
408+ case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X :
409+ MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY (pplm , * fec_policy , write , 100 g_2x );
410+ break ;
411+ case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X :
412+ MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY (pplm , * fec_policy , write , 200 g_4x );
413+ break ;
414+ case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X :
415+ MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY (pplm , * fec_policy , write , 400 g_8x );
416+ break ;
386417 default :
387418 return - EINVAL ;
388419 }
@@ -393,7 +424,7 @@ static int mlx5e_fec_admin_field(u32 *pplm, u8 *fec_policy, bool write,
393424 MLX5_GET(pplm_reg, buf, fec_override_cap_##link)
394425
395426/* returns FEC capabilities for a given speed */
396- static int mlx5e_get_fec_cap_field (u32 * pplm , u8 * fec_cap ,
427+ static int mlx5e_get_fec_cap_field (u32 * pplm , u16 * fec_cap ,
397428 enum mlx5e_fec_supported_link_mode link_mode )
398429{
399430 switch (link_mode ) {
@@ -412,6 +443,18 @@ static int mlx5e_get_fec_cap_field(u32 *pplm, u8 *fec_cap,
412443 case MLX5E_FEC_SUPPORTED_LINK_MODES_100G :
413444 * fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP (pplm , 100 g );
414445 break ;
446+ case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X :
447+ * fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP (pplm , 50 g_1x );
448+ break ;
449+ case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X :
450+ * fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP (pplm , 100 g_2x );
451+ break ;
452+ case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X :
453+ * fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP (pplm , 200 g_4x );
454+ break ;
455+ case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X :
456+ * fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP (pplm , 400 g_8x );
457+ break ;
415458 default :
416459 return - EINVAL ;
417460 }
@@ -420,6 +463,7 @@ static int mlx5e_get_fec_cap_field(u32 *pplm, u8 *fec_cap,
420463
421464bool mlx5e_fec_in_caps (struct mlx5_core_dev * dev , int fec_policy )
422465{
466+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE (dev , fec_50G_per_lane_in_pplm );
423467 u32 out [MLX5_ST_SZ_DW (pplm_reg )] = {};
424468 u32 in [MLX5_ST_SZ_DW (pplm_reg )] = {};
425469 int sz = MLX5_ST_SZ_BYTES (pplm_reg );
@@ -438,7 +482,10 @@ bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
438482 return false;
439483
440484 for (i = 0 ; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE ; i ++ ) {
441- u8 fec_caps ;
485+ u16 fec_caps ;
486+
487+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane )
488+ break ;
442489
443490 mlx5e_get_fec_cap_field (out , & fec_caps , i );
444491 if (fec_caps & fec_policy )
@@ -448,8 +495,9 @@ bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
448495}
449496
450497int mlx5e_get_fec_mode (struct mlx5_core_dev * dev , u32 * fec_mode_active ,
451- u8 * fec_configured_mode )
498+ u16 * fec_configured_mode )
452499{
500+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE (dev , fec_50G_per_lane_in_pplm );
453501 u32 out [MLX5_ST_SZ_DW (pplm_reg )] = {};
454502 u32 in [MLX5_ST_SZ_DW (pplm_reg )] = {};
455503 int sz = MLX5_ST_SZ_BYTES (pplm_reg );
@@ -474,6 +522,9 @@ int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
474522
475523 * fec_configured_mode = 0 ;
476524 for (i = 0 ; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE ; i ++ ) {
525+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane )
526+ break ;
527+
477528 mlx5e_fec_admin_field (out , fec_configured_mode , 0 , i );
478529 if (* fec_configured_mode != 0 )
479530 goto out ;
@@ -482,13 +533,13 @@ int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
482533 return 0 ;
483534}
484535
485- int mlx5e_set_fec_mode (struct mlx5_core_dev * dev , u8 fec_policy )
536+ int mlx5e_set_fec_mode (struct mlx5_core_dev * dev , u16 fec_policy )
486537{
538+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE (dev , fec_50G_per_lane_in_pplm );
487539 u32 out [MLX5_ST_SZ_DW (pplm_reg )] = {};
488540 u32 in [MLX5_ST_SZ_DW (pplm_reg )] = {};
489541 int sz = MLX5_ST_SZ_BYTES (pplm_reg );
490- u8 fec_policy_auto = 0 ;
491- u8 fec_caps = 0 ;
542+ u16 fec_policy_auto = 0 ;
492543 int err ;
493544 int i ;
494545
@@ -498,6 +549,9 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
498549 if (!MLX5_CAP_PCAM_REG (dev , pplm ))
499550 return - EOPNOTSUPP ;
500551
552+ if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1 ) && !fec_50g_per_lane )
553+ return - EOPNOTSUPP ;
554+
501555 MLX5_SET (pplm_reg , in , local_port , 1 );
502556 err = mlx5_core_access_reg (dev , in , sz , out , sz , MLX5_REG_PPLM , 0 , 0 );
503557 if (err )
@@ -506,10 +560,26 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
506560 MLX5_SET (pplm_reg , out , local_port , 1 );
507561
508562 for (i = 0 ; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE ; i ++ ) {
563+ u16 conf_fec = fec_policy ;
564+ u16 fec_caps = 0 ;
565+
566+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane )
567+ break ;
568+
569+ /* RS fec in ethtool is mapped to MLX5E_FEC_RS_528_514
570+ * to link modes up to 25G per lane and to
571+ * MLX5E_FEC_RS_544_514 in the new link modes based on
572+ * 50 G per lane
573+ */
574+ if (conf_fec == (1 << MLX5E_FEC_RS_528_514 ) &&
575+ i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE )
576+ conf_fec = (1 << MLX5E_FEC_RS_544_514 );
577+
509578 mlx5e_get_fec_cap_field (out , & fec_caps , i );
579+
510580 /* policy supported for link speed */
511- if (fec_caps & fec_policy )
512- mlx5e_fec_admin_field (out , & fec_policy , 1 , i );
581+ if (fec_caps & conf_fec )
582+ mlx5e_fec_admin_field (out , & conf_fec , 1 , i );
513583 else
514584 /* set FEC to auto*/
515585 mlx5e_fec_admin_field (out , & fec_policy_auto , 1 , i );
0 commit comments