127422fc3SAshish Gupta /* SPDX-License-Identifier: BSD-3-Clause 227422fc3SAshish Gupta * Copyright(c) 2018 Cavium Networks 327422fc3SAshish Gupta */ 427422fc3SAshish Gupta 527422fc3SAshish Gupta #include <string.h> 627422fc3SAshish Gupta 71acb7f54SDavid Marchand #include <dev_driver.h> 827422fc3SAshish Gupta #include <rte_common.h> 927422fc3SAshish Gupta #include <rte_malloc.h> 1027422fc3SAshish Gupta 1127422fc3SAshish Gupta #include "zlib_pmd_private.h" 1227422fc3SAshish Gupta 1327422fc3SAshish Gupta static const struct rte_compressdev_capabilities zlib_pmd_capabilities[] = { 1427422fc3SAshish Gupta { /* Deflate */ 1527422fc3SAshish Gupta .algo = RTE_COMP_ALGO_DEFLATE, 1627422fc3SAshish Gupta .comp_feature_flags = (RTE_COMP_FF_NONCOMPRESSED_BLOCKS | 1727422fc3SAshish Gupta RTE_COMP_FF_HUFFMAN_FIXED | 1827422fc3SAshish Gupta RTE_COMP_FF_HUFFMAN_DYNAMIC), 1927422fc3SAshish Gupta .window_size = { 2027422fc3SAshish Gupta .min = 8, 2127422fc3SAshish Gupta .max = 15, 2227422fc3SAshish Gupta .increment = 1 2327422fc3SAshish Gupta }, 2427422fc3SAshish Gupta }, 2527422fc3SAshish Gupta 2627422fc3SAshish Gupta RTE_COMP_END_OF_CAPABILITIES_LIST() 2727422fc3SAshish Gupta 2827422fc3SAshish Gupta }; 2927422fc3SAshish Gupta 3027422fc3SAshish Gupta /** Configure device */ 3127422fc3SAshish Gupta static int 3227422fc3SAshish Gupta zlib_pmd_config(struct rte_compressdev *dev, 3327422fc3SAshish Gupta struct rte_compressdev_config *config) 3427422fc3SAshish Gupta { 3527422fc3SAshish Gupta struct rte_mempool *mp; 3627422fc3SAshish Gupta char mp_name[RTE_MEMPOOL_NAMESIZE]; 3727422fc3SAshish Gupta struct zlib_private *internals = dev->data->dev_private; 3827422fc3SAshish Gupta 3927422fc3SAshish Gupta snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, 4027422fc3SAshish Gupta "stream_mp_%u", dev->data->dev_id); 4127422fc3SAshish Gupta mp = internals->mp; 4227422fc3SAshish Gupta if (mp == NULL) { 4327422fc3SAshish Gupta mp = rte_mempool_create(mp_name, 4427422fc3SAshish Gupta config->max_nb_priv_xforms + 4527422fc3SAshish Gupta config->max_nb_streams, 4627422fc3SAshish Gupta sizeof(struct zlib_priv_xform), 4727422fc3SAshish Gupta 0, 0, NULL, NULL, NULL, 4827422fc3SAshish Gupta NULL, config->socket_id, 4927422fc3SAshish Gupta 0); 5027422fc3SAshish Gupta if (mp == NULL) { 51*f665790aSDavid Marchand ZLIB_PMD_ERR("Cannot create private xform pool on socket %d", 52*f665790aSDavid Marchand config->socket_id); 5327422fc3SAshish Gupta return -ENOMEM; 5427422fc3SAshish Gupta } 5527422fc3SAshish Gupta internals->mp = mp; 5627422fc3SAshish Gupta } 5727422fc3SAshish Gupta return 0; 5827422fc3SAshish Gupta } 5927422fc3SAshish Gupta 6027422fc3SAshish Gupta /** Start device */ 6127422fc3SAshish Gupta static int 6227422fc3SAshish Gupta zlib_pmd_start(__rte_unused struct rte_compressdev *dev) 6327422fc3SAshish Gupta { 6427422fc3SAshish Gupta return 0; 6527422fc3SAshish Gupta } 6627422fc3SAshish Gupta 6727422fc3SAshish Gupta /** Stop device */ 6827422fc3SAshish Gupta static void 6927422fc3SAshish Gupta zlib_pmd_stop(__rte_unused struct rte_compressdev *dev) 7027422fc3SAshish Gupta { 7127422fc3SAshish Gupta } 7227422fc3SAshish Gupta 7327422fc3SAshish Gupta /** Close device */ 7427422fc3SAshish Gupta static int 7527422fc3SAshish Gupta zlib_pmd_close(struct rte_compressdev *dev) 7627422fc3SAshish Gupta { 7727422fc3SAshish Gupta struct zlib_private *internals = dev->data->dev_private; 7827422fc3SAshish Gupta rte_mempool_free(internals->mp); 7927422fc3SAshish Gupta internals->mp = NULL; 8027422fc3SAshish Gupta return 0; 8127422fc3SAshish Gupta } 8227422fc3SAshish Gupta 8327422fc3SAshish Gupta /** Get device statistics */ 8427422fc3SAshish Gupta static void 8527422fc3SAshish Gupta zlib_pmd_stats_get(struct rte_compressdev *dev, 8627422fc3SAshish Gupta struct rte_compressdev_stats *stats) 8727422fc3SAshish Gupta { 8827422fc3SAshish Gupta int qp_id; 8927422fc3SAshish Gupta 9027422fc3SAshish Gupta for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 9127422fc3SAshish Gupta struct zlib_qp *qp = dev->data->queue_pairs[qp_id]; 9227422fc3SAshish Gupta 9327422fc3SAshish Gupta stats->enqueued_count += qp->qp_stats.enqueued_count; 9427422fc3SAshish Gupta stats->dequeued_count += qp->qp_stats.dequeued_count; 9527422fc3SAshish Gupta 9627422fc3SAshish Gupta stats->enqueue_err_count += qp->qp_stats.enqueue_err_count; 9727422fc3SAshish Gupta stats->dequeue_err_count += qp->qp_stats.dequeue_err_count; 9827422fc3SAshish Gupta } 9927422fc3SAshish Gupta } 10027422fc3SAshish Gupta 10127422fc3SAshish Gupta /** Reset device statistics */ 10227422fc3SAshish Gupta static void 10327422fc3SAshish Gupta zlib_pmd_stats_reset(struct rte_compressdev *dev) 10427422fc3SAshish Gupta { 10527422fc3SAshish Gupta int qp_id; 10627422fc3SAshish Gupta 10727422fc3SAshish Gupta for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 10827422fc3SAshish Gupta struct zlib_qp *qp = dev->data->queue_pairs[qp_id]; 10927422fc3SAshish Gupta 11027422fc3SAshish Gupta memset(&qp->qp_stats, 0, sizeof(qp->qp_stats)); 11127422fc3SAshish Gupta } 11227422fc3SAshish Gupta } 11327422fc3SAshish Gupta 11427422fc3SAshish Gupta /** Get device info */ 11527422fc3SAshish Gupta static void 11627422fc3SAshish Gupta zlib_pmd_info_get(struct rte_compressdev *dev, 11727422fc3SAshish Gupta struct rte_compressdev_info *dev_info) 11827422fc3SAshish Gupta { 11927422fc3SAshish Gupta if (dev_info != NULL) { 12027422fc3SAshish Gupta dev_info->driver_name = dev->device->name; 12127422fc3SAshish Gupta dev_info->feature_flags = dev->feature_flags; 12227422fc3SAshish Gupta dev_info->capabilities = zlib_pmd_capabilities; 12327422fc3SAshish Gupta } 12427422fc3SAshish Gupta } 12527422fc3SAshish Gupta 12627422fc3SAshish Gupta /** Release queue pair */ 12727422fc3SAshish Gupta static int 12827422fc3SAshish Gupta zlib_pmd_qp_release(struct rte_compressdev *dev, uint16_t qp_id) 12927422fc3SAshish Gupta { 13027422fc3SAshish Gupta struct zlib_qp *qp = dev->data->queue_pairs[qp_id]; 13127422fc3SAshish Gupta 13227422fc3SAshish Gupta if (qp != NULL) { 13327422fc3SAshish Gupta rte_ring_free(qp->processed_pkts); 13427422fc3SAshish Gupta rte_free(qp); 13527422fc3SAshish Gupta dev->data->queue_pairs[qp_id] = NULL; 13627422fc3SAshish Gupta } 13727422fc3SAshish Gupta return 0; 13827422fc3SAshish Gupta } 13927422fc3SAshish Gupta 14027422fc3SAshish Gupta /** set a unique name for the queue pair based on its name, dev_id and qp_id */ 14127422fc3SAshish Gupta static int 14227422fc3SAshish Gupta zlib_pmd_qp_set_unique_name(struct rte_compressdev *dev, 14327422fc3SAshish Gupta struct zlib_qp *qp) 14427422fc3SAshish Gupta { 14527422fc3SAshish Gupta unsigned int n = snprintf(qp->name, sizeof(qp->name), 14627422fc3SAshish Gupta "zlib_pmd_%u_qp_%u", 14727422fc3SAshish Gupta dev->data->dev_id, qp->id); 14827422fc3SAshish Gupta 14927422fc3SAshish Gupta if (n >= sizeof(qp->name)) 15027422fc3SAshish Gupta return -1; 15127422fc3SAshish Gupta 15227422fc3SAshish Gupta return 0; 15327422fc3SAshish Gupta } 15427422fc3SAshish Gupta 15527422fc3SAshish Gupta /** Create a ring to place process packets on */ 15627422fc3SAshish Gupta static struct rte_ring * 15727422fc3SAshish Gupta zlib_pmd_qp_create_processed_pkts_ring(struct zlib_qp *qp, 15827422fc3SAshish Gupta unsigned int ring_size, int socket_id) 15927422fc3SAshish Gupta { 16027422fc3SAshish Gupta struct rte_ring *r = qp->processed_pkts; 16127422fc3SAshish Gupta 16227422fc3SAshish Gupta if (r) { 16327422fc3SAshish Gupta if (rte_ring_get_size(r) >= ring_size) { 16427422fc3SAshish Gupta ZLIB_PMD_INFO("Reusing existing ring %s for processed" 16527422fc3SAshish Gupta " packets", qp->name); 16627422fc3SAshish Gupta return r; 16727422fc3SAshish Gupta } 16827422fc3SAshish Gupta 16927422fc3SAshish Gupta ZLIB_PMD_ERR("Unable to reuse existing ring %s for processed" 17027422fc3SAshish Gupta " packets", qp->name); 17127422fc3SAshish Gupta return NULL; 17227422fc3SAshish Gupta } 17327422fc3SAshish Gupta 17427422fc3SAshish Gupta return rte_ring_create(qp->name, ring_size, socket_id, 17527422fc3SAshish Gupta RING_F_EXACT_SZ); 17627422fc3SAshish Gupta } 17727422fc3SAshish Gupta 17827422fc3SAshish Gupta /** Setup a queue pair */ 17927422fc3SAshish Gupta static int 18027422fc3SAshish Gupta zlib_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id, 18127422fc3SAshish Gupta uint32_t max_inflight_ops, int socket_id) 18227422fc3SAshish Gupta { 18327422fc3SAshish Gupta struct zlib_qp *qp = NULL; 18427422fc3SAshish Gupta 18527422fc3SAshish Gupta /* Free memory prior to re-allocation if needed. */ 18627422fc3SAshish Gupta if (dev->data->queue_pairs[qp_id] != NULL) 18727422fc3SAshish Gupta zlib_pmd_qp_release(dev, qp_id); 18827422fc3SAshish Gupta 18927422fc3SAshish Gupta /* Allocate the queue pair data structure. */ 19027422fc3SAshish Gupta qp = rte_zmalloc_socket("ZLIB PMD Queue Pair", sizeof(*qp), 19127422fc3SAshish Gupta RTE_CACHE_LINE_SIZE, socket_id); 19227422fc3SAshish Gupta if (qp == NULL) 19327422fc3SAshish Gupta return (-ENOMEM); 19427422fc3SAshish Gupta 19527422fc3SAshish Gupta qp->id = qp_id; 19627422fc3SAshish Gupta dev->data->queue_pairs[qp_id] = qp; 19727422fc3SAshish Gupta 19827422fc3SAshish Gupta if (zlib_pmd_qp_set_unique_name(dev, qp)) 19927422fc3SAshish Gupta goto qp_setup_cleanup; 20027422fc3SAshish Gupta 20127422fc3SAshish Gupta qp->processed_pkts = zlib_pmd_qp_create_processed_pkts_ring(qp, 20227422fc3SAshish Gupta max_inflight_ops, socket_id); 20327422fc3SAshish Gupta if (qp->processed_pkts == NULL) 20427422fc3SAshish Gupta goto qp_setup_cleanup; 20527422fc3SAshish Gupta 20627422fc3SAshish Gupta memset(&qp->qp_stats, 0, sizeof(qp->qp_stats)); 20727422fc3SAshish Gupta return 0; 20827422fc3SAshish Gupta 20927422fc3SAshish Gupta qp_setup_cleanup: 21027422fc3SAshish Gupta if (qp) { 21127422fc3SAshish Gupta rte_free(qp); 21227422fc3SAshish Gupta qp = NULL; 21327422fc3SAshish Gupta } 21427422fc3SAshish Gupta return -1; 21527422fc3SAshish Gupta } 21627422fc3SAshish Gupta 2170cc20d33SSunila Sahu /** Configure stream */ 2180cc20d33SSunila Sahu static int 2190cc20d33SSunila Sahu zlib_pmd_stream_create(struct rte_compressdev *dev, 2200cc20d33SSunila Sahu const struct rte_comp_xform *xform, 2210cc20d33SSunila Sahu void **zstream) 2220cc20d33SSunila Sahu { 2230cc20d33SSunila Sahu int ret = 0; 2240cc20d33SSunila Sahu struct zlib_stream *stream; 2250cc20d33SSunila Sahu struct zlib_private *internals = dev->data->dev_private; 2260cc20d33SSunila Sahu 2270cc20d33SSunila Sahu if (xform == NULL) { 2280cc20d33SSunila Sahu ZLIB_PMD_ERR("invalid xform struct"); 2290cc20d33SSunila Sahu return -EINVAL; 2300cc20d33SSunila Sahu } 2310cc20d33SSunila Sahu 2320cc20d33SSunila Sahu if (rte_mempool_get(internals->mp, zstream)) { 2330cc20d33SSunila Sahu ZLIB_PMD_ERR("Couldn't get object from session mempool"); 2340cc20d33SSunila Sahu return -ENOMEM; 2350cc20d33SSunila Sahu } 2360cc20d33SSunila Sahu stream = *((struct zlib_stream **)zstream); 2370cc20d33SSunila Sahu 2380cc20d33SSunila Sahu ret = zlib_set_stream_parameters(xform, stream); 2390cc20d33SSunila Sahu 2400cc20d33SSunila Sahu if (ret < 0) { 2410cc20d33SSunila Sahu ZLIB_PMD_ERR("failed configure session parameters"); 2420cc20d33SSunila Sahu 2430cc20d33SSunila Sahu memset(stream, 0, sizeof(struct zlib_stream)); 2440cc20d33SSunila Sahu /* Return session to mempool */ 2450cc20d33SSunila Sahu rte_mempool_put(internals->mp, stream); 2460cc20d33SSunila Sahu return ret; 2470cc20d33SSunila Sahu } 2480cc20d33SSunila Sahu 2490cc20d33SSunila Sahu return 0; 2500cc20d33SSunila Sahu } 2510cc20d33SSunila Sahu 2520cc20d33SSunila Sahu /** Configure private xform */ 2530cc20d33SSunila Sahu static int 2540cc20d33SSunila Sahu zlib_pmd_private_xform_create(struct rte_compressdev *dev, 2550cc20d33SSunila Sahu const struct rte_comp_xform *xform, 2560cc20d33SSunila Sahu void **private_xform) 2570cc20d33SSunila Sahu { 2580cc20d33SSunila Sahu return zlib_pmd_stream_create(dev, xform, private_xform); 2590cc20d33SSunila Sahu } 2600cc20d33SSunila Sahu 2610cc20d33SSunila Sahu /** Clear the memory of stream so it doesn't leave key material behind */ 2620cc20d33SSunila Sahu static int 2630cc20d33SSunila Sahu zlib_pmd_stream_free(__rte_unused struct rte_compressdev *dev, 2640cc20d33SSunila Sahu void *zstream) 2650cc20d33SSunila Sahu { 2660cc20d33SSunila Sahu struct zlib_stream *stream = (struct zlib_stream *)zstream; 2670cc20d33SSunila Sahu if (!stream) 2680cc20d33SSunila Sahu return -EINVAL; 2690cc20d33SSunila Sahu 2700cc20d33SSunila Sahu stream->free(&stream->strm); 2710cc20d33SSunila Sahu /* Zero out the whole structure */ 2720cc20d33SSunila Sahu memset(stream, 0, sizeof(struct zlib_stream)); 2730cc20d33SSunila Sahu struct rte_mempool *mp = rte_mempool_from_obj(stream); 2740cc20d33SSunila Sahu rte_mempool_put(mp, stream); 2750cc20d33SSunila Sahu 2760cc20d33SSunila Sahu return 0; 2770cc20d33SSunila Sahu } 2780cc20d33SSunila Sahu 2790cc20d33SSunila Sahu /** Clear the memory of stream so it doesn't leave key material behind */ 2800cc20d33SSunila Sahu static int 2810cc20d33SSunila Sahu zlib_pmd_private_xform_free(struct rte_compressdev *dev, 2820cc20d33SSunila Sahu void *private_xform) 2830cc20d33SSunila Sahu { 2840cc20d33SSunila Sahu return zlib_pmd_stream_free(dev, private_xform); 2850cc20d33SSunila Sahu } 2860cc20d33SSunila Sahu 28727422fc3SAshish Gupta struct rte_compressdev_ops zlib_pmd_ops = { 28827422fc3SAshish Gupta .dev_configure = zlib_pmd_config, 28927422fc3SAshish Gupta .dev_start = zlib_pmd_start, 29027422fc3SAshish Gupta .dev_stop = zlib_pmd_stop, 29127422fc3SAshish Gupta .dev_close = zlib_pmd_close, 29227422fc3SAshish Gupta 29327422fc3SAshish Gupta .stats_get = zlib_pmd_stats_get, 29427422fc3SAshish Gupta .stats_reset = zlib_pmd_stats_reset, 29527422fc3SAshish Gupta 29627422fc3SAshish Gupta .dev_infos_get = zlib_pmd_info_get, 29727422fc3SAshish Gupta 29827422fc3SAshish Gupta .queue_pair_setup = zlib_pmd_qp_setup, 29927422fc3SAshish Gupta .queue_pair_release = zlib_pmd_qp_release, 30027422fc3SAshish Gupta 3010cc20d33SSunila Sahu .private_xform_create = zlib_pmd_private_xform_create, 3020cc20d33SSunila Sahu .private_xform_free = zlib_pmd_private_xform_free, 30327422fc3SAshish Gupta 30427422fc3SAshish Gupta .stream_create = NULL, 30527422fc3SAshish Gupta .stream_free = NULL 30627422fc3SAshish Gupta }; 30727422fc3SAshish Gupta 30827422fc3SAshish Gupta struct rte_compressdev_ops *rte_zlib_pmd_ops = &zlib_pmd_ops; 309