1*e9dcd831SSlava Shwartsman /*- 2*e9dcd831SSlava Shwartsman * Copyright (c) 2017 Mellanox Technologies. All rights reserved. 3*e9dcd831SSlava Shwartsman * 4*e9dcd831SSlava Shwartsman * This software is available to you under a choice of one of two 5*e9dcd831SSlava Shwartsman * licenses. You may choose to be licensed under the terms of the GNU 6*e9dcd831SSlava Shwartsman * General Public License (GPL) Version 2, available from the file 7*e9dcd831SSlava Shwartsman * COPYING in the main directory of this source tree, or the 8*e9dcd831SSlava Shwartsman * OpenIB.org BSD license below: 9*e9dcd831SSlava Shwartsman * 10*e9dcd831SSlava Shwartsman * Redistribution and use in source and binary forms, with or 11*e9dcd831SSlava Shwartsman * without modification, are permitted provided that the following 12*e9dcd831SSlava Shwartsman * conditions are met: 13*e9dcd831SSlava Shwartsman * 14*e9dcd831SSlava Shwartsman * - Redistributions of source code must retain the above 15*e9dcd831SSlava Shwartsman * copyright notice, this list of conditions and the following 16*e9dcd831SSlava Shwartsman * disclaimer. 17*e9dcd831SSlava Shwartsman * 18*e9dcd831SSlava Shwartsman * - Redistributions in binary form must reproduce the above 19*e9dcd831SSlava Shwartsman * copyright notice, this list of conditions and the following 20*e9dcd831SSlava Shwartsman * disclaimer in the documentation and/or other materials 21*e9dcd831SSlava Shwartsman * provided with the distribution. 22*e9dcd831SSlava Shwartsman * 23*e9dcd831SSlava Shwartsman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24*e9dcd831SSlava Shwartsman * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25*e9dcd831SSlava Shwartsman * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26*e9dcd831SSlava Shwartsman * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27*e9dcd831SSlava Shwartsman * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28*e9dcd831SSlava Shwartsman * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29*e9dcd831SSlava Shwartsman * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30*e9dcd831SSlava Shwartsman * SOFTWARE. 31*e9dcd831SSlava Shwartsman * 32*e9dcd831SSlava Shwartsman * $FreeBSD$ 33*e9dcd831SSlava Shwartsman */ 34*e9dcd831SSlava Shwartsman 35*e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/trans.h> 36*e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/conn.h> 37*e9dcd831SSlava Shwartsman 38*e9dcd831SSlava Shwartsman enum mlx5_fpga_transaction_state { 39*e9dcd831SSlava Shwartsman TRANS_STATE_NONE, 40*e9dcd831SSlava Shwartsman TRANS_STATE_SEND, 41*e9dcd831SSlava Shwartsman TRANS_STATE_WAIT, 42*e9dcd831SSlava Shwartsman TRANS_STATE_COMPLETE, 43*e9dcd831SSlava Shwartsman }; 44*e9dcd831SSlava Shwartsman 45*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv { 46*e9dcd831SSlava Shwartsman const struct mlx5_fpga_transaction *user_trans; 47*e9dcd831SSlava Shwartsman u8 tid; 48*e9dcd831SSlava Shwartsman enum mlx5_fpga_transaction_state state; 49*e9dcd831SSlava Shwartsman u8 status; 50*e9dcd831SSlava Shwartsman u32 header[MLX5_ST_SZ_DW(fpga_shell_qp_packet)]; 51*e9dcd831SSlava Shwartsman struct mlx5_fpga_dma_buf buf; 52*e9dcd831SSlava Shwartsman struct list_head list_item; 53*e9dcd831SSlava Shwartsman }; 54*e9dcd831SSlava Shwartsman 55*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_device_state { 56*e9dcd831SSlava Shwartsman spinlock_t lock; /* Protects all members of this struct */ 57*e9dcd831SSlava Shwartsman struct list_head free_queue; 58*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv transactions[MLX5_FPGA_TID_COUNT]; 59*e9dcd831SSlava Shwartsman }; 60*e9dcd831SSlava Shwartsman 61*e9dcd831SSlava Shwartsman static struct mlx5_fpga_trans_priv *find_tid(struct mlx5_fpga_device *fdev, 62*e9dcd831SSlava Shwartsman u8 tid) 63*e9dcd831SSlava Shwartsman { 64*e9dcd831SSlava Shwartsman if (tid >= MLX5_FPGA_TID_COUNT) { 65*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Unexpected transaction ID %u\n", tid); 66*e9dcd831SSlava Shwartsman return NULL; 67*e9dcd831SSlava Shwartsman } 68*e9dcd831SSlava Shwartsman return &fdev->trans->transactions[tid]; 69*e9dcd831SSlava Shwartsman } 70*e9dcd831SSlava Shwartsman 71*e9dcd831SSlava Shwartsman static struct mlx5_fpga_trans_priv *alloc_tid(struct mlx5_fpga_device *fdev) 72*e9dcd831SSlava Shwartsman { 73*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *ret; 74*e9dcd831SSlava Shwartsman unsigned long flags; 75*e9dcd831SSlava Shwartsman 76*e9dcd831SSlava Shwartsman spin_lock_irqsave(&fdev->trans->lock, flags); 77*e9dcd831SSlava Shwartsman 78*e9dcd831SSlava Shwartsman if (list_empty(&fdev->trans->free_queue)) { 79*e9dcd831SSlava Shwartsman mlx5_fpga_dbg(fdev, "No free transaction ID available\n"); 80*e9dcd831SSlava Shwartsman ret = NULL; 81*e9dcd831SSlava Shwartsman goto out; 82*e9dcd831SSlava Shwartsman } 83*e9dcd831SSlava Shwartsman 84*e9dcd831SSlava Shwartsman ret = list_first_entry(&fdev->trans->free_queue, 85*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv, list_item); 86*e9dcd831SSlava Shwartsman list_del(&ret->list_item); 87*e9dcd831SSlava Shwartsman 88*e9dcd831SSlava Shwartsman ret->state = TRANS_STATE_NONE; 89*e9dcd831SSlava Shwartsman out: 90*e9dcd831SSlava Shwartsman spin_unlock_irqrestore(&fdev->trans->lock, flags); 91*e9dcd831SSlava Shwartsman return ret; 92*e9dcd831SSlava Shwartsman } 93*e9dcd831SSlava Shwartsman 94*e9dcd831SSlava Shwartsman static void free_tid(struct mlx5_fpga_device *fdev, 95*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *trans_priv) 96*e9dcd831SSlava Shwartsman { 97*e9dcd831SSlava Shwartsman unsigned long flags; 98*e9dcd831SSlava Shwartsman 99*e9dcd831SSlava Shwartsman spin_lock_irqsave(&fdev->trans->lock, flags); 100*e9dcd831SSlava Shwartsman list_add_tail(&trans_priv->list_item, &fdev->trans->free_queue); 101*e9dcd831SSlava Shwartsman spin_unlock_irqrestore(&fdev->trans->lock, flags); 102*e9dcd831SSlava Shwartsman } 103*e9dcd831SSlava Shwartsman 104*e9dcd831SSlava Shwartsman static void trans_complete(struct mlx5_fpga_device *fdev, 105*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *trans_priv, u8 status) 106*e9dcd831SSlava Shwartsman { 107*e9dcd831SSlava Shwartsman const struct mlx5_fpga_transaction *user_trans; 108*e9dcd831SSlava Shwartsman unsigned long flags; 109*e9dcd831SSlava Shwartsman 110*e9dcd831SSlava Shwartsman mlx5_fpga_dbg(fdev, "Transaction %u is complete with status %u\n", 111*e9dcd831SSlava Shwartsman trans_priv->tid, status); 112*e9dcd831SSlava Shwartsman 113*e9dcd831SSlava Shwartsman spin_lock_irqsave(&fdev->trans->lock, flags); 114*e9dcd831SSlava Shwartsman trans_priv->state = TRANS_STATE_COMPLETE; 115*e9dcd831SSlava Shwartsman trans_priv->status = status; 116*e9dcd831SSlava Shwartsman spin_unlock_irqrestore(&fdev->trans->lock, flags); 117*e9dcd831SSlava Shwartsman 118*e9dcd831SSlava Shwartsman user_trans = trans_priv->user_trans; 119*e9dcd831SSlava Shwartsman free_tid(fdev, trans_priv); 120*e9dcd831SSlava Shwartsman 121*e9dcd831SSlava Shwartsman if (user_trans->complete1) 122*e9dcd831SSlava Shwartsman user_trans->complete1(user_trans, status); 123*e9dcd831SSlava Shwartsman } 124*e9dcd831SSlava Shwartsman 125*e9dcd831SSlava Shwartsman static void trans_send_complete(struct mlx5_fpga_conn *conn, 126*e9dcd831SSlava Shwartsman struct mlx5_fpga_device *fdev, 127*e9dcd831SSlava Shwartsman struct mlx5_fpga_dma_buf *buf, u8 status) 128*e9dcd831SSlava Shwartsman { 129*e9dcd831SSlava Shwartsman unsigned long flags; 130*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *trans_priv; 131*e9dcd831SSlava Shwartsman 132*e9dcd831SSlava Shwartsman trans_priv = container_of(buf, struct mlx5_fpga_trans_priv, buf); 133*e9dcd831SSlava Shwartsman mlx5_fpga_dbg(fdev, "send complete tid %u. Status: %u\n", 134*e9dcd831SSlava Shwartsman trans_priv->tid, status); 135*e9dcd831SSlava Shwartsman if (status) { 136*e9dcd831SSlava Shwartsman trans_complete(fdev, trans_priv, status); 137*e9dcd831SSlava Shwartsman return; 138*e9dcd831SSlava Shwartsman } 139*e9dcd831SSlava Shwartsman 140*e9dcd831SSlava Shwartsman spin_lock_irqsave(&fdev->trans->lock, flags); 141*e9dcd831SSlava Shwartsman if (trans_priv->state == TRANS_STATE_SEND) 142*e9dcd831SSlava Shwartsman trans_priv->state = TRANS_STATE_WAIT; 143*e9dcd831SSlava Shwartsman spin_unlock_irqrestore(&fdev->trans->lock, flags); 144*e9dcd831SSlava Shwartsman } 145*e9dcd831SSlava Shwartsman 146*e9dcd831SSlava Shwartsman static int trans_validate(struct mlx5_fpga_device *fdev, u64 addr, size_t size) 147*e9dcd831SSlava Shwartsman { 148*e9dcd831SSlava Shwartsman if (size > MLX5_FPGA_TRANSACTION_MAX_SIZE) { 149*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes at once. Max is %u\n", 150*e9dcd831SSlava Shwartsman size, MLX5_FPGA_TRANSACTION_MAX_SIZE); 151*e9dcd831SSlava Shwartsman return -EINVAL; 152*e9dcd831SSlava Shwartsman } 153*e9dcd831SSlava Shwartsman if (size & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) { 154*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes. Must be full dwords\n", 155*e9dcd831SSlava Shwartsman size); 156*e9dcd831SSlava Shwartsman return -EINVAL; 157*e9dcd831SSlava Shwartsman } 158*e9dcd831SSlava Shwartsman if (size < 1) { 159*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes. Empty transaction not allowed\n", 160*e9dcd831SSlava Shwartsman size); 161*e9dcd831SSlava Shwartsman return -EINVAL; 162*e9dcd831SSlava Shwartsman } 163*e9dcd831SSlava Shwartsman if (addr & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) { 164*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes at unaligned address %jx\n", 165*e9dcd831SSlava Shwartsman size, (uintmax_t)addr); 166*e9dcd831SSlava Shwartsman return -EINVAL; 167*e9dcd831SSlava Shwartsman } 168*e9dcd831SSlava Shwartsman if ((addr >> MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS) != 169*e9dcd831SSlava Shwartsman ((addr + size - 1) >> MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS)) { 170*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes at address %jx. Crosses page boundary\n", 171*e9dcd831SSlava Shwartsman size, (uintmax_t)addr); 172*e9dcd831SSlava Shwartsman return -EINVAL; 173*e9dcd831SSlava Shwartsman } 174*e9dcd831SSlava Shwartsman if (addr < mlx5_fpga_ddr_base_get(fdev)) { 175*e9dcd831SSlava Shwartsman if (size != sizeof(u32)) { 176*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Cannot access %zu bytes at cr-space address %jx. Must access a single dword\n", 177*e9dcd831SSlava Shwartsman size, (uintmax_t)addr); 178*e9dcd831SSlava Shwartsman return -EINVAL; 179*e9dcd831SSlava Shwartsman } 180*e9dcd831SSlava Shwartsman } 181*e9dcd831SSlava Shwartsman return 0; 182*e9dcd831SSlava Shwartsman } 183*e9dcd831SSlava Shwartsman 184*e9dcd831SSlava Shwartsman int mlx5_fpga_trans_exec(const struct mlx5_fpga_transaction *trans) 185*e9dcd831SSlava Shwartsman { 186*e9dcd831SSlava Shwartsman struct mlx5_fpga_conn *conn = trans->conn; 187*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *trans_priv; 188*e9dcd831SSlava Shwartsman u32 *header; 189*e9dcd831SSlava Shwartsman int err; 190*e9dcd831SSlava Shwartsman 191*e9dcd831SSlava Shwartsman if (!trans->complete1) { 192*e9dcd831SSlava Shwartsman mlx5_fpga_warn(conn->fdev, "Transaction must have a completion callback\n"); 193*e9dcd831SSlava Shwartsman err = -EINVAL; 194*e9dcd831SSlava Shwartsman goto out; 195*e9dcd831SSlava Shwartsman } 196*e9dcd831SSlava Shwartsman 197*e9dcd831SSlava Shwartsman err = trans_validate(conn->fdev, trans->addr, trans->size); 198*e9dcd831SSlava Shwartsman if (err) 199*e9dcd831SSlava Shwartsman goto out; 200*e9dcd831SSlava Shwartsman 201*e9dcd831SSlava Shwartsman trans_priv = alloc_tid(conn->fdev); 202*e9dcd831SSlava Shwartsman if (!trans_priv) { 203*e9dcd831SSlava Shwartsman err = -EBUSY; 204*e9dcd831SSlava Shwartsman goto out; 205*e9dcd831SSlava Shwartsman } 206*e9dcd831SSlava Shwartsman trans_priv->user_trans = trans; 207*e9dcd831SSlava Shwartsman header = trans_priv->header; 208*e9dcd831SSlava Shwartsman 209*e9dcd831SSlava Shwartsman memset(header, 0, sizeof(trans_priv->header)); 210*e9dcd831SSlava Shwartsman memset(&trans_priv->buf, 0, sizeof(trans_priv->buf)); 211*e9dcd831SSlava Shwartsman MLX5_SET(fpga_shell_qp_packet, header, type, 212*e9dcd831SSlava Shwartsman (trans->direction == MLX5_FPGA_WRITE) ? 213*e9dcd831SSlava Shwartsman MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE : 214*e9dcd831SSlava Shwartsman MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ); 215*e9dcd831SSlava Shwartsman MLX5_SET(fpga_shell_qp_packet, header, tid, trans_priv->tid); 216*e9dcd831SSlava Shwartsman MLX5_SET(fpga_shell_qp_packet, header, len, trans->size); 217*e9dcd831SSlava Shwartsman MLX5_SET64(fpga_shell_qp_packet, header, address, trans->addr); 218*e9dcd831SSlava Shwartsman 219*e9dcd831SSlava Shwartsman trans_priv->buf.sg[0].data = header; 220*e9dcd831SSlava Shwartsman trans_priv->buf.sg[0].size = sizeof(trans_priv->header); 221*e9dcd831SSlava Shwartsman if (trans->direction == MLX5_FPGA_WRITE) { 222*e9dcd831SSlava Shwartsman trans_priv->buf.sg[1].data = trans->data; 223*e9dcd831SSlava Shwartsman trans_priv->buf.sg[1].size = trans->size; 224*e9dcd831SSlava Shwartsman } 225*e9dcd831SSlava Shwartsman 226*e9dcd831SSlava Shwartsman trans_priv->buf.complete = trans_send_complete; 227*e9dcd831SSlava Shwartsman trans_priv->state = TRANS_STATE_SEND; 228*e9dcd831SSlava Shwartsman 229*e9dcd831SSlava Shwartsman #ifdef NOT_YET 230*e9dcd831SSlava Shwartsman /* XXXKIB */ 231*e9dcd831SSlava Shwartsman err = mlx5_fpga_conn_send(conn->fdev->shell_conn, &trans_priv->buf); 232*e9dcd831SSlava Shwartsman #else 233*e9dcd831SSlava Shwartsman err = 0; 234*e9dcd831SSlava Shwartsman #endif 235*e9dcd831SSlava Shwartsman if (err) 236*e9dcd831SSlava Shwartsman goto out_buf_tid; 237*e9dcd831SSlava Shwartsman goto out; 238*e9dcd831SSlava Shwartsman 239*e9dcd831SSlava Shwartsman out_buf_tid: 240*e9dcd831SSlava Shwartsman free_tid(conn->fdev, trans_priv); 241*e9dcd831SSlava Shwartsman out: 242*e9dcd831SSlava Shwartsman return err; 243*e9dcd831SSlava Shwartsman } 244*e9dcd831SSlava Shwartsman 245*e9dcd831SSlava Shwartsman void mlx5_fpga_trans_recv(void *cb_arg, struct mlx5_fpga_dma_buf *buf) 246*e9dcd831SSlava Shwartsman { 247*e9dcd831SSlava Shwartsman struct mlx5_fpga_device *fdev = cb_arg; 248*e9dcd831SSlava Shwartsman struct mlx5_fpga_trans_priv *trans_priv; 249*e9dcd831SSlava Shwartsman size_t payload_len; 250*e9dcd831SSlava Shwartsman u8 status = 0; 251*e9dcd831SSlava Shwartsman u8 tid, type; 252*e9dcd831SSlava Shwartsman 253*e9dcd831SSlava Shwartsman mlx5_fpga_dbg(fdev, "Rx QP message on core conn; %u bytes\n", 254*e9dcd831SSlava Shwartsman buf->sg[0].size); 255*e9dcd831SSlava Shwartsman 256*e9dcd831SSlava Shwartsman if (buf->sg[0].size < MLX5_ST_SZ_BYTES(fpga_shell_qp_packet)) { 257*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Short message %u bytes from device\n", 258*e9dcd831SSlava Shwartsman buf->sg[0].size); 259*e9dcd831SSlava Shwartsman goto out; 260*e9dcd831SSlava Shwartsman } 261*e9dcd831SSlava Shwartsman payload_len = buf->sg[0].size - MLX5_ST_SZ_BYTES(fpga_shell_qp_packet); 262*e9dcd831SSlava Shwartsman 263*e9dcd831SSlava Shwartsman tid = MLX5_GET(fpga_shell_qp_packet, buf->sg[0].data, tid); 264*e9dcd831SSlava Shwartsman trans_priv = find_tid(fdev, tid); 265*e9dcd831SSlava Shwartsman if (!trans_priv) 266*e9dcd831SSlava Shwartsman goto out; 267*e9dcd831SSlava Shwartsman 268*e9dcd831SSlava Shwartsman type = MLX5_GET(fpga_shell_qp_packet, buf->sg[0].data, type); 269*e9dcd831SSlava Shwartsman switch (type) { 270*e9dcd831SSlava Shwartsman case MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ_RESPONSE: 271*e9dcd831SSlava Shwartsman if (trans_priv->user_trans->direction != MLX5_FPGA_READ) { 272*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Wrong answer type %u to a %u transaction\n", 273*e9dcd831SSlava Shwartsman type, trans_priv->user_trans->direction); 274*e9dcd831SSlava Shwartsman status = -EIO; 275*e9dcd831SSlava Shwartsman goto complete; 276*e9dcd831SSlava Shwartsman } 277*e9dcd831SSlava Shwartsman if (payload_len != trans_priv->user_trans->size) { 278*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Incorrect transaction payload length %zu expected %zu\n", 279*e9dcd831SSlava Shwartsman payload_len, 280*e9dcd831SSlava Shwartsman trans_priv->user_trans->size); 281*e9dcd831SSlava Shwartsman goto complete; 282*e9dcd831SSlava Shwartsman } 283*e9dcd831SSlava Shwartsman memcpy(trans_priv->user_trans->data, 284*e9dcd831SSlava Shwartsman MLX5_ADDR_OF(fpga_shell_qp_packet, buf->sg[0].data, 285*e9dcd831SSlava Shwartsman data), payload_len); 286*e9dcd831SSlava Shwartsman break; 287*e9dcd831SSlava Shwartsman case MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE_RESPONSE: 288*e9dcd831SSlava Shwartsman if (trans_priv->user_trans->direction != MLX5_FPGA_WRITE) { 289*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Wrong answer type %u to a %u transaction\n", 290*e9dcd831SSlava Shwartsman type, trans_priv->user_trans->direction); 291*e9dcd831SSlava Shwartsman status = -EIO; 292*e9dcd831SSlava Shwartsman goto complete; 293*e9dcd831SSlava Shwartsman } 294*e9dcd831SSlava Shwartsman break; 295*e9dcd831SSlava Shwartsman default: 296*e9dcd831SSlava Shwartsman mlx5_fpga_warn(fdev, "Unexpected message type %u len %u from device\n", 297*e9dcd831SSlava Shwartsman type, buf->sg[0].size); 298*e9dcd831SSlava Shwartsman status = -EIO; 299*e9dcd831SSlava Shwartsman goto complete; 300*e9dcd831SSlava Shwartsman } 301*e9dcd831SSlava Shwartsman 302*e9dcd831SSlava Shwartsman complete: 303*e9dcd831SSlava Shwartsman trans_complete(fdev, trans_priv, status); 304*e9dcd831SSlava Shwartsman out: 305*e9dcd831SSlava Shwartsman return; 306*e9dcd831SSlava Shwartsman } 307*e9dcd831SSlava Shwartsman 308*e9dcd831SSlava Shwartsman int mlx5_fpga_trans_device_init(struct mlx5_fpga_device *fdev) 309*e9dcd831SSlava Shwartsman { 310*e9dcd831SSlava Shwartsman int ret = 0; 311*e9dcd831SSlava Shwartsman int tid; 312*e9dcd831SSlava Shwartsman 313*e9dcd831SSlava Shwartsman fdev->trans = kzalloc(sizeof(*fdev->trans), GFP_KERNEL); 314*e9dcd831SSlava Shwartsman if (!fdev->trans) { 315*e9dcd831SSlava Shwartsman ret = -ENOMEM; 316*e9dcd831SSlava Shwartsman goto out; 317*e9dcd831SSlava Shwartsman } 318*e9dcd831SSlava Shwartsman 319*e9dcd831SSlava Shwartsman INIT_LIST_HEAD(&fdev->trans->free_queue); 320*e9dcd831SSlava Shwartsman for (tid = 0; tid < ARRAY_SIZE(fdev->trans->transactions); tid++) { 321*e9dcd831SSlava Shwartsman fdev->trans->transactions[tid].tid = tid; 322*e9dcd831SSlava Shwartsman list_add_tail(&fdev->trans->transactions[tid].list_item, 323*e9dcd831SSlava Shwartsman &fdev->trans->free_queue); 324*e9dcd831SSlava Shwartsman } 325*e9dcd831SSlava Shwartsman 326*e9dcd831SSlava Shwartsman spin_lock_init(&fdev->trans->lock); 327*e9dcd831SSlava Shwartsman 328*e9dcd831SSlava Shwartsman out: 329*e9dcd831SSlava Shwartsman return ret; 330*e9dcd831SSlava Shwartsman } 331*e9dcd831SSlava Shwartsman 332*e9dcd831SSlava Shwartsman void mlx5_fpga_trans_device_cleanup(struct mlx5_fpga_device *fdev) 333*e9dcd831SSlava Shwartsman { 334*e9dcd831SSlava Shwartsman kfree(fdev->trans); 335*e9dcd831SSlava Shwartsman } 336