mlx5fpga_tools initial code import.

Submitted by:   kib@
Approved by:    hselasky (mentor)
MFC after:      1 week
Sponsored by:   Mellanox Technologies
This commit is contained in:
Slava Shwartsman 2018-12-05 14:17:22 +00:00
parent e9dcd83155
commit d50c55f17d
6 changed files with 609 additions and 0 deletions

View File

@ -0,0 +1,325 @@
/*-
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <dev/mlx5/mlx5io.h>
#include <dev/mlx5/mlx5_fpga_tools/tools_char.h>
#define CHUNK_SIZE (128 * 1024)
struct tools_context {
struct mlx5_fpga_tools_dev *tdev;
enum mlx5_fpga_access_type access_type;
};
static void
tools_char_ctx_dtor(void *data)
{
free(data, M_DEVBUF);
}
static int
tools_char_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
struct tools_context *context;
context = malloc(sizeof(*context), M_DEVBUF, M_WAITOK);
context->tdev = dev->si_drv1;
context->access_type = MLX5_FPGA_ACCESS_TYPE_DONTCARE;
devfs_set_cdevpriv(context, tools_char_ctx_dtor);
return (0);
}
static int
mem_read(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count,
u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt)
{
int ret;
ret = sx_xlock_sig(&tdev->lock);
if (ret != 0)
return (ret);
ret = mlx5_fpga_mem_read(tdev->fdev, count, address, buf, access_type);
sx_xunlock(&tdev->lock);
if (ret < 0) {
dev_dbg(mlx5_fpga_dev(tdev->fdev),
"Failed to read %zu bytes at address 0x%jx: %d\n",
count, (uintmax_t)address, ret);
return (-ret);
}
*retcnt = ret;
return (0);
}
static int
mem_write(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count,
u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt)
{
int ret;
ret = sx_xlock_sig(&tdev->lock);
if (ret != 0)
return (ret);
ret = mlx5_fpga_mem_write(tdev->fdev, count, address, buf, access_type);
sx_xunlock(&tdev->lock);
if (ret < 0) {
dev_dbg(mlx5_fpga_dev(tdev->fdev),
"Failed to write %zu bytes at address 0x%jx: %d\n",
count, (uintmax_t)address, ret);
return (-ret);
}
*retcnt = ret;
return (0);
}
static void
tools_char_llseek(struct tools_context *context, struct uio *uio, ssize_t *len)
{
uint64_t fbase, fsize;
size_t llen;
llen = uio->uio_resid;
if (llen < 1) {
*len = 0;
return;
}
if (llen > CHUNK_SIZE)
llen = CHUNK_SIZE;
fbase = mlx5_fpga_ddr_base_get(context->tdev->fdev);
fsize = mlx5_fpga_ddr_size_get(context->tdev->fdev);
if (uio->uio_offset > fbase)
*len = 0;
else if (uio->uio_offset + *len > fbase + fsize)
*len = fbase + fsize - uio->uio_offset;
else
*len = llen;
}
static int
tools_char_read(struct cdev *dev, struct uio *uio, int ioflag)
{
struct tools_context *context;
void *kbuf;
size_t len, len1;
int ret;
ret = devfs_get_cdevpriv((void **)&context);
if (ret != 0)
return (ret);
dev_dbg(mlx5_fpga_dev(context->tdev->fdev),
"tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid,
(uintmax_t)uio->uio_offset);
tools_char_llseek(context, uio, &len);
if (len == 0)
return (0);
kbuf = malloc(len, M_DEVBUF, M_WAITOK);
ret = mem_read(context->tdev, kbuf, len, uio->uio_offset,
context->access_type, &len1);
if (ret == 0)
ret = uiomove(kbuf, len1, uio);
free(kbuf, M_DEVBUF);
return (ret);
}
static int
tools_char_write(struct cdev *dev, struct uio *uio, int ioflag)
{
struct tools_context *context;
void *kbuf;
off_t of;
size_t len, len1;
int ret;
ret = devfs_get_cdevpriv((void **)&context);
if (ret != 0)
return (ret);
dev_dbg(mlx5_fpga_dev(context->tdev->fdev),
"tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid,
(uintmax_t)uio->uio_offset);
tools_char_llseek(context, uio, &len);
if (len == 0)
return (0);
kbuf = malloc(len, M_DEVBUF, M_WAITOK);
len1 = uio->uio_resid;
of = uio->uio_offset;
ret = uiomove(kbuf, len, uio);
if (ret == 0) {
len1 -= uio->uio_resid;
ret = mem_write(context->tdev, kbuf, len, of,
context->access_type, &len1);
}
free(kbuf, M_DEVBUF);
return (ret);
}
CTASSERT(MLX5_FPGA_CAP_ARR_SZ == MLX5_ST_SZ_DW(fpga_cap));
static int
tools_char_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
struct tools_context *context;
struct mlx5_fpga_device *fdev;
struct mlx5_fpga_query query;
u32 fpga_cap[MLX5_ST_SZ_DW(fpga_cap)] = {0};
int arg, err;
err = devfs_get_cdevpriv((void **)&context);
if (err != 0)
return (err);
fdev = context->tdev->fdev;
if (fdev == NULL)
return (ENXIO);
switch (cmd) {
case MLX5_FPGA_ACCESS_TYPE:
arg = *(int *)data;
if (arg > MLX5_FPGA_ACCESS_TYPE_MAX) {
dev_err(mlx5_fpga_dev(fdev),
"unknown access type %u\n", arg);
err = EINVAL;
break;
}
context->access_type = arg;
break;
case MLX5_FPGA_LOAD:
arg = *(int *)data;
if (arg > MLX5_FPGA_IMAGE_MAX) {
dev_err(mlx5_fpga_dev(fdev),
"unknown image type %u\n", arg);
err = EINVAL;
break;
}
err = mlx5_fpga_device_reload(fdev, arg);
break;
case MLX5_FPGA_RESET:
err = mlx5_fpga_device_reload(fdev, MLX5_FPGA_IMAGE_MAX + 1);
break;
case MLX5_FPGA_IMAGE_SEL:
arg = *(int *)data;
if (arg > MLX5_FPGA_IMAGE_MAX) {
dev_err(mlx5_fpga_dev(fdev),
"unknown image type %u\n", arg);
err = EINVAL;
break;
}
err = mlx5_fpga_flash_select(fdev, arg);
break;
case MLX5_FPGA_QUERY:
mlx5_fpga_device_query(fdev, &query);
bcopy(&query, data, sizeof(query));
err = 0;
break;
case MLX5_FPGA_CAP:
mlx5_fpga_get_cap(fdev, fpga_cap);
bcopy(&fpga_cap, data, sizeof(fpga_cap));
err = 0;
break;
default:
dev_err(mlx5_fpga_dev(fdev),
"unknown ioctl command %#08lx\n", cmd);
err = ENOTTY;
}
return (err);
}
static struct cdevsw mlx5_tools_char_cdevsw = {
.d_version = D_VERSION,
.d_name = "mlx5_tools_char",
.d_open = tools_char_open,
.d_read = tools_char_read,
.d_write = tools_char_write,
.d_ioctl = tools_char_ioctl,
};
int
mlx5_fpga_tools_char_add_one(struct mlx5_fpga_tools_dev *tdev)
{
struct make_dev_args mda;
struct cdev *cd;
device_t bdev;
int ret;
make_dev_args_init(&mda);
mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
mda.mda_devsw = &mlx5_tools_char_cdevsw;
mda.mda_uid = UID_ROOT;
mda.mda_gid = GID_OPERATOR;
mda.mda_mode = 0660;
mda.mda_si_drv1 = tdev;
bdev = mlx5_fpga_dev(tdev->fdev)->bsddev;
ret = make_dev_s(&mda, &cd,
"%04x:%02x:%02x.%x" MLX5_FPGA_TOOLS_NAME_SUFFIX,
pci_get_domain(bdev), pci_get_bus(bdev), pci_get_slot(bdev),
pci_get_function(bdev));
if (ret != 0) {
tdev->char_device = NULL;
dev_err(mlx5_fpga_dev(tdev->fdev),
"Failed to create a char device: %d\n", ret);
return (-ret);
}
tdev->char_device = cd;
dev_dbg(mlx5_fpga_dev(tdev->fdev), "tools char device %s created\n",
cd->si_name);
return (0);
}
void mlx5_fpga_tools_char_remove_one(struct mlx5_fpga_tools_dev *tdev)
{
dev_err(mlx5_fpga_dev(tdev->fdev), "tools char device %s destroyed\n",
((struct cdev *)(tdev->char_device))->si_name);
destroy_dev((struct cdev *)(tdev->char_device));
}
int
mlx5_fpga_tools_char_init(void)
{
return (0);
}
void
mlx5_fpga_tools_char_deinit(void)
{
}

View File

@ -0,0 +1,143 @@
/*-
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* $FreeBSD$
*/
#include <linux/module.h>
#include <dev/mlx5/mlx5_fpga_tools/tools.h>
#include <dev/mlx5/mlx5_fpga_tools/tools_char.h>
#if (__FreeBSD_version >= 1100000)
MODULE_DEPEND(mlx5fpga_tools, linuxkpi, 1, 1, 1);
#endif
MODULE_DEPEND(mlx5fpga_tools, mlx5, 1, 1, 1);
MODULE_DEPEND(mlx5fpga_tools, mlx5fpga, 1, 1, 1);
MODULE_VERSION(mlx5fpga_tools, 1);
static void mlx5_fpga_tools_create(struct mlx5_fpga_device *fdev);
static int mlx5_fpga_tools_add(struct mlx5_fpga_device *fdev, u32 vid, u16 pid);
static void mlx5_fpga_tools_remove(struct mlx5_fpga_device *fdev);
static void mlx5_fpga_tools_destroy(struct mlx5_fpga_device *fdev);
struct mlx5_fpga_tools_dev *mlx5_fpga_tools_alloc(struct mlx5_fpga_device *fdev);
void mlx5_fpga_tools_free(struct mlx5_fpga_tools_dev *tdev);
static struct mlx5_fpga_client mlx5_fpga_tools_client = {
.name = MLX5_FPGA_TOOLS_DRIVER_NAME,
.create = mlx5_fpga_tools_create,
.add = mlx5_fpga_tools_add,
.remove = mlx5_fpga_tools_remove,
.destroy = mlx5_fpga_tools_destroy,
};
struct mlx5_fpga_tools_dev *mlx5_fpga_tools_alloc(struct mlx5_fpga_device *fdev)
{
int ret;
struct mlx5_fpga_tools_dev *tdev;
tdev = kzalloc(sizeof(*tdev), GFP_KERNEL);
if (!tdev)
goto out;
tdev->fdev = fdev;
sx_init(&tdev->lock, "mlx5fpgat");
ret = mlx5_fpga_tools_char_add_one(tdev);
if (ret)
goto err_free;
goto out;
err_free:
kfree(tdev);
tdev = NULL;
out:
return tdev;
}
void mlx5_fpga_tools_free(struct mlx5_fpga_tools_dev *tdev)
{
mlx5_fpga_tools_char_remove_one(tdev);
kfree(tdev);
}
static void mlx5_fpga_tools_create(struct mlx5_fpga_device *fdev)
{
struct mlx5_fpga_tools_dev *dev = NULL;
dev_dbg(mlx5_fpga_dev(fdev), "tools_create\n");
dev = mlx5_fpga_tools_alloc(fdev);
if (!dev)
return;
mlx5_fpga_client_data_set(fdev, &mlx5_fpga_tools_client, dev);
}
static int mlx5_fpga_tools_add(struct mlx5_fpga_device *fdev, u32 vid, u16 pid)
{
return 0;
}
static void mlx5_fpga_tools_remove(struct mlx5_fpga_device *fdev)
{
}
static void mlx5_fpga_tools_destroy(struct mlx5_fpga_device *fdev)
{
struct mlx5_fpga_tools_dev *dev;
dev_dbg(mlx5_fpga_dev(fdev), "tools_destroy\n");
dev = mlx5_fpga_client_data_get(fdev, &mlx5_fpga_tools_client);
if (dev)
mlx5_fpga_tools_free(dev);
}
static int __init mlx5_fpga_tools_init(void)
{
int ret = mlx5_fpga_tools_char_init();
if (ret)
return ret;
mlx5_fpga_client_register(&mlx5_fpga_tools_client);
return 0;
}
static void __exit mlx5_fpga_tools_exit(void)
{
mlx5_fpga_client_unregister(&mlx5_fpga_tools_client);
mlx5_fpga_tools_char_deinit();
}
module_init(mlx5_fpga_tools_init);
module_exit(mlx5_fpga_tools_exit);

