103260531SWei Huang /* SPDX-License-Identifier: BSD-3-Clause
203260531SWei Huang * Copyright 2022 Intel Corporation
303260531SWei Huang */
403260531SWei Huang
503260531SWei Huang #include <errno.h>
603260531SWei Huang #include <stdio.h>
703260531SWei Huang #include <stdint.h>
803260531SWei Huang #include <stdlib.h>
903260531SWei Huang #include <string.h>
1003260531SWei Huang #include <unistd.h>
1103260531SWei Huang #include <fcntl.h>
1203260531SWei Huang #include <poll.h>
1303260531SWei Huang #include <sys/eventfd.h>
1403260531SWei Huang
1503260531SWei Huang #include <rte_eal.h>
1603260531SWei Huang #include <rte_malloc.h>
1703260531SWei Huang #include <rte_memzone.h>
1803260531SWei Huang #include <rte_rawdev_pmd.h>
1903260531SWei Huang
2003260531SWei Huang #include "afu_pmd_core.h"
2103260531SWei Huang
2203260531SWei Huang static struct rte_afu_uuid afu_pmd_uuid_map[AFU_RAWDEV_MAX_DRVS+1];
2303260531SWei Huang TAILQ_HEAD(afu_drv_list, afu_rawdev_drv);
2403260531SWei Huang static struct afu_drv_list afu_pmd_list = TAILQ_HEAD_INITIALIZER(afu_pmd_list);
2503260531SWei Huang
26*2234f7d0SDavid Marchand #define afu_rawdev_trylock(dev) rte_spinlock_trylock(&dev->sd->lock)
27*2234f7d0SDavid Marchand #define afu_rawdev_unlock(dev) rte_spinlock_unlock(&dev->sd->lock)
2803260531SWei Huang
afu_rawdev_configure(const struct rte_rawdev * rawdev,rte_rawdev_obj_t config,size_t config_size)2903260531SWei Huang static int afu_rawdev_configure(const struct rte_rawdev *rawdev,
3003260531SWei Huang rte_rawdev_obj_t config, size_t config_size)
3103260531SWei Huang {
3203260531SWei Huang struct afu_rawdev *dev = NULL;
3303260531SWei Huang int ret = 0;
3403260531SWei Huang
3503260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
3603260531SWei Huang
3703260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
3803260531SWei Huang if (!dev)
3903260531SWei Huang return -ENODEV;
4003260531SWei Huang
4103260531SWei Huang if (dev->ops && dev->ops->config)
4203260531SWei Huang ret = (*dev->ops->config)(dev, config, config_size);
4303260531SWei Huang
4403260531SWei Huang return ret;
4503260531SWei Huang }
4603260531SWei Huang
afu_rawdev_start(struct rte_rawdev * rawdev)4703260531SWei Huang static int afu_rawdev_start(struct rte_rawdev *rawdev)
4803260531SWei Huang {
4903260531SWei Huang struct afu_rawdev *dev = NULL;
5003260531SWei Huang int ret = 0;
5103260531SWei Huang
5203260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
5303260531SWei Huang
5403260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
5503260531SWei Huang if (!dev)
5603260531SWei Huang return -ENODEV;
5703260531SWei Huang
5803260531SWei Huang ret = afu_rawdev_trylock(dev);
5903260531SWei Huang if (!ret) {
6003260531SWei Huang IFPGA_RAWDEV_PMD_WARN("AFU is busy, please start it later");
6103260531SWei Huang return ret;
6203260531SWei Huang }
6303260531SWei Huang
6403260531SWei Huang if (dev->ops && dev->ops->start)
6503260531SWei Huang ret = (*dev->ops->start)(dev);
6603260531SWei Huang
6703260531SWei Huang afu_rawdev_unlock(dev);
6803260531SWei Huang
6903260531SWei Huang return ret;
7003260531SWei Huang }
7103260531SWei Huang
afu_rawdev_stop(struct rte_rawdev * rawdev)7203260531SWei Huang static void afu_rawdev_stop(struct rte_rawdev *rawdev)
7303260531SWei Huang {
7403260531SWei Huang struct afu_rawdev *dev = NULL;
7503260531SWei Huang int ret = 0;
7603260531SWei Huang
7703260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
7803260531SWei Huang
7903260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
8003260531SWei Huang if (!dev)
8103260531SWei Huang return;
8203260531SWei Huang
8303260531SWei Huang ret = afu_rawdev_trylock(dev);
8403260531SWei Huang if (!ret) {
8503260531SWei Huang IFPGA_RAWDEV_PMD_WARN("AFU is busy, please stop it later");
8603260531SWei Huang return;
8703260531SWei Huang }
8803260531SWei Huang
8903260531SWei Huang if (dev->ops && dev->ops->stop)
9003260531SWei Huang ret = (*dev->ops->stop)(dev);
9103260531SWei Huang
9203260531SWei Huang afu_rawdev_unlock(dev);
9303260531SWei Huang }
9403260531SWei Huang
afu_rawdev_close(struct rte_rawdev * rawdev)9503260531SWei Huang static int afu_rawdev_close(struct rte_rawdev *rawdev)
9603260531SWei Huang {
9703260531SWei Huang struct afu_rawdev *dev = NULL;
9803260531SWei Huang int ret = 0;
9903260531SWei Huang
10003260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
10103260531SWei Huang
10203260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
10303260531SWei Huang if (!dev)
10403260531SWei Huang return -ENODEV;
10503260531SWei Huang
10603260531SWei Huang if (dev->ops && dev->ops->close)
10703260531SWei Huang ret = (*dev->ops->close)(dev);
10803260531SWei Huang
10903260531SWei Huang return ret;
11003260531SWei Huang }
11103260531SWei Huang
afu_rawdev_reset(struct rte_rawdev * rawdev)11203260531SWei Huang static int afu_rawdev_reset(struct rte_rawdev *rawdev)
11303260531SWei Huang {
11403260531SWei Huang struct afu_rawdev *dev = NULL;
11503260531SWei Huang int ret = 0;
11603260531SWei Huang
11703260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
11803260531SWei Huang
11903260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
12003260531SWei Huang if (!dev)
12103260531SWei Huang return -ENODEV;
12203260531SWei Huang
12303260531SWei Huang ret = afu_rawdev_trylock(dev);
12403260531SWei Huang if (!ret) {
12503260531SWei Huang IFPGA_RAWDEV_PMD_WARN("AFU is busy, please reset it later");
12603260531SWei Huang return ret;
12703260531SWei Huang }
12803260531SWei Huang
12903260531SWei Huang if (dev->ops && dev->ops->reset)
13003260531SWei Huang ret = (*dev->ops->reset)(dev);
13103260531SWei Huang
13203260531SWei Huang afu_rawdev_unlock(dev);
13303260531SWei Huang
13403260531SWei Huang return ret;
13503260531SWei Huang }
13603260531SWei Huang
afu_rawdev_selftest(uint16_t dev_id)13703260531SWei Huang static int afu_rawdev_selftest(uint16_t dev_id)
13803260531SWei Huang {
13903260531SWei Huang struct afu_rawdev *dev = NULL;
14003260531SWei Huang int ret = 0;
14103260531SWei Huang
14203260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
14303260531SWei Huang
14403260531SWei Huang if (!rte_rawdev_pmd_is_valid_dev(dev_id))
14503260531SWei Huang return -ENODEV;
14603260531SWei Huang
14703260531SWei Huang dev = afu_rawdev_get_priv(&rte_rawdevs[dev_id]);
14803260531SWei Huang if (!dev)
14903260531SWei Huang return -ENOENT;
15003260531SWei Huang
15103260531SWei Huang ret = afu_rawdev_trylock(dev);
15203260531SWei Huang if (!ret) {
15303260531SWei Huang IFPGA_RAWDEV_PMD_WARN("AFU is busy, please test it later");
15403260531SWei Huang return ret;
15503260531SWei Huang }
15603260531SWei Huang
15703260531SWei Huang if (dev->ops && dev->ops->test)
15803260531SWei Huang ret = (*dev->ops->test)(dev);
15903260531SWei Huang
16003260531SWei Huang afu_rawdev_unlock(dev);
16103260531SWei Huang
16203260531SWei Huang return ret;
16303260531SWei Huang }
16403260531SWei Huang
afu_rawdev_dump(struct rte_rawdev * rawdev,FILE * f)16503260531SWei Huang static int afu_rawdev_dump(struct rte_rawdev *rawdev, FILE *f)
16603260531SWei Huang {
16703260531SWei Huang struct afu_rawdev *dev = NULL;
16803260531SWei Huang int ret = 0;
16903260531SWei Huang
17003260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
17103260531SWei Huang
17203260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
17303260531SWei Huang if (!dev)
17403260531SWei Huang return -ENODEV;
17503260531SWei Huang
17603260531SWei Huang if (dev->ops && dev->ops->dump)
17703260531SWei Huang ret = (*dev->ops->dump)(dev, f);
17803260531SWei Huang
17903260531SWei Huang return ret;
18003260531SWei Huang }
18103260531SWei Huang
18203260531SWei Huang static const struct rte_rawdev_ops afu_rawdev_ops = {
18303260531SWei Huang .dev_info_get = NULL,
18403260531SWei Huang .dev_configure = afu_rawdev_configure,
18503260531SWei Huang .dev_start = afu_rawdev_start,
18603260531SWei Huang .dev_stop = afu_rawdev_stop,
18703260531SWei Huang .dev_close = afu_rawdev_close,
18803260531SWei Huang .dev_reset = afu_rawdev_reset,
18903260531SWei Huang
19003260531SWei Huang .queue_def_conf = NULL,
19103260531SWei Huang .queue_setup = NULL,
19203260531SWei Huang .queue_release = NULL,
19303260531SWei Huang .queue_count = NULL,
19403260531SWei Huang
19503260531SWei Huang .attr_get = NULL,
19603260531SWei Huang .attr_set = NULL,
19703260531SWei Huang
19803260531SWei Huang .enqueue_bufs = NULL,
19903260531SWei Huang .dequeue_bufs = NULL,
20003260531SWei Huang
20103260531SWei Huang .dump = afu_rawdev_dump,
20203260531SWei Huang
20303260531SWei Huang .xstats_get = NULL,
20403260531SWei Huang .xstats_get_names = NULL,
20503260531SWei Huang .xstats_get_by_name = NULL,
20603260531SWei Huang .xstats_reset = NULL,
20703260531SWei Huang
20803260531SWei Huang .firmware_status_get = NULL,
20903260531SWei Huang .firmware_version_get = NULL,
21003260531SWei Huang .firmware_load = NULL,
21103260531SWei Huang .firmware_unload = NULL,
21203260531SWei Huang
21303260531SWei Huang .dev_selftest = afu_rawdev_selftest,
21403260531SWei Huang };
21503260531SWei Huang
afu_shared_data_alloc(const char * name,struct afu_shared_data ** data,int socket_id)21603260531SWei Huang static int afu_shared_data_alloc(const char *name,
21703260531SWei Huang struct afu_shared_data **data, int socket_id)
21803260531SWei Huang {
21903260531SWei Huang const struct rte_memzone *mz;
22003260531SWei Huang char mz_name[RTE_MEMZONE_NAMESIZE];
22103260531SWei Huang struct afu_shared_data *sd = NULL;
22203260531SWei Huang int init_mz = 0;
22303260531SWei Huang
22403260531SWei Huang if (!name || !data)
22503260531SWei Huang return -EINVAL;
22603260531SWei Huang
22703260531SWei Huang /* name format is afu_?|??:??.? which is unique */
22803260531SWei Huang snprintf(mz_name, sizeof(mz_name), "%s", name);
22903260531SWei Huang
23003260531SWei Huang mz = rte_memzone_lookup(mz_name);
23103260531SWei Huang if (!mz) {
23203260531SWei Huang mz = rte_memzone_reserve(mz_name, sizeof(struct afu_shared_data),
23303260531SWei Huang socket_id, 0);
23403260531SWei Huang init_mz = 1;
23503260531SWei Huang }
23603260531SWei Huang
23703260531SWei Huang if (!mz) {
23803260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Allocate memory zone %s failed!",
23903260531SWei Huang mz_name);
24003260531SWei Huang return -ENOMEM;
24103260531SWei Huang }
24203260531SWei Huang
24303260531SWei Huang sd = (struct afu_shared_data *)mz->addr;
24403260531SWei Huang
24503260531SWei Huang if (init_mz) /* initialize memory zone on the first time */
24603260531SWei Huang rte_spinlock_init(&sd->lock);
24703260531SWei Huang
24803260531SWei Huang *data = sd;
24903260531SWei Huang
25003260531SWei Huang return 0;
25103260531SWei Huang }
25203260531SWei Huang
afu_rawdev_name_get(struct rte_afu_device * afu_dev,char * name,size_t size)25303260531SWei Huang static int afu_rawdev_name_get(struct rte_afu_device *afu_dev, char *name,
25403260531SWei Huang size_t size)
25503260531SWei Huang {
25603260531SWei Huang int n = 0;
25703260531SWei Huang
25803260531SWei Huang if (!afu_dev || !name || !size)
25903260531SWei Huang return -EINVAL;
26003260531SWei Huang
26103260531SWei Huang n = snprintf(name, size, "afu_%s", afu_dev->device.name);
26203260531SWei Huang if (n >= (int)size) {
26303260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Name of AFU device is too long!");
26403260531SWei Huang return -ENAMETOOLONG;
26503260531SWei Huang }
26603260531SWei Huang
26703260531SWei Huang return 0;
26803260531SWei Huang }
26903260531SWei Huang
afu_ops_get(struct rte_afu_uuid * afu_id)27003260531SWei Huang static struct afu_ops *afu_ops_get(struct rte_afu_uuid *afu_id)
27103260531SWei Huang {
27203260531SWei Huang struct afu_rawdev_drv *drv = NULL;
27303260531SWei Huang
27403260531SWei Huang if (!afu_id)
27503260531SWei Huang return NULL;
27603260531SWei Huang
27703260531SWei Huang TAILQ_FOREACH(drv, &afu_pmd_list, next) {
27803260531SWei Huang if ((drv->uuid.uuid_low == afu_id->uuid_low) &&
27903260531SWei Huang (drv->uuid.uuid_high == afu_id->uuid_high))
28003260531SWei Huang break;
28103260531SWei Huang }
28203260531SWei Huang
28303260531SWei Huang return drv ? drv->ops : NULL;
28403260531SWei Huang }
28503260531SWei Huang
afu_rawdev_create(struct rte_afu_device * afu_dev,int socket_id)28603260531SWei Huang static int afu_rawdev_create(struct rte_afu_device *afu_dev, int socket_id)
28703260531SWei Huang {
28803260531SWei Huang struct rte_rawdev *rawdev = NULL;
28903260531SWei Huang struct afu_rawdev *dev = NULL;
29003260531SWei Huang char name[RTE_RAWDEV_NAME_MAX_LEN] = {0};
29103260531SWei Huang int ret = 0;
29203260531SWei Huang
29303260531SWei Huang if (!afu_dev)
29403260531SWei Huang return -EINVAL;
29503260531SWei Huang
29603260531SWei Huang ret = afu_rawdev_name_get(afu_dev, name, sizeof(name));
29703260531SWei Huang if (ret)
29803260531SWei Huang return ret;
29903260531SWei Huang
30003260531SWei Huang IFPGA_RAWDEV_PMD_INFO("Create raw device %s on NUMA node %d",
30103260531SWei Huang name, socket_id);
30203260531SWei Huang
30303260531SWei Huang /* Allocate device structure */
30403260531SWei Huang rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct afu_rawdev),
30503260531SWei Huang socket_id);
30603260531SWei Huang if (!rawdev) {
30703260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Unable to allocate raw device");
30803260531SWei Huang return -ENOMEM;
30903260531SWei Huang }
31003260531SWei Huang
31103260531SWei Huang rawdev->dev_ops = &afu_rawdev_ops;
31203260531SWei Huang rawdev->device = &afu_dev->device;
31303260531SWei Huang rawdev->driver_name = afu_dev->driver->driver.name;
31403260531SWei Huang
31503260531SWei Huang dev = afu_rawdev_get_priv(rawdev);
31603260531SWei Huang if (!dev)
31703260531SWei Huang goto cleanup;
31803260531SWei Huang
31903260531SWei Huang dev->rawdev = rawdev;
32003260531SWei Huang dev->port = afu_dev->id.port;
32103260531SWei Huang dev->addr = afu_dev->mem_resource[0].addr;
32203260531SWei Huang dev->ops = afu_ops_get(&afu_dev->id.uuid);
32303260531SWei Huang if (dev->ops == NULL) {
32403260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Unsupported AFU device");
32503260531SWei Huang goto cleanup;
32603260531SWei Huang }
32703260531SWei Huang
32803260531SWei Huang if (dev->ops->init) {
32903260531SWei Huang ret = (*dev->ops->init)(dev);
33003260531SWei Huang if (ret) {
33103260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Failed to init %s", name);
33203260531SWei Huang goto cleanup;
33303260531SWei Huang }
33403260531SWei Huang }
33503260531SWei Huang
33603260531SWei Huang ret = afu_shared_data_alloc(name, &dev->sd, socket_id);
33703260531SWei Huang if (ret)
33803260531SWei Huang goto cleanup;
33903260531SWei Huang
34003260531SWei Huang return ret;
34103260531SWei Huang
34203260531SWei Huang cleanup:
34303260531SWei Huang rte_rawdev_pmd_release(rawdev);
34403260531SWei Huang return ret;
34503260531SWei Huang }
34603260531SWei Huang
afu_rawdev_destroy(struct rte_afu_device * afu_dev)34703260531SWei Huang static int afu_rawdev_destroy(struct rte_afu_device *afu_dev)
34803260531SWei Huang {
34903260531SWei Huang struct rte_rawdev *rawdev = NULL;
35003260531SWei Huang char name[RTE_RAWDEV_NAME_MAX_LEN] = {0};
35103260531SWei Huang int ret = 0;
35203260531SWei Huang
35303260531SWei Huang if (!afu_dev)
35403260531SWei Huang return -EINVAL;
35503260531SWei Huang
35603260531SWei Huang ret = afu_rawdev_name_get(afu_dev, name, sizeof(name));
35703260531SWei Huang if (ret)
35803260531SWei Huang return ret;
35903260531SWei Huang
36003260531SWei Huang IFPGA_RAWDEV_PMD_INFO("Destroy raw device %s", name);
36103260531SWei Huang
36203260531SWei Huang rawdev = rte_rawdev_pmd_get_named_dev(name);
36303260531SWei Huang if (!rawdev) {
36403260531SWei Huang IFPGA_RAWDEV_PMD_ERR("Raw device %s not found", name);
36503260531SWei Huang return -EINVAL;
36603260531SWei Huang }
36703260531SWei Huang
36803260531SWei Huang /* rte_rawdev_close is called by pmd_release */
36903260531SWei Huang ret = rte_rawdev_pmd_release(rawdev);
37003260531SWei Huang if (ret)
37103260531SWei Huang IFPGA_RAWDEV_PMD_DEBUG("Device cleanup failed");
37203260531SWei Huang
37303260531SWei Huang return 0;
37403260531SWei Huang }
37503260531SWei Huang
afu_rawdev_probe(struct rte_afu_device * afu_dev)37603260531SWei Huang static int afu_rawdev_probe(struct rte_afu_device *afu_dev)
37703260531SWei Huang {
37803260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
37903260531SWei Huang return afu_rawdev_create(afu_dev, rte_socket_id());
38003260531SWei Huang }
38103260531SWei Huang
afu_rawdev_remove(struct rte_afu_device * afu_dev)38203260531SWei Huang static int afu_rawdev_remove(struct rte_afu_device *afu_dev)
38303260531SWei Huang {
38403260531SWei Huang IFPGA_RAWDEV_PMD_FUNC_TRACE();
38503260531SWei Huang return afu_rawdev_destroy(afu_dev);
38603260531SWei Huang }
38703260531SWei Huang
38803260531SWei Huang static struct rte_afu_driver afu_pmd = {
38903260531SWei Huang .id_table = afu_pmd_uuid_map,
39003260531SWei Huang .probe = afu_rawdev_probe,
39103260531SWei Huang .remove = afu_rawdev_remove
39203260531SWei Huang };
39303260531SWei Huang
39403260531SWei Huang RTE_PMD_REGISTER_AFU(afu_rawdev_driver, afu_pmd);
39503260531SWei Huang
update_uuid_map(void)39603260531SWei Huang static void update_uuid_map(void)
39703260531SWei Huang {
39803260531SWei Huang int i = 0;
39903260531SWei Huang struct rte_afu_uuid *afu_id = afu_pmd_uuid_map;
40003260531SWei Huang struct afu_rawdev_drv *drv;
40103260531SWei Huang
40203260531SWei Huang TAILQ_FOREACH(drv, &afu_pmd_list, next) {
40303260531SWei Huang if (i++ < AFU_RAWDEV_MAX_DRVS) {
40403260531SWei Huang afu_id->uuid_low = drv->uuid.uuid_low;
40503260531SWei Huang afu_id->uuid_high = drv->uuid.uuid_high;
40603260531SWei Huang afu_id++;
40703260531SWei Huang }
40803260531SWei Huang }
40903260531SWei Huang if (i <= AFU_RAWDEV_MAX_DRVS) {
41003260531SWei Huang afu_id->uuid_low = 0;
41103260531SWei Huang afu_id->uuid_high = 0;
41203260531SWei Huang }
41303260531SWei Huang }
41403260531SWei Huang
afu_pmd_register(struct afu_rawdev_drv * driver)41503260531SWei Huang void afu_pmd_register(struct afu_rawdev_drv *driver)
41603260531SWei Huang {
41703260531SWei Huang TAILQ_INSERT_TAIL(&afu_pmd_list, driver, next);
41803260531SWei Huang update_uuid_map();
41903260531SWei Huang }
42003260531SWei Huang
afu_pmd_unregister(struct afu_rawdev_drv * driver)42103260531SWei Huang void afu_pmd_unregister(struct afu_rawdev_drv *driver)
42203260531SWei Huang {
42303260531SWei Huang TAILQ_REMOVE(&afu_pmd_list, driver, next);
42403260531SWei Huang update_uuid_map();
42503260531SWei Huang }
426