1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
|
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2018 Cavium Networks
*/
#include <string.h>
#include <dev_driver.h>
#include <rte_common.h>
#include <rte_malloc.h>
#include "zlib_pmd_private.h"
static const struct rte_compressdev_capabilities zlib_pmd_capabilities[] = {
{ /* Deflate */
.algo = RTE_COMP_ALGO_DEFLATE,
.comp_feature_flags = (RTE_COMP_FF_NONCOMPRESSED_BLOCKS |
RTE_COMP_FF_HUFFMAN_FIXED |
RTE_COMP_FF_HUFFMAN_DYNAMIC),
.window_size = {
.min = 8,
.max = 15,
.increment = 1
},
},
RTE_COMP_END_OF_CAPABILITIES_LIST()
};
/** Configure device */
static int
zlib_pmd_config(struct rte_compressdev *dev,
struct rte_compressdev_config *config)
{
struct rte_mempool *mp;
char mp_name[RTE_MEMPOOL_NAMESIZE];
struct zlib_private *internals = dev->data->dev_private;
snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
"stream_mp_%u", dev->data->dev_id);
mp = internals->mp;
if (mp == NULL) {
mp = rte_mempool_create(mp_name,
config->max_nb_priv_xforms +
config->max_nb_streams,
sizeof(struct zlib_priv_xform),
0, 0, NULL, NULL, NULL,
NULL, config->socket_id,
0);
if (mp == NULL) {
ZLIB_PMD_ERR("Cannot create private xform pool on socket %d",
config->socket_id);
return -ENOMEM;
}
internals->mp = mp;
}
return 0;
}
/** Start device */
static int
zlib_pmd_start(__rte_unused struct rte_compressdev *dev)
{
return 0;
}
/** Stop device */
static void
zlib_pmd_stop(__rte_unused struct rte_compressdev *dev)
{
}
/** Close device */
static int
zlib_pmd_close(struct rte_compressdev *dev)
{
struct zlib_private *internals = dev->data->dev_private;
rte_mempool_free(internals->mp);
internals->mp = NULL;
return 0;
}
/** Get device statistics */
static void
zlib_pmd_stats_get(struct rte_compressdev *dev,
struct rte_compressdev_stats *stats)
{
int qp_id;
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
stats->enqueued_count += qp->qp_stats.enqueued_count;
stats->dequeued_count += qp->qp_stats.dequeued_count;
stats->enqueue_err_count += qp->qp_stats.enqueue_err_count;
stats->dequeue_err_count += qp->qp_stats.dequeue_err_count;
}
}
/** Reset device statistics */
static void
zlib_pmd_stats_reset(struct rte_compressdev *dev)
{
int qp_id;
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
}
}
/** Get device info */
static void
zlib_pmd_info_get(struct rte_compressdev *dev,
struct rte_compressdev_info *dev_info)
{
if (dev_info != NULL) {
dev_info->driver_name = dev->device->name;
dev_info->feature_flags = dev->feature_flags;
dev_info->capabilities = zlib_pmd_capabilities;
}
}
/** Release queue pair */
static int
zlib_pmd_qp_release(struct rte_compressdev *dev, uint16_t qp_id)
{
struct zlib_qp *qp = dev->data->queue_pairs[qp_id];
if (qp != NULL) {
rte_ring_free(qp->processed_pkts);
rte_free(qp);
dev->data->queue_pairs[qp_id] = NULL;
}
return 0;
}
/** set a unique name for the queue pair based on its name, dev_id and qp_id */
static int
zlib_pmd_qp_set_unique_name(struct rte_compressdev *dev,
struct zlib_qp *qp)
{
unsigned int n = snprintf(qp->name, sizeof(qp->name),
"zlib_pmd_%u_qp_%u",
dev->data->dev_id, qp->id);
if (n >= sizeof(qp->name))
return -1;
return 0;
}
/** Create a ring to place process packets on */
static struct rte_ring *
zlib_pmd_qp_create_processed_pkts_ring(struct zlib_qp *qp,
unsigned int ring_size, int socket_id)
{
struct rte_ring *r = qp->processed_pkts;
if (r) {
if (rte_ring_get_size(r) >= ring_size) {
ZLIB_PMD_INFO("Reusing existing ring %s for processed"
" packets", qp->name);
return r;
}
ZLIB_PMD_ERR("Unable to reuse existing ring %s for processed"
" packets", qp->name);
return NULL;
}
return rte_ring_create(qp->name, ring_size, socket_id,
RING_F_EXACT_SZ);
}
/** Setup a queue pair */
static int
zlib_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
uint32_t max_inflight_ops, int socket_id)
{
struct zlib_qp *qp = NULL;
/* Free memory prior to re-allocation if needed. */
if (dev->data->queue_pairs[qp_id] != NULL)
zlib_pmd_qp_release(dev, qp_id);
/* Allocate the queue pair data structure. */
qp = rte_zmalloc_socket("ZLIB PMD Queue Pair", sizeof(*qp),
RTE_CACHE_LINE_SIZE, socket_id);
if (qp == NULL)
return (-ENOMEM);
qp->id = qp_id;
dev->data->queue_pairs[qp_id] = qp;
if (zlib_pmd_qp_set_unique_name(dev, qp))
goto qp_setup_cleanup;
qp->processed_pkts = zlib_pmd_qp_create_processed_pkts_ring(qp,
max_inflight_ops, socket_id);
if (qp->processed_pkts == NULL)
goto qp_setup_cleanup;
memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
return 0;
qp_setup_cleanup:
if (qp) {
rte_free(qp);
qp = NULL;
}
return -1;
}
/** Configure stream */
static int
zlib_pmd_stream_create(struct rte_compressdev *dev,
const struct rte_comp_xform *xform,
void **zstream)
{
int ret = 0;
struct zlib_stream *stream;
struct zlib_private *internals = dev->data->dev_private;
if (xform == NULL) {
ZLIB_PMD_ERR("invalid xform struct");
return -EINVAL;
}
if (rte_mempool_get(internals->mp, zstream)) {
ZLIB_PMD_ERR("Couldn't get object from session mempool");
return -ENOMEM;
}
stream = *((struct zlib_stream **)zstream);
ret = zlib_set_stream_parameters(xform, stream);
if (ret < 0) {
ZLIB_PMD_ERR("failed configure session parameters");
memset(stream, 0, sizeof(struct zlib_stream));
/* Return session to mempool */
rte_mempool_put(internals->mp, stream);
return ret;
}
return 0;
}
/** Configure private xform */
static int
zlib_pmd_private_xform_create(struct rte_compressdev *dev,
const struct rte_comp_xform *xform,
void **private_xform)
{
return zlib_pmd_stream_create(dev, xform, private_xform);
}
/** Clear the memory of stream so it doesn't leave key material behind */
static int
zlib_pmd_stream_free(__rte_unused struct rte_compressdev *dev,
void *zstream)
{
struct zlib_stream *stream = (struct zlib_stream *)zstream;
if (!stream)
return -EINVAL;
stream->free(&stream->strm);
/* Zero out the whole structure */
memset(stream, 0, sizeof(struct zlib_stream));
struct rte_mempool *mp = rte_mempool_from_obj(stream);
rte_mempool_put(mp, stream);
return 0;
}
/** Clear the memory of stream so it doesn't leave key material behind */
static int
zlib_pmd_private_xform_free(struct rte_compressdev *dev,
void *private_xform)
{
return zlib_pmd_stream_free(dev, private_xform);
}
struct rte_compressdev_ops zlib_pmd_ops = {
.dev_configure = zlib_pmd_config,
.dev_start = zlib_pmd_start,
.dev_stop = zlib_pmd_stop,
.dev_close = zlib_pmd_close,
.stats_get = zlib_pmd_stats_get,
.stats_reset = zlib_pmd_stats_reset,
.dev_infos_get = zlib_pmd_info_get,
.queue_pair_setup = zlib_pmd_qp_setup,
.queue_pair_release = zlib_pmd_qp_release,
.private_xform_create = zlib_pmd_private_xform_create,
.private_xform_free = zlib_pmd_private_xform_free,
.stream_create = NULL,
.stream_free = NULL
};
struct rte_compressdev_ops *rte_zlib_pmd_ops = &zlib_pmd_ops;
|