View File

@ -0,0 +1,65 @@
/*-
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* $FreeBSD$
*/
#ifndef __TOOLS_H__
#define __TOOLS_H__
#include <sys/lock.h>
#include <sys/sx.h>
#include <linux/types.h>
#include <linux/kobject.h>
#include <linux/list.h>
#include <dev/mlx5/mlx5_fpga/sdk.h>
#define MLX5_FPGA_TOOLS_DRIVER_NAME "mlx5_fpga_tools"
struct mlx5_fpga_tools_dev {
/* Core device and connection to FPGA */
struct mlx5_fpga_device *fdev;
/* Serializes memory accesses */
struct sx lock;
/* Char device state */
void *char_device;
};
int mlx5_fpga_tools_mem_write(struct mlx5_fpga_tools_dev *tdev,
void *buf, size_t count, u64 address,
enum mlx5_fpga_access_type access_type);
int mlx5_fpga_tools_mem_read(struct mlx5_fpga_tools_dev *tdev, void *buf,
size_t count, u64 address,
enum mlx5_fpga_access_type access_type);
#endif /* __TOOLS_H__ */

View File

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* $FreeBSD$
*/
#ifndef __TOOLS_CHAR_H__
#define __TOOLS_CHAR_H__
#include <dev/mlx5/mlx5_fpga_tools/tools.h>
int mlx5_fpga_tools_char_init(void);
void mlx5_fpga_tools_char_deinit(void);
int mlx5_fpga_tools_char_add_one(struct mlx5_fpga_tools_dev *tdev);
void mlx5_fpga_tools_char_remove_one(struct mlx5_fpga_tools_dev *tdev);
#endif /* __TOOLS_CHAR_H__ */

