The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
    3  *
    4  * This software is available to you under a choice of one of two
    5  * licenses.  You may choose to be licensed under the terms of the GNU
    6  * General Public License (GPL) Version 2, available from the file
    7  * COPYING in the main directory of this source tree, or the
    8  * OpenIB.org BSD license below:
    9  *
   10  *     Redistribution and use in source and binary forms, with or
   11  *     without modification, are permitted provided that the following
   12  *     conditions are met:
   13  *
   14  *      - Redistributions of source code must retain the above
   15  *        copyright notice, this list of conditions and the following
   16  *        disclaimer.
   17  *
   18  *      - Redistributions in binary form must reproduce the above
   19  *        copyright notice, this list of conditions and the following
   20  *        disclaimer in the documentation and/or other materials
   21  *        provided with the distribution.
   22  *
   23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   30  * SOFTWARE.
   31  *
   32  * $FreeBSD$
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/conf.h>
   38 #include <dev/mlx5/mlx5io.h>
   39 #include <dev/mlx5/mlx5_fpga_tools/tools_char.h>
   40 
   41 #define CHUNK_SIZE (128 * 1024)
   42 
   43 struct tools_context {
   44         struct mlx5_fpga_tools_dev *tdev;
   45         enum mlx5_fpga_access_type access_type;
   46 };
   47 
   48 static void
   49 tools_char_ctx_dtor(void *data)
   50 {
   51 
   52         free(data, M_DEVBUF);
   53 }
   54 
   55 static int
   56 tools_char_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
   57 {
   58         struct tools_context *context;
   59 
   60         context = malloc(sizeof(*context), M_DEVBUF, M_WAITOK);
   61         context->tdev = dev->si_drv1;
   62         context->access_type = MLX5_FPGA_ACCESS_TYPE_DONTCARE;
   63         devfs_set_cdevpriv(context, tools_char_ctx_dtor);
   64         return (0);
   65 }
   66 
   67 static int
   68 mem_read(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count,
   69     u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt)
   70 {
   71         int ret;
   72 
   73         ret = sx_xlock_sig(&tdev->lock);
   74         if (ret != 0)
   75                 return (ret);
   76         ret = mlx5_fpga_mem_read(tdev->fdev, count, address, buf, access_type);
   77         sx_xunlock(&tdev->lock);
   78         if (ret < 0) {
   79                 dev_dbg(mlx5_fpga_dev(tdev->fdev),
   80                         "Failed to read %zu bytes at address 0x%jx: %d\n",
   81                         count, (uintmax_t)address, ret);
   82                 return (-ret);
   83         }
   84         *retcnt = ret;
   85         return (0);
   86 }
   87 
   88 static int
   89 mem_write(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count,
   90     u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt)
   91 {
   92         int ret;
   93 
   94         ret = sx_xlock_sig(&tdev->lock);
   95         if (ret != 0)
   96                 return (ret);
   97         ret = mlx5_fpga_mem_write(tdev->fdev, count, address, buf, access_type);
   98         sx_xunlock(&tdev->lock);
   99         if (ret < 0) {
  100                 dev_dbg(mlx5_fpga_dev(tdev->fdev),
  101                         "Failed to write %zu bytes at address 0x%jx: %d\n",
  102                         count, (uintmax_t)address, ret);
  103                 return (-ret);
  104         }
  105         *retcnt = ret;
  106         return (0);
  107 }
  108 
  109 static void
  110 tools_char_llseek(struct tools_context *context, struct uio *uio, ssize_t *len)
  111 {
  112         uint64_t fbase, fsize;
  113         size_t llen;
  114 
  115         llen = uio->uio_resid;
  116         if (llen < 1) {
  117                 *len = 0;
  118                 return;
  119         }
  120         if (llen > CHUNK_SIZE)
  121                 llen = CHUNK_SIZE;
  122         fbase = mlx5_fpga_ddr_base_get(context->tdev->fdev);
  123         fsize = mlx5_fpga_ddr_size_get(context->tdev->fdev);
  124         if (uio->uio_offset > fbase)
  125                 *len = 0;
  126         else if (uio->uio_offset + *len > fbase + fsize)
  127                 *len = fbase + fsize - uio->uio_offset;
  128         else
  129                 *len = llen;
  130 }
  131 
  132 static int
  133 tools_char_read(struct cdev *dev, struct uio *uio, int ioflag)
  134 {
  135         struct tools_context *context;
  136         void *kbuf;
  137         size_t len, len1;
  138         int ret;
  139 
  140         ret = devfs_get_cdevpriv((void **)&context);
  141         if (ret != 0)
  142                 return (ret);
  143         dev_dbg(mlx5_fpga_dev(context->tdev->fdev),
  144             "tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid,
  145              (uintmax_t)uio->uio_offset);
  146 
  147         tools_char_llseek(context, uio, &len);
  148         if (len == 0)
  149                 return (0);
  150 
  151         kbuf = malloc(len, M_DEVBUF, M_WAITOK);
  152         ret = mem_read(context->tdev, kbuf, len, uio->uio_offset,
  153             context->access_type, &len1);
  154         if (ret == 0)
  155                 ret = uiomove(kbuf, len1, uio);
  156         free(kbuf, M_DEVBUF);
  157         return (ret);
  158 }
  159 
  160 static int
  161 tools_char_write(struct cdev *dev, struct uio *uio, int ioflag)
  162 {
  163         struct tools_context *context;
  164         void *kbuf;
  165         off_t of;
  166         size_t len, len1;
  167         int ret;
  168 
  169         ret = devfs_get_cdevpriv((void **)&context);
  170         if (ret != 0)
  171                 return (ret);
  172         dev_dbg(mlx5_fpga_dev(context->tdev->fdev),
  173             "tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid,
  174             (uintmax_t)uio->uio_offset);
  175 
  176         tools_char_llseek(context, uio, &len);
  177         if (len == 0)
  178                 return (0);
  179 
  180         kbuf = malloc(len, M_DEVBUF, M_WAITOK);
  181         len1 = uio->uio_resid;
  182         of = uio->uio_offset;
  183 
  184         ret = uiomove(kbuf, len, uio);
  185         if (ret == 0) {
  186                 len1 -= uio->uio_resid;
  187                 ret = mem_write(context->tdev, kbuf, len, of,
  188                     context->access_type, &len1);
  189         }
  190         free(kbuf, M_DEVBUF);
  191         return (ret);
  192 }
  193 
  194 CTASSERT(MLX5_FPGA_CAP_ARR_SZ == MLX5_ST_SZ_DW(fpga_cap));
  195 
  196 static int
  197 tools_char_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
  198     struct thread *td)
  199 {
  200         struct tools_context *context;
  201         struct mlx5_fpga_device *fdev;
  202         struct mlx5_fpga_query query;
  203         struct mlx5_fpga_temperature *temperature;
  204         enum mlx5_fpga_connect *connect;
  205         u32 fpga_cap[MLX5_ST_SZ_DW(fpga_cap)] = {0};
  206         int arg, err;
  207 
  208         err = devfs_get_cdevpriv((void **)&context);
  209         if (err != 0)
  210                 return (err);
  211         fdev = context->tdev->fdev;
  212         if (fdev == NULL)
  213                 return (ENXIO);
  214 
  215         switch (cmd) {
  216         case MLX5_FPGA_ACCESS_TYPE:
  217                 arg = *(int *)data;
  218                 if (arg > MLX5_FPGA_ACCESS_TYPE_MAX) {
  219                         dev_err(mlx5_fpga_dev(fdev),
  220                             "unknown access type %u\n", arg);
  221                         err = EINVAL;
  222                         break;
  223                 }
  224                 context->access_type = arg;
  225                 break;
  226         case MLX5_FPGA_LOAD:
  227                 arg = *(int *)data;
  228                 if (arg > MLX5_FPGA_IMAGE_FACTORY) {
  229                         dev_err(mlx5_fpga_dev(fdev),
  230                                 "unknown image type %u\n", arg);
  231                         err = EINVAL;
  232                         break;
  233                 }
  234                 err = mlx5_fpga_device_reload(fdev, arg);
  235                 break;
  236         case MLX5_FPGA_RESET:
  237                 err = mlx5_fpga_device_reload(fdev, MLX5_FPGA_IMAGE_RESET);
  238                 break;
  239         case MLX5_FPGA_RELOAD:
  240                 err = mlx5_fpga_device_reload(fdev, MLX5_FPGA_IMAGE_RELOAD);
  241                 break;
  242         case MLX5_FPGA_IMAGE_SEL:
  243                 arg = *(int *)data;
  244                 if (arg > MLX5_FPGA_IMAGE_FACTORY) {
  245                         dev_err(mlx5_fpga_dev(fdev),
  246                             "unknown image type %u\n", arg);
  247                         err = EINVAL;
  248                         break;
  249                 }
  250                 err = mlx5_fpga_flash_select(fdev, arg);
  251                 break;
  252         case MLX5_FPGA_QUERY:
  253                 mlx5_fpga_device_query(fdev, &query);
  254                 bcopy(&query, data, sizeof(query));
  255                 err = 0;
  256                 break;
  257         case MLX5_FPGA_CAP:
  258                 mlx5_fpga_get_cap(fdev, fpga_cap);
  259                 bcopy(&fpga_cap, data, sizeof(fpga_cap));
  260                 err = 0;
  261                 break;
  262         case MLX5_FPGA_TEMPERATURE:
  263                 temperature = (struct mlx5_fpga_temperature *)data;
  264                 mlx5_fpga_temperature(fdev, temperature);
  265                 err = 0; /* XXXKIB */
  266                 break;
  267         case MLX5_FPGA_CONNECT:
  268                 connect = (enum mlx5_fpga_connect *)data;
  269                 mlx5_fpga_connectdisconnect(fdev, connect);
  270                 err = 0; /* XXXKIB */
  271                 break;
  272         default:
  273                 dev_err(mlx5_fpga_dev(fdev),
  274                         "unknown ioctl command %#08lx\n", cmd);
  275                 err = ENOTTY;
  276         }
  277         return (err);
  278 }
  279 
  280 static struct cdevsw mlx5_tools_char_cdevsw = {
  281         .d_version =    D_VERSION,
  282         .d_name =       "mlx5_tools_char",
  283         .d_open =       tools_char_open,
  284         .d_read =       tools_char_read,
  285         .d_write =      tools_char_write,
  286         .d_ioctl =      tools_char_ioctl,
  287 };
  288 
  289 int
  290 mlx5_fpga_tools_char_add_one(struct mlx5_fpga_tools_dev *tdev)
  291 {
  292         struct make_dev_args mda;
  293         struct cdev *cd;
  294         device_t bdev;
  295         int ret;
  296 
  297         make_dev_args_init(&mda);
  298         mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
  299         mda.mda_devsw = &mlx5_tools_char_cdevsw;
  300         mda.mda_uid = UID_ROOT;
  301         mda.mda_gid = GID_OPERATOR;
  302         mda.mda_mode = 0660;
  303         mda.mda_si_drv1 = tdev;
  304         bdev = mlx5_fpga_dev(tdev->fdev)->bsddev;
  305         ret = make_dev_s(&mda, &cd,
  306             "%04x:%02x:%02x.%x" MLX5_FPGA_TOOLS_NAME_SUFFIX,
  307             pci_get_domain(bdev), pci_get_bus(bdev), pci_get_slot(bdev),
  308             pci_get_function(bdev));
  309         if (ret != 0) {
  310                 tdev->char_device = NULL;
  311                 dev_err(mlx5_fpga_dev(tdev->fdev),
  312                     "Failed to create a char device: %d\n", ret);
  313                 return (-ret);
  314         }
  315         tdev->char_device = cd;
  316 
  317         dev_dbg(mlx5_fpga_dev(tdev->fdev), "tools char device %s created\n",
  318             cd->si_name);
  319         return (0);
  320 }
  321 
  322 void mlx5_fpga_tools_char_remove_one(struct mlx5_fpga_tools_dev *tdev)
  323 {
  324 
  325         dev_err(mlx5_fpga_dev(tdev->fdev), "tools char device %s destroyed\n",
  326             ((struct cdev *)(tdev->char_device))->si_name);
  327         destroy_dev((struct cdev *)(tdev->char_device));
  328 }
  329 
  330 int
  331 mlx5_fpga_tools_char_init(void)
  332 {
  333 
  334         return (0);
  335 }
  336 
  337 void
  338 mlx5_fpga_tools_char_deinit(void)
  339 {
  340 }

Cache object: fcb7b61273c9287a42daa4e55ebd3003


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.