Congestion counters are counted and queried per physical function. When working in LAG mode, CNP packets can be sent or received on both of the functions, thus congestion counters should be aggregated from the two physical functions.
Unified · Split
| @@ -47,17 +47,6 @@ int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey) · 46 unmodified lines | |||
| 47 | return err; | 47 | return err; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 51 | bool reset, void *out, int out_size) | ||
| 52 | { | ||
| 53 | u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = { }; | ||
| 54 | |||
| 55 | MLX5_SET(query_cong_statistics_in, in, opcode, | ||
| 56 | MLX5_CMD_OP_QUERY_CONG_STATISTICS); | ||
| 57 | MLX5_SET(query_cong_statistics_in, in, clear, reset); | ||
| 58 | return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size); | ||
| 59 | } | ||
| 60 | |||
| 61 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, | 50 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, |
| 62 | void *out, int out_size) | 51 | void *out, int out_size) |
| 63 | { | 52 | { |
| @@ -37,8 +37,6 @@ · 36 unmodified lines | |||
| 37 | #include <linux/mlx5/driver.h> | 37 | #include <linux/mlx5/driver.h> |
| 38 | 38 | ||
| 39 | int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey); | 39 | int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey); |
| 40 | int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 41 | bool reset, void *out, int out_size); | ||
| 42 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, | 40 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, |
| 43 | void *out, int out_size); | 41 | void *out, int out_size); |
| 44 | int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev, | 42 | int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev, |
| @@ -3737,34 +3737,6 @@ free: · 3736 unmodified lines | |||
| 3737 | return ret; | 3737 | return ret; |
| 3738 | } | 3738 | } |
| 3739 | 3739 | ||
| 3740 | static int mlx5_ib_query_cong_counters(struct mlx5_ib_dev *dev, | ||
| 3741 | struct mlx5_ib_port *port, | ||
| 3742 | struct rdma_hw_stats *stats) | ||
| 3743 | { | ||
| 3744 | int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out); | ||
| 3745 | void *out; | ||
| 3746 | int ret, i; | ||
| 3747 | int offset = port->cnts.num_q_counters; | ||
| 3748 | |||
| 3749 | out = kvzalloc(outlen, GFP_KERNEL); | ||
| 3750 | if (!out) | ||
| 3751 | return -ENOMEM; | ||
| 3752 | |||
| 3753 | ret = mlx5_cmd_query_cong_counter(dev->mdev, false, out, outlen); | ||
| 3754 | if (ret) | ||
| 3755 | goto free; | ||
| 3756 | |||
| 3757 | for (i = 0; i < port->cnts.num_cong_counters; i++) { | ||
| 3758 | stats->value[i + offset] = | ||
| 3759 | be64_to_cpup((__be64 *)(out + | ||
| 3760 | port->cnts.offsets[i + offset])); | ||
| 3761 | } | ||
| 3762 | |||
| 3763 | free: | ||
| 3764 | kvfree(out); | ||
| 3765 | return ret; | ||
| 3766 | } | ||
| 3767 | |||
| 3768 | static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, | 3740 | static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, |
| 3769 | struct rdma_hw_stats *stats, | 3741 | struct rdma_hw_stats *stats, |
| 3770 | u8 port_num, int index) | 3742 | u8 port_num, int index) |
| @@ -3782,7 +3754,12 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, · 11 unmodified lines | |||
| 3782 | num_counters = port->cnts.num_q_counters; | 3754 | num_counters = port->cnts.num_q_counters; |
| 3783 | 3755 | ||
| 3784 | if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { | 3756 | if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { |
| 3785 | ret = mlx5_ib_query_cong_counters(dev, port, stats); | 3757 | ret = mlx5_lag_query_cong_counters(dev->mdev, |
| 3758 | stats->value + | ||
| 3759 | port->cnts.num_q_counters, | ||
| 3760 | port->cnts.num_cong_counters, | ||
| 3761 | port->cnts.offsets + | ||
| 3762 | port->cnts.num_q_counters); | ||
| 3786 | if (ret) | 3763 | if (ret) |
| 3787 | return ret; | 3764 | return ret; |
| 3788 | num_counters += port->cnts.num_cong_counters; | 3765 | num_counters += port->cnts.num_cong_counters; |
| @@ -137,6 +137,17 @@ int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev) · 136 unmodified lines | |||
| 137 | } | 137 | } |
| 138 | EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag); | 138 | EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag); |
| 139 | 139 | ||
| 140 | static int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 141 | bool reset, void *out, int out_size) | ||
| 142 | { | ||
| 143 | u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = { }; | ||
| 144 | |||
| 145 | MLX5_SET(query_cong_statistics_in, in, opcode, | ||
| 146 | MLX5_CMD_OP_QUERY_CONG_STATISTICS); | ||
| 147 | MLX5_SET(query_cong_statistics_in, in, clear, reset); | ||
| 148 | return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size); | ||
| 149 | } | ||
| 150 | |||
| 140 | static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev) | 151 | static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev) |
| 141 | { | 152 | { |
| 142 | return dev->priv.lag; | 153 | return dev->priv.lag; |
| @@ -633,3 +644,48 @@ bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv) · 490 unmodified lines | |||
| 633 | /* If bonded, we do not add an IB device for PF1. */ | 644 | /* If bonded, we do not add an IB device for PF1. */ |
| 634 | return false; | 645 | return false; |
| 635 | } | 646 | } |
| 647 | |||
| 648 | int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, | ||
| 649 | u64 *values, | ||
| 650 | int num_counters, | ||
| 651 | size_t *offsets) | ||
| 652 | { | ||
| 653 | int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out); | ||
| 654 | struct mlx5_core_dev *mdev[MLX5_MAX_PORTS]; | ||
| 655 | struct mlx5_lag *ldev; | ||
| 656 | int num_ports; | ||
| 657 | int ret, i, j; | ||
| 658 | void *out; | ||
| 659 | |||
| 660 | out = kvzalloc(outlen, GFP_KERNEL); | ||
| 661 | if (!out) | ||
| 662 | return -ENOMEM; | ||
| 663 | |||
| 664 | memset(values, 0, sizeof(*values) * num_counters); | ||
| 665 | |||
| 666 | mutex_lock(&lag_mutex); | ||
| 667 | ldev = mlx5_lag_dev_get(dev); | ||
| 668 | if (ldev && mlx5_lag_is_bonded(ldev)) { | ||
| 669 | num_ports = MLX5_MAX_PORTS; | ||
| 670 | mdev[0] = ldev->pf[0].dev; | ||
| 671 | mdev[1] = ldev->pf[1].dev; | ||
| 672 | } else { | ||
| 673 | num_ports = 1; | ||
| 674 | mdev[0] = dev; | ||
| 675 | } | ||
| 676 | |||
| 677 | for (i = 0; i < num_ports; ++i) { | ||
| 678 | ret = mlx5_cmd_query_cong_counter(mdev[i], false, out, outlen); | ||
| 679 | if (ret) | ||
| 680 | goto unlock; | ||
| 681 | |||
| 682 | for (j = 0; j < num_counters; ++j) | ||
| 683 | values[j] += be64_to_cpup((__be64 *)(out + offsets[j])); | ||
| 684 | } | ||
| 685 | |||
| 686 | unlock: | ||
| 687 | mutex_unlock(&lag_mutex); | ||
| 688 | kvfree(out); | ||
| 689 | return ret; | ||
| 690 | } | ||
| 691 | EXPORT_SYMBOL(mlx5_lag_query_cong_counters); | ||
| @@ -1164,6 +1164,10 @@ int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev); · 1163 unmodified lines | |||
| 1164 | int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev); | 1164 | int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev); |
| 1165 | bool mlx5_lag_is_active(struct mlx5_core_dev *dev); | 1165 | bool mlx5_lag_is_active(struct mlx5_core_dev *dev); |
| 1166 | struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev); | 1166 | struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev); |
| 1167 | int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, | ||
| 1168 | u64 *values, | ||
| 1169 | int num_counters, | ||
| 1170 | size_t *offsets); | ||
| 1167 | struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); | 1171 | struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); |
| 1168 | void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); | 1172 | void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); |
| 1169 | 1173 | ||