diff --git a/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c b/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c new file mode 100644 index 000000000000..7dfe51a713c7 --- /dev/null +++ b/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c @@ -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 +#include +#include +#include +#include + +#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) +{ +} diff --git a/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_main.c b/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_main.c new file mode 100644 index 000000000000..b68643c97f12 --- /dev/null +++ b/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_main.c @@ -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 +#include +#include + +#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); diff --git a/sys/dev/mlx5/mlx5_fpga_tools/tools.h b/sys/dev/mlx5/mlx5_fpga_tools/tools.h new file mode 100644 index 000000000000..6b545eb2795f --- /dev/null +++ b/sys/dev/mlx5/mlx5_fpga_tools/tools.h @@ -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 +#include +#include +#include +#include +#include + +#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__ */ diff --git a/sys/dev/mlx5/mlx5_fpga_tools/tools_char.h b/sys/dev/mlx5/mlx5_fpga_tools/tools_char.h new file mode 100644 index 000000000000..1f80669c5811 --- /dev/null +++ b/sys/dev/mlx5/mlx5_fpga_tools/tools_char.h @@ -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 + +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__ */ diff --git a/sys/dev/mlx5/mlx5io.h b/sys/dev/mlx5/mlx5io.h index de10db26cba9..8e49056044fe 100644 --- a/sys/dev/mlx5/mlx5io.h +++ b/sys/dev/mlx5/mlx5io.h @@ -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 diff --git a/sys/modules/mlx5fpga_tools/Makefile b/sys/modules/mlx5fpga_tools/Makefile new file mode 100644 index 000000000000..c9bb559c7fcf --- /dev/null +++ b/sys/modules/mlx5fpga_tools/Makefile @@ -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 + +CFLAGS+= -Wno-cast-qual -Wno-pointer-arith ${GCC_MS_EXTENSIONS} +CFLAGS+= -DCONFIG_MLX5_FPGA -DCONFIG_MLX5_ACCEL