diff options
author | Raed Salem <raeds@mellanox.com> | 2018-05-31 09:43:39 -0400 |
---|---|---|
committer | Leon Romanovsky <leonro@mellanox.com> | 2018-06-02 00:35:32 -0400 |
commit | 3b3233fbf02ee4c5de4d635ca6c4f2566d9716df (patch) | |
tree | c3ddeb7941981e4f1029110cdee3ff63946e0f45 | |
parent | b29e2a1309e38cd1afa598a54f3ccb4e4d2ee01c (diff) |
IB/mlx5: Add flow counters binding support
Associates a counters with a flow when IB_FLOW_SPEC_ACTION_COUNT is part
of the flow specifications.
The counters user space placements of location and description (index,
description) pairs are passed as private data of the counters flow
specification.
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Raed Salem <raeds@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 222 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 15 | ||||
-rw-r--r-- | include/linux/mlx5/fs.h | 1 | ||||
-rw-r--r-- | include/uapi/rdma/mlx5-abi.h | 24 |
4 files changed, 249 insertions, 13 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 81471013b776..c52841bad4e7 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
@@ -2449,6 +2449,7 @@ static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val) | |||
2449 | #define LAST_TUNNEL_FIELD tunnel_id | 2449 | #define LAST_TUNNEL_FIELD tunnel_id |
2450 | #define LAST_FLOW_TAG_FIELD tag_id | 2450 | #define LAST_FLOW_TAG_FIELD tag_id |
2451 | #define LAST_DROP_FIELD size | 2451 | #define LAST_DROP_FIELD size |
2452 | #define LAST_COUNTERS_FIELD counters | ||
2452 | 2453 | ||
2453 | /* Field is the last supported field */ | 2454 | /* Field is the last supported field */ |
2454 | #define FIELDS_NOT_SUPPORTED(filter, field)\ | 2455 | #define FIELDS_NOT_SUPPORTED(filter, field)\ |
@@ -2721,6 +2722,18 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c, | |||
2721 | if (ret) | 2722 | if (ret) |
2722 | return ret; | 2723 | return ret; |
2723 | break; | 2724 | break; |
2725 | case IB_FLOW_SPEC_ACTION_COUNT: | ||
2726 | if (FIELDS_NOT_SUPPORTED(ib_spec->flow_count, | ||
2727 | LAST_COUNTERS_FIELD)) | ||
2728 | return -EOPNOTSUPP; | ||
2729 | |||
2730 | /* for now support only one counters spec per flow */ | ||
2731 | if (action->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) | ||
2732 | return -EINVAL; | ||
2733 | |||
2734 | action->counters = ib_spec->flow_count.counters; | ||
2735 | action->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; | ||
2736 | break; | ||
2724 | default: | 2737 | default: |
2725 | return -EINVAL; | 2738 | return -EINVAL; |
2726 | } | 2739 | } |
@@ -2868,6 +2881,17 @@ static void put_flow_table(struct mlx5_ib_dev *dev, | |||
2868 | } | 2881 | } |
2869 | } | 2882 | } |
2870 | 2883 | ||
2884 | static void counters_clear_description(struct ib_counters *counters) | ||
2885 | { | ||
2886 | struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); | ||
2887 | |||
2888 | mutex_lock(&mcounters->mcntrs_mutex); | ||
2889 | kfree(mcounters->counters_data); | ||
2890 | mcounters->counters_data = NULL; | ||
2891 | mcounters->cntrs_max_index = 0; | ||
2892 | mutex_unlock(&mcounters->mcntrs_mutex); | ||
2893 | } | ||
2894 | |||
2871 | static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) | 2895 | static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) |
2872 | { | 2896 | { |
2873 | struct mlx5_ib_dev *dev = to_mdev(flow_id->qp->device); | 2897 | struct mlx5_ib_dev *dev = to_mdev(flow_id->qp->device); |
@@ -2887,8 +2911,11 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) | |||
2887 | 2911 | ||
2888 | mlx5_del_flow_rules(handler->rule); | 2912 | mlx5_del_flow_rules(handler->rule); |
2889 | put_flow_table(dev, handler->prio, true); | 2913 | put_flow_table(dev, handler->prio, true); |
2890 | mutex_unlock(&dev->flow_db->lock); | 2914 | if (handler->ibcounters && |
2915 | atomic_read(&handler->ibcounters->usecnt) == 1) | ||
2916 | counters_clear_description(handler->ibcounters); | ||
2891 | 2917 | ||
2918 | mutex_unlock(&dev->flow_db->lock); | ||
2892 | kfree(handler); | 2919 | kfree(handler); |
2893 | 2920 | ||
2894 | return 0; | 2921 | return 0; |
@@ -3008,21 +3035,127 @@ static void set_underlay_qp(struct mlx5_ib_dev *dev, | |||
3008 | } | 3035 | } |
3009 | } | 3036 | } |
3010 | 3037 | ||
3038 | static int counters_set_description(struct ib_counters *counters, | ||
3039 | enum mlx5_ib_counters_type counters_type, | ||
3040 | struct mlx5_ib_flow_counters_desc *desc_data, | ||
3041 | u32 ncounters) | ||
3042 | { | ||
3043 | struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); | ||
3044 | u32 cntrs_max_index = 0; | ||
3045 | int i; | ||
3046 | |||
3047 | if (counters_type != MLX5_IB_COUNTERS_FLOW) | ||
3048 | return -EINVAL; | ||
3049 | |||
3050 | /* init the fields for the object */ | ||
3051 | mcounters->type = counters_type; | ||
3052 | mcounters->ncounters = ncounters; | ||
3053 | /* each counter entry have both description and index pair */ | ||
3054 | for (i = 0; i < ncounters; i++) { | ||
3055 | if (desc_data[i].description > IB_COUNTER_BYTES) | ||
3056 | return -EINVAL; | ||
3057 | |||
3058 | if (cntrs_max_index <= desc_data[i].index) | ||
3059 | cntrs_max_index = desc_data[i].index + 1; | ||
3060 | } | ||
3061 | |||
3062 | mutex_lock(&mcounters->mcntrs_mutex); | ||
3063 | mcounters->counters_data = desc_data; | ||
3064 | mcounters->cntrs_max_index = cntrs_max_index; | ||
3065 | mutex_unlock(&mcounters->mcntrs_mutex); | ||
3066 | |||
3067 | return 0; | ||
3068 | } | ||
3069 | |||
3070 | #define MAX_COUNTERS_NUM (USHRT_MAX / (sizeof(u32) * 2)) | ||
3071 | static int flow_counters_set_data(struct ib_counters *ibcounters, | ||
3072 | struct mlx5_ib_create_flow *ucmd) | ||
3073 | { | ||
3074 | struct mlx5_ib_mcounters *mcounters = to_mcounters(ibcounters); | ||
3075 | struct mlx5_ib_flow_counters_data *cntrs_data = NULL; | ||
3076 | struct mlx5_ib_flow_counters_desc *desc_data = NULL; | ||
3077 | bool hw_hndl = false; | ||
3078 | int ret = 0; | ||
3079 | |||
3080 | if (ucmd && ucmd->ncounters_data != 0) { | ||
3081 | cntrs_data = ucmd->data; | ||
3082 | if (cntrs_data->ncounters > MAX_COUNTERS_NUM) | ||
3083 | return -EINVAL; | ||
3084 | |||
3085 | desc_data = kcalloc(cntrs_data->ncounters, | ||
3086 | sizeof(*desc_data), | ||
3087 | GFP_KERNEL); | ||
3088 | if (!desc_data) | ||
3089 | return -ENOMEM; | ||
3090 | |||
3091 | if (copy_from_user(desc_data, | ||
3092 | u64_to_user_ptr(cntrs_data->counters_data), | ||
3093 | sizeof(*desc_data) * cntrs_data->ncounters)) { | ||
3094 | ret = -EFAULT; | ||
3095 | goto free; | ||
3096 | } | ||
3097 | } | ||
3098 | |||
3099 | if (!mcounters->hw_cntrs_hndl) { | ||
3100 | mcounters->hw_cntrs_hndl = mlx5_fc_create( | ||
3101 | to_mdev(ibcounters->device)->mdev, false); | ||
3102 | if (!mcounters->hw_cntrs_hndl) { | ||
3103 | ret = -ENOMEM; | ||
3104 | goto free; | ||
3105 | } | ||
3106 | hw_hndl = true; | ||
3107 | } | ||
3108 | |||
3109 | if (desc_data) { | ||
3110 | /* counters already bound to at least one flow */ | ||
3111 | if (mcounters->cntrs_max_index) { | ||
3112 | ret = -EINVAL; | ||
3113 | goto free_hndl; | ||
3114 | } | ||
3115 | |||
3116 | ret = counters_set_description(ibcounters, | ||
3117 | MLX5_IB_COUNTERS_FLOW, | ||
3118 | desc_data, | ||
3119 | cntrs_data->ncounters); | ||
3120 | if (ret) | ||
3121 | goto free_hndl; | ||
3122 | |||
3123 | } else if (!mcounters->cntrs_max_index) { | ||
3124 | /* counters not bound yet, must have udata passed */ | ||
3125 | ret = -EINVAL; | ||
3126 | goto free_hndl; | ||
3127 | } | ||
3128 | |||
3129 | return 0; | ||
3130 | |||
3131 | free_hndl: | ||
3132 | if (hw_hndl) { | ||
3133 | mlx5_fc_destroy(to_mdev(ibcounters->device)->mdev, | ||
3134 | mcounters->hw_cntrs_hndl); | ||
3135 | mcounters->hw_cntrs_hndl = NULL; | ||
3136 | } | ||
3137 | free: | ||
3138 | kfree(desc_data); | ||
3139 | return ret; | ||
3140 | } | ||
3141 | |||
3011 | static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, | 3142 | static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, |
3012 | struct mlx5_ib_flow_prio *ft_prio, | 3143 | struct mlx5_ib_flow_prio *ft_prio, |
3013 | const struct ib_flow_attr *flow_attr, | 3144 | const struct ib_flow_attr *flow_attr, |
3014 | struct mlx5_flow_destination *dst, | 3145 | struct mlx5_flow_destination *dst, |
3015 | u32 underlay_qpn) | 3146 | u32 underlay_qpn, |
3147 | struct mlx5_ib_create_flow *ucmd) | ||
3016 | { | 3148 | { |
3017 | struct mlx5_flow_table *ft = ft_prio->flow_table; | 3149 | struct mlx5_flow_table *ft = ft_prio->flow_table; |
3018 | struct mlx5_ib_flow_handler *handler; | 3150 | struct mlx5_ib_flow_handler *handler; |
3019 | struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG}; | 3151 | struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG}; |
3020 | struct mlx5_flow_spec *spec; | 3152 | struct mlx5_flow_spec *spec; |
3021 | struct mlx5_flow_destination *rule_dst = dst; | 3153 | struct mlx5_flow_destination dest_arr[2] = {}; |
3154 | struct mlx5_flow_destination *rule_dst = dest_arr; | ||
3022 | const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr); | 3155 | const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr); |
3023 | unsigned int spec_index; | 3156 | unsigned int spec_index; |
3024 | int err = 0; | 3157 | int err = 0; |
3025 | int dest_num = 1; | 3158 | int dest_num = 0; |
3026 | bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; | 3159 | bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; |
3027 | 3160 | ||
3028 | if (!is_valid_attr(dev->mdev, flow_attr)) | 3161 | if (!is_valid_attr(dev->mdev, flow_attr)) |
@@ -3036,6 +3169,10 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, | |||
3036 | } | 3169 | } |
3037 | 3170 | ||
3038 | INIT_LIST_HEAD(&handler->list); | 3171 | INIT_LIST_HEAD(&handler->list); |
3172 | if (dst) { | ||
3173 | memcpy(&dest_arr[0], dst, sizeof(*dst)); | ||
3174 | dest_num++; | ||
3175 | } | ||
3039 | 3176 | ||
3040 | for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { | 3177 | for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { |
3041 | err = parse_flow_attr(dev->mdev, spec->match_criteria, | 3178 | err = parse_flow_attr(dev->mdev, spec->match_criteria, |
@@ -3070,15 +3207,30 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, | |||
3070 | goto free; | 3207 | goto free; |
3071 | } | 3208 | } |
3072 | 3209 | ||
3210 | if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { | ||
3211 | err = flow_counters_set_data(flow_act.counters, ucmd); | ||
3212 | if (err) | ||
3213 | goto free; | ||
3214 | |||
3215 | handler->ibcounters = flow_act.counters; | ||
3216 | dest_arr[dest_num].type = | ||
3217 | MLX5_FLOW_DESTINATION_TYPE_COUNTER; | ||
3218 | dest_arr[dest_num].counter = | ||
3219 | to_mcounters(flow_act.counters)->hw_cntrs_hndl; | ||
3220 | dest_num++; | ||
3221 | } | ||
3222 | |||
3073 | if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) { | 3223 | if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) { |
3074 | rule_dst = NULL; | 3224 | if (!(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) { |
3075 | dest_num = 0; | 3225 | rule_dst = NULL; |
3226 | dest_num = 0; | ||
3227 | } | ||
3076 | } else { | 3228 | } else { |
3077 | if (is_egress) | 3229 | if (is_egress) |
3078 | flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; | 3230 | flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; |
3079 | else | 3231 | else |
3080 | flow_act.action |= | 3232 | flow_act.action |= |
3081 | dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST : | 3233 | dest_num ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST : |
3082 | MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; | 3234 | MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; |
3083 | } | 3235 | } |
3084 | 3236 | ||
@@ -3104,8 +3256,12 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, | |||
3104 | 3256 | ||
3105 | ft_prio->flow_table = ft; | 3257 | ft_prio->flow_table = ft; |
3106 | free: | 3258 | free: |
3107 | if (err) | 3259 | if (err && handler) { |
3260 | if (handler->ibcounters && | ||
3261 | atomic_read(&handler->ibcounters->usecnt) == 1) | ||
3262 | counters_clear_description(handler->ibcounters); | ||
3108 | kfree(handler); | 3263 | kfree(handler); |
3264 | } | ||
3109 | kvfree(spec); | 3265 | kvfree(spec); |
3110 | return err ? ERR_PTR(err) : handler; | 3266 | return err ? ERR_PTR(err) : handler; |
3111 | } | 3267 | } |
@@ -3115,7 +3271,7 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, | |||
3115 | const struct ib_flow_attr *flow_attr, | 3271 | const struct ib_flow_attr *flow_attr, |
3116 | struct mlx5_flow_destination *dst) | 3272 | struct mlx5_flow_destination *dst) |
3117 | { | 3273 | { |
3118 | return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0); | 3274 | return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL); |
3119 | } | 3275 | } |
3120 | 3276 | ||
3121 | static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev, | 3277 | static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev, |
@@ -3255,12 +3411,43 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, | |||
3255 | struct mlx5_ib_flow_prio *ft_prio_tx = NULL; | 3411 | struct mlx5_ib_flow_prio *ft_prio_tx = NULL; |
3256 | struct mlx5_ib_flow_prio *ft_prio; | 3412 | struct mlx5_ib_flow_prio *ft_prio; |
3257 | bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; | 3413 | bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; |
3414 | struct mlx5_ib_create_flow *ucmd = NULL, ucmd_hdr; | ||
3415 | size_t min_ucmd_sz, required_ucmd_sz; | ||
3258 | int err; | 3416 | int err; |
3259 | int underlay_qpn; | 3417 | int underlay_qpn; |
3260 | 3418 | ||
3261 | if (udata && | 3419 | if (udata && udata->inlen) { |
3262 | udata->inlen && !ib_is_udata_cleared(udata, 0, udata->inlen)) | 3420 | min_ucmd_sz = offsetof(typeof(ucmd_hdr), reserved) + |
3263 | return ERR_PTR(-EOPNOTSUPP); | 3421 | sizeof(ucmd_hdr.reserved); |
3422 | if (udata->inlen < min_ucmd_sz) | ||
3423 | return ERR_PTR(-EOPNOTSUPP); | ||
3424 | |||
3425 | err = ib_copy_from_udata(&ucmd_hdr, udata, min_ucmd_sz); | ||
3426 | if (err) | ||
3427 | return ERR_PTR(err); | ||
3428 | |||
3429 | /* currently supports only one counters data */ | ||
3430 | if (ucmd_hdr.ncounters_data > 1) | ||
3431 | return ERR_PTR(-EINVAL); | ||
3432 | |||
3433 | required_ucmd_sz = min_ucmd_sz + | ||
3434 | sizeof(struct mlx5_ib_flow_counters_data) * | ||
3435 | ucmd_hdr.ncounters_data; | ||
3436 | if (udata->inlen > required_ucmd_sz && | ||
3437 | !ib_is_udata_cleared(udata, required_ucmd_sz, | ||
3438 | udata->inlen - required_ucmd_sz)) | ||
3439 | return ERR_PTR(-EOPNOTSUPP); | ||
3440 | |||
3441 | ucmd = kzalloc(required_ucmd_sz, GFP_KERNEL); | ||
3442 | if (!ucmd) | ||
3443 | return ERR_PTR(-ENOMEM); | ||
3444 | |||
3445 | err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz); | ||
3446 | if (err) { | ||
3447 | kfree(ucmd); | ||
3448 | return ERR_PTR(err); | ||
3449 | } | ||
3450 | } | ||
3264 | 3451 | ||
3265 | if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) | 3452 | if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) |
3266 | return ERR_PTR(-ENOMEM); | 3453 | return ERR_PTR(-ENOMEM); |
@@ -3315,7 +3502,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, | |||
3315 | underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ? | 3502 | underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ? |
3316 | mqp->underlay_qpn : 0; | 3503 | mqp->underlay_qpn : 0; |
3317 | handler = _create_flow_rule(dev, ft_prio, flow_attr, | 3504 | handler = _create_flow_rule(dev, ft_prio, flow_attr, |
3318 | dst, underlay_qpn); | 3505 | dst, underlay_qpn, ucmd); |
3319 | } | 3506 | } |
3320 | } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || | 3507 | } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || |
3321 | flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { | 3508 | flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { |
@@ -3336,6 +3523,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, | |||
3336 | 3523 | ||
3337 | mutex_unlock(&dev->flow_db->lock); | 3524 | mutex_unlock(&dev->flow_db->lock); |
3338 | kfree(dst); | 3525 | kfree(dst); |
3526 | kfree(ucmd); | ||
3339 | 3527 | ||
3340 | return &handler->ibflow; | 3528 | return &handler->ibflow; |
3341 | 3529 | ||
@@ -3346,6 +3534,7 @@ destroy_ft: | |||
3346 | unlock: | 3534 | unlock: |
3347 | mutex_unlock(&dev->flow_db->lock); | 3535 | mutex_unlock(&dev->flow_db->lock); |
3348 | kfree(dst); | 3536 | kfree(dst); |
3537 | kfree(ucmd); | ||
3349 | kfree(handler); | 3538 | kfree(handler); |
3350 | return ERR_PTR(err); | 3539 | return ERR_PTR(err); |
3351 | } | 3540 | } |
@@ -5010,6 +5199,11 @@ static int mlx5_ib_destroy_counters(struct ib_counters *counters) | |||
5010 | { | 5199 | { |
5011 | struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); | 5200 | struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); |
5012 | 5201 | ||
5202 | counters_clear_description(counters); | ||
5203 | if (mcounters->hw_cntrs_hndl) | ||
5204 | mlx5_fc_destroy(to_mdev(counters->device)->mdev, | ||
5205 | mcounters->hw_cntrs_hndl); | ||
5206 | |||
5013 | kfree(mcounters); | 5207 | kfree(mcounters); |
5014 | 5208 | ||
5015 | return 0; | 5209 | return 0; |
@@ -5024,6 +5218,8 @@ static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device, | |||
5024 | if (!mcounters) | 5218 | if (!mcounters) |
5025 | return ERR_PTR(-ENOMEM); | 5219 | return ERR_PTR(-ENOMEM); |
5026 | 5220 | ||
5221 | mutex_init(&mcounters->mcntrs_mutex); | ||
5222 | |||
5027 | return &mcounters->ibcntrs; | 5223 | return &mcounters->ibcntrs; |
5028 | } | 5224 | } |
5029 | 5225 | ||
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index fd27ec1aed08..155bca627222 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
@@ -175,6 +175,7 @@ struct mlx5_ib_flow_handler { | |||
175 | struct ib_flow ibflow; | 175 | struct ib_flow ibflow; |
176 | struct mlx5_ib_flow_prio *prio; | 176 | struct mlx5_ib_flow_prio *prio; |
177 | struct mlx5_flow_handle *rule; | 177 | struct mlx5_flow_handle *rule; |
178 | struct ib_counters *ibcounters; | ||
178 | }; | 179 | }; |
179 | 180 | ||
180 | struct mlx5_ib_flow_db { | 181 | struct mlx5_ib_flow_db { |
@@ -813,8 +814,22 @@ struct mlx5_memic { | |||
813 | DECLARE_BITMAP(memic_alloc_pages, MLX5_MAX_MEMIC_PAGES); | 814 | DECLARE_BITMAP(memic_alloc_pages, MLX5_MAX_MEMIC_PAGES); |
814 | }; | 815 | }; |
815 | 816 | ||
817 | enum mlx5_ib_counters_type { | ||
818 | MLX5_IB_COUNTERS_FLOW, | ||
819 | }; | ||
820 | |||
816 | struct mlx5_ib_mcounters { | 821 | struct mlx5_ib_mcounters { |
817 | struct ib_counters ibcntrs; | 822 | struct ib_counters ibcntrs; |
823 | enum mlx5_ib_counters_type type; | ||
824 | void *hw_cntrs_hndl; | ||
825 | /* max index set as part of create_flow */ | ||
826 | u32 cntrs_max_index; | ||
827 | /* number of counters data entries (<description,index> pair) */ | ||
828 | u32 ncounters; | ||
829 | /* counters data array for descriptions and indexes */ | ||
830 | struct mlx5_ib_flow_counters_desc *counters_data; | ||
831 | /* protects access to mcounters internal data */ | ||
832 | struct mutex mcntrs_mutex; | ||
818 | }; | 833 | }; |
819 | 834 | ||
820 | static inline struct mlx5_ib_mcounters * | 835 | static inline struct mlx5_ib_mcounters * |
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index 3b4c3298061c..757b4a30281e 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h | |||
@@ -160,6 +160,7 @@ struct mlx5_flow_act { | |||
160 | u32 modify_id; | 160 | u32 modify_id; |
161 | uintptr_t esp_id; | 161 | uintptr_t esp_id; |
162 | struct mlx5_fs_vlan vlan; | 162 | struct mlx5_fs_vlan vlan; |
163 | struct ib_counters *counters; | ||
163 | }; | 164 | }; |
164 | 165 | ||
165 | #define MLX5_DECLARE_FLOW_ACT(name) \ | 166 | #define MLX5_DECLARE_FLOW_ACT(name) \ |
diff --git a/include/uapi/rdma/mlx5-abi.h b/include/uapi/rdma/mlx5-abi.h index cb4a02c4a1ce..ab71e939eb78 100644 --- a/include/uapi/rdma/mlx5-abi.h +++ b/include/uapi/rdma/mlx5-abi.h | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include <linux/types.h> | 37 | #include <linux/types.h> |
38 | #include <linux/if_ether.h> /* For ETH_ALEN. */ | 38 | #include <linux/if_ether.h> /* For ETH_ALEN. */ |
39 | #include <rdma/ib_user_ioctl_verbs.h> | ||
39 | 40 | ||
40 | enum { | 41 | enum { |
41 | MLX5_QP_FLAG_SIGNATURE = 1 << 0, | 42 | MLX5_QP_FLAG_SIGNATURE = 1 << 0, |
@@ -441,4 +442,27 @@ enum { | |||
441 | enum { | 442 | enum { |
442 | MLX5_IB_CLOCK_INFO_V1 = 0, | 443 | MLX5_IB_CLOCK_INFO_V1 = 0, |
443 | }; | 444 | }; |
445 | |||
446 | struct mlx5_ib_flow_counters_desc { | ||
447 | __u32 description; | ||
448 | __u32 index; | ||
449 | }; | ||
450 | |||
451 | struct mlx5_ib_flow_counters_data { | ||
452 | RDMA_UAPI_PTR(struct mlx5_ib_flow_counters_desc *, counters_data); | ||
453 | __u32 ncounters; | ||
454 | __u32 reserved; | ||
455 | }; | ||
456 | |||
457 | struct mlx5_ib_create_flow { | ||
458 | __u32 ncounters_data; | ||
459 | __u32 reserved; | ||
460 | /* | ||
461 | * Following are counters data based on ncounters_data, each | ||
462 | * entry in the data[] should match a corresponding counter object | ||
463 | * that was pointed by a counters spec upon the flow creation | ||
464 | */ | ||
465 | struct mlx5_ib_flow_counters_data data[]; | ||
466 | }; | ||
467 | |||
444 | #endif /* MLX5_ABI_USER_H */ | 468 | #endif /* MLX5_ABI_USER_H */ |