View File

@ -97,4 +97,15 @@ enum mlx5_fpga_access_type {
MLX5_FPGA_ACCESS_TYPE_MAX = MLX5_FPGA_ACCESS_TYPE_DONTCARE,
};
#define MLX5_FPGA_CAP_ARR_SZ 0x40
#define MLX5_FPGA_ACCESS_TYPE _IOWINT('m', 0x80)
#define MLX5_FPGA_LOAD _IOWINT('m', 0x81)
#define MLX5_FPGA_RESET _IO('m', 0x82)
#define MLX5_FPGA_IMAGE_SEL _IOWINT('m', 0x83)
#define MLX5_FPGA_QUERY _IOR('m', 0x84, struct mlx5_fpga_query)
#define MLX5_FPGA_CAP _IOR('m', 0x85, u32[MLX5_FPGA_CAP_ARR_SZ])
#define MLX5_FPGA_TOOLS_NAME_SUFFIX "_mlx5_fpga_tools"
#endif

View File

@ -0,0 +1,19 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/mlx5/mlx5_fpga_tools
KMOD=mlx5fpga_tools
SRCS= \
mlx5fpga_tools_main.c \
mlx5fpga_tools_char.c
SRCS+= \
device_if.h bus_if.h vnode_if.h pci_if.h \
opt_inet.h opt_inet6.h opt_rss.h opt_ratelimit.h
CFLAGS+= -I${SRCTOP}/sys/ofed/include
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
.include <bsd.kmod.mk>
CFLAGS+= -Wno-cast-qual -Wno-pointer-arith ${GCC_MS_EXTENSIONS}
CFLAGS+= -DCONFIG_MLX5_FPGA -DCONFIG_MLX5_ACCEL