1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 5 #include <rte_log.h> 6 #include <rte_errno.h> 7 #include <rte_malloc.h> 8 #include <rte_regexdev.h> 9 #include <rte_regexdev_core.h> 10 #include <rte_regexdev_driver.h> 11 #include <sys/mman.h> 12 13 #include <mlx5_glue.h> 14 #include <mlx5_devx_cmds.h> 15 #include <mlx5_prm.h> 16 #include <mlx5_common_os.h> 17 18 #include "mlx5_regex.h" 19 #include "mlx5_regex_utils.h" 20 #include "mlx5_rxp_csrs.h" 21 #include "mlx5_rxp.h" 22 23 #define MLX5_REGEX_MAX_MATCHES MLX5_RXP_MAX_MATCHES 24 #define MLX5_REGEX_MAX_PAYLOAD_SIZE MLX5_RXP_MAX_JOB_LENGTH 25 #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT32_MAX 26 #define MLX5_REGEX_MAX_GROUPS MLX5_RXP_MAX_SUBSETS 27 28 #define MLX5_REGEX_RXP_ROF2_LINE_LEN 34 29 30 /* Private Declarations */ 31 static int 32 rxp_create_mkey(struct mlx5_regex_priv *priv, void *ptr, size_t size, 33 uint32_t access, struct mlx5_regex_mkey *mkey); 34 static inline void 35 rxp_destroy_mkey(struct mlx5_regex_mkey *mkey); 36 37 int 38 mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused, 39 struct rte_regexdev_info *info) 40 { 41 info->max_matches = MLX5_REGEX_MAX_MATCHES; 42 info->max_payload_size = MLX5_REGEX_MAX_PAYLOAD_SIZE; 43 info->max_rules_per_group = MLX5_REGEX_MAX_RULES_PER_GROUP; 44 info->max_groups = MLX5_REGEX_MAX_GROUPS; 45 info->regexdev_capa = RTE_REGEXDEV_SUPP_PCRE_GREEDY_F | 46 RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F; 47 info->rule_flags = 0; 48 info->max_queue_pairs = UINT16_MAX; 49 return 0; 50 } 51 52 static int 53 rxp_create_mkey(struct mlx5_regex_priv *priv, void *ptr, size_t size, 54 uint32_t access, struct mlx5_regex_mkey *mkey) 55 { 56 struct mlx5_devx_mkey_attr mkey_attr; 57 58 /* Register the memory. */ 59 mkey->umem = mlx5_glue->devx_umem_reg(priv->cdev->ctx, ptr, size, access); 60 if (!mkey->umem) { 61 DRV_LOG(ERR, "Failed to register memory!"); 62 return -ENODEV; 63 } 64 /* Create mkey */ 65 mkey_attr = (struct mlx5_devx_mkey_attr) { 66 .addr = (uintptr_t)ptr, 67 .size = (uint32_t)size, 68 .umem_id = mlx5_os_get_umem_id(mkey->umem), 69 .pg_access = 1, 70 .umr_en = 0, 71 }; 72 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 73 mkey_attr.pd = priv->cdev->pdn; 74 #endif 75 mkey->mkey = mlx5_devx_cmd_mkey_create(priv->cdev->ctx, &mkey_attr); 76 if (!mkey->mkey) { 77 DRV_LOG(ERR, "Failed to create direct mkey!"); 78 return -ENODEV; 79 } 80 return 0; 81 } 82 83 static inline void 84 rxp_destroy_mkey(struct mlx5_regex_mkey *mkey) 85 { 86 if (mkey->mkey) 87 claim_zero(mlx5_devx_cmd_destroy(mkey->mkey)); 88 if (mkey->umem) 89 claim_zero(mlx5_glue->devx_umem_dereg(mkey->umem)); 90 } 91 92 int 93 mlx5_regex_rules_db_import(struct rte_regexdev *dev, 94 const char *rule_db, uint32_t rule_db_len) 95 { 96 struct mlx5_regex_priv *priv = dev->data->dev_private; 97 struct mlx5_regex_mkey mkey; 98 uint32_t id; 99 int ret; 100 void *ptr; 101 102 if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) { 103 DRV_LOG(ERR, "RXP programming mode not set!"); 104 return -1; 105 } 106 if (rule_db == NULL) { 107 DRV_LOG(ERR, "Database empty!"); 108 return -ENODEV; 109 } 110 if (rule_db_len == 0) 111 return -EINVAL; 112 /* copy rules - rules have to be 4KB aligned. */ 113 ptr = rte_malloc("", rule_db_len, 1 << 12); 114 if (!ptr) { 115 DRV_LOG(ERR, "Failed to allocate rules file memory."); 116 return -ENOMEM; 117 } 118 rte_memcpy(ptr, rule_db, rule_db_len); 119 /* Register umem and create rof mkey. */ 120 ret = rxp_create_mkey(priv, ptr, rule_db_len, /*access=*/7, &mkey); 121 if (ret < 0) 122 return ret; 123 124 for (id = 0; id < priv->nb_engines; id++) { 125 ret = mlx5_devx_regex_rules_program(priv->cdev->ctx, id, 126 mkey.mkey->id, rule_db_len, (uintptr_t)ptr); 127 if (ret < 0) { 128 DRV_LOG(ERR, "Failed to program rxp rules."); 129 ret = -ENODEV; 130 break; 131 } 132 ret = 0; 133 } 134 rxp_destroy_mkey(&mkey); 135 rte_free(ptr); 136 return ret; 137 } 138 139 int 140 mlx5_regex_configure(struct rte_regexdev *dev, 141 const struct rte_regexdev_config *cfg) 142 { 143 struct mlx5_regex_priv *priv = dev->data->dev_private; 144 int ret; 145 146 if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) 147 return -1; 148 priv->nb_queues = cfg->nb_queue_pairs; 149 dev->data->dev_conf.nb_queue_pairs = priv->nb_queues; 150 priv->qps = rte_zmalloc(NULL, sizeof(struct mlx5_regex_qp) * 151 priv->nb_queues, 0); 152 if (!priv->nb_queues) { 153 DRV_LOG(ERR, "can't allocate qps memory"); 154 rte_errno = ENOMEM; 155 return -rte_errno; 156 } 157 priv->nb_max_matches = cfg->nb_max_matches; 158 if (cfg->rule_db != NULL) { 159 ret = mlx5_regex_rules_db_import(dev, cfg->rule_db, 160 cfg->rule_db_len); 161 if (ret < 0) { 162 DRV_LOG(ERR, "Failed to program rxp rules."); 163 rte_errno = ENODEV; 164 goto configure_error; 165 } 166 } else 167 DRV_LOG(DEBUG, "Regex config without rules programming!"); 168 return 0; 169 configure_error: 170 if (priv->qps) 171 rte_free(priv->qps); 172 return -rte_errno; 173 } 174