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 (dev->data->queue_pairs[qp_id] != NULL) 171 rte_free(dev->data->queue_pairs[qp_id]); 172 173 return 0; 174 } 175 176 /** Create a ring to place process packets on */ 177 static struct rte_ring * 178 isal_comp_pmd_qp_create_processed_pkts_ring(struct isal_comp_qp *qp, 179 unsigned int ring_size, int socket_id) 180 { 181 struct rte_ring *r; 182 183 r = rte_ring_lookup(qp->name); 184 if (r) { 185 if (rte_ring_get_size(r) >= ring_size) { 186 ISAL_PMD_LOG(DEBUG, 187 "Reusing existing ring %s for processed packets", 188 qp->name); 189 return r; 190 } 191 192 ISAL_PMD_LOG(ERR, 193 "Unable to reuse existing ring %s" 194 " for processed packets", 195 qp->name); 196 return NULL; 197 } 198 199 return rte_ring_create(qp->name, ring_size, socket_id, 200 RING_F_SP_ENQ | RING_F_SC_DEQ); 201 } 202 203 /** set a unique name for the queue pair based on its name, dev_id and qp_id */ 204 static int 205 isal_comp_pmd_qp_set_unique_name(struct rte_compressdev *dev, 206 struct isal_comp_qp *qp) 207 { 208 unsigned int n = snprintf(qp->name, sizeof(qp->name), 209 "isal_compression_pmd_%u_qp_%u", 210 dev->data->dev_id, qp->id); 211 212 if (n >= sizeof(qp->name)) 213 return -1; 214 215 return 0; 216 } 217 218 /* Setup a queue pair */ 219 static int 220 isal_comp_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id, 221 uint32_t max_inflight_ops, int socket_id) 222 { 223 struct isal_comp_qp *qp = NULL; 224 int retval; 225 226 /* Free memory prior to re-allocation if needed. */ 227 if (dev->data->queue_pairs[qp_id] != NULL) 228 isal_comp_pmd_qp_release(dev, qp_id); 229 230 /* Allocate the queue pair data structure. */ 231 qp = rte_zmalloc_socket("Isa-l compression PMD Queue Pair", sizeof(*qp), 232 RTE_CACHE_LINE_SIZE, socket_id); 233 if (qp == NULL) { 234 ISAL_PMD_LOG(ERR, "Failed to allocate queue pair memory"); 235 return (-ENOMEM); 236 } 237 238 /* Initialize memory for compression stream structure */ 239 qp->stream = rte_zmalloc_socket("Isa-l compression stream ", 240 sizeof(struct isal_zstream), RTE_CACHE_LINE_SIZE, 241 socket_id); 242 243 /* Initialize memory for compression level buffer */ 244 qp->stream->level_buf = rte_zmalloc_socket("Isa-l compression lev_buf", 245 ISAL_DEF_LVL3_DEFAULT, RTE_CACHE_LINE_SIZE, 246 socket_id); 247 248 /* Initialize memory for decompression state structure */ 249 qp->state = rte_zmalloc_socket("Isa-l decompression state", 250 sizeof(struct inflate_state), RTE_CACHE_LINE_SIZE, 251 socket_id); 252 253 qp->id = qp_id; 254 dev->data->queue_pairs[qp_id] = qp; 255 256 retval = isal_comp_pmd_qp_set_unique_name(dev, qp); 257 if (retval) { 258 ISAL_PMD_LOG(ERR, "Failed to create unique name for isal " 259 "compression device"); 260 goto qp_setup_cleanup; 261 } 262 263 qp->processed_pkts = isal_comp_pmd_qp_create_processed_pkts_ring(qp, 264 max_inflight_ops, socket_id); 265 if (qp->processed_pkts == NULL) { 266 ISAL_PMD_LOG(ERR, "Failed to create unique name for isal " 267 "compression device"); 268 goto qp_setup_cleanup; 269 } 270 271 qp->num_free_elements = rte_ring_free_count(qp->processed_pkts); 272 273 memset(&qp->qp_stats, 0, sizeof(qp->qp_stats)); 274 return 0; 275 276 qp_setup_cleanup: 277 if (qp) 278 rte_free(qp); 279 280 return -1; 281 } 282 283 /** Set private xform data*/ 284 static int 285 isal_comp_pmd_priv_xform_create(struct rte_compressdev *dev, 286 const struct rte_comp_xform *xform, void **priv_xform) 287 { 288 int ret; 289 struct isal_comp_private *internals = dev->data->dev_private; 290 291 if (xform == NULL) { 292 ISAL_PMD_LOG(ERR, "Invalid Xform struct"); 293 return -EINVAL; 294 } 295 296 if (rte_mempool_get(internals->priv_xform_mp, priv_xform)) { 297 ISAL_PMD_LOG(ERR, 298 "Couldn't get object from private xform mempool"); 299 return -ENOMEM; 300 } 301 302 ret = isal_comp_set_priv_xform_parameters(*priv_xform, xform); 303 if (ret != 0) { 304 ISAL_PMD_LOG(ERR, "Failed to configure private xform parameters"); 305 306 /* Return private xform to mempool */ 307 rte_mempool_put(internals->priv_xform_mp, priv_xform); 308 return ret; 309 } 310 return 0; 311 } 312 313 /** Clear memory of the private xform so it doesn't leave key material behind */ 314 static int 315 isal_comp_pmd_priv_xform_free(struct rte_compressdev *dev, void *priv_xform) 316 { 317 struct isal_comp_private *internals = dev->data->dev_private; 318 319 /* Zero out the whole structure */ 320 if (priv_xform) { 321 memset(priv_xform, 0, sizeof(struct isal_priv_xform)); 322 rte_mempool_put(internals->priv_xform_mp, priv_xform); 323 } 324 return 0; 325 } 326 327 struct rte_compressdev_ops isal_pmd_ops = { 328 .dev_configure = isal_comp_pmd_config, 329 .dev_start = isal_comp_pmd_start, 330 .dev_stop = isal_comp_pmd_stop, 331 .dev_close = isal_comp_pmd_close, 332 333 .stats_get = isal_comp_pmd_stats_get, 334 .stats_reset = isal_comp_pmd_stats_reset, 335 336 .dev_infos_get = isal_comp_pmd_info_get, 337 338 .queue_pair_setup = isal_comp_pmd_qp_setup, 339 .queue_pair_release = isal_comp_pmd_qp_release, 340 341 .private_xform_create = isal_comp_pmd_priv_xform_create, 342 .private_xform_free = isal_comp_pmd_priv_xform_free, 343 }; 344 345 struct rte_compressdev_ops *isal_compress_pmd_ops = &isal_pmd_ops; 346