14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright 2017 NXP
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <assert.h>
64418919fSjohnjiang #include <stdio.h>
74418919fSjohnjiang #include <stdbool.h>
84418919fSjohnjiang #include <errno.h>
94418919fSjohnjiang #include <stdint.h>
104418919fSjohnjiang #include <inttypes.h>
114418919fSjohnjiang #include <string.h>
124418919fSjohnjiang
134418919fSjohnjiang #include <rte_byteorder.h>
144418919fSjohnjiang #include <rte_common.h>
154418919fSjohnjiang #include <rte_debug.h>
164418919fSjohnjiang #include <rte_dev.h>
174418919fSjohnjiang #include <rte_eal.h>
184418919fSjohnjiang #include <rte_kvargs.h>
194418919fSjohnjiang #include <rte_log.h>
204418919fSjohnjiang #include <rte_malloc.h>
214418919fSjohnjiang #include <rte_memory.h>
224418919fSjohnjiang #include <rte_memcpy.h>
234418919fSjohnjiang #include <rte_lcore.h>
244418919fSjohnjiang #include <rte_bus_vdev.h>
254418919fSjohnjiang
264418919fSjohnjiang #include <rte_rawdev.h>
274418919fSjohnjiang #include <rte_rawdev_pmd.h>
284418919fSjohnjiang
294418919fSjohnjiang #include "skeleton_rawdev.h"
304418919fSjohnjiang
314418919fSjohnjiang /* Count of instances */
324418919fSjohnjiang static uint16_t skeldev_init_once;
334418919fSjohnjiang
344418919fSjohnjiang /**< Rawdev Skeleton dummy driver name */
354418919fSjohnjiang #define SKELETON_PMD_RAWDEV_NAME rawdev_skeleton
364418919fSjohnjiang
374418919fSjohnjiang struct queue_buffers {
384418919fSjohnjiang void *bufs[SKELETON_QUEUE_MAX_DEPTH];
394418919fSjohnjiang };
404418919fSjohnjiang
414418919fSjohnjiang static struct queue_buffers queue_buf[SKELETON_MAX_QUEUES] = {};
424418919fSjohnjiang static void clear_queue_bufs(int queue_id);
434418919fSjohnjiang
skeleton_rawdev_info_get(struct rte_rawdev * dev,rte_rawdev_obj_t dev_info,size_t dev_info_size)44*2d9fd380Sjfb8856606 static int skeleton_rawdev_info_get(struct rte_rawdev *dev,
45*2d9fd380Sjfb8856606 rte_rawdev_obj_t dev_info,
46*2d9fd380Sjfb8856606 size_t dev_info_size)
474418919fSjohnjiang {
484418919fSjohnjiang struct skeleton_rawdev *skeldev;
494418919fSjohnjiang struct skeleton_rawdev_conf *skeldev_conf;
504418919fSjohnjiang
514418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
524418919fSjohnjiang
53*2d9fd380Sjfb8856606 if (!dev_info || dev_info_size != sizeof(*skeldev_conf)) {
544418919fSjohnjiang SKELETON_PMD_ERR("Invalid request");
55*2d9fd380Sjfb8856606 return -EINVAL;
564418919fSjohnjiang }
574418919fSjohnjiang
584418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
594418919fSjohnjiang
604418919fSjohnjiang skeldev_conf = dev_info;
614418919fSjohnjiang
624418919fSjohnjiang skeldev_conf->num_queues = skeldev->num_queues;
634418919fSjohnjiang skeldev_conf->capabilities = skeldev->capabilities;
644418919fSjohnjiang skeldev_conf->device_state = skeldev->device_state;
654418919fSjohnjiang skeldev_conf->firmware_state = skeldev->fw.firmware_state;
66*2d9fd380Sjfb8856606
67*2d9fd380Sjfb8856606 return 0;
684418919fSjohnjiang }
694418919fSjohnjiang
skeleton_rawdev_configure(const struct rte_rawdev * dev,rte_rawdev_obj_t config,size_t config_size)704418919fSjohnjiang static int skeleton_rawdev_configure(const struct rte_rawdev *dev,
71*2d9fd380Sjfb8856606 rte_rawdev_obj_t config,
72*2d9fd380Sjfb8856606 size_t config_size)
734418919fSjohnjiang {
744418919fSjohnjiang struct skeleton_rawdev *skeldev;
754418919fSjohnjiang struct skeleton_rawdev_conf *skeldev_conf;
764418919fSjohnjiang
774418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
784418919fSjohnjiang
794418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
804418919fSjohnjiang
81*2d9fd380Sjfb8856606 if (config == NULL || config_size != sizeof(*skeldev_conf)) {
824418919fSjohnjiang SKELETON_PMD_ERR("Invalid configuration");
834418919fSjohnjiang return -EINVAL;
844418919fSjohnjiang }
854418919fSjohnjiang
864418919fSjohnjiang skeldev_conf = config;
874418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
884418919fSjohnjiang
894418919fSjohnjiang if (skeldev_conf->num_queues <= SKELETON_MAX_QUEUES)
904418919fSjohnjiang skeldev->num_queues = skeldev_conf->num_queues;
914418919fSjohnjiang else
924418919fSjohnjiang return -EINVAL;
934418919fSjohnjiang
944418919fSjohnjiang skeldev->capabilities = skeldev_conf->capabilities;
954418919fSjohnjiang skeldev->num_queues = skeldev_conf->num_queues;
964418919fSjohnjiang
974418919fSjohnjiang return 0;
984418919fSjohnjiang }
994418919fSjohnjiang
skeleton_rawdev_start(struct rte_rawdev * dev)1004418919fSjohnjiang static int skeleton_rawdev_start(struct rte_rawdev *dev)
1014418919fSjohnjiang {
1024418919fSjohnjiang int ret = 0;
1034418919fSjohnjiang struct skeleton_rawdev *skeldev;
1044418919fSjohnjiang enum skeleton_firmware_state fw_state;
1054418919fSjohnjiang enum skeleton_device_state device_state;
1064418919fSjohnjiang
1074418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
1084418919fSjohnjiang
1094418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
1104418919fSjohnjiang
1114418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
1124418919fSjohnjiang
1134418919fSjohnjiang fw_state = skeldev->fw.firmware_state;
1144418919fSjohnjiang device_state = skeldev->device_state;
1154418919fSjohnjiang
1164418919fSjohnjiang if (fw_state == SKELETON_FW_LOADED &&
1174418919fSjohnjiang device_state == SKELETON_DEV_STOPPED) {
1184418919fSjohnjiang skeldev->device_state = SKELETON_DEV_RUNNING;
1194418919fSjohnjiang } else {
1204418919fSjohnjiang SKELETON_PMD_ERR("Device not ready for starting");
1214418919fSjohnjiang ret = -EINVAL;
1224418919fSjohnjiang }
1234418919fSjohnjiang
1244418919fSjohnjiang return ret;
1254418919fSjohnjiang }
1264418919fSjohnjiang
skeleton_rawdev_stop(struct rte_rawdev * dev)1274418919fSjohnjiang static void skeleton_rawdev_stop(struct rte_rawdev *dev)
1284418919fSjohnjiang {
1294418919fSjohnjiang struct skeleton_rawdev *skeldev;
1304418919fSjohnjiang
1314418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
1324418919fSjohnjiang
1334418919fSjohnjiang if (dev) {
1344418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
1354418919fSjohnjiang skeldev->device_state = SKELETON_DEV_STOPPED;
1364418919fSjohnjiang }
1374418919fSjohnjiang }
1384418919fSjohnjiang
1394418919fSjohnjiang static void
reset_queues(struct skeleton_rawdev * skeldev)1404418919fSjohnjiang reset_queues(struct skeleton_rawdev *skeldev)
1414418919fSjohnjiang {
1424418919fSjohnjiang int i;
1434418919fSjohnjiang
1444418919fSjohnjiang for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
1454418919fSjohnjiang skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
1464418919fSjohnjiang skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
1474418919fSjohnjiang }
1484418919fSjohnjiang }
1494418919fSjohnjiang
1504418919fSjohnjiang static void
reset_attribute_table(struct skeleton_rawdev * skeldev)1514418919fSjohnjiang reset_attribute_table(struct skeleton_rawdev *skeldev)
1524418919fSjohnjiang {
1534418919fSjohnjiang int i;
1544418919fSjohnjiang
1554418919fSjohnjiang for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
1564418919fSjohnjiang if (skeldev->attr[i].name) {
1574418919fSjohnjiang free(skeldev->attr[i].name);
1584418919fSjohnjiang skeldev->attr[i].name = NULL;
1594418919fSjohnjiang }
1604418919fSjohnjiang }
1614418919fSjohnjiang }
1624418919fSjohnjiang
skeleton_rawdev_close(struct rte_rawdev * dev)1634418919fSjohnjiang static int skeleton_rawdev_close(struct rte_rawdev *dev)
1644418919fSjohnjiang {
1654418919fSjohnjiang int ret = 0, i;
1664418919fSjohnjiang struct skeleton_rawdev *skeldev;
1674418919fSjohnjiang enum skeleton_firmware_state fw_state;
1684418919fSjohnjiang enum skeleton_device_state device_state;
1694418919fSjohnjiang
1704418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
1714418919fSjohnjiang
1724418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
1734418919fSjohnjiang
1744418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
1754418919fSjohnjiang
1764418919fSjohnjiang fw_state = skeldev->fw.firmware_state;
1774418919fSjohnjiang device_state = skeldev->device_state;
1784418919fSjohnjiang
1794418919fSjohnjiang reset_queues(skeldev);
1804418919fSjohnjiang reset_attribute_table(skeldev);
1814418919fSjohnjiang
1824418919fSjohnjiang switch (fw_state) {
1834418919fSjohnjiang case SKELETON_FW_LOADED:
1844418919fSjohnjiang if (device_state == SKELETON_DEV_RUNNING) {
1854418919fSjohnjiang SKELETON_PMD_ERR("Cannot close running device");
1864418919fSjohnjiang ret = -EINVAL;
1874418919fSjohnjiang } else {
1884418919fSjohnjiang /* Probably call fw reset here */
1894418919fSjohnjiang skeldev->fw.firmware_state = SKELETON_FW_READY;
1904418919fSjohnjiang }
1914418919fSjohnjiang break;
1924418919fSjohnjiang case SKELETON_FW_READY:
1930c6bd470Sfengbojiang SKELETON_PMD_DEBUG("Device already in stopped state");
1940c6bd470Sfengbojiang break;
1954418919fSjohnjiang case SKELETON_FW_ERROR:
1964418919fSjohnjiang default:
1970c6bd470Sfengbojiang SKELETON_PMD_DEBUG("Device in impossible state");
1984418919fSjohnjiang ret = -EINVAL;
1994418919fSjohnjiang break;
2004418919fSjohnjiang }
2014418919fSjohnjiang
2024418919fSjohnjiang /* Clear all allocated queues */
2034418919fSjohnjiang for (i = 0; i < SKELETON_MAX_QUEUES; i++)
2044418919fSjohnjiang clear_queue_bufs(i);
2054418919fSjohnjiang
2064418919fSjohnjiang return ret;
2074418919fSjohnjiang }
2084418919fSjohnjiang
skeleton_rawdev_reset(struct rte_rawdev * dev)2094418919fSjohnjiang static int skeleton_rawdev_reset(struct rte_rawdev *dev)
2104418919fSjohnjiang {
2114418919fSjohnjiang struct skeleton_rawdev *skeldev;
2124418919fSjohnjiang
2134418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
2144418919fSjohnjiang
2154418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
2164418919fSjohnjiang
2174418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
2184418919fSjohnjiang
2194418919fSjohnjiang SKELETON_PMD_DEBUG("Resetting device");
2204418919fSjohnjiang skeldev->fw.firmware_state = SKELETON_FW_READY;
2214418919fSjohnjiang
2224418919fSjohnjiang return 0;
2234418919fSjohnjiang }
2244418919fSjohnjiang
skeleton_rawdev_queue_def_conf(struct rte_rawdev * dev,uint16_t queue_id,rte_rawdev_obj_t queue_conf,size_t conf_size)225*2d9fd380Sjfb8856606 static int skeleton_rawdev_queue_def_conf(struct rte_rawdev *dev,
2264418919fSjohnjiang uint16_t queue_id,
227*2d9fd380Sjfb8856606 rte_rawdev_obj_t queue_conf,
228*2d9fd380Sjfb8856606 size_t conf_size)
2294418919fSjohnjiang {
2304418919fSjohnjiang struct skeleton_rawdev *skeldev;
2314418919fSjohnjiang struct skeleton_rawdev_queue *skelq;
2324418919fSjohnjiang
2334418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
2344418919fSjohnjiang
235*2d9fd380Sjfb8856606 if (!dev || !queue_conf ||
236*2d9fd380Sjfb8856606 conf_size != sizeof(struct skeleton_rawdev_queue))
237*2d9fd380Sjfb8856606 return -EINVAL;
2384418919fSjohnjiang
2394418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
2404418919fSjohnjiang skelq = &skeldev->queues[queue_id];
2414418919fSjohnjiang
2424418919fSjohnjiang if (queue_id < SKELETON_MAX_QUEUES)
2434418919fSjohnjiang rte_memcpy(queue_conf, skelq,
2444418919fSjohnjiang sizeof(struct skeleton_rawdev_queue));
245*2d9fd380Sjfb8856606
246*2d9fd380Sjfb8856606 return 0;
2474418919fSjohnjiang }
2484418919fSjohnjiang
2494418919fSjohnjiang static void
clear_queue_bufs(int queue_id)2504418919fSjohnjiang clear_queue_bufs(int queue_id)
2514418919fSjohnjiang {
2524418919fSjohnjiang int i;
2534418919fSjohnjiang
2544418919fSjohnjiang /* Clear buffers for queue_id */
2554418919fSjohnjiang for (i = 0; i < SKELETON_QUEUE_MAX_DEPTH; i++)
2564418919fSjohnjiang queue_buf[queue_id].bufs[i] = NULL;
2574418919fSjohnjiang }
2584418919fSjohnjiang
skeleton_rawdev_queue_setup(struct rte_rawdev * dev,uint16_t queue_id,rte_rawdev_obj_t queue_conf,size_t conf_size)2594418919fSjohnjiang static int skeleton_rawdev_queue_setup(struct rte_rawdev *dev,
2604418919fSjohnjiang uint16_t queue_id,
261*2d9fd380Sjfb8856606 rte_rawdev_obj_t queue_conf,
262*2d9fd380Sjfb8856606 size_t conf_size)
2634418919fSjohnjiang {
2644418919fSjohnjiang int ret = 0;
2654418919fSjohnjiang struct skeleton_rawdev *skeldev;
2664418919fSjohnjiang struct skeleton_rawdev_queue *q;
2674418919fSjohnjiang
2684418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
2694418919fSjohnjiang
270*2d9fd380Sjfb8856606 if (!dev || !queue_conf ||
271*2d9fd380Sjfb8856606 conf_size != sizeof(struct skeleton_rawdev_queue))
2724418919fSjohnjiang return -EINVAL;
2734418919fSjohnjiang
2744418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
2754418919fSjohnjiang q = &skeldev->queues[queue_id];
2764418919fSjohnjiang
2774418919fSjohnjiang if (skeldev->num_queues > queue_id &&
2784418919fSjohnjiang q->depth < SKELETON_QUEUE_MAX_DEPTH) {
2794418919fSjohnjiang rte_memcpy(q, queue_conf,
2804418919fSjohnjiang sizeof(struct skeleton_rawdev_queue));
2814418919fSjohnjiang clear_queue_bufs(queue_id);
2824418919fSjohnjiang } else {
2834418919fSjohnjiang SKELETON_PMD_ERR("Invalid queue configuration");
2844418919fSjohnjiang ret = -EINVAL;
2854418919fSjohnjiang }
2864418919fSjohnjiang
2874418919fSjohnjiang return ret;
2884418919fSjohnjiang }
2894418919fSjohnjiang
skeleton_rawdev_queue_release(struct rte_rawdev * dev,uint16_t queue_id)2904418919fSjohnjiang static int skeleton_rawdev_queue_release(struct rte_rawdev *dev,
2914418919fSjohnjiang uint16_t queue_id)
2924418919fSjohnjiang {
2934418919fSjohnjiang int ret = 0;
2944418919fSjohnjiang struct skeleton_rawdev *skeldev;
2954418919fSjohnjiang
2964418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
2974418919fSjohnjiang
2984418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
2994418919fSjohnjiang
3004418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
3014418919fSjohnjiang
3024418919fSjohnjiang if (skeldev->num_queues > queue_id) {
3034418919fSjohnjiang skeldev->queues[queue_id].state = SKELETON_QUEUE_DETACH;
3044418919fSjohnjiang skeldev->queues[queue_id].depth = SKELETON_QUEUE_DEF_DEPTH;
3054418919fSjohnjiang clear_queue_bufs(queue_id);
3064418919fSjohnjiang } else {
3074418919fSjohnjiang SKELETON_PMD_ERR("Invalid queue configuration");
3084418919fSjohnjiang ret = -EINVAL;
3094418919fSjohnjiang }
3104418919fSjohnjiang
3114418919fSjohnjiang return ret;
3124418919fSjohnjiang }
3134418919fSjohnjiang
skeleton_rawdev_queue_count(struct rte_rawdev * dev)3144418919fSjohnjiang static uint16_t skeleton_rawdev_queue_count(struct rte_rawdev *dev)
3154418919fSjohnjiang {
3164418919fSjohnjiang struct skeleton_rawdev *skeldev;
3174418919fSjohnjiang
3184418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
3194418919fSjohnjiang
3204418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
3214418919fSjohnjiang
3224418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
3234418919fSjohnjiang return skeldev->num_queues;
3244418919fSjohnjiang }
3254418919fSjohnjiang
skeleton_rawdev_get_attr(struct rte_rawdev * dev,const char * attr_name,uint64_t * attr_value)3264418919fSjohnjiang static int skeleton_rawdev_get_attr(struct rte_rawdev *dev,
3274418919fSjohnjiang const char *attr_name,
3284418919fSjohnjiang uint64_t *attr_value)
3294418919fSjohnjiang {
3304418919fSjohnjiang int i;
3314418919fSjohnjiang uint8_t done = 0;
3324418919fSjohnjiang struct skeleton_rawdev *skeldev;
3334418919fSjohnjiang
3344418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
3354418919fSjohnjiang
3364418919fSjohnjiang if (!dev || !attr_name || !attr_value) {
3374418919fSjohnjiang SKELETON_PMD_ERR("Invalid arguments for getting attributes");
3384418919fSjohnjiang return -EINVAL;
3394418919fSjohnjiang }
3404418919fSjohnjiang
3414418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
3424418919fSjohnjiang
3434418919fSjohnjiang for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
3444418919fSjohnjiang if (!skeldev->attr[i].name)
3454418919fSjohnjiang continue;
3464418919fSjohnjiang
3474418919fSjohnjiang if (!strncmp(skeldev->attr[i].name, attr_name,
3484418919fSjohnjiang SKELETON_ATTRIBUTE_NAME_MAX)) {
3494418919fSjohnjiang *attr_value = skeldev->attr[i].value;
3504418919fSjohnjiang done = 1;
3514418919fSjohnjiang SKELETON_PMD_DEBUG("Attribute (%s) Value (%" PRIu64 ")",
3524418919fSjohnjiang attr_name, *attr_value);
3534418919fSjohnjiang break;
3544418919fSjohnjiang }
3554418919fSjohnjiang }
3564418919fSjohnjiang
3574418919fSjohnjiang if (done)
3584418919fSjohnjiang return 0;
3594418919fSjohnjiang
3604418919fSjohnjiang /* Attribute not found */
3614418919fSjohnjiang return -EINVAL;
3624418919fSjohnjiang }
3634418919fSjohnjiang
skeleton_rawdev_set_attr(struct rte_rawdev * dev,const char * attr_name,const uint64_t attr_value)3644418919fSjohnjiang static int skeleton_rawdev_set_attr(struct rte_rawdev *dev,
3654418919fSjohnjiang const char *attr_name,
3664418919fSjohnjiang const uint64_t attr_value)
3674418919fSjohnjiang {
3684418919fSjohnjiang int i;
3694418919fSjohnjiang uint8_t done = 0;
3704418919fSjohnjiang struct skeleton_rawdev *skeldev;
3714418919fSjohnjiang
3724418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
3734418919fSjohnjiang
3744418919fSjohnjiang if (!dev || !attr_name) {
3754418919fSjohnjiang SKELETON_PMD_ERR("Invalid arguments for setting attributes");
3764418919fSjohnjiang return -EINVAL;
3774418919fSjohnjiang }
3784418919fSjohnjiang
3794418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
3804418919fSjohnjiang
3814418919fSjohnjiang /* Check if attribute already exists */
3824418919fSjohnjiang for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
3834418919fSjohnjiang if (!skeldev->attr[i].name)
3844418919fSjohnjiang break;
3854418919fSjohnjiang
3864418919fSjohnjiang if (!strncmp(skeldev->attr[i].name, attr_name,
3874418919fSjohnjiang SKELETON_ATTRIBUTE_NAME_MAX)) {
3884418919fSjohnjiang /* Update value */
3894418919fSjohnjiang skeldev->attr[i].value = attr_value;
3904418919fSjohnjiang done = 1;
3914418919fSjohnjiang break;
3924418919fSjohnjiang }
3934418919fSjohnjiang }
3944418919fSjohnjiang
3954418919fSjohnjiang if (!done) {
3964418919fSjohnjiang if (i < (SKELETON_MAX_ATTRIBUTES - 1)) {
3974418919fSjohnjiang /* There is still space to insert one more */
3984418919fSjohnjiang skeldev->attr[i].name = strdup(attr_name);
3994418919fSjohnjiang if (!skeldev->attr[i].name)
4004418919fSjohnjiang return -ENOMEM;
4014418919fSjohnjiang
4024418919fSjohnjiang skeldev->attr[i].value = attr_value;
4034418919fSjohnjiang return 0;
4044418919fSjohnjiang }
4054418919fSjohnjiang }
4064418919fSjohnjiang
4074418919fSjohnjiang return -EINVAL;
4084418919fSjohnjiang }
4094418919fSjohnjiang
skeleton_rawdev_enqueue_bufs(struct rte_rawdev * dev,struct rte_rawdev_buf ** buffers,unsigned int count,rte_rawdev_obj_t context)4104418919fSjohnjiang static int skeleton_rawdev_enqueue_bufs(struct rte_rawdev *dev,
4114418919fSjohnjiang struct rte_rawdev_buf **buffers,
4124418919fSjohnjiang unsigned int count,
4134418919fSjohnjiang rte_rawdev_obj_t context)
4144418919fSjohnjiang {
4154418919fSjohnjiang unsigned int i;
4164418919fSjohnjiang uint16_t q_id;
4174418919fSjohnjiang RTE_SET_USED(dev);
4184418919fSjohnjiang
4194418919fSjohnjiang /* context is essentially the queue_id which is
4204418919fSjohnjiang * transferred as opaque object through the library layer. This can
4214418919fSjohnjiang * help in complex implementation which require more information than
4224418919fSjohnjiang * just an integer - for example, a queue-pair.
4234418919fSjohnjiang */
4244418919fSjohnjiang q_id = *((int *)context);
4254418919fSjohnjiang
4264418919fSjohnjiang for (i = 0; i < count; i++)
4274418919fSjohnjiang queue_buf[q_id].bufs[i] = buffers[i]->buf_addr;
4284418919fSjohnjiang
4294418919fSjohnjiang return i;
4304418919fSjohnjiang }
4314418919fSjohnjiang
skeleton_rawdev_dequeue_bufs(struct rte_rawdev * dev,struct rte_rawdev_buf ** buffers,unsigned int count,rte_rawdev_obj_t context)4324418919fSjohnjiang static int skeleton_rawdev_dequeue_bufs(struct rte_rawdev *dev,
4334418919fSjohnjiang struct rte_rawdev_buf **buffers,
4344418919fSjohnjiang unsigned int count,
4354418919fSjohnjiang rte_rawdev_obj_t context)
4364418919fSjohnjiang {
4374418919fSjohnjiang unsigned int i;
4384418919fSjohnjiang uint16_t q_id;
4394418919fSjohnjiang RTE_SET_USED(dev);
4404418919fSjohnjiang
4414418919fSjohnjiang /* context is essentially the queue_id which is
4424418919fSjohnjiang * transferred as opaque object through the library layer. This can
4434418919fSjohnjiang * help in complex implementation which require more information than
4444418919fSjohnjiang * just an integer - for example, a queue-pair.
4454418919fSjohnjiang */
4464418919fSjohnjiang q_id = *((int *)context);
4474418919fSjohnjiang
4484418919fSjohnjiang for (i = 0; i < count; i++)
4494418919fSjohnjiang buffers[i]->buf_addr = queue_buf[q_id].bufs[i];
4504418919fSjohnjiang
4514418919fSjohnjiang return i;
4524418919fSjohnjiang }
4534418919fSjohnjiang
skeleton_rawdev_dump(struct rte_rawdev * dev,FILE * f)4544418919fSjohnjiang static int skeleton_rawdev_dump(struct rte_rawdev *dev, FILE *f)
4554418919fSjohnjiang {
4564418919fSjohnjiang RTE_SET_USED(dev);
4574418919fSjohnjiang RTE_SET_USED(f);
4584418919fSjohnjiang
4594418919fSjohnjiang return 0;
4604418919fSjohnjiang }
4614418919fSjohnjiang
skeleton_rawdev_firmware_status_get(struct rte_rawdev * dev,rte_rawdev_obj_t status_info)4624418919fSjohnjiang static int skeleton_rawdev_firmware_status_get(struct rte_rawdev *dev,
4634418919fSjohnjiang rte_rawdev_obj_t status_info)
4644418919fSjohnjiang {
4654418919fSjohnjiang struct skeleton_rawdev *skeldev;
4664418919fSjohnjiang
4674418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
4684418919fSjohnjiang
4694418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
4704418919fSjohnjiang
4714418919fSjohnjiang RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
4724418919fSjohnjiang
4734418919fSjohnjiang if (status_info)
4744418919fSjohnjiang memcpy(status_info, &skeldev->fw.firmware_state,
4754418919fSjohnjiang sizeof(enum skeleton_firmware_state));
4764418919fSjohnjiang
4774418919fSjohnjiang return 0;
4784418919fSjohnjiang }
4794418919fSjohnjiang
4804418919fSjohnjiang
skeleton_rawdev_firmware_version_get(struct rte_rawdev * dev,rte_rawdev_obj_t version_info)4814418919fSjohnjiang static int skeleton_rawdev_firmware_version_get(
4824418919fSjohnjiang struct rte_rawdev *dev,
4834418919fSjohnjiang rte_rawdev_obj_t version_info)
4844418919fSjohnjiang {
4854418919fSjohnjiang struct skeleton_rawdev *skeldev;
4864418919fSjohnjiang struct skeleton_firmware_version_info *vi;
4874418919fSjohnjiang
4884418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
4894418919fSjohnjiang
4904418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
4914418919fSjohnjiang vi = version_info;
4924418919fSjohnjiang
4934418919fSjohnjiang vi->major = skeldev->fw.firmware_version.major;
4944418919fSjohnjiang vi->minor = skeldev->fw.firmware_version.minor;
4954418919fSjohnjiang vi->subrel = skeldev->fw.firmware_version.subrel;
4964418919fSjohnjiang
4974418919fSjohnjiang return 0;
4984418919fSjohnjiang }
4994418919fSjohnjiang
skeleton_rawdev_firmware_load(struct rte_rawdev * dev,rte_rawdev_obj_t firmware_buf)5004418919fSjohnjiang static int skeleton_rawdev_firmware_load(struct rte_rawdev *dev,
5014418919fSjohnjiang rte_rawdev_obj_t firmware_buf)
5024418919fSjohnjiang {
5034418919fSjohnjiang struct skeleton_rawdev *skeldev;
5044418919fSjohnjiang
5054418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
5064418919fSjohnjiang
5074418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
5084418919fSjohnjiang
5094418919fSjohnjiang /* firmware_buf is a mmaped, possibly DMA'able area, buffer. Being
5104418919fSjohnjiang * dummy, all this does is check if firmware_buf is not NULL and
5114418919fSjohnjiang * sets the state of the firmware.
5124418919fSjohnjiang */
5134418919fSjohnjiang if (!firmware_buf)
5144418919fSjohnjiang return -EINVAL;
5154418919fSjohnjiang
5164418919fSjohnjiang skeldev->fw.firmware_state = SKELETON_FW_LOADED;
5174418919fSjohnjiang
5184418919fSjohnjiang return 0;
5194418919fSjohnjiang }
5204418919fSjohnjiang
skeleton_rawdev_firmware_unload(struct rte_rawdev * dev)5214418919fSjohnjiang static int skeleton_rawdev_firmware_unload(struct rte_rawdev *dev)
5224418919fSjohnjiang {
5234418919fSjohnjiang struct skeleton_rawdev *skeldev;
5244418919fSjohnjiang
5254418919fSjohnjiang SKELETON_PMD_FUNC_TRACE();
5264418919fSjohnjiang
5274418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(dev);
5284418919fSjohnjiang
5294418919fSjohnjiang skeldev->fw.firmware_state = SKELETON_FW_READY;
5304418919fSjohnjiang
5314418919fSjohnjiang return 0;
5324418919fSjohnjiang }
5334418919fSjohnjiang
5344418919fSjohnjiang static const struct rte_rawdev_ops skeleton_rawdev_ops = {
5354418919fSjohnjiang .dev_info_get = skeleton_rawdev_info_get,
5364418919fSjohnjiang .dev_configure = skeleton_rawdev_configure,
5374418919fSjohnjiang .dev_start = skeleton_rawdev_start,
5384418919fSjohnjiang .dev_stop = skeleton_rawdev_stop,
5394418919fSjohnjiang .dev_close = skeleton_rawdev_close,
5404418919fSjohnjiang .dev_reset = skeleton_rawdev_reset,
5414418919fSjohnjiang
5424418919fSjohnjiang .queue_def_conf = skeleton_rawdev_queue_def_conf,
5434418919fSjohnjiang .queue_setup = skeleton_rawdev_queue_setup,
5444418919fSjohnjiang .queue_release = skeleton_rawdev_queue_release,
5454418919fSjohnjiang .queue_count = skeleton_rawdev_queue_count,
5464418919fSjohnjiang
5474418919fSjohnjiang .attr_get = skeleton_rawdev_get_attr,
5484418919fSjohnjiang .attr_set = skeleton_rawdev_set_attr,
5494418919fSjohnjiang
5504418919fSjohnjiang .enqueue_bufs = skeleton_rawdev_enqueue_bufs,
5514418919fSjohnjiang .dequeue_bufs = skeleton_rawdev_dequeue_bufs,
5524418919fSjohnjiang
5534418919fSjohnjiang .dump = skeleton_rawdev_dump,
5544418919fSjohnjiang
5554418919fSjohnjiang .xstats_get = NULL,
5564418919fSjohnjiang .xstats_get_names = NULL,
5574418919fSjohnjiang .xstats_get_by_name = NULL,
5584418919fSjohnjiang .xstats_reset = NULL,
5594418919fSjohnjiang
5604418919fSjohnjiang .firmware_status_get = skeleton_rawdev_firmware_status_get,
5614418919fSjohnjiang .firmware_version_get = skeleton_rawdev_firmware_version_get,
5624418919fSjohnjiang .firmware_load = skeleton_rawdev_firmware_load,
5634418919fSjohnjiang .firmware_unload = skeleton_rawdev_firmware_unload,
5644418919fSjohnjiang
5654418919fSjohnjiang .dev_selftest = test_rawdev_skeldev,
5664418919fSjohnjiang };
5674418919fSjohnjiang
5684418919fSjohnjiang static int
skeleton_rawdev_create(const char * name,struct rte_vdev_device * vdev,int socket_id)5694418919fSjohnjiang skeleton_rawdev_create(const char *name,
5704418919fSjohnjiang struct rte_vdev_device *vdev,
5714418919fSjohnjiang int socket_id)
5724418919fSjohnjiang {
5734418919fSjohnjiang int ret = 0, i;
5744418919fSjohnjiang struct rte_rawdev *rawdev = NULL;
5754418919fSjohnjiang struct skeleton_rawdev *skeldev = NULL;
5764418919fSjohnjiang
5774418919fSjohnjiang if (!name) {
5784418919fSjohnjiang SKELETON_PMD_ERR("Invalid name of the device!");
5794418919fSjohnjiang ret = -EINVAL;
5804418919fSjohnjiang goto cleanup;
5814418919fSjohnjiang }
5824418919fSjohnjiang
5834418919fSjohnjiang /* Allocate device structure */
5844418919fSjohnjiang rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct skeleton_rawdev),
5854418919fSjohnjiang socket_id);
5864418919fSjohnjiang if (rawdev == NULL) {
5874418919fSjohnjiang SKELETON_PMD_ERR("Unable to allocate rawdevice");
5884418919fSjohnjiang ret = -EINVAL;
5894418919fSjohnjiang goto cleanup;
5904418919fSjohnjiang }
5914418919fSjohnjiang
5924418919fSjohnjiang ret = rawdev->dev_id; /* return the rawdev id of new device */
5934418919fSjohnjiang
5944418919fSjohnjiang rawdev->dev_ops = &skeleton_rawdev_ops;
5954418919fSjohnjiang rawdev->device = &vdev->device;
5964418919fSjohnjiang
5974418919fSjohnjiang skeldev = skeleton_rawdev_get_priv(rawdev);
5984418919fSjohnjiang
5994418919fSjohnjiang skeldev->device_id = SKELETON_DEVICE_ID;
6004418919fSjohnjiang skeldev->vendor_id = SKELETON_VENDOR_ID;
6014418919fSjohnjiang skeldev->capabilities = SKELETON_DEFAULT_CAPA;
6024418919fSjohnjiang
6034418919fSjohnjiang memset(&skeldev->fw, 0, sizeof(struct skeleton_firmware));
6044418919fSjohnjiang
6054418919fSjohnjiang skeldev->fw.firmware_state = SKELETON_FW_READY;
6064418919fSjohnjiang skeldev->fw.firmware_version.major = SKELETON_MAJOR_VER;
6074418919fSjohnjiang skeldev->fw.firmware_version.minor = SKELETON_MINOR_VER;
6084418919fSjohnjiang skeldev->fw.firmware_version.subrel = SKELETON_SUB_VER;
6094418919fSjohnjiang
6104418919fSjohnjiang skeldev->device_state = SKELETON_DEV_STOPPED;
6114418919fSjohnjiang
6124418919fSjohnjiang /* Reset/set to default queue configuration for this device */
6134418919fSjohnjiang for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
6144418919fSjohnjiang skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
6154418919fSjohnjiang skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
6164418919fSjohnjiang }
6174418919fSjohnjiang
6184418919fSjohnjiang /* Clear all allocated queue buffers */
6194418919fSjohnjiang for (i = 0; i < SKELETON_MAX_QUEUES; i++)
6204418919fSjohnjiang clear_queue_bufs(i);
6214418919fSjohnjiang
6224418919fSjohnjiang return ret;
6234418919fSjohnjiang
6244418919fSjohnjiang cleanup:
6254418919fSjohnjiang if (rawdev)
6264418919fSjohnjiang rte_rawdev_pmd_release(rawdev);
6274418919fSjohnjiang
6284418919fSjohnjiang return ret;
6294418919fSjohnjiang }
6304418919fSjohnjiang
6314418919fSjohnjiang static int
skeleton_rawdev_destroy(const char * name)6324418919fSjohnjiang skeleton_rawdev_destroy(const char *name)
6334418919fSjohnjiang {
6344418919fSjohnjiang int ret;
6354418919fSjohnjiang struct rte_rawdev *rdev;
6364418919fSjohnjiang
6374418919fSjohnjiang if (!name) {
6384418919fSjohnjiang SKELETON_PMD_ERR("Invalid device name");
6394418919fSjohnjiang return -EINVAL;
6404418919fSjohnjiang }
6414418919fSjohnjiang
6424418919fSjohnjiang rdev = rte_rawdev_pmd_get_named_dev(name);
6434418919fSjohnjiang if (!rdev) {
6444418919fSjohnjiang SKELETON_PMD_ERR("Invalid device name (%s)", name);
6454418919fSjohnjiang return -EINVAL;
6464418919fSjohnjiang }
6474418919fSjohnjiang
6484418919fSjohnjiang /* rte_rawdev_close is called by pmd_release */
6494418919fSjohnjiang ret = rte_rawdev_pmd_release(rdev);
6504418919fSjohnjiang if (ret)
6514418919fSjohnjiang SKELETON_PMD_DEBUG("Device cleanup failed");
6524418919fSjohnjiang
6534418919fSjohnjiang return 0;
6544418919fSjohnjiang }
6554418919fSjohnjiang
6564418919fSjohnjiang static int
skeldev_get_selftest(const char * key __rte_unused,const char * value,void * opaque)6574418919fSjohnjiang skeldev_get_selftest(const char *key __rte_unused,
6584418919fSjohnjiang const char *value,
6594418919fSjohnjiang void *opaque)
6604418919fSjohnjiang {
6614418919fSjohnjiang int *flag = opaque;
6624418919fSjohnjiang *flag = atoi(value);
6634418919fSjohnjiang return 0;
6644418919fSjohnjiang }
6654418919fSjohnjiang
6664418919fSjohnjiang static int
skeldev_parse_vdev_args(struct rte_vdev_device * vdev)6674418919fSjohnjiang skeldev_parse_vdev_args(struct rte_vdev_device *vdev)
6684418919fSjohnjiang {
6694418919fSjohnjiang int selftest = 0;
6704418919fSjohnjiang const char *name;
6714418919fSjohnjiang const char *params;
6724418919fSjohnjiang
6734418919fSjohnjiang static const char *const args[] = {
6744418919fSjohnjiang SKELETON_SELFTEST_ARG,
6754418919fSjohnjiang NULL
6764418919fSjohnjiang };
6774418919fSjohnjiang
6784418919fSjohnjiang name = rte_vdev_device_name(vdev);
6794418919fSjohnjiang
6804418919fSjohnjiang params = rte_vdev_device_args(vdev);
6814418919fSjohnjiang if (params != NULL && params[0] != '\0') {
6824418919fSjohnjiang struct rte_kvargs *kvlist = rte_kvargs_parse(params, args);
6834418919fSjohnjiang
6844418919fSjohnjiang if (!kvlist) {
6854418919fSjohnjiang SKELETON_PMD_INFO(
6864418919fSjohnjiang "Ignoring unsupported params supplied '%s'",
6874418919fSjohnjiang name);
6884418919fSjohnjiang } else {
6894418919fSjohnjiang int ret = rte_kvargs_process(kvlist,
6904418919fSjohnjiang SKELETON_SELFTEST_ARG,
6914418919fSjohnjiang skeldev_get_selftest, &selftest);
6924418919fSjohnjiang if (ret != 0 || (selftest < 0 || selftest > 1)) {
6934418919fSjohnjiang SKELETON_PMD_ERR("%s: Error in parsing args",
6944418919fSjohnjiang name);
6954418919fSjohnjiang rte_kvargs_free(kvlist);
6964418919fSjohnjiang ret = -1; /* enforce if selftest is invalid */
6974418919fSjohnjiang return ret;
6984418919fSjohnjiang }
6994418919fSjohnjiang }
7004418919fSjohnjiang
7014418919fSjohnjiang rte_kvargs_free(kvlist);
7024418919fSjohnjiang }
7034418919fSjohnjiang
7044418919fSjohnjiang return selftest;
7054418919fSjohnjiang }
7064418919fSjohnjiang
7074418919fSjohnjiang static int
skeleton_rawdev_probe(struct rte_vdev_device * vdev)7084418919fSjohnjiang skeleton_rawdev_probe(struct rte_vdev_device *vdev)
7094418919fSjohnjiang {
7104418919fSjohnjiang const char *name;
7114418919fSjohnjiang int selftest = 0, ret = 0;
7124418919fSjohnjiang
7134418919fSjohnjiang
7144418919fSjohnjiang name = rte_vdev_device_name(vdev);
7154418919fSjohnjiang if (name == NULL)
7164418919fSjohnjiang return -EINVAL;
7174418919fSjohnjiang
7184418919fSjohnjiang /* More than one instance is not supported */
7194418919fSjohnjiang if (skeldev_init_once) {
7204418919fSjohnjiang SKELETON_PMD_ERR("Multiple instance not supported for %s",
7214418919fSjohnjiang name);
7224418919fSjohnjiang return -EINVAL;
7234418919fSjohnjiang }
7244418919fSjohnjiang
7254418919fSjohnjiang SKELETON_PMD_INFO("Init %s on NUMA node %d", name, rte_socket_id());
7264418919fSjohnjiang
7274418919fSjohnjiang selftest = skeldev_parse_vdev_args(vdev);
7284418919fSjohnjiang /* In case of invalid argument, selftest != 1; ignore other values */
7294418919fSjohnjiang
7304418919fSjohnjiang ret = skeleton_rawdev_create(name, vdev, rte_socket_id());
7314418919fSjohnjiang if (ret >= 0) {
7324418919fSjohnjiang /* In case command line argument for 'selftest' was passed;
7334418919fSjohnjiang * if invalid arguments were passed, execution continues but
7344418919fSjohnjiang * without selftest.
7354418919fSjohnjiang */
7364418919fSjohnjiang if (selftest == 1)
7374418919fSjohnjiang test_rawdev_skeldev(ret);
7384418919fSjohnjiang }
7394418919fSjohnjiang
7404418919fSjohnjiang /* Device instance created; Second instance not possible */
7414418919fSjohnjiang skeldev_init_once = 1;
7424418919fSjohnjiang
7434418919fSjohnjiang return ret < 0 ? ret : 0;
7444418919fSjohnjiang }
7454418919fSjohnjiang
7464418919fSjohnjiang static int
skeleton_rawdev_remove(struct rte_vdev_device * vdev)7474418919fSjohnjiang skeleton_rawdev_remove(struct rte_vdev_device *vdev)
7484418919fSjohnjiang {
7494418919fSjohnjiang const char *name;
7504418919fSjohnjiang int ret;
7514418919fSjohnjiang
7524418919fSjohnjiang name = rte_vdev_device_name(vdev);
7534418919fSjohnjiang if (name == NULL)
7544418919fSjohnjiang return -1;
7554418919fSjohnjiang
7564418919fSjohnjiang SKELETON_PMD_INFO("Closing %s on NUMA node %d", name, rte_socket_id());
7574418919fSjohnjiang
7584418919fSjohnjiang ret = skeleton_rawdev_destroy(name);
7594418919fSjohnjiang if (!ret)
7604418919fSjohnjiang skeldev_init_once = 0;
7614418919fSjohnjiang
7624418919fSjohnjiang return ret;
7634418919fSjohnjiang }
7644418919fSjohnjiang
7654418919fSjohnjiang static struct rte_vdev_driver skeleton_pmd_drv = {
7664418919fSjohnjiang .probe = skeleton_rawdev_probe,
7674418919fSjohnjiang .remove = skeleton_rawdev_remove
7684418919fSjohnjiang };
7694418919fSjohnjiang
7704418919fSjohnjiang RTE_PMD_REGISTER_VDEV(SKELETON_PMD_RAWDEV_NAME, skeleton_pmd_drv);
771*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(skeleton_pmd_logtype, rawdev.skeleton, INFO);
772