Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/mlx5e: PFC stall prevention support

Implement set/get functions to configure PFC stall prevention
timeout by tunables api through ethtool.
By default the stall prevention timeout is configured to 8 sec.
Timeout range is: 80-8000 msec.

Enabling stall prevention with the auto timeout will set
the timeout to 100 msec.

Signed-off-by: Inbar Karmy <inbark@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>

authored by

Inbar Karmy and committed by
Saeed Mahameed
2afa609f e1577c1c

+132 -12
+57
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 1066 1066 return err; 1067 1067 } 1068 1068 1069 + #define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC 100 1070 + #define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC 8000 1071 + #define MLX5E_PFC_PREVEN_MINOR_PRECENT 85 1072 + #define MLX5E_PFC_PREVEN_TOUT_MIN_MSEC 80 1073 + #define MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout) \ 1074 + max_t(u16, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC, \ 1075 + (critical_tout * MLX5E_PFC_PREVEN_MINOR_PRECENT) / 100) 1076 + 1077 + static int mlx5e_get_pfc_prevention_tout(struct net_device *netdev, 1078 + u16 *pfc_prevention_tout) 1079 + { 1080 + struct mlx5e_priv *priv = netdev_priv(netdev); 1081 + struct mlx5_core_dev *mdev = priv->mdev; 1082 + 1083 + if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) || 1084 + !MLX5_CAP_DEBUG((priv)->mdev, stall_detect)) 1085 + return -EOPNOTSUPP; 1086 + 1087 + return mlx5_query_port_stall_watermark(mdev, pfc_prevention_tout, NULL); 1088 + } 1089 + 1090 + static int mlx5e_set_pfc_prevention_tout(struct net_device *netdev, 1091 + u16 pfc_preven) 1092 + { 1093 + struct mlx5e_priv *priv = netdev_priv(netdev); 1094 + struct mlx5_core_dev *mdev = priv->mdev; 1095 + u16 critical_tout; 1096 + u16 minor; 1097 + 1098 + if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) || 1099 + !MLX5_CAP_DEBUG((priv)->mdev, stall_detect)) 1100 + return -EOPNOTSUPP; 1101 + 1102 + critical_tout = (pfc_preven == PFC_STORM_PREVENTION_AUTO) ? 1103 + MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC : 1104 + pfc_preven; 1105 + 1106 + if (critical_tout != PFC_STORM_PREVENTION_DISABLE && 1107 + (critical_tout > MLX5E_PFC_PREVEN_TOUT_MAX_MSEC || 1108 + critical_tout < MLX5E_PFC_PREVEN_TOUT_MIN_MSEC)) { 1109 + netdev_info(netdev, "%s: pfc prevention tout not in range (%d-%d)\n", 1110 + __func__, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC, 1111 + MLX5E_PFC_PREVEN_TOUT_MAX_MSEC); 1112 + return -EINVAL; 1113 + } 1114 + 1115 + minor = MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout); 1116 + return mlx5_set_port_stall_watermark(mdev, critical_tout, 1117 + minor); 1118 + } 1119 + 1069 1120 static int mlx5e_get_tunable(struct net_device *dev, 1070 1121 const struct ethtool_tunable *tuna, 1071 1122 void *data) ··· 1127 1076 switch (tuna->id) { 1128 1077 case ETHTOOL_TX_COPYBREAK: 1129 1078 *(u32 *)data = priv->channels.params.tx_max_inline; 1079 + break; 1080 + case ETHTOOL_PFC_PREVENTION_TOUT: 1081 + err = mlx5e_get_pfc_prevention_tout(dev, data); 1130 1082 break; 1131 1083 default: 1132 1084 err = -EINVAL; ··· 1172 1118 break; 1173 1119 mlx5e_switch_priv_channels(priv, &new_channels, NULL); 1174 1120 1121 + break; 1122 + case ETHTOOL_PFC_PREVENTION_TOUT: 1123 + err = mlx5e_set_pfc_prevention_tout(dev, *(u16 *)data); 1175 1124 break; 1176 1125 default: 1177 1126 err = -EINVAL;
+56 -8
drivers/net/ethernet/mellanox/mlx5/core/port.c
··· 483 483 } 484 484 EXPORT_SYMBOL_GPL(mlx5_core_query_ib_ppcnt); 485 485 486 + static int mlx5_query_pfcc_reg(struct mlx5_core_dev *dev, u32 *out, 487 + u32 out_size) 488 + { 489 + u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 490 + 491 + MLX5_SET(pfcc_reg, in, local_port, 1); 492 + 493 + return mlx5_core_access_reg(dev, in, sizeof(in), out, 494 + out_size, MLX5_REG_PFCC, 0, 0); 495 + } 496 + 486 497 int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause) 487 498 { 488 499 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; ··· 511 500 int mlx5_query_port_pause(struct mlx5_core_dev *dev, 512 501 u32 *rx_pause, u32 *tx_pause) 513 502 { 514 - u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 515 503 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 516 504 int err; 517 505 518 - MLX5_SET(pfcc_reg, in, local_port, 1); 519 - err = mlx5_core_access_reg(dev, in, sizeof(in), out, 520 - sizeof(out), MLX5_REG_PFCC, 0, 0); 506 + err = mlx5_query_pfcc_reg(dev, out, sizeof(out)); 521 507 if (err) 522 508 return err; 523 509 ··· 527 519 return 0; 528 520 } 529 521 EXPORT_SYMBOL_GPL(mlx5_query_port_pause); 522 + 523 + int mlx5_set_port_stall_watermark(struct mlx5_core_dev *dev, 524 + u16 stall_critical_watermark, 525 + u16 stall_minor_watermark) 526 + { 527 + u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 528 + u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 529 + 530 + MLX5_SET(pfcc_reg, in, local_port, 1); 531 + MLX5_SET(pfcc_reg, in, pptx_mask_n, 1); 532 + MLX5_SET(pfcc_reg, in, pprx_mask_n, 1); 533 + MLX5_SET(pfcc_reg, in, ppan_mask_n, 1); 534 + MLX5_SET(pfcc_reg, in, critical_stall_mask, 1); 535 + MLX5_SET(pfcc_reg, in, minor_stall_mask, 1); 536 + MLX5_SET(pfcc_reg, in, device_stall_critical_watermark, 537 + stall_critical_watermark); 538 + MLX5_SET(pfcc_reg, in, device_stall_minor_watermark, stall_minor_watermark); 539 + 540 + return mlx5_core_access_reg(dev, in, sizeof(in), out, 541 + sizeof(out), MLX5_REG_PFCC, 0, 1); 542 + } 543 + 544 + int mlx5_query_port_stall_watermark(struct mlx5_core_dev *dev, 545 + u16 *stall_critical_watermark, 546 + u16 *stall_minor_watermark) 547 + { 548 + u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 549 + int err; 550 + 551 + err = mlx5_query_pfcc_reg(dev, out, sizeof(out)); 552 + if (err) 553 + return err; 554 + 555 + if (stall_critical_watermark) 556 + *stall_critical_watermark = MLX5_GET(pfcc_reg, out, 557 + device_stall_critical_watermark); 558 + 559 + if (stall_minor_watermark) 560 + *stall_minor_watermark = MLX5_GET(pfcc_reg, out, 561 + device_stall_minor_watermark); 562 + 563 + return 0; 564 + } 530 565 531 566 int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx) 532 567 { ··· 589 538 590 539 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) 591 540 { 592 - u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0}; 593 541 u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; 594 542 int err; 595 543 596 - MLX5_SET(pfcc_reg, in, local_port, 1); 597 - err = mlx5_core_access_reg(dev, in, sizeof(in), out, 598 - sizeof(out), MLX5_REG_PFCC, 0, 0); 544 + err = mlx5_query_pfcc_reg(dev, out, sizeof(out)); 599 545 if (err) 600 546 return err; 601 547
+13 -4
include/linux/mlx5/mlx5_ifc.h
··· 7833 7833 struct mlx5_ifc_pfcc_reg_bits { 7834 7834 u8 reserved_at_0[0x8]; 7835 7835 u8 local_port[0x8]; 7836 - u8 reserved_at_10[0x10]; 7836 + u8 reserved_at_10[0xb]; 7837 + u8 ppan_mask_n[0x1]; 7838 + u8 minor_stall_mask[0x1]; 7839 + u8 critical_stall_mask[0x1]; 7840 + u8 reserved_at_1e[0x2]; 7837 7841 7838 7842 u8 ppan[0x4]; 7839 7843 u8 reserved_at_24[0x4]; ··· 7847 7843 7848 7844 u8 pptx[0x1]; 7849 7845 u8 aptx[0x1]; 7850 - u8 reserved_at_42[0x6]; 7846 + u8 pptx_mask_n[0x1]; 7847 + u8 reserved_at_43[0x5]; 7851 7848 u8 pfctx[0x8]; 7852 7849 u8 reserved_at_50[0x10]; 7853 7850 7854 7851 u8 pprx[0x1]; 7855 7852 u8 aprx[0x1]; 7856 - u8 reserved_at_62[0x6]; 7853 + u8 pprx_mask_n[0x1]; 7854 + u8 reserved_at_63[0x5]; 7857 7855 u8 pfcrx[0x8]; 7858 7856 u8 reserved_at_70[0x10]; 7859 7857 7860 - u8 reserved_at_80[0x80]; 7858 + u8 device_stall_minor_watermark[0x10]; 7859 + u8 device_stall_critical_watermark[0x10]; 7860 + 7861 + u8 reserved_at_a0[0x60]; 7861 7862 }; 7862 7863 7863 7864 struct mlx5_ifc_pelc_reg_bits {
+6
include/linux/mlx5/port.h
··· 151 151 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, 152 152 u8 *pfc_en_rx); 153 153 154 + int mlx5_set_port_stall_watermark(struct mlx5_core_dev *dev, 155 + u16 stall_critical_watermark, 156 + u16 stall_minor_watermark); 157 + int mlx5_query_port_stall_watermark(struct mlx5_core_dev *dev, 158 + u16 *stall_critical_watermark, u16 *stall_minor_watermark); 159 + 154 160 int mlx5_max_tc(struct mlx5_core_dev *mdev); 155 161 156 162 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc);