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/mlx5fpga_sdk.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 <linux/errno.h>
   36 #include <linux/err.h>
   37 #include <linux/completion.h>
   38 #include <dev/mlx5/device.h>
   39 #include <dev/mlx5/mlx5_fpga/core.h>
   40 #include <dev/mlx5/mlx5_fpga/conn.h>
   41 #include <dev/mlx5/mlx5_fpga/sdk.h>
   42 #include <dev/mlx5/mlx5_fpga/xfer.h>
   43 #include <dev/mlx5/mlx5_core/mlx5_core.h>
   44 /* #include "accel/ipsec.h" */
   45 
   46 #define MLX5_FPGA_LOAD_TIMEOUT 25000 /* msec */
   47 
   48 struct mem_transfer {
   49         struct mlx5_fpga_transaction t;
   50         struct completion comp;
   51         u8 status;
   52 };
   53 
   54 struct mlx5_fpga_conn *
   55 mlx5_fpga_sbu_conn_create(struct mlx5_fpga_device *fdev,
   56                           struct mlx5_fpga_conn_attr *attr)
   57 {
   58 #ifdef NOT_YET
   59         /* XXXKIB */
   60         return mlx5_fpga_conn_create(fdev, attr, MLX5_FPGA_QPC_QP_TYPE_SANDBOX_QP);
   61 #else
   62         return (NULL);
   63 #endif
   64 }
   65 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_create);
   66 
   67 void mlx5_fpga_sbu_conn_destroy(struct mlx5_fpga_conn *conn)
   68 {
   69 #ifdef NOT_YET
   70         /* XXXKIB */
   71         mlx5_fpga_conn_destroy(conn);
   72 #endif
   73 }
   74 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_destroy);
   75 
   76 int mlx5_fpga_sbu_conn_sendmsg(struct mlx5_fpga_conn *conn,
   77                                struct mlx5_fpga_dma_buf *buf)
   78 {
   79 #ifdef NOT_YET
   80         /* XXXKIB */
   81         return mlx5_fpga_conn_send(conn, buf);
   82 #else
   83         return (0);
   84 #endif
   85 }
   86 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_sendmsg);
   87 
   88 static void mem_complete(const struct mlx5_fpga_transaction *complete,
   89                          u8 status)
   90 {
   91         struct mem_transfer *xfer;
   92 
   93         mlx5_fpga_dbg(complete->conn->fdev,
   94                       "transaction %p complete status %u", complete, status);
   95 
   96         xfer = container_of(complete, struct mem_transfer, t);
   97         xfer->status = status;
   98         complete_all(&xfer->comp);
   99 }
  100 
  101 static int mem_transaction(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
  102                            void *buf, enum mlx5_fpga_direction direction)
  103 {
  104         int ret;
  105         struct mem_transfer xfer;
  106 
  107         if (!fdev->shell_conn) {
  108                 ret = -ENOTCONN;
  109                 goto out;
  110         }
  111 
  112         xfer.t.data = buf;
  113         xfer.t.size = size;
  114         xfer.t.addr = addr;
  115         xfer.t.conn = fdev->shell_conn;
  116         xfer.t.direction = direction;
  117         xfer.t.complete1 = mem_complete;
  118         init_completion(&xfer.comp);
  119         ret = mlx5_fpga_xfer_exec(&xfer.t);
  120         if (ret) {
  121                 mlx5_fpga_dbg(fdev, "Transfer execution failed: %d\n", ret);
  122                 goto out;
  123         }
  124         wait_for_completion(&xfer.comp);
  125         if (xfer.status != 0)
  126                 ret = -EIO;
  127 
  128 out:
  129         return ret;
  130 }
  131 
  132 static int mlx5_fpga_mem_read_i2c(struct mlx5_fpga_device *fdev, size_t size,
  133                                   u64 addr, u8 *buf)
  134 {
  135         size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
  136         size_t bytes_done = 0;
  137         u8 actual_size;
  138         int err = 0;
  139 
  140         if (!size)
  141                 return -EINVAL;
  142 
  143         if (!fdev->mdev)
  144                 return -ENOTCONN;
  145 
  146         while (bytes_done < size) {
  147                 actual_size = min(max_size, (size - bytes_done));
  148 
  149                 err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
  150                                            addr + bytes_done,
  151                                            buf + bytes_done, false);
  152                 if (err) {
  153                         mlx5_fpga_err(fdev, "Failed to read over I2C: %d\n",
  154                                       err);
  155                         break;
  156                 }
  157 
  158                 bytes_done += actual_size;
  159         }
  160 
  161         return err;
  162 }
  163 
  164 static int mlx5_fpga_mem_write_i2c(struct mlx5_fpga_device *fdev, size_t size,
  165                                    u64 addr, u8 *buf)
  166 {
  167         size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
  168         size_t bytes_done = 0;
  169         u8 actual_size;
  170         int err = 0;
  171 
  172         if (!size)
  173                 return -EINVAL;
  174 
  175         if (!fdev->mdev)
  176                 return -ENOTCONN;
  177 
  178         while (bytes_done < size) {
  179                 actual_size = min(max_size, (size - bytes_done));
  180 
  181                 err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
  182                                            addr + bytes_done,
  183                                            buf + bytes_done, true);
  184                 if (err) {
  185                         mlx5_fpga_err(fdev, "Failed to write FPGA crspace\n");
  186                         break;
  187                 }
  188 
  189                 bytes_done += actual_size;
  190         }
  191 
  192         return err;
  193 }
  194 
  195 int mlx5_fpga_mem_read(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
  196                        void *buf, enum mlx5_fpga_access_type access_type)
  197 {
  198         int ret;
  199 
  200         if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
  201                 access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
  202                                                  MLX5_FPGA_ACCESS_TYPE_I2C;
  203 
  204         mlx5_fpga_dbg(fdev, "Reading %zu bytes at 0x%jx over %s",
  205                       size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
  206 
  207         switch (access_type) {
  208         case MLX5_FPGA_ACCESS_TYPE_RDMA:
  209                 ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_READ);
  210                 if (ret)
  211                         return ret;
  212                 break;
  213         case MLX5_FPGA_ACCESS_TYPE_I2C:
  214                 ret = mlx5_fpga_mem_read_i2c(fdev, size, addr, buf);
  215                 if (ret)
  216                         return ret;
  217                 break;
  218         default:
  219                 mlx5_fpga_warn(fdev, "Unexpected read access_type %u\n",
  220                                access_type);
  221                 return -EACCES;
  222         }
  223 
  224         return size;
  225 }
  226 EXPORT_SYMBOL(mlx5_fpga_mem_read);
  227 
  228 int mlx5_fpga_mem_write(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
  229                         void *buf, enum mlx5_fpga_access_type access_type)
  230 {
  231         int ret;
  232 
  233         if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
  234                 access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
  235                                                  MLX5_FPGA_ACCESS_TYPE_I2C;
  236 
  237         mlx5_fpga_dbg(fdev, "Writing %zu bytes at 0x%jx over %s",
  238                       size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
  239 
  240         switch (access_type) {
  241         case MLX5_FPGA_ACCESS_TYPE_RDMA:
  242                 ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_WRITE);
  243                 if (ret)
  244                         return ret;
  245                 break;
  246         case MLX5_FPGA_ACCESS_TYPE_I2C:
  247                 ret = mlx5_fpga_mem_write_i2c(fdev, size, addr, buf);
  248                 if (ret)
  249                         return ret;
  250                 break;
  251         default:
  252                 mlx5_fpga_warn(fdev, "Unexpected write access_type %u\n",
  253                                access_type);
  254                 return -EACCES;
  255         }
  256 
  257         return size;
  258 }
  259 EXPORT_SYMBOL(mlx5_fpga_mem_write);
  260 
  261 int mlx5_fpga_get_sbu_caps(struct mlx5_fpga_device *fdev, int size, void *buf)
  262 {
  263         return mlx5_fpga_sbu_caps(fdev->mdev, buf, size);
  264 }
  265 EXPORT_SYMBOL(mlx5_fpga_get_sbu_caps);
  266 
  267 u64 mlx5_fpga_ddr_size_get(struct mlx5_fpga_device *fdev)
  268 {
  269         return (u64)MLX5_CAP_FPGA(fdev->mdev, fpga_ddr_size) << 10;
  270 }
  271 EXPORT_SYMBOL(mlx5_fpga_ddr_size_get);
  272 
  273 u64 mlx5_fpga_ddr_base_get(struct mlx5_fpga_device *fdev)
  274 {
  275         return MLX5_CAP64_FPGA(fdev->mdev, fpga_ddr_start_addr);
  276 }
  277 EXPORT_SYMBOL(mlx5_fpga_ddr_base_get);
  278 
  279 void mlx5_fpga_client_data_set(struct mlx5_fpga_device *fdev,
  280                                struct mlx5_fpga_client *client, void *data)
  281 {
  282         struct mlx5_fpga_client_data *context;
  283 
  284         list_for_each_entry(context, &fdev->client_data_list, list) {
  285                 if (context->client != client)
  286                         continue;
  287                 context->data = data;
  288                 return;
  289         }
  290 
  291         mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
  292 }
  293 EXPORT_SYMBOL(mlx5_fpga_client_data_set);
  294 
  295 void *mlx5_fpga_client_data_get(struct mlx5_fpga_device *fdev,
  296                                 struct mlx5_fpga_client *client)
  297 {
  298         struct mlx5_fpga_client_data *context;
  299         void *ret = NULL;
  300 
  301         list_for_each_entry(context, &fdev->client_data_list, list) {
  302                 if (context->client != client)
  303                         continue;
  304                 ret = context->data;
  305                 goto out;
  306         }
  307         mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
  308 
  309 out:
  310         return ret;
  311 }
  312 EXPORT_SYMBOL(mlx5_fpga_client_data_get);
  313 
  314 void mlx5_fpga_device_query(struct mlx5_fpga_device *fdev,
  315                             struct mlx5_fpga_query *query)
  316 {
  317         unsigned long flags;
  318 
  319         spin_lock_irqsave(&fdev->state_lock, flags);
  320         query->image_status = fdev->image_status;
  321         query->admin_image = fdev->last_admin_image;
  322         query->oper_image = fdev->last_oper_image;
  323         spin_unlock_irqrestore(&fdev->state_lock, flags);
  324 }
  325 EXPORT_SYMBOL(mlx5_fpga_device_query);
  326 
  327 static int mlx5_fpga_device_reload_cmd(struct mlx5_fpga_device *fdev)
  328 {
  329         struct mlx5_core_dev *mdev = fdev->mdev;
  330         unsigned long timeout;
  331         unsigned long flags;
  332         int err = 0;
  333 
  334         mlx5_fpga_info(fdev, "mlx5/fpga - reload started\n");
  335         fdev->fdev_state = MLX5_FDEV_STATE_IN_PROGRESS;
  336         reinit_completion(&fdev->load_event);
  337         err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RELOAD);
  338         if (err) {
  339                 mlx5_fpga_err(fdev, "Failed to request reload: %d\n",
  340                               err);
  341                 goto out;
  342         }
  343         timeout = jiffies + msecs_to_jiffies(MLX5_FPGA_LOAD_TIMEOUT);
  344         err = wait_for_completion_timeout(&fdev->load_event,
  345                                           timeout - jiffies);
  346         if (err < 0) {
  347                 mlx5_fpga_err(fdev, "Failed waiting for reload: %d\n", err);
  348                 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
  349                 goto out;
  350         }
  351         /* Check device loaded successful */
  352         err = mlx5_fpga_device_start(mdev);
  353         if (err) {
  354                 mlx5_fpga_err(fdev, "Failed load check for reload: %d\n", err);
  355                 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
  356                 goto out;
  357         }
  358         spin_lock_irqsave(&fdev->state_lock, flags);
  359         fdev->fdev_state = MLX5_FDEV_STATE_SUCCESS;
  360         spin_unlock_irqrestore(&fdev->state_lock, flags);
  361         mlx5_fpga_info(fdev, "mlx5/fpga - reload ended\n");
  362 out:
  363         return err;
  364 }
  365 
  366 int mlx5_fpga_device_reload(struct mlx5_fpga_device *fdev,
  367                             enum mlx5_fpga_image image)
  368 {
  369         struct mlx5_core_dev *mdev = fdev->mdev;
  370         unsigned long timeout;
  371         unsigned long flags;
  372         int err = 0;
  373 
  374         spin_lock_irqsave(&fdev->state_lock, flags);
  375         switch (fdev->fdev_state) {
  376         case MLX5_FDEV_STATE_NONE:
  377                 err = -ENODEV;
  378                 break;
  379         case MLX5_FDEV_STATE_IN_PROGRESS:
  380                 err = -EBUSY;
  381                 break;
  382         case MLX5_FDEV_STATE_SUCCESS:
  383         case MLX5_FDEV_STATE_FAILURE:
  384         case MLX5_FDEV_STATE_DISCONNECTED:
  385                 break;
  386         }
  387         spin_unlock_irqrestore(&fdev->state_lock, flags);
  388         if (err)
  389                 return err;
  390 
  391         mutex_lock(&mdev->intf_state_mutex);
  392 
  393         if (image == MLX5_FPGA_IMAGE_RELOAD) {
  394                 err = mlx5_fpga_device_reload_cmd(fdev);
  395                 goto out;
  396         }
  397 
  398         clear_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
  399 
  400         mlx5_unregister_device(mdev);
  401         /* XXXKIB       mlx5_accel_ipsec_cleanup(mdev); */
  402         mlx5_fpga_device_stop(mdev);
  403 
  404         fdev->fdev_state = MLX5_FDEV_STATE_IN_PROGRESS;
  405         reinit_completion(&fdev->load_event);
  406 
  407         if (image <= MLX5_FPGA_IMAGE_FACTORY) {
  408                 mlx5_fpga_info(fdev, "Loading from flash\n");
  409                 err = mlx5_fpga_load(mdev, image);
  410                 if (err) {
  411                         mlx5_fpga_err(fdev, "Failed to request load: %d\n",
  412                                       err);
  413                         goto out;
  414                 }
  415         } else if (image == MLX5_FPGA_IMAGE_RESET) {
  416                 mlx5_fpga_info(fdev, "Resetting\n");
  417                 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET);
  418                 if (err) {
  419                         mlx5_fpga_err(fdev, "Failed to request reset: %d\n",
  420                                       err);
  421                         goto out;
  422                 }
  423         } else {
  424                 mlx5_fpga_err(fdev, "Unknown command: %d\n",
  425                               image);
  426                 goto out;
  427         }
  428 
  429         timeout = jiffies + msecs_to_jiffies(MLX5_FPGA_LOAD_TIMEOUT);
  430         err = wait_for_completion_timeout(&fdev->load_event, timeout - jiffies);
  431         if (err < 0) {
  432                 mlx5_fpga_err(fdev, "Failed waiting for FPGA load: %d\n", err);
  433                 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
  434                 goto out;
  435         }
  436 
  437         err = mlx5_fpga_device_start(mdev);
  438         if (err) {
  439                 mlx5_core_err(mdev, "fpga device start failed %d\n", err);
  440                 goto out;
  441         }
  442         /* XXXKIB err = mlx5_accel_ipsec_init(mdev); */
  443         if (err) {
  444                 mlx5_core_err(mdev, "IPSec device start failed %d\n", err);
  445                 goto err_fpga;
  446         }
  447 
  448         err = mlx5_register_device(mdev);
  449         if (err) {
  450                 mlx5_core_err(mdev, "mlx5_register_device failed %d\n", err);
  451                 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
  452                 goto err_ipsec;
  453         }
  454 
  455         set_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
  456         goto out;
  457 
  458 err_ipsec:
  459         /* XXXKIB mlx5_accel_ipsec_cleanup(mdev); */
  460 err_fpga:
  461         mlx5_fpga_device_stop(mdev);
  462 out:
  463         mutex_unlock(&mdev->intf_state_mutex);
  464         return err;
  465 }
  466 EXPORT_SYMBOL(mlx5_fpga_device_reload);
  467 
  468 int mlx5_fpga_flash_select(struct mlx5_fpga_device *fdev,
  469                            enum mlx5_fpga_image image)
  470 {
  471         unsigned long flags;
  472         int err;
  473 
  474         spin_lock_irqsave(&fdev->state_lock, flags);
  475         switch (fdev->fdev_state) {
  476         case MLX5_FDEV_STATE_NONE:
  477                 spin_unlock_irqrestore(&fdev->state_lock, flags);
  478                 return -ENODEV;
  479         case MLX5_FDEV_STATE_DISCONNECTED:
  480         case MLX5_FDEV_STATE_IN_PROGRESS:
  481         case MLX5_FDEV_STATE_SUCCESS:
  482         case MLX5_FDEV_STATE_FAILURE:
  483                 break;
  484         }
  485         spin_unlock_irqrestore(&fdev->state_lock, flags);
  486 
  487         err = mlx5_fpga_image_select(fdev->mdev, image);
  488         if (err)
  489                 mlx5_fpga_err(fdev, "Failed to select flash image: %d\n", err);
  490         else
  491                 fdev->last_admin_image = image;
  492         return err;
  493 }
  494 EXPORT_SYMBOL(mlx5_fpga_flash_select);
  495 
  496 int mlx5_fpga_connectdisconnect(struct mlx5_fpga_device *fdev,
  497                                 enum mlx5_fpga_connect *connect)
  498 {
  499         unsigned long flags;
  500         int err;
  501 
  502         spin_lock_irqsave(&fdev->state_lock, flags);
  503         switch (fdev->fdev_state) {
  504         case MLX5_FDEV_STATE_NONE:
  505                 spin_unlock_irqrestore(&fdev->state_lock, flags);
  506                 return -ENODEV;
  507         case MLX5_FDEV_STATE_IN_PROGRESS:
  508         case MLX5_FDEV_STATE_SUCCESS:
  509         case MLX5_FDEV_STATE_FAILURE:
  510         case MLX5_FDEV_STATE_DISCONNECTED:
  511                 break;
  512         }
  513         spin_unlock_irqrestore(&fdev->state_lock, flags);
  514 
  515         err = mlx5_fpga_ctrl_connect(fdev->mdev, connect);
  516         if (err)
  517                 mlx5_fpga_err(fdev, "Failed to connect/disconnect: %d\n", err);
  518         return err;
  519 }
  520 EXPORT_SYMBOL(mlx5_fpga_connectdisconnect);
  521 
  522 int mlx5_fpga_temperature(struct mlx5_fpga_device *fdev,
  523                           struct mlx5_fpga_temperature *temp)
  524 {
  525         return mlx5_fpga_query_mtmp(fdev->mdev, temp);
  526 }
  527 EXPORT_SYMBOL(mlx5_fpga_temperature);
  528 
  529 struct device *mlx5_fpga_dev(struct mlx5_fpga_device *fdev)
  530 {
  531         return &fdev->mdev->pdev->dev;
  532 }
  533 EXPORT_SYMBOL(mlx5_fpga_dev);
  534 
  535 void mlx5_fpga_get_cap(struct mlx5_fpga_device *fdev, u32 *fpga_caps)
  536 {
  537         unsigned long flags;
  538 
  539         spin_lock_irqsave(&fdev->state_lock, flags);
  540         memcpy(fpga_caps, &fdev->mdev->caps.fpga, sizeof(fdev->mdev->caps.fpga));
  541         spin_unlock_irqrestore(&fdev->state_lock, flags);
  542 }
  543 EXPORT_SYMBOL(mlx5_fpga_get_cap);

Cache object: da9deb056133976303a7e10435d46acd


[ 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.