1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Intel Corporation 3 */ 4 #include <isa-l.h> 5 6 #include <rte_common.h> 7 #include <rte_compressdev_pmd.h> 8 #include <rte_malloc.h> 9 10 #include "isal_compress_pmd_private.h" 11 12 static const struct rte_compressdev_capabilities isal_pmd_capabilities[] = { 13 { 14 .algo = RTE_COMP_ALGO_DEFLATE, 15 .comp_feature_flags = RTE_COMP_FF_SHAREABLE_PRIV_XFORM | 16 RTE_COMP_FF_HUFFMAN_FIXED | 17 RTE_COMP_FF_HUFFMAN_DYNAMIC, 18 .window_size = { 19 .min = 15, 20 .max = 15, 21 .increment = 0 22 }, 23 }, 24 RTE_COMP_END_OF_CAPABILITIES_LIST() 25 }; 26 27 /** Configure device */ 28 static int 29 isal_comp_pmd_config(struct rte_compressdev *dev, 30 struct rte_compressdev_config *config) 31 { 32 int ret = 0; 33 unsigned int n; 34 char mp_name[RTE_COMPRESSDEV_NAME_MAX_LEN]; 35 unsigned int elt_size = sizeof(struct isal_priv_xform); 36 struct isal_comp_private *internals = dev->data->dev_private; 37 38 n = snprintf(mp_name, sizeof(mp_name), "compdev_%d_xform_mp", 39 dev->data->dev_id); 40 if (n > sizeof(mp_name)) { 41 ISAL_PMD_LOG(ERR, 42 "Unable to create unique name for xform mempool"); 43 return -ENOMEM; 44 } 45 46 internals->priv_xform_mp = rte_mempool_lookup(mp_name); 47 48 if (internals->priv_xform_mp != NULL) { 49 if (((internals->priv_xform_mp)->elt_size != elt_size) || 50 ((internals->priv_xform_mp)->size < 51 config->max_nb_priv_xforms)) { 52 53 ISAL_PMD_LOG(ERR, "%s mempool already exists with different" 54 " initialization parameters", mp_name); 55 internals->priv_xform_mp = NULL; 56 return -ENOMEM; 57 } 58 } else { /* First time configuration */ 59 internals->priv_xform_mp = rte_mempool_create( 60 mp_name, /* mempool name */ 61 /* number of elements*/ 62 config->max_nb_priv_xforms, 63 elt_size, /* element size*/ 64 0, /* Cache size*/ 65 0, /* private data size */ 66 NULL, /* obj initialization constructor */ 67 NULL, /* obj initialization constructor arg */ 68 NULL, /**< obj constructor*/ 69 NULL, /* obj constructor arg */ 70 config->socket_id, /* socket id */ 71 0); /* flags */ 72 } 73 74 if (internals->priv_xform_mp == NULL) { 75 ISAL_PMD_LOG(ERR, "%s mempool allocation failed", mp_name); 76 return -ENOMEM; 77 } 78 79 dev->data->dev_private = internals; 80 81 return ret; 82 } 83 84 /** Start device */ 85 static int 86 isal_comp_pmd_start(__rte_unused struct rte_compressdev *dev) 87 { 88 return 0; 89 } 90 91 /** Stop device */ 92 static void 93 isal_comp_pmd_stop(__rte_unused struct rte_compressdev *dev) 94 { 95 } 96 97 /** Close device */ 98 static int 99 isal_comp_pmd_close(struct rte_compressdev *dev) 100 { 101 /* Free private data */ 102 struct isal_comp_private *internals = dev->data->dev_private; 103 104 rte_mempool_free(internals->priv_xform_mp); 105 return 0; 106 } 107 108 /** Get device statistics */ 109 static void 110 isal_comp_pmd_stats_get(struct rte_compressdev *dev, 111 struct rte_compressdev_stats *stats) 112 { 113 uint16_t qp_id; 114 115 for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 116 struct isal_comp_qp *qp = dev->data->queue_pairs[qp_id]; 117 118 stats->enqueued_count += qp->qp_stats.enqueued_count; 119 stats->dequeued_count += qp->qp_stats.dequeued_count; 120 121 stats->enqueue_err_count += qp->qp_stats.enqueue_err_count; 122 stats->dequeue_err_count += qp->qp_stats.dequeue_err_count; 123 } 124 } 125 126 /** Get device info */ 127 static void 128 isal_comp_pmd_info_get(struct rte_compressdev *dev __rte_unused, 129 struct rte_compressdev_info *dev_info) 130 { 131 if (dev_info != NULL) { 132 dev_info->capabilities = isal_pmd_capabilities; 133 dev_info->feature_flags = RTE_COMPDEV_FF_CPU_AVX512 | 134 RTE_COMPDEV_FF_CPU_AVX2 | 135 RTE_COMPDEV_FF_CPU_AVX | 136 RTE_COMPDEV_FF_CPU_SSE; 137 } 138 } 139 140 /** Reset device statistics */ 141 static void 142 isal_comp_pmd_stats_reset(struct rte_compressdev *dev) 143 { 144 uint16_t qp_id; 145 146 for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 147 struct isal_comp_qp *qp = dev->data->queue_pairs[qp_id]; 148 memset(&qp->qp_stats, 0, sizeof(qp->qp_stats)); 149 } 150 } 151 152 /** Release queue pair */ 153 static int 154 isal_comp_pmd_qp_release(struct rte_compressdev *dev, uint16_t qp_id) 155 { 156 struct isal_comp_qp *qp = dev->data->queue_pairs[qp_id]; 157 158 if (qp == NULL) 159 return -EINVAL; 160 161 if (qp->stream != NULL) 162 rte_free(qp->stream); 163 164 if (qp->stream->level_buf != NULL) 165 rte_free(qp->stream->level_buf); 166 167 if (qp->state != NULL) 168 rte_free(qp->state); 169 170 if (qp->processed_pkts != NULL) 171 rte_ring_free(qp->processed_pkts); 172 173 rte_free(qp); 174 dev->data->queue_pairs[qp_id] = NULL; 175 176 return 0; 177 } 178 179 /** Create a ring to place process packets on */ 180 static struct rte_ring * 181 isal_comp_pmd_qp_create_processed_pkts_ring(struct isal_comp_qp *qp, 182 unsigned int ring_size, int socket_id) 183 { 184 struct rte_ring *r; 185 186 r = rte_ring_lookup(qp->name); 187 if (r) { 188 if (rte_ring_get_size(r) >= ring_size) { 189 ISAL_PMD_LOG(DEBUG, 190 "Reusing existing ring %s for processed packets", 191 qp->name); 192 return r; 193 } 194 195 ISAL_PMD_LOG(ERR, 196 "Unable to reuse existing ring %s" 197 " for processed packets", 198 qp->name); 199 return NULL; 200 } 201 202 return rte_ring_create(qp->name, ring_size, socket_id, 203 RING_F_SP_ENQ | RING_F_SC_DEQ); 204 } 205 206 /** set a unique name for the queue pair based on its name, dev_id and qp_id */ 207 static int 208 isal_comp_pmd_qp_set_unique_name(struct rte_compressdev *dev, 209 struct isal_comp_qp *qp) 210 { 211 unsigned int n = snprintf(qp->name, sizeof(qp->name), 212 "isal_compression_pmd_%u_qp_%u", 213 dev->data->dev_id, qp->id); 214 215 if (n >= sizeof(qp->name)) 216 return -1; 217 218 return 0; 219 } 220 221 /* Setup a queue pair */ 222 static int 223 isal_comp_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id, 224 uint32_t max_inflight_ops, int socket_id) 225 { 226 struct isal_comp_qp *qp = NULL; 227 int retval; 228 229 /* Free memory prior to re-allocation if needed. */ 230 if (dev->data->queue_pairs[qp_id] != NULL) 231 isal_comp_pmd_qp_release(dev, qp_id); 232 233 /* Allocate the queue pair data structure. */ 234 qp = rte_zmalloc_socket("Isa-l compression PMD Queue Pair", sizeof(*qp), 235 RTE_CACHE_LINE_SIZE, socket_id); 236 if (qp == NULL) { 237 ISAL_PMD_LOG(ERR, "Failed to allocate queue pair memory"); 238 return (-ENOMEM); 239 } 240 241 /* Initialize memory for compression stream structure */ 242 qp->stream = rte_zmalloc_socket("Isa-l compression stream ", 243 sizeof(struct isal_zstream), RTE_CACHE_LINE_SIZE, 244 socket_id); 245 246 /* Initialize memory for compression level buffer */ 247 qp->stream->level_buf = rte_zmalloc_socket("Isa-l compression lev_buf", 248 ISAL_DEF_LVL3_DEFAULT, RTE_CACHE_LINE_SIZE, 249 socket_id); 250 251 /* Initialize memory for decompression state structure */ 252 qp->state = rte_zmalloc_socket("Isa-l decompression state", 253 sizeof(struct inflate_state), RTE_CACHE_LINE_SIZE, 254 socket_id); 255 256 qp->id = qp_id; 257 dev->data->queue_pairs[qp_id] = qp; 258 259 retval = isal_comp_pmd_qp_set_unique_name(dev, qp); 260 if (retval) { 261 ISAL_PMD_LOG(ERR, "Failed to create unique name for isal " 262 "compression device"); 263 goto qp_setup_cleanup; 264 } 265 266 qp->processed_pkts = isal_comp_pmd_qp_create_processed_pkts_ring(qp, 267 max_inflight_ops, socket_id); 268 if (qp->processed_pkts == NULL) { 269 ISAL_PMD_LOG(ERR, "Failed to create unique name for isal " 270 "compression device"); 271 goto qp_setup_cleanup; 272 } 273 274 qp->num_free_elements = rte_ring_free_count(qp->processed_pkts); 275 276 memset(&qp->qp_stats, 0, sizeof(qp->qp_stats)); 277 return 0; 278 279 qp_setup_cleanup: 280 if (qp) 281 rte_free(qp); 282 283 return -1; 284 } 285 286 /** Set private xform data*/ 287 static int 288 isal_comp_pmd_priv_xform_create(struct rte_compressdev *dev, 289 const struct rte_comp_xform *xform, void **priv_xform) 290 { 291 int ret; 292 struct isal_comp_private *internals = dev->data->dev_private; 293 294 if (xform == NULL) { 295 ISAL_PMD_LOG(ERR, "Invalid Xform struct"); 296 return -EINVAL; 297 } 298 299 if (rte_mempool_get(internals->priv_xform_mp, priv_xform)) { 300 ISAL_PMD_LOG(ERR, 301 "Couldn't get object from private xform mempool"); 302 return -ENOMEM; 303 } 304 305 ret = isal_comp_set_priv_xform_parameters(*priv_xform, xform); 306 if (ret != 0) { 307 ISAL_PMD_LOG(ERR, "Failed to configure private xform parameters"); 308 309 /* Return private xform to mempool */ 310 rte_mempool_put(internals->priv_xform_mp, priv_xform); 311 return ret; 312 } 313 return 0; 314 } 315 316 /** Clear memory of the private xform so it doesn't leave key material behind */ 317 static int 318 isal_comp_pmd_priv_xform_free(struct rte_compressdev *dev, void *priv_xform) 319 { 320 struct isal_comp_private *internals = dev->data->dev_private; 321 322 /* Zero out the whole structure */ 323 if (priv_xform) { 324 memset(priv_xform, 0, sizeof(struct isal_priv_xform)); 325 rte_mempool_put(internals->priv_xform_mp, priv_xform); 326 } 327 return 0; 328 } 329 330 struct rte_compressdev_ops isal_pmd_ops = { 331 .dev_configure = isal_comp_pmd_config, 332 .dev_start = isal_comp_pmd_start, 333 .dev_stop = isal_comp_pmd_stop, 334 .dev_close = isal_comp_pmd_close, 335 336 .stats_get = isal_comp_pmd_stats_get, 337 .stats_reset = isal_comp_pmd_stats_reset, 338 339 .dev_infos_get = isal_comp_pmd_info_get, 340 341 .queue_pair_setup = isal_comp_pmd_qp_setup, 342 .queue_pair_release = isal_comp_pmd_qp_release, 343 344 .private_xform_create = isal_comp_pmd_priv_xform_create, 345 .private_xform_free = isal_comp_pmd_priv_xform_free, 346 }; 347 348 struct rte_compressdev_ops *isal_compress_pmd_ops = &isal_pmd_ops; 349