2022-06-03 19:15:11 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2021-03-31 10:09:42 +00:00
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "spdk/stdinc.h"
|
|
|
|
|
|
|
|
#include <accel-config/libaccel_config.h>
|
|
|
|
|
|
|
|
#include "spdk/env.h"
|
|
|
|
#include "spdk/util.h"
|
|
|
|
#include "spdk/memory.h"
|
|
|
|
#include "spdk/likely.h"
|
|
|
|
|
|
|
|
#include "spdk/log.h"
|
|
|
|
#include "spdk_internal/idxd.h"
|
|
|
|
|
2022-07-20 00:54:17 +00:00
|
|
|
#include "idxd_internal.h"
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
struct spdk_kernel_idxd_device {
|
|
|
|
struct spdk_idxd_device idxd;
|
|
|
|
struct accfg_ctx *ctx;
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
unsigned int max_batch_size;
|
|
|
|
unsigned int max_xfer_size;
|
|
|
|
unsigned int max_xfer_bits;
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
/* We only use a single WQ */
|
|
|
|
struct accfg_wq *wq;
|
|
|
|
int fd;
|
|
|
|
void *portal;
|
2021-03-31 10:09:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define __kernel_idxd(idxd) SPDK_CONTAINEROF(idxd, struct spdk_kernel_idxd_device, idxd)
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
static void
|
|
|
|
kernel_idxd_device_destruct(struct spdk_idxd_device *idxd)
|
2021-03-31 10:09:42 +00:00
|
|
|
{
|
2022-01-21 17:30:26 +00:00
|
|
|
struct spdk_kernel_idxd_device *kernel_idxd = __kernel_idxd(idxd);
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
if (kernel_idxd->portal != NULL) {
|
|
|
|
munmap(kernel_idxd->portal, 0x1000);
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
if (kernel_idxd->fd >= 0) {
|
|
|
|
close(kernel_idxd->fd);
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
accfg_unref(kernel_idxd->ctx);
|
|
|
|
free(kernel_idxd);
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-05-11 23:09:08 +00:00
|
|
|
static struct spdk_idxd_impl g_kernel_idxd_impl;
|
|
|
|
|
2021-03-31 10:09:42 +00:00
|
|
|
static int
|
2022-05-20 16:40:25 +00:00
|
|
|
kernel_idxd_probe(void *cb_ctx, spdk_idxd_attach_cb attach_cb, spdk_idxd_probe_cb probe_cb)
|
2021-03-31 10:09:42 +00:00
|
|
|
{
|
|
|
|
int rc;
|
2022-01-21 17:30:26 +00:00
|
|
|
struct accfg_ctx *ctx;
|
|
|
|
struct accfg_device *device;
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
rc = accfg_new(&ctx);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Unable to allocate accel-config context\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Loop over each IDXD device */
|
|
|
|
accfg_device_foreach(ctx, device) {
|
2021-03-31 10:09:42 +00:00
|
|
|
enum accfg_device_state dstate;
|
2022-01-21 17:30:26 +00:00
|
|
|
struct spdk_kernel_idxd_device *kernel_idxd;
|
|
|
|
struct accfg_wq *wq;
|
2021-03-31 10:09:42 +00:00
|
|
|
|
|
|
|
/* Make sure that the device is enabled */
|
|
|
|
dstate = accfg_device_get_state(device);
|
|
|
|
if (dstate != ACCFG_DEVICE_ENABLED) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
kernel_idxd = calloc(1, sizeof(struct spdk_kernel_idxd_device));
|
|
|
|
if (kernel_idxd == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to allocate memory for kernel_idxd device.\n");
|
|
|
|
/* TODO: Goto error cleanup */
|
|
|
|
return -ENOMEM;
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
kernel_idxd->max_batch_size = accfg_device_get_max_batch_size(device);
|
|
|
|
kernel_idxd->max_xfer_size = accfg_device_get_max_transfer_size(device);
|
|
|
|
kernel_idxd->idxd.socket_id = accfg_device_get_numa_node(device);
|
2022-05-11 23:09:08 +00:00
|
|
|
kernel_idxd->idxd.impl = &g_kernel_idxd_impl;
|
2022-01-21 17:30:26 +00:00
|
|
|
kernel_idxd->fd = -1;
|
|
|
|
|
2021-03-31 10:09:42 +00:00
|
|
|
accfg_wq_foreach(device, wq) {
|
|
|
|
enum accfg_wq_state wstate;
|
|
|
|
enum accfg_wq_mode mode;
|
|
|
|
enum accfg_wq_type type;
|
2022-01-21 17:30:26 +00:00
|
|
|
int major, minor;
|
|
|
|
char path[1024];
|
2021-03-31 10:09:42 +00:00
|
|
|
|
|
|
|
wstate = accfg_wq_get_state(wq);
|
|
|
|
if (wstate != ACCFG_WQ_ENABLED) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = accfg_wq_get_type(wq);
|
|
|
|
if (type != ACCFG_WQT_USER) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
/* TODO: For now, only support dedicated WQ */
|
2021-03-31 10:09:42 +00:00
|
|
|
mode = accfg_wq_get_mode(wq);
|
2022-01-21 17:30:26 +00:00
|
|
|
if (mode != ACCFG_WQ_DEDICATED) {
|
2021-03-31 10:09:42 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
major = accfg_device_get_cdev_major(device);
|
|
|
|
if (major < 0) {
|
|
|
|
continue;
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
minor = accfg_wq_get_cdev_minor(wq);
|
|
|
|
if (minor < 0) {
|
|
|
|
continue;
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
/* Map the portal */
|
|
|
|
snprintf(path, sizeof(path), "/dev/char/%u:%u", major, minor);
|
|
|
|
kernel_idxd->fd = open(path, O_RDWR);
|
|
|
|
if (kernel_idxd->fd < 0) {
|
|
|
|
SPDK_ERRLOG("Can not open the WQ file descriptor on path=%s\n",
|
|
|
|
path);
|
|
|
|
continue;
|
|
|
|
}
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
kernel_idxd->portal = mmap(NULL, 0x1000, PROT_WRITE,
|
|
|
|
MAP_SHARED | MAP_POPULATE, kernel_idxd->fd, 0);
|
|
|
|
if (kernel_idxd->portal == MAP_FAILED) {
|
|
|
|
perror("mmap");
|
|
|
|
continue;
|
2021-03-31 10:09:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
kernel_idxd->wq = wq;
|
2021-03-31 10:09:42 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
/* Since we only use a single WQ, the total size is the size of this WQ */
|
|
|
|
kernel_idxd->idxd.total_wq_size = accfg_wq_get_size(wq);
|
|
|
|
kernel_idxd->idxd.chan_per_device = (kernel_idxd->idxd.total_wq_size >= 128) ? 8 : 4;
|
|
|
|
/* TODO: Handle BOF when we add support for shared WQ */
|
|
|
|
/* wq_ctx->bof = accfg_wq_get_block_on_fault(wq); */
|
2022-01-21 19:50:31 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
/* We only use a single WQ, so once we've found one we can stop looking. */
|
|
|
|
break;
|
|
|
|
}
|
2022-01-21 19:50:31 +00:00
|
|
|
|
2022-01-21 17:30:26 +00:00
|
|
|
if (kernel_idxd->idxd.total_wq_size > 0) {
|
|
|
|
/* This device has at least 1 WQ available, so ask the user if they want to use it. */
|
|
|
|
attach_cb(cb_ctx, &kernel_idxd->idxd);
|
|
|
|
} else {
|
|
|
|
kernel_idxd_device_destruct(&kernel_idxd->idxd);
|
|
|
|
}
|
2022-01-21 19:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
kernel_idxd_dump_sw_error(struct spdk_idxd_device *idxd, void *portal)
|
|
|
|
{
|
|
|
|
/* Need to be enhanced later */
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
kernel_idxd_portal_get_addr(struct spdk_idxd_device *idxd)
|
|
|
|
{
|
|
|
|
struct spdk_kernel_idxd_device *kernel_idxd = __kernel_idxd(idxd);
|
2022-01-21 17:30:26 +00:00
|
|
|
|
|
|
|
return kernel_idxd->portal;
|
2022-01-21 19:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct spdk_idxd_impl g_kernel_idxd_impl = {
|
|
|
|
.name = "kernel",
|
|
|
|
.probe = kernel_idxd_probe,
|
|
|
|
.destruct = kernel_idxd_device_destruct,
|
|
|
|
.dump_sw_error = kernel_idxd_dump_sw_error,
|
|
|
|
.portal_get_addr = kernel_idxd_portal_get_addr,
|
|
|
|
};
|
|
|
|
|
2021-03-31 10:09:42 +00:00
|
|
|
SPDK_IDXD_IMPL_REGISTER(kernel, &g_kernel_idxd_impl);
|