mlx5fpga: Initial code import.
Submitted by: kib@ Approved by: hselasky (mentor) MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
4a2699276d
commit
16b94054c2
@ -1034,6 +1034,12 @@ enum mlx5_qcam_feature_groups {
|
||||
#define MLX5_CAP_QCAM_FEATURE(mdev, fld) \
|
||||
MLX5_GET(qcam_reg, (mdev)->caps.qcam, qos_feature_cap_mask.feature_cap.fld)
|
||||
|
||||
#define MLX5_CAP_FPGA(mdev, cap) \
|
||||
MLX5_GET(fpga_cap, (mdev)->caps.fpga, cap)
|
||||
|
||||
#define MLX5_CAP64_FPGA(mdev, cap) \
|
||||
MLX5_GET64(fpga_cap, (mdev)->caps.fpga, cap)
|
||||
|
||||
enum {
|
||||
MLX5_CMD_STAT_OK = 0x0,
|
||||
MLX5_CMD_STAT_INT_ERR = 0x1,
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <dev/mlx5/device.h>
|
||||
#include <dev/mlx5/doorbell.h>
|
||||
@ -131,6 +132,10 @@ enum {
|
||||
MLX5_REG_DCBX_PARAM = 0x4020,
|
||||
MLX5_REG_DCBX_APP = 0x4021,
|
||||
MLX5_REG_PCAP = 0x5001,
|
||||
MLX5_REG_FPGA_CAP = 0x4022,
|
||||
MLX5_REG_FPGA_CTRL = 0x4023,
|
||||
MLX5_REG_FPGA_ACCESS_REG = 0x4024,
|
||||
MLX5_REG_FPGA_SHELL_CNTR = 0x4025,
|
||||
MLX5_REG_PMTU = 0x5003,
|
||||
MLX5_REG_PTYS = 0x5004,
|
||||
MLX5_REG_PAOS = 0x5006,
|
||||
@ -404,6 +409,13 @@ struct mlx5_buf {
|
||||
u8 load_done;
|
||||
};
|
||||
|
||||
struct mlx5_frag_buf {
|
||||
struct mlx5_buf_list *frags;
|
||||
int npages;
|
||||
int size;
|
||||
u8 page_shift;
|
||||
};
|
||||
|
||||
struct mlx5_eq {
|
||||
struct mlx5_core_dev *dev;
|
||||
__be32 __iomem *doorbell;
|
||||
@ -442,6 +454,20 @@ struct mlx5_core_sig_ctx {
|
||||
u32 sigerr_count;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_MKEY_MR = 1,
|
||||
MLX5_MKEY_MW,
|
||||
MLX5_MKEY_MR_USER,
|
||||
};
|
||||
|
||||
struct mlx5_core_mkey {
|
||||
u64 iova;
|
||||
u64 size;
|
||||
u32 key;
|
||||
u32 pd;
|
||||
u32 type;
|
||||
};
|
||||
|
||||
struct mlx5_core_mr {
|
||||
u64 iova;
|
||||
u64 size;
|
||||
@ -645,6 +671,14 @@ enum mlx5_pci_status {
|
||||
MLX5_PCI_STATUS_ENABLED,
|
||||
};
|
||||
|
||||
#define MLX5_MAX_RESERVED_GIDS 8
|
||||
|
||||
struct mlx5_rsvd_gids {
|
||||
unsigned int start;
|
||||
unsigned int count;
|
||||
struct ida ida;
|
||||
};
|
||||
|
||||
struct mlx5_special_contexts {
|
||||
int resd_lkey;
|
||||
};
|
||||
@ -663,6 +697,7 @@ struct mlx5_core_dev {
|
||||
u32 hca_caps_max[MLX5_CAP_NUM][MLX5_UN_SZ_DW(hca_cap_union)];
|
||||
struct {
|
||||
u32 qcam[MLX5_ST_SZ_DW(qcam_reg)];
|
||||
u32 fpga[MLX5_ST_SZ_DW(fpga_cap)];
|
||||
} caps;
|
||||
phys_addr_t iseg_base;
|
||||
struct mlx5_init_seg __iomem *iseg;
|
||||
@ -691,6 +726,14 @@ struct mlx5_core_dev {
|
||||
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
int msix_eqvec;
|
||||
|
||||
struct {
|
||||
struct mlx5_rsvd_gids reserved_gids;
|
||||
atomic_t roce_en;
|
||||
} roce;
|
||||
#ifdef CONFIG_MLX5_FPGA
|
||||
struct mlx5_fpga_device *fpga;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -1106,6 +1149,11 @@ void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol);
|
||||
int mlx5_register_interface(struct mlx5_interface *intf);
|
||||
void mlx5_unregister_interface(struct mlx5_interface *intf);
|
||||
|
||||
unsigned int mlx5_core_reserved_gids_count(struct mlx5_core_dev *dev);
|
||||
int mlx5_core_roce_gid_set(struct mlx5_core_dev *dev, unsigned int index,
|
||||
u8 roce_version, u8 roce_l3_type, const u8 *gid,
|
||||
const u8 *mac, bool vlan, u16 vlan_id);
|
||||
|
||||
struct mlx5_profile {
|
||||
u64 mask;
|
||||
u8 log_max_qp;
|
||||
|
139
sys/dev/mlx5/mlx5_accel/ipsec.h
Normal file
139
sys/dev/mlx5/mlx5_accel/ipsec.h
Normal file
@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* 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 __MLX5_ACCEL_IPSEC_H__
|
||||
#define __MLX5_ACCEL_IPSEC_H__
|
||||
|
||||
#ifdef CONFIG_MLX5_ACCEL
|
||||
|
||||
#include <dev/mlx5/driver.h>
|
||||
|
||||
enum {
|
||||
MLX5_ACCEL_IPSEC_DEVICE = BIT(1),
|
||||
MLX5_ACCEL_IPSEC_IPV6 = BIT(2),
|
||||
MLX5_ACCEL_IPSEC_ESP = BIT(3),
|
||||
MLX5_ACCEL_IPSEC_LSO = BIT(4),
|
||||
};
|
||||
|
||||
#define MLX5_IPSEC_SADB_IP_AH BIT(7)
|
||||
#define MLX5_IPSEC_SADB_IP_ESP BIT(6)
|
||||
#define MLX5_IPSEC_SADB_SA_VALID BIT(5)
|
||||
#define MLX5_IPSEC_SADB_SPI_EN BIT(4)
|
||||
#define MLX5_IPSEC_SADB_DIR_SX BIT(3)
|
||||
#define MLX5_IPSEC_SADB_IPV6 BIT(2)
|
||||
|
||||
enum {
|
||||
MLX5_IPSEC_CMD_ADD_SA = 0,
|
||||
MLX5_IPSEC_CMD_DEL_SA = 1,
|
||||
};
|
||||
|
||||
enum mlx5_accel_ipsec_enc_mode {
|
||||
MLX5_IPSEC_SADB_MODE_NONE = 0,
|
||||
MLX5_IPSEC_SADB_MODE_AES_GCM_128_AUTH_128 = 1,
|
||||
MLX5_IPSEC_SADB_MODE_AES_GCM_256_AUTH_128 = 3,
|
||||
};
|
||||
|
||||
#define MLX5_IPSEC_DEV(mdev) (mlx5_accel_ipsec_device_caps(mdev) & \
|
||||
MLX5_ACCEL_IPSEC_DEVICE)
|
||||
|
||||
struct mlx5_accel_ipsec_sa {
|
||||
__be32 cmd;
|
||||
u8 key_enc[32];
|
||||
u8 key_auth[32];
|
||||
__be32 sip[4];
|
||||
__be32 dip[4];
|
||||
union {
|
||||
struct {
|
||||
__be32 reserved;
|
||||
u8 salt_iv[8];
|
||||
__be32 salt;
|
||||
} __packed gcm;
|
||||
struct {
|
||||
u8 salt[16];
|
||||
} __packed cbc;
|
||||
};
|
||||
__be32 spi;
|
||||
__be32 sw_sa_handle;
|
||||
__be16 tfclen;
|
||||
u8 enc_mode;
|
||||
u8 sip_masklen;
|
||||
u8 dip_masklen;
|
||||
u8 flags;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* mlx5_accel_ipsec_sa_cmd_exec - Execute an IPSec SADB command
|
||||
* @mdev: mlx5 device
|
||||
* @cmd: command to execute
|
||||
* May be called from atomic context. Returns context pointer, or error
|
||||
* Caller must eventually call mlx5_accel_ipsec_sa_cmd_wait from non-atomic
|
||||
* context, to cleanup the context pointer
|
||||
*/
|
||||
void *mlx5_accel_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev,
|
||||
struct mlx5_accel_ipsec_sa *cmd);
|
||||
|
||||
/**
|
||||
* mlx5_accel_ipsec_sa_cmd_wait - Wait for command execution completion
|
||||
* @context: Context pointer returned from call to mlx5_accel_ipsec_sa_cmd_exec
|
||||
* Sleeps (killable) until command execution is complete.
|
||||
* Returns the command result, or -EINTR if killed
|
||||
*/
|
||||
int mlx5_accel_ipsec_sa_cmd_wait(void *context);
|
||||
|
||||
u32 mlx5_accel_ipsec_device_caps(struct mlx5_core_dev *mdev);
|
||||
|
||||
unsigned int mlx5_accel_ipsec_counters_count(struct mlx5_core_dev *mdev);
|
||||
int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
|
||||
unsigned int count);
|
||||
|
||||
int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev);
|
||||
void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev);
|
||||
|
||||
#else
|
||||
|
||||
#define MLX5_IPSEC_DEV(mdev) false
|
||||
|
||||
static inline int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __MLX5_ACCEL_IPSEC_H__ */
|
@ -85,6 +85,9 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force);
|
||||
void mlx5_disable_device(struct mlx5_core_dev *dev);
|
||||
void mlx5_recover_device(struct mlx5_core_dev *dev);
|
||||
|
||||
int mlx5_register_device(struct mlx5_core_dev *dev);
|
||||
void mlx5_unregister_device(struct mlx5_core_dev *dev);
|
||||
|
||||
void mlx5e_init(void);
|
||||
void mlx5e_cleanup(void);
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <dev/mlx5/srq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <dev/mlx5/mlx5_ifc.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
#include <dev/mlx5/mlx5_lib/mlx5.h>
|
||||
#include "mlx5_core.h"
|
||||
#include "fs_core.h"
|
||||
|
||||
@ -734,7 +736,8 @@ static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *pr
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5_register_device(struct mlx5_core_dev *dev)
|
||||
int
|
||||
mlx5_register_device(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
struct mlx5_interface *intf;
|
||||
@ -748,7 +751,8 @@ static int mlx5_register_device(struct mlx5_core_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlx5_unregister_device(struct mlx5_core_dev *dev)
|
||||
void
|
||||
mlx5_unregister_device(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
struct mlx5_interface *intf;
|
||||
@ -912,6 +916,9 @@ static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
||||
mlx5_init_srq_table(dev);
|
||||
mlx5_init_mr_table(dev);
|
||||
|
||||
mlx5_init_reserved_gids(dev);
|
||||
mlx5_fpga_init(dev);
|
||||
|
||||
#ifdef RATELIMIT
|
||||
err = mlx5_init_rl_table(dev);
|
||||
if (err) {
|
||||
@ -941,6 +948,8 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
|
||||
#ifdef RATELIMIT
|
||||
mlx5_cleanup_rl_table(dev);
|
||||
#endif
|
||||
mlx5_fpga_cleanup(dev);
|
||||
mlx5_cleanup_reserved_gids(dev);
|
||||
mlx5_cleanup_mr_table(dev);
|
||||
mlx5_cleanup_srq_table(dev);
|
||||
mlx5_cleanup_qp_table(dev);
|
||||
@ -1075,6 +1084,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
||||
goto err_free_comp_eqs;
|
||||
}
|
||||
|
||||
err = mlx5_fpga_device_start(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "fpga device start failed %d\n", err);
|
||||
goto err_fpga_start;
|
||||
}
|
||||
|
||||
err = mlx5_register_device(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
|
||||
@ -1088,6 +1103,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
||||
mutex_unlock(&dev->intf_state_mutex);
|
||||
return 0;
|
||||
|
||||
err_fpga_start:
|
||||
err_fs:
|
||||
mlx5_cleanup_fs(dev);
|
||||
|
||||
@ -1152,6 +1168,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
||||
|
||||
mlx5_unregister_device(dev);
|
||||
|
||||
mlx5_fpga_device_stop(dev);
|
||||
mlx5_cleanup_fs(dev);
|
||||
unmap_bf_area(dev);
|
||||
mlx5_wait_for_reclaim_vfs_pages(dev);
|
||||
|
@ -42,6 +42,12 @@ struct mlx5_wq_ctrl {
|
||||
struct mlx5_db db;
|
||||
};
|
||||
|
||||
struct mlx5_frag_wq_ctrl {
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5_frag_buf frag_buf;
|
||||
struct mlx5_db db;
|
||||
};
|
||||
|
||||
struct mlx5_wq_cyc {
|
||||
void *buf;
|
||||
__be32 *db;
|
||||
@ -49,6 +55,11 @@ struct mlx5_wq_cyc {
|
||||
u8 log_stride;
|
||||
};
|
||||
|
||||
struct mlx5_wq_qp {
|
||||
struct mlx5_wq_cyc rq;
|
||||
struct mlx5_wq_cyc sq;
|
||||
};
|
||||
|
||||
struct mlx5_cqwq {
|
||||
void *buf;
|
||||
__be32 *db;
|
||||
|
82
sys/dev/mlx5/mlx5_fpga/cmd.h
Normal file
82
sys/dev/mlx5/mlx5_fpga/cmd.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*-
|
||||
* Copyright (c) 2017, Mellanox Technologies, Ltd. 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 __MLX5_FPGA_H__
|
||||
#define __MLX5_FPGA_H__
|
||||
|
||||
#include <linux/in6.h>
|
||||
#include <dev/mlx5/driver.h>
|
||||
#include <dev/mlx5/mlx5io.h>
|
||||
|
||||
enum mlx5_fpga_qpc_field_select {
|
||||
MLX5_FPGA_QPC_STATE = BIT(0),
|
||||
};
|
||||
|
||||
struct mlx5_fpga_qp_counters {
|
||||
u64 rx_ack_packets;
|
||||
u64 rx_send_packets;
|
||||
u64 tx_ack_packets;
|
||||
u64 tx_send_packets;
|
||||
u64 rx_total_drop;
|
||||
};
|
||||
|
||||
struct mlx5_fpga_shell_counters {
|
||||
u64 ddr_read_requests;
|
||||
u64 ddr_write_requests;
|
||||
u64 ddr_read_bytes;
|
||||
u64 ddr_write_bytes;
|
||||
};
|
||||
|
||||
int mlx5_fpga_caps(struct mlx5_core_dev *dev);
|
||||
int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query);
|
||||
int mlx5_fpga_ctrl_op(struct mlx5_core_dev *dev, u8 op);
|
||||
int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr,
|
||||
void *buf, bool write);
|
||||
int mlx5_fpga_sbu_caps(struct mlx5_core_dev *dev, void *caps, int size);
|
||||
int mlx5_fpga_load(struct mlx5_core_dev *dev, enum mlx5_fpga_image image);
|
||||
int mlx5_fpga_image_select(struct mlx5_core_dev *dev,
|
||||
enum mlx5_fpga_image image);
|
||||
int mlx5_fpga_shell_counters(struct mlx5_core_dev *dev, bool clear,
|
||||
struct mlx5_fpga_shell_counters *data);
|
||||
|
||||
int mlx5_fpga_create_qp(struct mlx5_core_dev *dev, void *fpga_qpc,
|
||||
u32 *fpga_qpn);
|
||||
int mlx5_fpga_modify_qp(struct mlx5_core_dev *dev, u32 fpga_qpn,
|
||||
enum mlx5_fpga_qpc_field_select fields, void *fpga_qpc);
|
||||
int mlx5_fpga_query_qp(struct mlx5_core_dev *dev, u32 fpga_qpn, void *fpga_qpc);
|
||||
int mlx5_fpga_query_qp_counters(struct mlx5_core_dev *dev, u32 fpga_qpn,
|
||||
bool clear, struct mlx5_fpga_qp_counters *data);
|
||||
int mlx5_fpga_destroy_qp(struct mlx5_core_dev *dev, u32 fpga_qpn);
|
||||
|
||||
#endif /* __MLX5_FPGA_H__ */
|
97
sys/dev/mlx5/mlx5_fpga/conn.h
Normal file
97
sys/dev/mlx5/mlx5_fpga/conn.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*-
|
||||
* 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 __MLX5_FPGA_CONN_H__
|
||||
#define __MLX5_FPGA_CONN_H__
|
||||
|
||||
#include <dev/mlx5/cq.h>
|
||||
#include <dev/mlx5/qp.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
#include <dev/mlx5/mlx5_fpga/sdk.h>
|
||||
#include <dev/mlx5/mlx5_core/wq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
struct mlx5_fpga_conn {
|
||||
struct mlx5_fpga_device *fdev;
|
||||
|
||||
void (*recv_cb)(void *cb_arg, struct mlx5_fpga_dma_buf *buf);
|
||||
void *cb_arg;
|
||||
|
||||
/* FPGA QP */
|
||||
u32 fpga_qpc[MLX5_ST_SZ_DW(fpga_qpc)];
|
||||
u32 fpga_qpn;
|
||||
|
||||
/* CQ */
|
||||
struct {
|
||||
struct mlx5_cqwq wq;
|
||||
struct mlx5_frag_wq_ctrl wq_ctrl;
|
||||
struct mlx5_core_cq mcq;
|
||||
struct tasklet_struct tasklet;
|
||||
} cq;
|
||||
|
||||
/* QP */
|
||||
struct {
|
||||
bool active;
|
||||
int sgid_index;
|
||||
struct mlx5_wq_qp wq;
|
||||
struct mlx5_wq_ctrl wq_ctrl;
|
||||
struct mlx5_core_qp mqp;
|
||||
struct {
|
||||
spinlock_t lock; /* Protects all SQ state */
|
||||
unsigned int pc;
|
||||
unsigned int cc;
|
||||
unsigned int size;
|
||||
struct mlx5_fpga_dma_buf **bufs;
|
||||
struct list_head backlog;
|
||||
} sq;
|
||||
struct {
|
||||
unsigned int pc;
|
||||
unsigned int cc;
|
||||
unsigned int size;
|
||||
struct mlx5_fpga_dma_buf **bufs;
|
||||
} rq;
|
||||
} qp;
|
||||
};
|
||||
|
||||
int mlx5_fpga_conn_device_init(struct mlx5_fpga_device *fdev);
|
||||
void mlx5_fpga_conn_device_cleanup(struct mlx5_fpga_device *fdev);
|
||||
struct mlx5_fpga_conn *
|
||||
mlx5_fpga_conn_create(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_conn_attr *attr,
|
||||
enum mlx5_ifc_fpga_qp_type qp_type);
|
||||
void mlx5_fpga_conn_destroy(struct mlx5_fpga_conn *conn);
|
||||
int mlx5_fpga_conn_send(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_dma_buf *buf);
|
||||
|
||||
#endif /* __MLX5_FPGA_CONN_H__ */
|
140
sys/dev/mlx5/mlx5_fpga/core.h
Normal file
140
sys/dev/mlx5/mlx5_fpga/core.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*-
|
||||
* Copyright (c) 2017, Mellanox Technologies, Ltd. 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 __MLX5_FPGA_CORE_H__
|
||||
#define __MLX5_FPGA_CORE_H__
|
||||
|
||||
#ifdef CONFIG_MLX5_FPGA
|
||||
|
||||
#include <dev/mlx5/mlx5_fpga/cmd.h>
|
||||
#include <dev/mlx5/mlx5_fpga/sdk.h>
|
||||
|
||||
/* Represents client-specific and Innova device-specific information */
|
||||
struct mlx5_fpga_client_data {
|
||||
struct list_head list;
|
||||
struct mlx5_fpga_client *client;
|
||||
void *data;
|
||||
bool added;
|
||||
};
|
||||
|
||||
enum mlx5_fdev_state {
|
||||
MLX5_FDEV_STATE_SUCCESS = 0,
|
||||
MLX5_FDEV_STATE_FAILURE = 1,
|
||||
MLX5_FDEV_STATE_IN_PROGRESS = 2,
|
||||
MLX5_FDEV_STATE_NONE = 0xFFFF,
|
||||
};
|
||||
|
||||
/* Represents an Innova device */
|
||||
struct mlx5_fpga_device {
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct completion load_event;
|
||||
spinlock_t state_lock; /* Protects state transitions */
|
||||
enum mlx5_fdev_state fdev_state;
|
||||
enum mlx5_fpga_status image_status;
|
||||
enum mlx5_fpga_image last_admin_image;
|
||||
enum mlx5_fpga_image last_oper_image;
|
||||
|
||||
/* QP Connection resources */
|
||||
struct {
|
||||
u32 pdn;
|
||||
struct mlx5_core_mkey mkey;
|
||||
struct mlx5_uars_page *uar;
|
||||
} conn_res;
|
||||
|
||||
struct mlx5_fpga_ipsec *ipsec;
|
||||
|
||||
struct list_head list;
|
||||
struct list_head client_data_list;
|
||||
|
||||
/* Shell Transactions state */
|
||||
struct mlx5_fpga_conn *shell_conn;
|
||||
struct mlx5_fpga_trans_device_state *trans;
|
||||
};
|
||||
|
||||
#define mlx5_fpga_dbg(__adev, format, ...) \
|
||||
dev_dbg(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_err(__adev, format, ...) \
|
||||
dev_err(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_warn(__adev, format, ...) \
|
||||
dev_warn(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_warn_ratelimited(__adev, format, ...) \
|
||||
dev_warn_ratelimited(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d: " \
|
||||
format, __func__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_notice(__adev, format, ...) \
|
||||
dev_notice(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_info(__adev, format, ...) \
|
||||
dev_info(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
|
||||
|
||||
int mlx5_fpga_init(struct mlx5_core_dev *mdev);
|
||||
void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev);
|
||||
int mlx5_fpga_device_start(struct mlx5_core_dev *mdev);
|
||||
void mlx5_fpga_device_stop(struct mlx5_core_dev *mdev);
|
||||
void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data);
|
||||
|
||||
#else
|
||||
|
||||
static inline int mlx5_fpga_init(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mlx5_fpga_device_stop(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event,
|
||||
void *data)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __MLX5_FPGA_CORE_H__ */
|
95
sys/dev/mlx5/mlx5_fpga/ipsec.h
Normal file
95
sys/dev/mlx5/mlx5_fpga/ipsec.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*-
|
||||
* 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 __MLX5_FPGA_IPSEC_H__
|
||||
#define __MLX5_FPGA_IPSEC_H__
|
||||
|
||||
#include <dev/mlx5/mlx5_accel/ipsec.h>
|
||||
|
||||
#ifdef CONFIG_MLX5_FPGA
|
||||
|
||||
void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev,
|
||||
struct mlx5_accel_ipsec_sa *cmd);
|
||||
int mlx5_fpga_ipsec_sa_cmd_wait(void *context);
|
||||
|
||||
u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev);
|
||||
unsigned int mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev);
|
||||
int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
|
||||
unsigned int counters_count);
|
||||
|
||||
int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev);
|
||||
void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev);
|
||||
|
||||
#else
|
||||
|
||||
static inline void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev,
|
||||
struct mlx5_accel_ipsec_sa *cmd)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int mlx5_fpga_ipsec_sa_cmd_wait(void *context)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev,
|
||||
u64 *counters)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MLX5_FPGA */
|
||||
|
||||
#endif /* __MLX5_FPGA_SADB_H__ */
|
500
sys/dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h
Normal file
500
sys/dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h
Normal file
@ -0,0 +1,500 @@
|
||||
/*-
|
||||
* Copyright (c) 2017, Mellanox Technologies, Ltd. 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 MLX5_IFC_FPGA_H
|
||||
#define MLX5_IFC_FPGA_H
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX = 0x2c9,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_EXAMPLE = 0x1,
|
||||
MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_IPSEC = 0x2,
|
||||
MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_TLS = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_SHELL_CAPS_QP_TYPE_SHELL_QP = 0x1,
|
||||
MLX5_FPGA_SHELL_CAPS_QP_TYPE_SANDBOX_QP = 0x2,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_shell_caps_bits {
|
||||
u8 max_num_qps[0x10];
|
||||
u8 reserved_at_10[0x8];
|
||||
u8 total_rcv_credits[0x8];
|
||||
|
||||
u8 reserved_at_20[0xe];
|
||||
u8 qp_type[0x2];
|
||||
u8 reserved_at_30[0x5];
|
||||
u8 rae[0x1];
|
||||
u8 rwe[0x1];
|
||||
u8 rre[0x1];
|
||||
u8 reserved_at_38[0x4];
|
||||
u8 dc[0x1];
|
||||
u8 ud[0x1];
|
||||
u8 uc[0x1];
|
||||
u8 rc[0x1];
|
||||
|
||||
u8 reserved_at_40[0x1a];
|
||||
u8 log_ddr_size[0x6];
|
||||
|
||||
u8 max_fpga_qp_msg_size[0x20];
|
||||
|
||||
u8 reserved_at_80[0x180];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_cap_bits {
|
||||
u8 fpga_id[0x8];
|
||||
u8 fpga_device[0x18];
|
||||
|
||||
u8 register_file_ver[0x20];
|
||||
|
||||
u8 fpga_ctrl_modify[0x1];
|
||||
u8 reserved_at_41[0x5];
|
||||
u8 access_reg_query_mode[0x2];
|
||||
u8 reserved_at_48[0x6];
|
||||
u8 access_reg_modify_mode[0x2];
|
||||
u8 reserved_at_50[0x10];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
|
||||
u8 image_version[0x20];
|
||||
|
||||
u8 image_date[0x20];
|
||||
|
||||
u8 image_time[0x20];
|
||||
|
||||
u8 shell_version[0x20];
|
||||
|
||||
u8 reserved_at_100[0x80];
|
||||
|
||||
struct mlx5_ifc_fpga_shell_caps_bits shell_caps;
|
||||
|
||||
u8 reserved_at_380[0x8];
|
||||
u8 ieee_vendor_id[0x18];
|
||||
|
||||
u8 sandbox_product_version[0x10];
|
||||
u8 sandbox_product_id[0x10];
|
||||
|
||||
u8 sandbox_basic_caps[0x20];
|
||||
|
||||
u8 reserved_at_3e0[0x10];
|
||||
u8 sandbox_extended_caps_len[0x10];
|
||||
|
||||
u8 sandbox_extended_caps_addr[0x40];
|
||||
|
||||
u8 fpga_ddr_start_addr[0x40];
|
||||
|
||||
u8 fpga_cr_space_start_addr[0x40];
|
||||
|
||||
u8 fpga_ddr_size[0x20];
|
||||
|
||||
u8 fpga_cr_space_size[0x20];
|
||||
|
||||
u8 reserved_at_500[0x300];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_CTRL_OPERATION_LOAD = 0x1,
|
||||
MLX5_FPGA_CTRL_OPERATION_RESET = 0x2,
|
||||
MLX5_FPGA_CTRL_OPERATION_FLASH_SELECT = 0x3,
|
||||
MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON = 0x4,
|
||||
MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_OFF = 0x5,
|
||||
MLX5_FPGA_CTRL_OPERATION_RESET_SANDBOX = 0x6,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_ctrl_bits {
|
||||
u8 reserved_at_0[0x8];
|
||||
u8 operation[0x8];
|
||||
u8 reserved_at_10[0x8];
|
||||
u8 status[0x8];
|
||||
|
||||
u8 reserved_at_20[0x8];
|
||||
u8 flash_select_admin[0x8];
|
||||
u8 reserved_at_30[0x8];
|
||||
u8 flash_select_oper[0x8];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_CORRUPTED_DDR = 0x1,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_FLASH_TIMEOUT = 0x2,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_INTERNAL_LINK_ERROR = 0x3,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_WATCHDOG_FAILURE = 0x4,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_I2C_FAILURE = 0x5,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_IMAGE_CHANGED = 0x6,
|
||||
MLX5_FPGA_ERROR_EVENT_SYNDROME_TEMPERATURE_CRITICAL = 0x7,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_error_event_bits {
|
||||
u8 reserved_at_0[0x40];
|
||||
|
||||
u8 reserved_at_40[0x18];
|
||||
u8 syndrome[0x8];
|
||||
|
||||
u8 reserved_at_60[0x80];
|
||||
};
|
||||
|
||||
#define MLX5_FPGA_ACCESS_REG_SIZE_MAX 64
|
||||
|
||||
struct mlx5_ifc_fpga_access_reg_bits {
|
||||
u8 reserved_at_0[0x20];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 size[0x10];
|
||||
|
||||
u8 address[0x40];
|
||||
|
||||
u8 data[0][0x8];
|
||||
};
|
||||
|
||||
enum mlx5_ifc_fpga_qp_state {
|
||||
MLX5_FPGA_QPC_STATE_INIT = 0x0,
|
||||
MLX5_FPGA_QPC_STATE_ACTIVE = 0x1,
|
||||
MLX5_FPGA_QPC_STATE_ERROR = 0x2,
|
||||
};
|
||||
|
||||
enum mlx5_ifc_fpga_qp_type {
|
||||
MLX5_FPGA_QPC_QP_TYPE_SHELL_QP = 0x0,
|
||||
MLX5_FPGA_QPC_QP_TYPE_SANDBOX_QP = 0x1,
|
||||
};
|
||||
|
||||
enum mlx5_ifc_fpga_qp_service_type {
|
||||
MLX5_FPGA_QPC_ST_RC = 0x0,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_qpc_bits {
|
||||
u8 state[0x4];
|
||||
u8 reserved_at_4[0x1b];
|
||||
u8 qp_type[0x1];
|
||||
|
||||
u8 reserved_at_20[0x4];
|
||||
u8 st[0x4];
|
||||
u8 reserved_at_28[0x10];
|
||||
u8 traffic_class[0x8];
|
||||
|
||||
u8 ether_type[0x10];
|
||||
u8 prio[0x3];
|
||||
u8 dei[0x1];
|
||||
u8 vid[0xc];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
|
||||
u8 reserved_at_80[0x8];
|
||||
u8 next_rcv_psn[0x18];
|
||||
|
||||
u8 reserved_at_a0[0x8];
|
||||
u8 next_send_psn[0x18];
|
||||
|
||||
u8 reserved_at_c0[0x10];
|
||||
u8 pkey[0x10];
|
||||
|
||||
u8 reserved_at_e0[0x8];
|
||||
u8 remote_qpn[0x18];
|
||||
|
||||
u8 reserved_at_100[0x15];
|
||||
u8 rnr_retry[0x3];
|
||||
u8 reserved_at_118[0x5];
|
||||
u8 retry_count[0x3];
|
||||
|
||||
u8 reserved_at_120[0x20];
|
||||
|
||||
u8 reserved_at_140[0x10];
|
||||
u8 remote_mac_47_32[0x10];
|
||||
|
||||
u8 remote_mac_31_0[0x20];
|
||||
|
||||
u8 remote_ip[16][0x8];
|
||||
|
||||
u8 reserved_at_200[0x40];
|
||||
|
||||
u8 reserved_at_240[0x10];
|
||||
u8 fpga_mac_47_32[0x10];
|
||||
|
||||
u8 fpga_mac_31_0[0x20];
|
||||
|
||||
u8 fpga_ip[16][0x8];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_create_qp_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
|
||||
struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_create_qp_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x8];
|
||||
u8 fpga_qpn[0x18];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
|
||||
struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_modify_qp_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 reserved_at_40[0x8];
|
||||
u8 fpga_qpn[0x18];
|
||||
|
||||
u8 field_select[0x20];
|
||||
|
||||
struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_modify_qp_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_query_qp_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 reserved_at_40[0x8];
|
||||
u8 fpga_qpn[0x18];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_query_qp_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
|
||||
struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_query_qp_counters_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 clear[0x1];
|
||||
u8 reserved_at_41[0x7];
|
||||
u8 fpga_qpn[0x18];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_query_qp_counters_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
|
||||
u8 rx_ack_packets[0x40];
|
||||
|
||||
u8 rx_send_packets[0x40];
|
||||
|
||||
u8 tx_ack_packets[0x40];
|
||||
|
||||
u8 tx_send_packets[0x40];
|
||||
|
||||
u8 rx_total_drop[0x40];
|
||||
|
||||
u8 reserved_at_1c0[0x1c0];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_destroy_qp_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 reserved_at_40[0x8];
|
||||
u8 fpga_qpn[0x18];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_destroy_qp_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_ipsec_extended_cap_bits {
|
||||
u8 encapsulation[0x20];
|
||||
|
||||
u8 reserved_0[0x15];
|
||||
u8 ipv4_fragment[0x1];
|
||||
u8 ipv6[0x1];
|
||||
u8 esn[0x1];
|
||||
u8 lso[0x1];
|
||||
u8 transport_and_tunnel_mode[0x1];
|
||||
u8 tunnel_mode[0x1];
|
||||
u8 transport_mode[0x1];
|
||||
u8 ah_esp[0x1];
|
||||
u8 esp[0x1];
|
||||
u8 ah[0x1];
|
||||
u8 ipv4_options[0x1];
|
||||
|
||||
u8 auth_alg[0x20];
|
||||
|
||||
u8 enc_alg[0x20];
|
||||
|
||||
u8 sa_cap[0x20];
|
||||
|
||||
u8 reserved_1[0x10];
|
||||
u8 number_of_ipsec_counters[0x10];
|
||||
|
||||
u8 ipsec_counters_addr_low[0x20];
|
||||
u8 ipsec_counters_addr_high[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_ipsec_counters_bits {
|
||||
u8 dec_in_packets[0x40];
|
||||
|
||||
u8 dec_out_packets[0x40];
|
||||
|
||||
u8 dec_bypass_packets[0x40];
|
||||
|
||||
u8 enc_in_packets[0x40];
|
||||
|
||||
u8 enc_out_packets[0x40];
|
||||
|
||||
u8 enc_bypass_packets[0x40];
|
||||
|
||||
u8 drop_dec_packets[0x40];
|
||||
|
||||
u8 failed_auth_dec_packets[0x40];
|
||||
|
||||
u8 drop_enc_packets[0x40];
|
||||
|
||||
u8 success_add_sa[0x40];
|
||||
|
||||
u8 fail_add_sa[0x40];
|
||||
|
||||
u8 success_delete_sa[0x40];
|
||||
|
||||
u8 fail_delete_sa[0x40];
|
||||
|
||||
u8 dropped_cmd[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_shell_counters_bits {
|
||||
u8 reserved_0[0x20];
|
||||
|
||||
u8 clear[0x1];
|
||||
u8 reserved_1[0x1f];
|
||||
|
||||
u8 reserved_2[0x40];
|
||||
|
||||
u8 ddr_read_requests[0x40];
|
||||
|
||||
u8 ddr_write_requests[0x40];
|
||||
|
||||
u8 ddr_read_bytes[0x40];
|
||||
|
||||
u8 ddr_write_bytes[0x40];
|
||||
|
||||
u8 reserved_3[0x200];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ = 0x0,
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE = 0x1,
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ_RESPONSE = 0x2,
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE_RESPONSE = 0x3,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_shell_qp_packet_bits {
|
||||
u8 version[0x4];
|
||||
u8 syndrome[0x4];
|
||||
u8 reserved_at_8[0x4];
|
||||
u8 type[0x4];
|
||||
u8 reserved_at_10[0x8];
|
||||
u8 tid[0x8];
|
||||
|
||||
u8 len[0x20];
|
||||
|
||||
u8 address[0x40];
|
||||
|
||||
u8 data[0][0x8];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_FPGA_QP_ERROR_EVENT_SYNDROME_RETRY_COUNTER_EXPIRED = 0x1,
|
||||
MLX5_FPGA_QP_ERROR_EVENT_SYNDROME_RNR_EXPIRED = 0x2,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_fpga_qp_error_event_bits {
|
||||
u8 reserved_0[0x40];
|
||||
|
||||
u8 reserved_1[0x18];
|
||||
u8 syndrome[0x8];
|
||||
|
||||
u8 reserved_2[0x60];
|
||||
|
||||
u8 reserved_3[0x8];
|
||||
u8 fpga_qpn[0x18];
|
||||
};
|
||||
|
||||
#endif /* MLX5_IFC_FPGA_H */
|
289
sys/dev/mlx5/mlx5_fpga/mlx5fpga_cmd.c
Normal file
289
sys/dev/mlx5/mlx5_fpga/mlx5fpga_cmd.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*-
|
||||
* 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 <dev/mlx5/cmd.h>
|
||||
#include <dev/mlx5/driver.h>
|
||||
#include <dev/mlx5/device.h>
|
||||
#include <dev/mlx5/mlx5_core/mlx5_core.h>
|
||||
#include <dev/mlx5/mlx5_fpga/cmd.h>
|
||||
|
||||
#define MLX5_FPGA_ACCESS_REG_SZ (MLX5_ST_SZ_DW(fpga_access_reg) + \
|
||||
MLX5_FPGA_ACCESS_REG_SIZE_MAX)
|
||||
|
||||
int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr,
|
||||
void *buf, bool write)
|
||||
{
|
||||
u32 in[MLX5_FPGA_ACCESS_REG_SZ] = {0};
|
||||
u32 out[MLX5_FPGA_ACCESS_REG_SZ];
|
||||
int err;
|
||||
|
||||
if (size & 3)
|
||||
return -EINVAL;
|
||||
if (addr & 3)
|
||||
return -EINVAL;
|
||||
if (size > MLX5_FPGA_ACCESS_REG_SIZE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
MLX5_SET(fpga_access_reg, in, size, size);
|
||||
MLX5_SET64(fpga_access_reg, in, address, addr);
|
||||
if (write)
|
||||
memcpy(MLX5_ADDR_OF(fpga_access_reg, in, data), buf, size);
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_FPGA_ACCESS_REG, 0, write);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!write)
|
||||
memcpy(buf, MLX5_ADDR_OF(fpga_access_reg, out, data), size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_fpga_caps(struct mlx5_core_dev *dev)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_cap)] = {0};
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), dev->caps.fpga,
|
||||
MLX5_ST_SZ_BYTES(fpga_cap),
|
||||
MLX5_REG_FPGA_CAP, 0, 0);
|
||||
}
|
||||
|
||||
int mlx5_fpga_ctrl_op(struct mlx5_core_dev *dev, u8 op)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
|
||||
|
||||
MLX5_SET(fpga_ctrl, in, operation, op);
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_FPGA_CTRL, 0, true);
|
||||
}
|
||||
|
||||
int mlx5_fpga_sbu_caps(struct mlx5_core_dev *dev, void *caps, int size)
|
||||
{
|
||||
unsigned int cap_size = MLX5_CAP_FPGA(dev, sandbox_extended_caps_len);
|
||||
u64 addr = MLX5_CAP64_FPGA(dev, sandbox_extended_caps_addr);
|
||||
unsigned int read;
|
||||
int ret = 0;
|
||||
|
||||
if (cap_size > size) {
|
||||
mlx5_core_warn(dev, "Not enough buffer %u for FPGA SBU caps %u",
|
||||
size, cap_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (cap_size > 0) {
|
||||
read = min_t(unsigned int, cap_size,
|
||||
MLX5_FPGA_ACCESS_REG_SIZE_MAX);
|
||||
|
||||
ret = mlx5_fpga_access_reg(dev, read, addr, caps, false);
|
||||
if (ret) {
|
||||
mlx5_core_warn(dev, "Error reading FPGA SBU caps %u bytes at address %#jx: %d",
|
||||
read, (uintmax_t)addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cap_size -= read;
|
||||
addr += read;
|
||||
caps += read;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mlx5_fpga_ctrl_write(struct mlx5_core_dev *dev, u8 op,
|
||||
enum mlx5_fpga_image image)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
|
||||
|
||||
MLX5_SET(fpga_ctrl, in, operation, op);
|
||||
MLX5_SET(fpga_ctrl, in, flash_select_admin, image);
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_FPGA_CTRL, 0, true);
|
||||
}
|
||||
|
||||
int mlx5_fpga_load(struct mlx5_core_dev *dev, enum mlx5_fpga_image image)
|
||||
{
|
||||
return mlx5_fpga_ctrl_write(dev, MLX5_FPGA_CTRL_OPERATION_LOAD, image);
|
||||
}
|
||||
|
||||
int mlx5_fpga_image_select(struct mlx5_core_dev *dev,
|
||||
enum mlx5_fpga_image image)
|
||||
{
|
||||
return mlx5_fpga_ctrl_write(dev, MLX5_FPGA_CTRL_OPERATION_FLASH_SELECT, image);
|
||||
}
|
||||
|
||||
int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
|
||||
int err;
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_FPGA_CTRL, 0, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
query->image_status = MLX5_GET(fpga_ctrl, out, status);
|
||||
query->admin_image = MLX5_GET(fpga_ctrl, out, flash_select_admin);
|
||||
query->oper_image = MLX5_GET(fpga_ctrl, out, flash_select_oper);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_fpga_create_qp(struct mlx5_core_dev *dev, void *fpga_qpc,
|
||||
u32 *fpga_qpn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_create_qp_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_create_qp_out)];
|
||||
int ret;
|
||||
|
||||
MLX5_SET(fpga_create_qp_in, in, opcode, MLX5_CMD_OP_FPGA_CREATE_QP);
|
||||
memcpy(MLX5_ADDR_OF(fpga_create_qp_in, in, fpga_qpc), fpga_qpc,
|
||||
MLX5_FLD_SZ_BYTES(fpga_create_qp_in, fpga_qpc));
|
||||
|
||||
ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_create_qp_out, out, fpga_qpc),
|
||||
MLX5_FLD_SZ_BYTES(fpga_create_qp_out, fpga_qpc));
|
||||
*fpga_qpn = MLX5_GET(fpga_create_qp_out, out, fpga_qpn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mlx5_fpga_modify_qp(struct mlx5_core_dev *dev, u32 fpga_qpn,
|
||||
enum mlx5_fpga_qpc_field_select fields,
|
||||
void *fpga_qpc)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_modify_qp_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_modify_qp_out)];
|
||||
|
||||
MLX5_SET(fpga_modify_qp_in, in, opcode, MLX5_CMD_OP_FPGA_MODIFY_QP);
|
||||
MLX5_SET(fpga_modify_qp_in, in, field_select, fields);
|
||||
MLX5_SET(fpga_modify_qp_in, in, fpga_qpn, fpga_qpn);
|
||||
memcpy(MLX5_ADDR_OF(fpga_modify_qp_in, in, fpga_qpc), fpga_qpc,
|
||||
MLX5_FLD_SZ_BYTES(fpga_modify_qp_in, fpga_qpc));
|
||||
|
||||
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
|
||||
int mlx5_fpga_query_qp(struct mlx5_core_dev *dev,
|
||||
u32 fpga_qpn, void *fpga_qpc)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_query_qp_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_query_qp_out)];
|
||||
int ret;
|
||||
|
||||
MLX5_SET(fpga_query_qp_in, in, opcode, MLX5_CMD_OP_FPGA_QUERY_QP);
|
||||
MLX5_SET(fpga_query_qp_in, in, fpga_qpn, fpga_qpn);
|
||||
|
||||
ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_query_qp_out, out, fpga_qpc),
|
||||
MLX5_FLD_SZ_BYTES(fpga_query_qp_out, fpga_qpc));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mlx5_fpga_destroy_qp(struct mlx5_core_dev *dev, u32 fpga_qpn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_destroy_qp_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_destroy_qp_out)];
|
||||
|
||||
MLX5_SET(fpga_destroy_qp_in, in, opcode, MLX5_CMD_OP_FPGA_DESTROY_QP);
|
||||
MLX5_SET(fpga_destroy_qp_in, in, fpga_qpn, fpga_qpn);
|
||||
|
||||
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
|
||||
int mlx5_fpga_query_qp_counters(struct mlx5_core_dev *dev, u32 fpga_qpn,
|
||||
bool clear, struct mlx5_fpga_qp_counters *data)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_query_qp_counters_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_query_qp_counters_out)];
|
||||
int ret;
|
||||
|
||||
MLX5_SET(fpga_query_qp_counters_in, in, opcode,
|
||||
MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS);
|
||||
MLX5_SET(fpga_query_qp_counters_in, in, clear, clear);
|
||||
MLX5_SET(fpga_query_qp_counters_in, in, fpga_qpn, fpga_qpn);
|
||||
|
||||
ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->rx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
|
||||
rx_ack_packets);
|
||||
data->rx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
|
||||
rx_send_packets);
|
||||
data->tx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
|
||||
tx_ack_packets);
|
||||
data->tx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
|
||||
tx_send_packets);
|
||||
data->rx_total_drop = MLX5_GET64(fpga_query_qp_counters_out, out,
|
||||
rx_total_drop);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mlx5_fpga_shell_counters(struct mlx5_core_dev *dev, bool clear,
|
||||
struct mlx5_fpga_shell_counters *data)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(fpga_shell_counters)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(fpga_shell_counters)];
|
||||
int err;
|
||||
|
||||
MLX5_SET(fpga_shell_counters, in, clear, clear);
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_FPGA_SHELL_CNTR, 0, false);
|
||||
if (err)
|
||||
goto out;
|
||||
if (data) {
|
||||
data->ddr_read_requests = MLX5_GET64(fpga_shell_counters, out,
|
||||
ddr_read_requests);
|
||||
data->ddr_write_requests = MLX5_GET64(fpga_shell_counters, out,
|
||||
ddr_write_requests);
|
||||
data->ddr_read_bytes = MLX5_GET64(fpga_shell_counters, out,
|
||||
ddr_read_bytes);
|
||||
data->ddr_write_bytes = MLX5_GET64(fpga_shell_counters, out,
|
||||
ddr_write_bytes);
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
1042
sys/dev/mlx5/mlx5_fpga/mlx5fpga_conn.c
Normal file
1042
sys/dev/mlx5/mlx5_fpga/mlx5fpga_conn.c
Normal file
File diff suppressed because it is too large
Load Diff
568
sys/dev/mlx5/mlx5_fpga/mlx5fpga_core.c
Normal file
568
sys/dev/mlx5/mlx5_fpga/mlx5fpga_core.c
Normal file
@ -0,0 +1,568 @@
|
||||
/*-
|
||||
* 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 <linux/etherdevice.h>
|
||||
#include <dev/mlx5/driver.h>
|
||||
#include <dev/mlx5/mlx5_core/mlx5_core.h>
|
||||
#include <dev/mlx5/mlx5_lib/mlx5.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
#include <dev/mlx5/mlx5_fpga/conn.h>
|
||||
#include <dev/mlx5/mlx5_fpga/trans.h>
|
||||
|
||||
static LIST_HEAD(mlx5_fpga_devices);
|
||||
static LIST_HEAD(mlx5_fpga_clients);
|
||||
/* protects access between client un/registration and device add/remove calls */
|
||||
static DEFINE_MUTEX(mlx5_fpga_mutex);
|
||||
|
||||
static const char *const mlx5_fpga_error_strings[] = {
|
||||
"Null Syndrome",
|
||||
"Corrupted DDR",
|
||||
"Flash Timeout",
|
||||
"Internal Link Error",
|
||||
"Watchdog HW Failure",
|
||||
"I2C Failure",
|
||||
"Image Changed",
|
||||
"Temperature Critical",
|
||||
};
|
||||
|
||||
static const char * const mlx5_fpga_qp_error_strings[] = {
|
||||
"Null Syndrome",
|
||||
"Retry Counter Expired",
|
||||
"RNR Expired",
|
||||
};
|
||||
|
||||
static void client_context_destroy(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client_data *context)
|
||||
{
|
||||
mlx5_fpga_dbg(fdev, "Deleting client context %p of client %p\n",
|
||||
context, context->client);
|
||||
if (context->client->destroy)
|
||||
context->client->destroy(fdev);
|
||||
list_del(&context->list);
|
||||
kfree(context);
|
||||
}
|
||||
|
||||
static int client_context_create(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client *client,
|
||||
struct mlx5_fpga_client_data **pctx)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context;
|
||||
|
||||
context = kmalloc(sizeof(*context), GFP_KERNEL);
|
||||
if (!context)
|
||||
return -ENOMEM;
|
||||
|
||||
context->client = client;
|
||||
context->data = NULL;
|
||||
context->added = false;
|
||||
list_add(&context->list, &fdev->client_data_list);
|
||||
|
||||
mlx5_fpga_dbg(fdev, "Adding client context %p client %p\n",
|
||||
context, client);
|
||||
|
||||
if (client->create)
|
||||
client->create(fdev);
|
||||
|
||||
if (pctx)
|
||||
*pctx = context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mlx5_fpga_device *mlx5_fpga_device_alloc(void)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = NULL;
|
||||
|
||||
fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
|
||||
if (!fdev)
|
||||
return NULL;
|
||||
|
||||
spin_lock_init(&fdev->state_lock);
|
||||
init_completion(&fdev->load_event);
|
||||
fdev->fdev_state = MLX5_FDEV_STATE_NONE;
|
||||
INIT_LIST_HEAD(&fdev->client_data_list);
|
||||
return fdev;
|
||||
}
|
||||
|
||||
static const char *mlx5_fpga_image_name(enum mlx5_fpga_image image)
|
||||
{
|
||||
switch (image) {
|
||||
case MLX5_FPGA_IMAGE_USER:
|
||||
return "user";
|
||||
case MLX5_FPGA_IMAGE_FACTORY:
|
||||
return "factory";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *mlx5_fpga_name(u32 fpga_id)
|
||||
{
|
||||
static char ret[32];
|
||||
|
||||
switch (fpga_id) {
|
||||
case MLX5_FPGA_NEWTON:
|
||||
return "Newton";
|
||||
case MLX5_FPGA_EDISON:
|
||||
return "Edison";
|
||||
case MLX5_FPGA_MORSE:
|
||||
return "Morse";
|
||||
}
|
||||
|
||||
snprintf(ret, sizeof(ret), "Unknown %d", fpga_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mlx5_fpga_device_load_check(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
struct mlx5_fpga_query query;
|
||||
int err;
|
||||
|
||||
err = mlx5_fpga_query(fdev->mdev, &query);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to query status: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
fdev->last_admin_image = query.admin_image;
|
||||
fdev->last_oper_image = query.oper_image;
|
||||
fdev->image_status = query.image_status;
|
||||
|
||||
mlx5_fpga_info(fdev, "Status %u; Admin image %u; Oper image %u\n",
|
||||
query.image_status, query.admin_image, query.oper_image);
|
||||
|
||||
/* For Morse project FPGA has no influence to network functionality */
|
||||
if (MLX5_CAP_FPGA(fdev->mdev, fpga_id) == MLX5_FPGA_MORSE)
|
||||
return 0;
|
||||
|
||||
if (query.image_status != MLX5_FPGA_STATUS_SUCCESS) {
|
||||
mlx5_fpga_err(fdev, "%s image failed to load; status %u\n",
|
||||
mlx5_fpga_image_name(fdev->last_oper_image),
|
||||
query.image_status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_fpga_device_brb(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
int err;
|
||||
struct mlx5_core_dev *mdev = fdev->mdev;
|
||||
|
||||
err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to set bypass on: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET_SANDBOX);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to reset SBU: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_OFF);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to set bypass off: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_client_data *client_context;
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
struct mlx5_fpga_conn_attr conn_attr = {0};
|
||||
struct mlx5_fpga_conn *conn;
|
||||
unsigned int max_num_qps;
|
||||
unsigned long flags;
|
||||
u32 fpga_id;
|
||||
u32 vid;
|
||||
u16 pid;
|
||||
int err;
|
||||
|
||||
if (!fdev)
|
||||
return 0;
|
||||
|
||||
err = mlx5_fpga_caps(fdev->mdev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mlx5_fpga_device_load_check(fdev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
fpga_id = MLX5_CAP_FPGA(fdev->mdev, fpga_id);
|
||||
mlx5_fpga_info(fdev, "FPGA card %s\n", mlx5_fpga_name(fpga_id));
|
||||
|
||||
if (fpga_id == MLX5_FPGA_MORSE)
|
||||
goto out;
|
||||
|
||||
mlx5_fpga_info(fdev, "%s(%d) image, version %u; SBU %06x:%04x version %d\n",
|
||||
mlx5_fpga_image_name(fdev->last_oper_image),
|
||||
fdev->last_oper_image,
|
||||
MLX5_CAP_FPGA(fdev->mdev, image_version),
|
||||
MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id),
|
||||
MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id),
|
||||
MLX5_CAP_FPGA(fdev->mdev, sandbox_product_version));
|
||||
|
||||
max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
|
||||
err = mlx5_core_reserve_gids(mdev, max_num_qps);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
err = mlx5_fpga_conn_device_init(fdev);
|
||||
#else
|
||||
err = 0;
|
||||
#endif
|
||||
if (err)
|
||||
goto err_rsvd_gid;
|
||||
|
||||
err = mlx5_fpga_trans_device_init(fdev);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to init transaction: %d\n",
|
||||
err);
|
||||
goto err_conn_init;
|
||||
}
|
||||
|
||||
conn_attr.tx_size = MLX5_FPGA_TID_COUNT;
|
||||
conn_attr.rx_size = MLX5_FPGA_TID_COUNT;
|
||||
conn_attr.recv_cb = mlx5_fpga_trans_recv;
|
||||
conn_attr.cb_arg = fdev;
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
conn = mlx5_fpga_conn_create(fdev, &conn_attr,
|
||||
MLX5_FPGA_QPC_QP_TYPE_SHELL_QP);
|
||||
if (IS_ERR(conn)) {
|
||||
err = PTR_ERR(conn);
|
||||
mlx5_fpga_err(fdev, "Failed to create shell conn: %d\n", err);
|
||||
goto err_trans;
|
||||
}
|
||||
#else
|
||||
conn = NULL;
|
||||
#endif
|
||||
fdev->shell_conn = conn;
|
||||
|
||||
if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
|
||||
err = mlx5_fpga_device_brb(fdev);
|
||||
if (err)
|
||||
goto err_shell_conn;
|
||||
|
||||
vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
|
||||
pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
list_for_each_entry(client_context, &fdev->client_data_list,
|
||||
list) {
|
||||
if (client_context->client->add(fdev, vid, pid))
|
||||
continue;
|
||||
client_context->added = true;
|
||||
}
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
err_shell_conn:
|
||||
if (fdev->shell_conn) {
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
mlx5_fpga_conn_destroy(fdev->shell_conn);
|
||||
#endif
|
||||
fdev->shell_conn = NULL;
|
||||
}
|
||||
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
err_trans:
|
||||
#endif
|
||||
mlx5_fpga_trans_device_cleanup(fdev);
|
||||
|
||||
err_conn_init:
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
mlx5_fpga_conn_device_cleanup(fdev);
|
||||
#endif
|
||||
|
||||
err_rsvd_gid:
|
||||
mlx5_core_unreserve_gids(mdev, max_num_qps);
|
||||
out:
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
fdev->fdev_state = err ? MLX5_FDEV_STATE_FAILURE : MLX5_FDEV_STATE_SUCCESS;
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_fpga_init(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = NULL;
|
||||
struct mlx5_fpga_client *client;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, fpga)) {
|
||||
mlx5_core_dbg(mdev, "FPGA capability not present\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mlx5_core_dbg(mdev, "Initializing FPGA\n");
|
||||
|
||||
fdev = mlx5_fpga_device_alloc();
|
||||
if (!fdev)
|
||||
return -ENOMEM;
|
||||
|
||||
fdev->mdev = mdev;
|
||||
mdev->fpga = fdev;
|
||||
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
|
||||
list_add_tail(&fdev->list, &mlx5_fpga_devices);
|
||||
list_for_each_entry(client, &mlx5_fpga_clients, list)
|
||||
client_context_create(fdev, client, NULL);
|
||||
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_fpga_device_stop(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_client_data *client_context;
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
unsigned int max_num_qps;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
if (!fdev)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
if (MLX5_CAP_FPGA(mdev, fpga_id) == MLX5_FPGA_MORSE)
|
||||
return;
|
||||
|
||||
if (fdev->fdev_state != MLX5_FDEV_STATE_SUCCESS) {
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
return;
|
||||
}
|
||||
fdev->fdev_state = MLX5_FDEV_STATE_NONE;
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
|
||||
if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
|
||||
err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
|
||||
if (err)
|
||||
mlx5_fpga_err(fdev, "Failed to re-set SBU bypass on: %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
list_for_each_entry(client_context, &fdev->client_data_list, list) {
|
||||
if (!client_context->added)
|
||||
continue;
|
||||
client_context->client->remove(fdev);
|
||||
client_context->added = false;
|
||||
}
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
|
||||
if (fdev->shell_conn) {
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
mlx5_fpga_conn_destroy(fdev->shell_conn);
|
||||
#endif
|
||||
fdev->shell_conn = NULL;
|
||||
mlx5_fpga_trans_device_cleanup(fdev);
|
||||
}
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
mlx5_fpga_conn_device_cleanup(fdev);
|
||||
#endif
|
||||
max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
|
||||
mlx5_core_unreserve_gids(mdev, max_num_qps);
|
||||
}
|
||||
|
||||
void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context, *tmp;
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
|
||||
if (!fdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
|
||||
mlx5_fpga_device_stop(mdev);
|
||||
|
||||
list_for_each_entry_safe(context, tmp, &fdev->client_data_list, list)
|
||||
client_context_destroy(fdev, context);
|
||||
|
||||
list_del(&fdev->list);
|
||||
kfree(fdev);
|
||||
mdev->fpga = NULL;
|
||||
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
}
|
||||
|
||||
static const char *mlx5_fpga_syndrome_to_string(u8 syndrome)
|
||||
{
|
||||
if (syndrome < ARRAY_SIZE(mlx5_fpga_error_strings))
|
||||
return mlx5_fpga_error_strings[syndrome];
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char *mlx5_fpga_qp_syndrome_to_string(u8 syndrome)
|
||||
{
|
||||
if (syndrome < ARRAY_SIZE(mlx5_fpga_qp_error_strings))
|
||||
return mlx5_fpga_qp_error_strings[syndrome];
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
const char *event_name;
|
||||
bool teardown = false;
|
||||
unsigned long flags;
|
||||
u32 fpga_qpn;
|
||||
u8 syndrome;
|
||||
|
||||
switch (event) {
|
||||
case MLX5_EVENT_TYPE_FPGA_ERROR:
|
||||
syndrome = MLX5_GET(fpga_error_event, data, syndrome);
|
||||
event_name = mlx5_fpga_syndrome_to_string(syndrome);
|
||||
break;
|
||||
case MLX5_EVENT_TYPE_FPGA_QP_ERROR:
|
||||
syndrome = MLX5_GET(fpga_qp_error_event, data, syndrome);
|
||||
event_name = mlx5_fpga_qp_syndrome_to_string(syndrome);
|
||||
fpga_qpn = MLX5_GET(fpga_qp_error_event, data, fpga_qpn);
|
||||
mlx5_fpga_err(fdev, "Error %u on QP %u: %s\n",
|
||||
syndrome, fpga_qpn, event_name);
|
||||
break;
|
||||
default:
|
||||
mlx5_fpga_warn_ratelimited(fdev, "Unexpected event %u\n",
|
||||
event);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
switch (fdev->fdev_state) {
|
||||
case MLX5_FDEV_STATE_SUCCESS:
|
||||
mlx5_fpga_warn(fdev, "Error %u: %s\n", syndrome, event_name);
|
||||
teardown = true;
|
||||
break;
|
||||
case MLX5_FDEV_STATE_IN_PROGRESS:
|
||||
if (syndrome != MLX5_FPGA_ERROR_EVENT_SYNDROME_IMAGE_CHANGED)
|
||||
mlx5_fpga_warn(fdev, "Error while loading %u: %s\n",
|
||||
syndrome, event_name);
|
||||
complete(&fdev->load_event);
|
||||
break;
|
||||
default:
|
||||
mlx5_fpga_warn_ratelimited(fdev, "Unexpected error event %u: %s\n",
|
||||
syndrome, event_name);
|
||||
}
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
/* We tear-down the card's interfaces and functionality because
|
||||
* the FPGA bump-on-the-wire is misbehaving and we lose ability
|
||||
* to communicate with the network. User may still be able to
|
||||
* recover by re-programming or debugging the FPGA
|
||||
*/
|
||||
if (teardown)
|
||||
mlx5_trigger_health_work(fdev->mdev);
|
||||
}
|
||||
|
||||
void mlx5_fpga_client_register(struct mlx5_fpga_client *client)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context;
|
||||
struct mlx5_fpga_device *fdev;
|
||||
bool call_add = false;
|
||||
unsigned long flags;
|
||||
u32 vid;
|
||||
u16 pid;
|
||||
int err;
|
||||
|
||||
pr_debug("Client register %s\n", client->name);
|
||||
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
|
||||
list_add_tail(&client->list, &mlx5_fpga_clients);
|
||||
|
||||
list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
|
||||
err = client_context_create(fdev, client, &context);
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
call_add = (fdev->fdev_state == MLX5_FDEV_STATE_SUCCESS);
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
|
||||
if (call_add) {
|
||||
vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
|
||||
pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
|
||||
if (!client->add(fdev, vid, pid))
|
||||
context->added = true;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_client_register);
|
||||
|
||||
void mlx5_fpga_client_unregister(struct mlx5_fpga_client *client)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context, *tmp_context;
|
||||
struct mlx5_fpga_device *fdev;
|
||||
|
||||
pr_debug("Client unregister %s\n", client->name);
|
||||
|
||||
mutex_lock(&mlx5_fpga_mutex);
|
||||
|
||||
list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
|
||||
list_for_each_entry_safe(context, tmp_context,
|
||||
&fdev->client_data_list,
|
||||
list) {
|
||||
if (context->client != client)
|
||||
continue;
|
||||
if (context->added)
|
||||
client->remove(fdev);
|
||||
client_context_destroy(fdev, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&client->list);
|
||||
mutex_unlock(&mlx5_fpga_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_client_unregister);
|
||||
|
||||
#if (__FreeBSD_version >= 1100000)
|
||||
MODULE_DEPEND(mlx5fpga, linuxkpi, 1, 1, 1);
|
||||
#endif
|
||||
MODULE_DEPEND(mlx5fpga, mlx5, 1, 1, 1);
|
||||
MODULE_VERSION(mlx5fpga, 1);
|
377
sys/dev/mlx5/mlx5_fpga/mlx5fpga_ipsec.c
Normal file
377
sys/dev/mlx5/mlx5_fpga/mlx5fpga_ipsec.c
Normal file
@ -0,0 +1,377 @@
|
||||
/*-
|
||||
* 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 <dev/mlx5/driver.h>
|
||||
|
||||
#include <dev/mlx5/mlx5_core/mlx5_core.h>
|
||||
#include <dev/mlx5/mlx5_fpga/ipsec.h>
|
||||
#include <dev/mlx5/mlx5_fpga/sdk.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
|
||||
#define SBU_QP_QUEUE_SIZE 8
|
||||
|
||||
enum mlx5_ipsec_response_syndrome {
|
||||
MLX5_IPSEC_RESPONSE_SUCCESS = 0,
|
||||
MLX5_IPSEC_RESPONSE_ILLEGAL_REQUEST = 1,
|
||||
MLX5_IPSEC_RESPONSE_SADB_ISSUE = 2,
|
||||
MLX5_IPSEC_RESPONSE_WRITE_RESPONSE_ISSUE = 3,
|
||||
};
|
||||
|
||||
enum mlx5_fpga_ipsec_sacmd_status {
|
||||
MLX5_FPGA_IPSEC_SACMD_PENDING,
|
||||
MLX5_FPGA_IPSEC_SACMD_SEND_FAIL,
|
||||
MLX5_FPGA_IPSEC_SACMD_COMPLETE,
|
||||
};
|
||||
|
||||
struct mlx5_ipsec_command_context {
|
||||
struct mlx5_fpga_dma_buf buf;
|
||||
struct mlx5_accel_ipsec_sa sa;
|
||||
enum mlx5_fpga_ipsec_sacmd_status status;
|
||||
int status_code;
|
||||
struct completion complete;
|
||||
struct mlx5_fpga_device *dev;
|
||||
struct list_head list; /* Item in pending_cmds */
|
||||
};
|
||||
|
||||
struct mlx5_ipsec_sadb_resp {
|
||||
__be32 syndrome;
|
||||
__be32 sw_sa_handle;
|
||||
u8 reserved[24];
|
||||
} __packed;
|
||||
|
||||
struct mlx5_fpga_ipsec {
|
||||
struct list_head pending_cmds;
|
||||
spinlock_t pending_cmds_lock; /* Protects pending_cmds */
|
||||
u32 caps[MLX5_ST_SZ_DW(ipsec_extended_cap)];
|
||||
struct mlx5_fpga_conn *conn;
|
||||
};
|
||||
|
||||
static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga))
|
||||
return false;
|
||||
|
||||
if (MLX5_CAP_FPGA(mdev, ieee_vendor_id) !=
|
||||
MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX)
|
||||
return false;
|
||||
|
||||
if (MLX5_CAP_FPGA(mdev, sandbox_product_id) !=
|
||||
MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_IPSEC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mlx5_fpga_ipsec_send_complete(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_dma_buf *buf,
|
||||
u8 status)
|
||||
{
|
||||
struct mlx5_ipsec_command_context *context;
|
||||
|
||||
if (status) {
|
||||
context = container_of(buf, struct mlx5_ipsec_command_context,
|
||||
buf);
|
||||
mlx5_fpga_warn(fdev, "IPSec command send failed with status %u\n",
|
||||
status);
|
||||
context->status = MLX5_FPGA_IPSEC_SACMD_SEND_FAIL;
|
||||
complete(&context->complete);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int syndrome_to_errno(enum mlx5_ipsec_response_syndrome syndrome)
|
||||
{
|
||||
switch (syndrome) {
|
||||
case MLX5_IPSEC_RESPONSE_SUCCESS:
|
||||
return 0;
|
||||
case MLX5_IPSEC_RESPONSE_SADB_ISSUE:
|
||||
return -EEXIST;
|
||||
case MLX5_IPSEC_RESPONSE_ILLEGAL_REQUEST:
|
||||
return -EINVAL;
|
||||
case MLX5_IPSEC_RESPONSE_WRITE_RESPONSE_ISSUE:
|
||||
return -EIO;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void mlx5_fpga_ipsec_recv(void *cb_arg, struct mlx5_fpga_dma_buf *buf)
|
||||
{
|
||||
struct mlx5_ipsec_sadb_resp *resp = buf->sg[0].data;
|
||||
struct mlx5_ipsec_command_context *context;
|
||||
enum mlx5_ipsec_response_syndrome syndrome;
|
||||
struct mlx5_fpga_device *fdev = cb_arg;
|
||||
unsigned long flags;
|
||||
|
||||
if (buf->sg[0].size < sizeof(*resp)) {
|
||||
mlx5_fpga_warn(fdev, "Short receive from FPGA IPSec: %u < %zu bytes\n",
|
||||
buf->sg[0].size, sizeof(*resp));
|
||||
return;
|
||||
}
|
||||
|
||||
mlx5_fpga_dbg(fdev, "mlx5_ipsec recv_cb syndrome %08x sa_id %x\n",
|
||||
ntohl(resp->syndrome), ntohl(resp->sw_sa_handle));
|
||||
|
||||
spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
context = list_first_entry_or_null(&fdev->ipsec->pending_cmds,
|
||||
struct mlx5_ipsec_command_context,
|
||||
list);
|
||||
if (context)
|
||||
list_del(&context->list);
|
||||
spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
|
||||
if (!context) {
|
||||
mlx5_fpga_warn(fdev, "Received IPSec offload response without pending command request\n");
|
||||
return;
|
||||
}
|
||||
mlx5_fpga_dbg(fdev, "Handling response for %p\n", context);
|
||||
|
||||
if (context->sa.sw_sa_handle != resp->sw_sa_handle) {
|
||||
mlx5_fpga_err(fdev, "mismatch SA handle. cmd 0x%08x vs resp 0x%08x\n",
|
||||
ntohl(context->sa.sw_sa_handle),
|
||||
ntohl(resp->sw_sa_handle));
|
||||
return;
|
||||
}
|
||||
|
||||
syndrome = ntohl(resp->syndrome);
|
||||
context->status_code = syndrome_to_errno(syndrome);
|
||||
context->status = MLX5_FPGA_IPSEC_SACMD_COMPLETE;
|
||||
|
||||
if (context->status_code)
|
||||
mlx5_fpga_warn(fdev, "IPSec SADB command failed with syndrome %08x\n",
|
||||
syndrome);
|
||||
complete(&context->complete);
|
||||
}
|
||||
|
||||
void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev,
|
||||
struct mlx5_accel_ipsec_sa *cmd)
|
||||
{
|
||||
struct mlx5_ipsec_command_context *context;
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
unsigned long flags;
|
||||
int res = 0;
|
||||
|
||||
BUILD_BUG_ON((sizeof(struct mlx5_accel_ipsec_sa) & 3) != 0);
|
||||
if (!fdev || !fdev->ipsec)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
context = kzalloc(sizeof(*context), GFP_ATOMIC);
|
||||
if (!context)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(&context->sa, cmd, sizeof(*cmd));
|
||||
context->buf.complete = mlx5_fpga_ipsec_send_complete;
|
||||
context->buf.sg[0].size = sizeof(context->sa);
|
||||
context->buf.sg[0].data = &context->sa;
|
||||
init_completion(&context->complete);
|
||||
context->dev = fdev;
|
||||
spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
list_add_tail(&context->list, &fdev->ipsec->pending_cmds);
|
||||
spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
|
||||
context->status = MLX5_FPGA_IPSEC_SACMD_PENDING;
|
||||
|
||||
res = mlx5_fpga_sbu_conn_sendmsg(fdev->ipsec->conn, &context->buf);
|
||||
if (res) {
|
||||
mlx5_fpga_warn(fdev, "Failure sending IPSec command: %d\n",
|
||||
res);
|
||||
spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
list_del(&context->list);
|
||||
spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags);
|
||||
kfree(context);
|
||||
return ERR_PTR(res);
|
||||
}
|
||||
/* Context will be freed by wait func after completion */
|
||||
return context;
|
||||
}
|
||||
|
||||
int mlx5_fpga_ipsec_sa_cmd_wait(void *ctx)
|
||||
{
|
||||
struct mlx5_ipsec_command_context *context = ctx;
|
||||
int res;
|
||||
|
||||
res = wait_for_completion/*_killable XXXKIB*/(&context->complete);
|
||||
if (res) {
|
||||
mlx5_fpga_warn(context->dev, "Failure waiting for IPSec command response\n");
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (context->status == MLX5_FPGA_IPSEC_SACMD_COMPLETE)
|
||||
res = context->status_code;
|
||||
else
|
||||
res = -EIO;
|
||||
|
||||
kfree(context);
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
u32 ret = 0;
|
||||
|
||||
if (mlx5_fpga_is_ipsec_device(mdev))
|
||||
ret |= MLX5_ACCEL_IPSEC_DEVICE;
|
||||
else
|
||||
return ret;
|
||||
|
||||
if (!fdev->ipsec)
|
||||
return ret;
|
||||
|
||||
if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, esp))
|
||||
ret |= MLX5_ACCEL_IPSEC_ESP;
|
||||
|
||||
if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, ipv6))
|
||||
ret |= MLX5_ACCEL_IPSEC_IPV6;
|
||||
|
||||
if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, lso))
|
||||
ret |= MLX5_ACCEL_IPSEC_LSO;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
|
||||
if (!fdev || !fdev->ipsec)
|
||||
return 0;
|
||||
|
||||
return MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps,
|
||||
number_of_ipsec_counters);
|
||||
}
|
||||
|
||||
int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
|
||||
unsigned int counters_count)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
unsigned int i;
|
||||
__be32 *data;
|
||||
u32 count;
|
||||
u64 addr;
|
||||
int ret;
|
||||
|
||||
if (!fdev || !fdev->ipsec)
|
||||
return 0;
|
||||
|
||||
addr = (u64)MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps,
|
||||
ipsec_counters_addr_low) +
|
||||
((u64)MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps,
|
||||
ipsec_counters_addr_high) << 32);
|
||||
|
||||
count = mlx5_fpga_ipsec_counters_count(mdev);
|
||||
|
||||
data = kzalloc(sizeof(*data) * count * 2, GFP_KERNEL);
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = mlx5_fpga_mem_read(fdev, count * sizeof(u64), addr, data,
|
||||
MLX5_FPGA_ACCESS_TYPE_DONTCARE);
|
||||
if (ret < 0) {
|
||||
mlx5_fpga_err(fdev, "Failed to read IPSec counters from HW: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
if (count > counters_count)
|
||||
count = counters_count;
|
||||
|
||||
/* Each counter is low word, then high. But each word is big-endian */
|
||||
for (i = 0; i < count; i++)
|
||||
counters[i] = (u64)ntohl(data[i * 2]) |
|
||||
((u64)ntohl(data[i * 2 + 1]) << 32);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_conn_attr init_attr = {0};
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
struct mlx5_fpga_conn *conn;
|
||||
int err;
|
||||
|
||||
if (!mlx5_fpga_is_ipsec_device(mdev))
|
||||
return 0;
|
||||
|
||||
fdev->ipsec = kzalloc(sizeof(*fdev->ipsec), GFP_KERNEL);
|
||||
if (!fdev->ipsec)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx5_fpga_get_sbu_caps(fdev, sizeof(fdev->ipsec->caps),
|
||||
fdev->ipsec->caps);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to retrieve IPSec extended capabilities: %d\n",
|
||||
err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&fdev->ipsec->pending_cmds);
|
||||
spin_lock_init(&fdev->ipsec->pending_cmds_lock);
|
||||
|
||||
init_attr.rx_size = SBU_QP_QUEUE_SIZE;
|
||||
init_attr.tx_size = SBU_QP_QUEUE_SIZE;
|
||||
init_attr.recv_cb = mlx5_fpga_ipsec_recv;
|
||||
init_attr.cb_arg = fdev;
|
||||
conn = mlx5_fpga_sbu_conn_create(fdev, &init_attr);
|
||||
if (IS_ERR(conn)) {
|
||||
err = PTR_ERR(conn);
|
||||
mlx5_fpga_err(fdev, "Error creating IPSec command connection %d\n",
|
||||
err);
|
||||
goto error;
|
||||
}
|
||||
fdev->ipsec->conn = conn;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(fdev->ipsec);
|
||||
fdev->ipsec = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = mdev->fpga;
|
||||
|
||||
if (!mlx5_fpga_is_ipsec_device(mdev))
|
||||
return;
|
||||
|
||||
mlx5_fpga_sbu_conn_destroy(fdev->ipsec->conn);
|
||||
kfree(fdev->ipsec);
|
||||
fdev->ipsec = NULL;
|
||||
}
|
459
sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c
Normal file
459
sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c
Normal file
@ -0,0 +1,459 @@
|
||||
/*-
|
||||
* 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/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/completion.h>
|
||||
#include <dev/mlx5/device.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
#include <dev/mlx5/mlx5_fpga/conn.h>
|
||||
#include <dev/mlx5/mlx5_fpga/sdk.h>
|
||||
#include <dev/mlx5/mlx5_fpga/xfer.h>
|
||||
#include <dev/mlx5/mlx5_core/mlx5_core.h>
|
||||
/* #include "accel/ipsec.h" */
|
||||
|
||||
#define MLX5_FPGA_LOAD_TIMEOUT 25000 /* msec */
|
||||
|
||||
struct mem_transfer {
|
||||
struct mlx5_fpga_transaction t;
|
||||
struct completion comp;
|
||||
u8 status;
|
||||
};
|
||||
|
||||
struct mlx5_fpga_conn *
|
||||
mlx5_fpga_sbu_conn_create(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_conn_attr *attr)
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
return mlx5_fpga_conn_create(fdev, attr, MLX5_FPGA_QPC_QP_TYPE_SANDBOX_QP);
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_sbu_conn_create);
|
||||
|
||||
void mlx5_fpga_sbu_conn_destroy(struct mlx5_fpga_conn *conn)
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
mlx5_fpga_conn_destroy(conn);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_sbu_conn_destroy);
|
||||
|
||||
int mlx5_fpga_sbu_conn_sendmsg(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_dma_buf *buf)
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
return mlx5_fpga_conn_send(conn, buf);
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_sbu_conn_sendmsg);
|
||||
|
||||
static void mem_complete(const struct mlx5_fpga_transaction *complete,
|
||||
u8 status)
|
||||
{
|
||||
struct mem_transfer *xfer;
|
||||
|
||||
mlx5_fpga_dbg(complete->conn->fdev,
|
||||
"transaction %p complete status %u", complete, status);
|
||||
|
||||
xfer = container_of(complete, struct mem_transfer, t);
|
||||
xfer->status = status;
|
||||
complete_all(&xfer->comp);
|
||||
}
|
||||
|
||||
static int mem_transaction(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
|
||||
void *buf, enum mlx5_fpga_direction direction)
|
||||
{
|
||||
int ret;
|
||||
struct mem_transfer xfer;
|
||||
|
||||
if (!fdev->shell_conn) {
|
||||
ret = -ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfer.t.data = buf;
|
||||
xfer.t.size = size;
|
||||
xfer.t.addr = addr;
|
||||
xfer.t.conn = fdev->shell_conn;
|
||||
xfer.t.direction = direction;
|
||||
xfer.t.complete1 = mem_complete;
|
||||
init_completion(&xfer.comp);
|
||||
ret = mlx5_fpga_xfer_exec(&xfer.t);
|
||||
if (ret) {
|
||||
mlx5_fpga_dbg(fdev, "Transfer execution failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
wait_for_completion(&xfer.comp);
|
||||
if (xfer.status != 0)
|
||||
ret = -EIO;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mlx5_fpga_mem_read_i2c(struct mlx5_fpga_device *fdev, size_t size,
|
||||
u64 addr, u8 *buf)
|
||||
{
|
||||
size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
|
||||
size_t bytes_done = 0;
|
||||
u8 actual_size;
|
||||
int err = 0;
|
||||
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!fdev->mdev)
|
||||
return -ENOTCONN;
|
||||
|
||||
while (bytes_done < size) {
|
||||
actual_size = min(max_size, (size - bytes_done));
|
||||
|
||||
err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
|
||||
addr + bytes_done,
|
||||
buf + bytes_done, false);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to read over I2C: %d\n",
|
||||
err);
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_done += actual_size;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5_fpga_mem_write_i2c(struct mlx5_fpga_device *fdev, size_t size,
|
||||
u64 addr, u8 *buf)
|
||||
{
|
||||
size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
|
||||
size_t bytes_done = 0;
|
||||
u8 actual_size;
|
||||
int err = 0;
|
||||
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!fdev->mdev)
|
||||
return -ENOTCONN;
|
||||
|
||||
while (bytes_done < size) {
|
||||
actual_size = min(max_size, (size - bytes_done));
|
||||
|
||||
err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
|
||||
addr + bytes_done,
|
||||
buf + bytes_done, true);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to write FPGA crspace\n");
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_done += actual_size;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_fpga_mem_read(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
|
||||
void *buf, enum mlx5_fpga_access_type access_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
|
||||
access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
|
||||
MLX5_FPGA_ACCESS_TYPE_I2C;
|
||||
|
||||
mlx5_fpga_dbg(fdev, "Reading %zu bytes at 0x%jx over %s",
|
||||
size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
|
||||
|
||||
switch (access_type) {
|
||||
case MLX5_FPGA_ACCESS_TYPE_RDMA:
|
||||
ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_READ);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case MLX5_FPGA_ACCESS_TYPE_I2C:
|
||||
ret = mlx5_fpga_mem_read_i2c(fdev, size, addr, buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
mlx5_fpga_warn(fdev, "Unexpected read access_type %u\n",
|
||||
access_type);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_mem_read);
|
||||
|
||||
int mlx5_fpga_mem_write(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
|
||||
void *buf, enum mlx5_fpga_access_type access_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
|
||||
access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
|
||||
MLX5_FPGA_ACCESS_TYPE_I2C;
|
||||
|
||||
mlx5_fpga_dbg(fdev, "Writing %zu bytes at 0x%jx over %s",
|
||||
size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
|
||||
|
||||
switch (access_type) {
|
||||
case MLX5_FPGA_ACCESS_TYPE_RDMA:
|
||||
ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_WRITE);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case MLX5_FPGA_ACCESS_TYPE_I2C:
|
||||
ret = mlx5_fpga_mem_write_i2c(fdev, size, addr, buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
mlx5_fpga_warn(fdev, "Unexpected write access_type %u\n",
|
||||
access_type);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_mem_write);
|
||||
|
||||
int mlx5_fpga_get_sbu_caps(struct mlx5_fpga_device *fdev, int size, void *buf)
|
||||
{
|
||||
return mlx5_fpga_sbu_caps(fdev->mdev, buf, size);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_get_sbu_caps);
|
||||
|
||||
u64 mlx5_fpga_ddr_size_get(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
return (u64)MLX5_CAP_FPGA(fdev->mdev, fpga_ddr_size) << 10;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_ddr_size_get);
|
||||
|
||||
u64 mlx5_fpga_ddr_base_get(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
return MLX5_CAP64_FPGA(fdev->mdev, fpga_ddr_start_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_ddr_base_get);
|
||||
|
||||
void mlx5_fpga_client_data_set(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client *client, void *data)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context;
|
||||
|
||||
list_for_each_entry(context, &fdev->client_data_list, list) {
|
||||
if (context->client != client)
|
||||
continue;
|
||||
context->data = data;
|
||||
return;
|
||||
}
|
||||
|
||||
mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_client_data_set);
|
||||
|
||||
void *mlx5_fpga_client_data_get(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client *client)
|
||||
{
|
||||
struct mlx5_fpga_client_data *context;
|
||||
void *ret = NULL;
|
||||
|
||||
list_for_each_entry(context, &fdev->client_data_list, list) {
|
||||
if (context->client != client)
|
||||
continue;
|
||||
ret = context->data;
|
||||
goto out;
|
||||
}
|
||||
mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_client_data_get);
|
||||
|
||||
void mlx5_fpga_device_query(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_query *query)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
query->image_status = fdev->image_status;
|
||||
query->admin_image = fdev->last_admin_image;
|
||||
query->oper_image = fdev->last_oper_image;
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_device_query);
|
||||
|
||||
int mlx5_fpga_device_reload(struct mlx5_fpga_device *fdev,
|
||||
enum mlx5_fpga_image image)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = fdev->mdev;
|
||||
unsigned long timeout;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
switch (fdev->fdev_state) {
|
||||
case MLX5_FDEV_STATE_NONE:
|
||||
err = -ENODEV;
|
||||
break;
|
||||
case MLX5_FDEV_STATE_IN_PROGRESS:
|
||||
err = -EBUSY;
|
||||
break;
|
||||
case MLX5_FDEV_STATE_SUCCESS:
|
||||
case MLX5_FDEV_STATE_FAILURE:
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&mdev->intf_state_mutex);
|
||||
clear_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
|
||||
|
||||
mlx5_unregister_device(mdev);
|
||||
/* XXXKIB mlx5_accel_ipsec_cleanup(mdev); */
|
||||
mlx5_fpga_device_stop(mdev);
|
||||
|
||||
fdev->fdev_state = MLX5_FDEV_STATE_IN_PROGRESS;
|
||||
reinit_completion(&fdev->load_event);
|
||||
|
||||
if (image <= MLX5_FPGA_IMAGE_MAX) {
|
||||
mlx5_fpga_info(fdev, "Loading from flash\n");
|
||||
err = mlx5_fpga_load(mdev, image);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to request load: %d\n",
|
||||
err);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
mlx5_fpga_info(fdev, "Resetting\n");
|
||||
err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET);
|
||||
if (err) {
|
||||
mlx5_fpga_err(fdev, "Failed to request reset: %d\n",
|
||||
err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MLX5_FPGA_LOAD_TIMEOUT);
|
||||
err = wait_for_completion_timeout(&fdev->load_event, timeout - jiffies);
|
||||
if (err < 0) {
|
||||
mlx5_fpga_err(fdev, "Failed waiting for FPGA load: %d\n", err);
|
||||
fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mlx5_fpga_device_start(mdev);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "fpga device start failed %d\n", err);
|
||||
goto out;
|
||||
}
|
||||
/* XXXKIB err = mlx5_accel_ipsec_init(mdev); */
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "IPSec device start failed %d\n", err);
|
||||
goto err_fpga;
|
||||
}
|
||||
|
||||
err = mlx5_register_device(mdev);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "mlx5_register_device failed %d\n", err);
|
||||
fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
|
||||
goto err_ipsec;
|
||||
}
|
||||
|
||||
set_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
|
||||
goto out;
|
||||
|
||||
err_ipsec:
|
||||
/* XXXKIB mlx5_accel_ipsec_cleanup(mdev); */
|
||||
err_fpga:
|
||||
mlx5_fpga_device_stop(mdev);
|
||||
out:
|
||||
mutex_unlock(&mdev->intf_state_mutex);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_device_reload);
|
||||
|
||||
int mlx5_fpga_flash_select(struct mlx5_fpga_device *fdev,
|
||||
enum mlx5_fpga_image image)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
switch (fdev->fdev_state) {
|
||||
case MLX5_FDEV_STATE_NONE:
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
return -ENODEV;
|
||||
case MLX5_FDEV_STATE_IN_PROGRESS:
|
||||
case MLX5_FDEV_STATE_SUCCESS:
|
||||
case MLX5_FDEV_STATE_FAILURE:
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
|
||||
err = mlx5_fpga_image_select(fdev->mdev, image);
|
||||
if (err)
|
||||
mlx5_fpga_err(fdev, "Failed to select flash image: %d\n", err);
|
||||
else
|
||||
fdev->last_admin_image = image;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_flash_select);
|
||||
|
||||
struct device *mlx5_fpga_dev(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
return &fdev->mdev->pdev->dev;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_dev);
|
||||
|
||||
void mlx5_fpga_get_cap(struct mlx5_fpga_device *fdev, u32 *fpga_caps)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fdev->state_lock, flags);
|
||||
memcpy(fpga_caps, &fdev->mdev->caps.fpga, sizeof(fdev->mdev->caps.fpga));
|
||||
spin_unlock_irqrestore(&fdev->state_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fpga_get_cap);
|
335
sys/dev/mlx5/mlx5_fpga/mlx5fpga_trans.c
Normal file
335
sys/dev/mlx5/mlx5_fpga/mlx5fpga_trans.c
Normal file
@ -0,0 +1,335 @@
|
||||
/*-
|
||||
* 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 <dev/mlx5/mlx5_fpga/trans.h>
|
||||
#include <dev/mlx5/mlx5_fpga/conn.h>
|
||||
|
||||
enum mlx5_fpga_transaction_state {
|
||||
TRANS_STATE_NONE,
|
||||
TRANS_STATE_SEND,
|
||||
TRANS_STATE_WAIT,
|
||||
TRANS_STATE_COMPLETE,
|
||||
};
|
||||
|
||||
struct mlx5_fpga_trans_priv {
|
||||
const struct mlx5_fpga_transaction *user_trans;
|
||||
u8 tid;
|
||||
enum mlx5_fpga_transaction_state state;
|
||||
u8 status;
|
||||
u32 header[MLX5_ST_SZ_DW(fpga_shell_qp_packet)];
|
||||
struct mlx5_fpga_dma_buf buf;
|
||||
struct list_head list_item;
|
||||
};
|
||||
|
||||
struct mlx5_fpga_trans_device_state {
|
||||
spinlock_t lock; /* Protects all members of this struct */
|
||||
struct list_head free_queue;
|
||||
struct mlx5_fpga_trans_priv transactions[MLX5_FPGA_TID_COUNT];
|
||||
};
|
||||
|
||||
static struct mlx5_fpga_trans_priv *find_tid(struct mlx5_fpga_device *fdev,
|
||||
u8 tid)
|
||||
{
|
||||
if (tid >= MLX5_FPGA_TID_COUNT) {
|
||||
mlx5_fpga_warn(fdev, "Unexpected transaction ID %u\n", tid);
|
||||
return NULL;
|
||||
}
|
||||
return &fdev->trans->transactions[tid];
|
||||
}
|
||||
|
||||
static struct mlx5_fpga_trans_priv *alloc_tid(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
struct mlx5_fpga_trans_priv *ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fdev->trans->lock, flags);
|
||||
|
||||
if (list_empty(&fdev->trans->free_queue)) {
|
||||
mlx5_fpga_dbg(fdev, "No free transaction ID available\n");
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = list_first_entry(&fdev->trans->free_queue,
|
||||
struct mlx5_fpga_trans_priv, list_item);
|
||||
list_del(&ret->list_item);
|
||||
|
||||
ret->state = TRANS_STATE_NONE;
|
||||
out:
|
||||
spin_unlock_irqrestore(&fdev->trans->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_tid(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_trans_priv *trans_priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fdev->trans->lock, flags);
|
||||
list_add_tail(&trans_priv->list_item, &fdev->trans->free_queue);
|
||||
spin_unlock_irqrestore(&fdev->trans->lock, flags);
|
||||
}
|
||||
|
||||
static void trans_complete(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_trans_priv *trans_priv, u8 status)
|
||||
{
|
||||
const struct mlx5_fpga_transaction *user_trans;
|
||||
unsigned long flags;
|
||||
|
||||
mlx5_fpga_dbg(fdev, "Transaction %u is complete with status %u\n",
|
||||
trans_priv->tid, status);
|
||||
|
||||
spin_lock_irqsave(&fdev->trans->lock, flags);
|
||||
trans_priv->state = TRANS_STATE_COMPLETE;
|
||||
trans_priv->status = status;
|
||||
spin_unlock_irqrestore(&fdev->trans->lock, flags);
|
||||
|
||||
user_trans = trans_priv->user_trans;
|
||||
free_tid(fdev, trans_priv);
|
||||
|
||||
if (user_trans->complete1)
|
||||
user_trans->complete1(user_trans, status);
|
||||
}
|
||||
|
||||
static void trans_send_complete(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_dma_buf *buf, u8 status)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mlx5_fpga_trans_priv *trans_priv;
|
||||
|
||||
trans_priv = container_of(buf, struct mlx5_fpga_trans_priv, buf);
|
||||
mlx5_fpga_dbg(fdev, "send complete tid %u. Status: %u\n",
|
||||
trans_priv->tid, status);
|
||||
if (status) {
|
||||
trans_complete(fdev, trans_priv, status);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fdev->trans->lock, flags);
|
||||
if (trans_priv->state == TRANS_STATE_SEND)
|
||||
trans_priv->state = TRANS_STATE_WAIT;
|
||||
spin_unlock_irqrestore(&fdev->trans->lock, flags);
|
||||
}
|
||||
|
||||
static int trans_validate(struct mlx5_fpga_device *fdev, u64 addr, size_t size)
|
||||
{
|
||||
if (size > MLX5_FPGA_TRANSACTION_MAX_SIZE) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes at once. Max is %u\n",
|
||||
size, MLX5_FPGA_TRANSACTION_MAX_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (size & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes. Must be full dwords\n",
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (size < 1) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes. Empty transaction not allowed\n",
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (addr & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes at unaligned address %jx\n",
|
||||
size, (uintmax_t)addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((addr >> MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS) !=
|
||||
((addr + size - 1) >> MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS)) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes at address %jx. Crosses page boundary\n",
|
||||
size, (uintmax_t)addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (addr < mlx5_fpga_ddr_base_get(fdev)) {
|
||||
if (size != sizeof(u32)) {
|
||||
mlx5_fpga_warn(fdev, "Cannot access %zu bytes at cr-space address %jx. Must access a single dword\n",
|
||||
size, (uintmax_t)addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_fpga_trans_exec(const struct mlx5_fpga_transaction *trans)
|
||||
{
|
||||
struct mlx5_fpga_conn *conn = trans->conn;
|
||||
struct mlx5_fpga_trans_priv *trans_priv;
|
||||
u32 *header;
|
||||
int err;
|
||||
|
||||
if (!trans->complete1) {
|
||||
mlx5_fpga_warn(conn->fdev, "Transaction must have a completion callback\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = trans_validate(conn->fdev, trans->addr, trans->size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
trans_priv = alloc_tid(conn->fdev);
|
||||
if (!trans_priv) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
trans_priv->user_trans = trans;
|
||||
header = trans_priv->header;
|
||||
|
||||
memset(header, 0, sizeof(trans_priv->header));
|
||||
memset(&trans_priv->buf, 0, sizeof(trans_priv->buf));
|
||||
MLX5_SET(fpga_shell_qp_packet, header, type,
|
||||
(trans->direction == MLX5_FPGA_WRITE) ?
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE :
|
||||
MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ);
|
||||
MLX5_SET(fpga_shell_qp_packet, header, tid, trans_priv->tid);
|
||||
MLX5_SET(fpga_shell_qp_packet, header, len, trans->size);
|
||||
MLX5_SET64(fpga_shell_qp_packet, header, address, trans->addr);
|
||||
|
||||
trans_priv->buf.sg[0].data = header;
|
||||
trans_priv->buf.sg[0].size = sizeof(trans_priv->header);
|
||||
if (trans->direction == MLX5_FPGA_WRITE) {
|
||||
trans_priv->buf.sg[1].data = trans->data;
|
||||
trans_priv->buf.sg[1].size = trans->size;
|
||||
}
|
||||
|
||||
trans_priv->buf.complete = trans_send_complete;
|
||||
trans_priv->state = TRANS_STATE_SEND;
|
||||
|
||||
#ifdef NOT_YET
|
||||
/* XXXKIB */
|
||||
err = mlx5_fpga_conn_send(conn->fdev->shell_conn, &trans_priv->buf);
|
||||
#else
|
||||
err = 0;
|
||||
#endif
|
||||
if (err)
|
||||
goto out_buf_tid;
|
||||
goto out;
|
||||
|
||||
out_buf_tid:
|
||||
free_tid(conn->fdev, trans_priv);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_fpga_trans_recv(void *cb_arg, struct mlx5_fpga_dma_buf *buf)
|
||||
{
|
||||
struct mlx5_fpga_device *fdev = cb_arg;
|
||||
struct mlx5_fpga_trans_priv *trans_priv;
|
||||
size_t payload_len;
|
||||
u8 status = 0;
|
||||
u8 tid, type;
|
||||
|
||||
mlx5_fpga_dbg(fdev, "Rx QP message on core conn; %u bytes\n",
|
||||
buf->sg[0].size);
|
||||
|
||||
if (buf->sg[0].size < MLX5_ST_SZ_BYTES(fpga_shell_qp_packet)) {
|
||||
mlx5_fpga_warn(fdev, "Short message %u bytes from device\n",
|
||||
buf->sg[0].size);
|
||||
goto out;
|
||||
}
|
||||
payload_len = buf->sg[0].size - MLX5_ST_SZ_BYTES(fpga_shell_qp_packet);
|
||||
|
||||
tid = MLX5_GET(fpga_shell_qp_packet, buf->sg[0].data, tid);
|
||||
trans_priv = find_tid(fdev, tid);
|
||||
if (!trans_priv)
|
||||
goto out;
|
||||
|
||||
type = MLX5_GET(fpga_shell_qp_packet, buf->sg[0].data, type);
|
||||
switch (type) {
|
||||
case MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_READ_RESPONSE:
|
||||
if (trans_priv->user_trans->direction != MLX5_FPGA_READ) {
|
||||
mlx5_fpga_warn(fdev, "Wrong answer type %u to a %u transaction\n",
|
||||
type, trans_priv->user_trans->direction);
|
||||
status = -EIO;
|
||||
goto complete;
|
||||
}
|
||||
if (payload_len != trans_priv->user_trans->size) {
|
||||
mlx5_fpga_warn(fdev, "Incorrect transaction payload length %zu expected %zu\n",
|
||||
payload_len,
|
||||
trans_priv->user_trans->size);
|
||||
goto complete;
|
||||
}
|
||||
memcpy(trans_priv->user_trans->data,
|
||||
MLX5_ADDR_OF(fpga_shell_qp_packet, buf->sg[0].data,
|
||||
data), payload_len);
|
||||
break;
|
||||
case MLX5_FPGA_SHELL_QP_PACKET_TYPE_DDR_WRITE_RESPONSE:
|
||||
if (trans_priv->user_trans->direction != MLX5_FPGA_WRITE) {
|
||||
mlx5_fpga_warn(fdev, "Wrong answer type %u to a %u transaction\n",
|
||||
type, trans_priv->user_trans->direction);
|
||||
status = -EIO;
|
||||
goto complete;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mlx5_fpga_warn(fdev, "Unexpected message type %u len %u from device\n",
|
||||
type, buf->sg[0].size);
|
||||
status = -EIO;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
complete:
|
||||
trans_complete(fdev, trans_priv, status);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
int mlx5_fpga_trans_device_init(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
int ret = 0;
|
||||
int tid;
|
||||
|
||||
fdev->trans = kzalloc(sizeof(*fdev->trans), GFP_KERNEL);
|
||||
if (!fdev->trans) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&fdev->trans->free_queue);
|
||||
for (tid = 0; tid < ARRAY_SIZE(fdev->trans->transactions); tid++) {
|
||||
fdev->trans->transactions[tid].tid = tid;
|
||||
list_add_tail(&fdev->trans->transactions[tid].list_item,
|
||||
&fdev->trans->free_queue);
|
||||
}
|
||||
|
||||
spin_lock_init(&fdev->trans->lock);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mlx5_fpga_trans_device_cleanup(struct mlx5_fpga_device *fdev)
|
||||
{
|
||||
kfree(fdev->trans);
|
||||
}
|
244
sys/dev/mlx5/mlx5_fpga/mlx5fpga_xfer.c
Normal file
244
sys/dev/mlx5/mlx5_fpga/mlx5fpga_xfer.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*-
|
||||
* 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 <dev/mlx5/mlx5_fpga/xfer.h>
|
||||
#include <dev/mlx5/mlx5_fpga/conn.h>
|
||||
|
||||
struct xfer_state {
|
||||
const struct mlx5_fpga_transaction *xfer;
|
||||
/* Total transactions */
|
||||
unsigned int start_count;
|
||||
unsigned int done_count;
|
||||
unsigned int error_count;
|
||||
u8 status;
|
||||
/* Inflight transactions */
|
||||
unsigned int budget;
|
||||
unsigned int inflight_count;
|
||||
/* Chunking state */
|
||||
size_t pos;
|
||||
spinlock_t lock; /* Protects all members of this struct */
|
||||
};
|
||||
|
||||
struct xfer_transaction {
|
||||
struct xfer_state *xfer_state;
|
||||
struct mlx5_fpga_transaction transaction;
|
||||
};
|
||||
|
||||
static void trans_complete(const struct mlx5_fpga_transaction *complete,
|
||||
u8 status);
|
||||
|
||||
static void xfer_complete(struct xfer_state *xfer_state)
|
||||
{
|
||||
const struct mlx5_fpga_transaction *xfer = xfer_state->xfer;
|
||||
u8 status = xfer_state->status;
|
||||
|
||||
kfree(xfer_state);
|
||||
xfer->complete1(xfer, status);
|
||||
}
|
||||
|
||||
/* Xfer state spin lock must be locked */
|
||||
static int exec_more(struct xfer_state *xfer_state)
|
||||
{
|
||||
struct xfer_transaction *xfer_trans;
|
||||
size_t left, cur_size, page_size;
|
||||
u64 pos_addr, ddr_base;
|
||||
u8 *pos_data;
|
||||
int ret = 0;
|
||||
|
||||
ddr_base = mlx5_fpga_ddr_base_get(xfer_state->xfer->conn->fdev);
|
||||
page_size = (xfer_state->xfer->addr + xfer_state->pos < ddr_base) ?
|
||||
sizeof(u32) : (1 << MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS);
|
||||
|
||||
do {
|
||||
if (xfer_state->status != IB_WC_SUCCESS) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
left = xfer_state->xfer->size - xfer_state->pos;
|
||||
if (!left)
|
||||
break;
|
||||
|
||||
xfer_trans = kzalloc(sizeof(*xfer_trans), GFP_ATOMIC);
|
||||
if (!xfer_trans) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
pos_addr = xfer_state->xfer->addr + xfer_state->pos;
|
||||
pos_data = xfer_state->xfer->data + xfer_state->pos;
|
||||
|
||||
/* Determine largest possible transaction at this point */
|
||||
cur_size = page_size - (pos_addr & (page_size - 1));
|
||||
if (cur_size > MLX5_FPGA_TRANSACTION_MAX_SIZE)
|
||||
cur_size = MLX5_FPGA_TRANSACTION_MAX_SIZE;
|
||||
if (cur_size > left)
|
||||
cur_size = left;
|
||||
|
||||
xfer_trans->xfer_state = xfer_state;
|
||||
xfer_trans->transaction.addr = pos_addr;
|
||||
xfer_trans->transaction.complete1 = trans_complete;
|
||||
xfer_trans->transaction.conn = xfer_state->xfer->conn;
|
||||
xfer_trans->transaction.data = pos_data;
|
||||
xfer_trans->transaction.direction = xfer_state->xfer->direction;
|
||||
xfer_trans->transaction.size = cur_size;
|
||||
|
||||
xfer_state->start_count++;
|
||||
xfer_state->inflight_count++;
|
||||
mlx5_fpga_dbg(xfer_state->xfer->conn->fdev, "Starting %zu bytes at %p done; %u started %u inflight %u done %u error\n",
|
||||
xfer_trans->transaction.size,
|
||||
xfer_trans->transaction.data,
|
||||
xfer_state->start_count,
|
||||
xfer_state->inflight_count,
|
||||
xfer_state->done_count,
|
||||
xfer_state->error_count);
|
||||
ret = mlx5_fpga_trans_exec(&xfer_trans->transaction);
|
||||
if (ret) {
|
||||
xfer_state->start_count--;
|
||||
xfer_state->inflight_count--;
|
||||
if (ret == -EBUSY)
|
||||
ret = 0;
|
||||
|
||||
if (ret) {
|
||||
mlx5_fpga_warn(xfer_state->xfer->conn->fdev, "Transfer failed to start transaction: %d. %u started %u done %u error\n",
|
||||
ret, xfer_state->start_count,
|
||||
xfer_state->done_count,
|
||||
xfer_state->error_count);
|
||||
xfer_state->status = IB_WC_GENERAL_ERR;
|
||||
}
|
||||
kfree(xfer_trans);
|
||||
break;
|
||||
}
|
||||
xfer_state->pos += cur_size;
|
||||
if (xfer_state->inflight_count >= xfer_state->budget)
|
||||
break;
|
||||
} while (cur_size != left);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void trans_complete(const struct mlx5_fpga_transaction *complete,
|
||||
u8 status)
|
||||
{
|
||||
struct xfer_transaction *xfer_trans;
|
||||
struct xfer_state *xfer_state;
|
||||
unsigned long flags;
|
||||
bool done = false;
|
||||
int ret;
|
||||
|
||||
xfer_trans = container_of(complete, struct xfer_transaction,
|
||||
transaction);
|
||||
xfer_state = xfer_trans->xfer_state;
|
||||
mlx5_fpga_dbg(complete->conn->fdev, "Transaction %zu bytes at %p done, status %u; %u started %u inflight %u done %u error\n",
|
||||
xfer_trans->transaction.size,
|
||||
xfer_trans->transaction.data, status,
|
||||
xfer_state->start_count, xfer_state->inflight_count,
|
||||
xfer_state->done_count, xfer_state->error_count);
|
||||
kfree(xfer_trans);
|
||||
|
||||
spin_lock_irqsave(&xfer_state->lock, flags);
|
||||
|
||||
if (status != IB_WC_SUCCESS) {
|
||||
xfer_state->error_count++;
|
||||
mlx5_fpga_warn(complete->conn->fdev, "Transaction failed during transfer. %u started %u inflight %u done %u error\n",
|
||||
xfer_state->start_count,
|
||||
xfer_state->inflight_count,
|
||||
xfer_state->done_count, xfer_state->error_count);
|
||||
if (xfer_state->status == IB_WC_SUCCESS)
|
||||
xfer_state->status = status;
|
||||
} else {
|
||||
xfer_state->done_count++;
|
||||
}
|
||||
ret = exec_more(xfer_state);
|
||||
|
||||
xfer_state->inflight_count--;
|
||||
if (!xfer_state->inflight_count)
|
||||
done = true;
|
||||
|
||||
spin_unlock_irqrestore(&xfer_state->lock, flags);
|
||||
|
||||
if (done)
|
||||
xfer_complete(xfer_state);
|
||||
}
|
||||
|
||||
int mlx5_fpga_xfer_exec(const struct mlx5_fpga_transaction *xfer)
|
||||
{
|
||||
u64 base = mlx5_fpga_ddr_base_get(xfer->conn->fdev);
|
||||
u64 size = mlx5_fpga_ddr_size_get(xfer->conn->fdev);
|
||||
struct xfer_state *xfer_state;
|
||||
unsigned long flags;
|
||||
bool done = false;
|
||||
int ret = 0;
|
||||
|
||||
if (xfer->addr + xfer->size > base + size) {
|
||||
mlx5_fpga_warn(xfer->conn->fdev, "Transfer ends at %jx outside of DDR range %jx\n",
|
||||
(uintmax_t)(xfer->addr + xfer->size), (uintmax_t)(base + size));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (xfer->addr & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) {
|
||||
mlx5_fpga_warn(xfer->conn->fdev, "Transfer address %jx not aligned\n",
|
||||
(uintmax_t)xfer->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (xfer->size & MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS) {
|
||||
mlx5_fpga_warn(xfer->conn->fdev, "Transfer size %zu not aligned\n",
|
||||
xfer->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (xfer->size < 1) {
|
||||
mlx5_fpga_warn(xfer->conn->fdev, "Empty transfer size %zu not allowed\n",
|
||||
xfer->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xfer_state = kzalloc(sizeof(*xfer_state), GFP_KERNEL);
|
||||
xfer_state->xfer = xfer;
|
||||
xfer_state->status = IB_WC_SUCCESS;
|
||||
xfer_state->budget = 7;
|
||||
spin_lock_init(&xfer_state->lock);
|
||||
spin_lock_irqsave(&xfer_state->lock, flags);
|
||||
|
||||
ret = exec_more(xfer_state);
|
||||
if (ret && (xfer_state->start_count == 0))
|
||||
done = true;
|
||||
|
||||
spin_unlock_irqrestore(&xfer_state->lock, flags);
|
||||
|
||||
if (done)
|
||||
xfer_complete(xfer_state);
|
||||
return ret;
|
||||
}
|
368
sys/dev/mlx5/mlx5_fpga/sdk.h
Normal file
368
sys/dev/mlx5/mlx5_fpga/sdk.h
Normal file
@ -0,0 +1,368 @@
|
||||
/*-
|
||||
* 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 MLX5_FPGA_SDK_H
|
||||
#define MLX5_FPGA_SDK_H
|
||||
|
||||
#include <dev/mlx5/driver.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
/* #include <linux/dma-direction.h> */
|
||||
|
||||
#include <dev/mlx5/mlx5_fpga/cmd.h>
|
||||
#include <dev/mlx5/mlx5io.h>
|
||||
|
||||
/**
|
||||
* DOC: Innova SDK
|
||||
* This header defines the in-kernel API for Innova FPGA client drivers.
|
||||
*/
|
||||
|
||||
#define MLX5_FPGA_CLIENT_NAME_MAX 64
|
||||
|
||||
struct mlx5_fpga_conn;
|
||||
struct mlx5_fpga_device;
|
||||
|
||||
/**
|
||||
* struct mlx5_fpga_client - Describes an Innova client driver
|
||||
*/
|
||||
struct mlx5_fpga_client {
|
||||
/**
|
||||
* @create: Informs the client that an Innova device was created.
|
||||
* The device is not yet operational at this stage
|
||||
* This callback is optional
|
||||
* @fdev: The FPGA device
|
||||
*/
|
||||
void (*create)(struct mlx5_fpga_device *fdev);
|
||||
/**
|
||||
* @add: Informs the client that a core device is ready and operational.
|
||||
* @fdev: The FPGA device
|
||||
* @param vid SBU Vendor ID
|
||||
* @param pid SBU Product ID
|
||||
* Any SBU-specific initialization should happen at this stage
|
||||
* Return: 0 on success, nonzero error value otherwise
|
||||
*/
|
||||
int (*add)(struct mlx5_fpga_device *fdev, u32 vid, u16 pid);
|
||||
/**
|
||||
* @remove: Informs the client that a core device is not operational
|
||||
* anymore.
|
||||
* @fdev: The FPGA device
|
||||
* SBU-specific cleanup should happen at this stage
|
||||
* This callback is called once for every successful call to add()
|
||||
*/
|
||||
void (*remove)(struct mlx5_fpga_device *fdev);
|
||||
/**
|
||||
* @destroy: Informs the client that a core device is being destroyed.
|
||||
* @fdev: The FPGA device
|
||||
* The device is not operational at this stage
|
||||
*/
|
||||
void (*destroy)(struct mlx5_fpga_device *fdev);
|
||||
/** The name of this client driver */
|
||||
char name[MLX5_FPGA_CLIENT_NAME_MAX];
|
||||
/** For use by core. A link in the list of client drivers */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mlx5_fpga_dma_entry - A scatter-gather DMA entry
|
||||
*/
|
||||
struct mlx5_fpga_dma_entry {
|
||||
/** @data: Virtual address pointer to the data */
|
||||
void *data;
|
||||
/** @size: Size in bytes of the data */
|
||||
unsigned int size;
|
||||
/** @dma_addr: Private member. Physical DMA-mapped address of the data */
|
||||
dma_addr_t dma_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mlx5_fpga_dma_buf - A packet buffer
|
||||
* May contain up to 2 scatter-gather data entries
|
||||
*/
|
||||
struct mlx5_fpga_dma_buf {
|
||||
/** @dma_dir: DMA direction */
|
||||
enum dma_data_direction dma_dir;
|
||||
/** @sg: Scatter-gather entries pointing to the data in memory */
|
||||
struct mlx5_fpga_dma_entry sg[2];
|
||||
/** @list: Item in SQ backlog, for TX packets */
|
||||
struct list_head list;
|
||||
/**
|
||||
* @complete: Completion routine, for TX packets
|
||||
* @conn: FPGA Connection this packet was sent to
|
||||
* @fdev: FPGA device this packet was sent to
|
||||
* @buf: The packet buffer
|
||||
* @status: 0 if successful, or an error code otherwise
|
||||
*/
|
||||
void (*complete)(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_dma_buf *buf, u8 status);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mlx5_fpga_conn_attr - FPGA connection attributes
|
||||
* Describes the attributes of a connection
|
||||
*/
|
||||
struct mlx5_fpga_conn_attr {
|
||||
/** @tx_size: Size of connection TX queue, in packets */
|
||||
unsigned int tx_size;
|
||||
/** @rx_size: Size of connection RX queue, in packets */
|
||||
unsigned int rx_size;
|
||||
/**
|
||||
* @recv_cb: Callback function which is called for received packets
|
||||
* @cb_arg: The value provided in mlx5_fpga_conn_attr.cb_arg
|
||||
* @buf: A buffer containing a received packet
|
||||
*
|
||||
* buf is guaranteed to only contain a single scatter-gather entry.
|
||||
* The size of the actual packet received is specified in buf.sg[0].size
|
||||
* When this callback returns, the packet buffer may be re-used for
|
||||
* subsequent receives.
|
||||
*/
|
||||
void (*recv_cb)(void *cb_arg, struct mlx5_fpga_dma_buf *buf);
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* mlx5_fpga_client_register() - Register a client driver
|
||||
* @client: The properties of the client driver
|
||||
*
|
||||
* Should be called from a client driver's module init routine.
|
||||
* Note: The core will immediately callback create() and add() for any existing
|
||||
* devices in the system, as well as new ones added later on.
|
||||
*/
|
||||
void mlx5_fpga_client_register(struct mlx5_fpga_client *client);
|
||||
/**
|
||||
* mlx5_fpga_client_unregister() - Unregister a client driver
|
||||
* @client: The client driver to unregister
|
||||
*
|
||||
* Should be called from a client driver's module exit routine.
|
||||
* Note: The core will immediately callback delete() and destroy() for any
|
||||
* created/added devices in the system, to clean up their state.
|
||||
*/
|
||||
void mlx5_fpga_client_unregister(struct mlx5_fpga_client *client);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_device_reload() - Force the FPGA to reload its synthesis from flash
|
||||
* @fdev: The FPGA device
|
||||
* @image: Which flash image to load
|
||||
*
|
||||
* This routine attempts graceful teardown of all device resources before
|
||||
* loading. This includes a callback to client driver delete().
|
||||
* Calls client driver add() once device is operational again.
|
||||
* Blocks until the new synthesis is loaded, and the device is fully
|
||||
* initialized.
|
||||
*
|
||||
* Return: 0 if successful, or a negative error value otherwise
|
||||
*/
|
||||
int mlx5_fpga_device_reload(struct mlx5_fpga_device *fdev,
|
||||
enum mlx5_fpga_image image);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_flash_select() - Select the current active flash
|
||||
* @fdev: The FPGA device
|
||||
* @image: Which flash image will be active
|
||||
*
|
||||
* This routine selects the active flash by programming the relevant MUX.
|
||||
* Useful prior to burning a new image on flash.
|
||||
* This setting is volatile and is reset upon reboot or power-cycle
|
||||
*
|
||||
* Return: 0 if successful, or a negative error value otherwise
|
||||
*/
|
||||
int mlx5_fpga_flash_select(struct mlx5_fpga_device *fdev,
|
||||
enum mlx5_fpga_image image);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_sbu_conn_create() - Initialize a new FPGA SBU connection
|
||||
* @fdev: The FPGA device
|
||||
* @attr: Attributes of the new connection
|
||||
*
|
||||
* Sets up a new FPGA SBU connection with the specified attributes.
|
||||
* The receive callback function may be called for incoming messages even
|
||||
* before this function returns.
|
||||
*
|
||||
* The caller must eventually destroy the connection by calling
|
||||
* mlx5_fpga_sbu_conn_destroy.
|
||||
*
|
||||
* Return: A new connection, or ERR_PTR() error value otherwise.
|
||||
*/
|
||||
struct mlx5_fpga_conn *
|
||||
mlx5_fpga_sbu_conn_create(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_conn_attr *attr);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_sbu_conn_destroy() - Destroy an FPGA SBU connection
|
||||
* @conn: The FPGA SBU connection to destroy
|
||||
*
|
||||
* Cleans up an FPGA SBU connection which was previously created with
|
||||
* mlx5_fpga_sbu_conn_create.
|
||||
*/
|
||||
void mlx5_fpga_sbu_conn_destroy(struct mlx5_fpga_conn *conn);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_sbu_conn_sendmsg() - Queue the transmission of a packet
|
||||
* @fdev: An FPGA SBU connection
|
||||
* @buf: The packet buffer
|
||||
*
|
||||
* Queues a packet for transmission over an FPGA SBU connection.
|
||||
* The buffer should not be modified or freed until completion.
|
||||
* Upon completion, the buf's complete() callback is invoked, indicating the
|
||||
* success or error status of the transmission.
|
||||
*
|
||||
* Return: 0 if successful, or an error value otherwise.
|
||||
*/
|
||||
int mlx5_fpga_sbu_conn_sendmsg(struct mlx5_fpga_conn *conn,
|
||||
struct mlx5_fpga_dma_buf *buf);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_mem_read() - Read from FPGA memory address space
|
||||
* @fdev: The FPGA device
|
||||
* @size: Size of chunk to read, in bytes
|
||||
* @addr: Starting address to read from, in FPGA address space
|
||||
* @buf: Buffer to read into
|
||||
* @access_type: Method for reading
|
||||
*
|
||||
* Reads from the specified address into the specified buffer.
|
||||
* The address may point to configuration space or to DDR.
|
||||
* Large reads may be performed internally as several non-atomic operations.
|
||||
* This function may sleep, so should not be called from atomic contexts.
|
||||
*
|
||||
* Return: 0 if successful, or an error value otherwise.
|
||||
*/
|
||||
int mlx5_fpga_mem_read(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
|
||||
void *buf, enum mlx5_fpga_access_type access_type);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_mem_write() - Write to FPGA memory address space
|
||||
* @fdev: The FPGA device
|
||||
* @size: Size of chunk to write, in bytes
|
||||
* @addr: Starting address to write to, in FPGA address space
|
||||
* @buf: Buffer which contains data to write
|
||||
* @access_type: Method for writing
|
||||
*
|
||||
* Writes the specified buffer data to FPGA memory at the specified address.
|
||||
* The address may point to configuration space or to DDR.
|
||||
* Large writes may be performed internally as several non-atomic operations.
|
||||
* This function may sleep, so should not be called from atomic contexts.
|
||||
*
|
||||
* Return: 0 if successful, or an error value otherwise.
|
||||
*/
|
||||
int mlx5_fpga_mem_write(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
|
||||
void *buf, enum mlx5_fpga_access_type access_type);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_get_sbu_caps() - Read the SBU capabilities
|
||||
* @fdev: The FPGA device
|
||||
* @size: Size of the buffer to read into
|
||||
* @buf: Buffer to read the capabilities into
|
||||
*
|
||||
* Reads the FPGA SBU capabilities into the specified buffer.
|
||||
* The format of the capabilities buffer is SBU-dependent.
|
||||
*
|
||||
* Return: 0 if successful
|
||||
* -EINVAL if the buffer is not large enough to contain SBU caps
|
||||
* or any other error value otherwise.
|
||||
*/
|
||||
int mlx5_fpga_get_sbu_caps(struct mlx5_fpga_device *fdev, int size, void *buf);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_ddr_size_get() - Retrieve the size of FPGA DDR
|
||||
* @fdev: The FPGA device
|
||||
*
|
||||
* Return: Size of DDR avaailable for FPGA, in bytes
|
||||
*/
|
||||
u64 mlx5_fpga_ddr_size_get(struct mlx5_fpga_device *fdev);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_ddr_base_get() - Retrieve the base address of FPGA DDR
|
||||
* @fdev: The FPGA device
|
||||
*
|
||||
* Return: Base address of DDR in FPGA address space
|
||||
*/
|
||||
u64 mlx5_fpga_ddr_base_get(struct mlx5_fpga_device *fdev);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_client_data_set() - Attach client-defined private value to a device
|
||||
* @fdev: The FPGA device
|
||||
* @client: The client driver
|
||||
* @data: Opaque private value
|
||||
*
|
||||
* Client driver may use the private value for storing device-specific
|
||||
* state and configuration information, and may retrieve it with a call to
|
||||
* mlx5_fpga_client_data_get().
|
||||
*/
|
||||
void mlx5_fpga_client_data_set(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client *client,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_client_data_get() - Retrieve client-defined private value
|
||||
* @fdev: The FPGA device
|
||||
* @client: The client driver
|
||||
*
|
||||
* Client driver may use the private value for storing device-specific
|
||||
* state and configuration information by calling mlx5_fpga_client_data_set()
|
||||
*
|
||||
* Return: The private value
|
||||
*/
|
||||
void *mlx5_fpga_client_data_get(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_client *client);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_device_query() - Query FPGA device state information
|
||||
* @fdev: The FPGA device
|
||||
* @query: Returns the device state
|
||||
*
|
||||
* Queries the device state and returns it in *query
|
||||
*/
|
||||
void mlx5_fpga_device_query(struct mlx5_fpga_device *fdev,
|
||||
struct mlx5_fpga_query *query);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_dev() - Retrieve FPGA device structure
|
||||
* @fdev: The FPGA device
|
||||
|
||||
* Return: A pointer to a struct device, which may be used with dev_* logging,
|
||||
* sysfs extensions, etc.
|
||||
*/
|
||||
struct device *mlx5_fpga_dev(struct mlx5_fpga_device *fdev);
|
||||
|
||||
/**
|
||||
* mlx5_fpga_get_cap() - Returns the FPGA cap mailbox from FW without parsing.
|
||||
* @fdev: The FPGA device
|
||||
* @fpga_caps: Is an array with a length of according to the size of
|
||||
* mlx5_ifc_fpga_cap_bits/32
|
||||
*
|
||||
* Returns a copy of the FPGA caps mailbox and returns it in fpga_caps
|
||||
*/
|
||||
void mlx5_fpga_get_cap(struct mlx5_fpga_device *fdev, u32 *fpga_caps);
|
||||
|
||||
#endif /* MLX5_FPGA_SDK_H */
|
66
sys/dev/mlx5/mlx5_fpga/trans.h
Normal file
66
sys/dev/mlx5/mlx5_fpga/trans.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*-
|
||||
* 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 __MLX5_FPGA_TRANS_H__
|
||||
#define __MLX5_FPGA_TRANS_H__
|
||||
|
||||
#include <dev/mlx5/mlx5_fpga/sdk.h>
|
||||
#include <dev/mlx5/mlx5_fpga/core.h>
|
||||
|
||||
#define MLX5_FPGA_TRANSACTION_MAX_SIZE 1008
|
||||
#define MLX5_FPGA_TRANSACTION_SEND_ALIGN_BITS 3
|
||||
#define MLX5_FPGA_TRANSACTION_SEND_PAGE_BITS 12
|
||||
#define MLX5_FPGA_TID_COUNT 256
|
||||
|
||||
enum mlx5_fpga_direction {
|
||||
MLX5_FPGA_READ,
|
||||
MLX5_FPGA_WRITE,
|
||||
};
|
||||
|
||||
struct mlx5_fpga_transaction {
|
||||
struct mlx5_fpga_conn *conn;
|
||||
enum mlx5_fpga_direction direction;
|
||||
size_t size;
|
||||
u64 addr;
|
||||
u8 *data;
|
||||
void (*complete1)(const struct mlx5_fpga_transaction *complete,
|
||||
u8 status);
|
||||
};
|
||||
|
||||
int mlx5_fpga_trans_device_init(struct mlx5_fpga_device *fdev);
|
||||
void mlx5_fpga_trans_device_cleanup(struct mlx5_fpga_device *fdev);
|
||||
int mlx5_fpga_trans_exec(const struct mlx5_fpga_transaction *trans);
|
||||
void mlx5_fpga_trans_recv(void *cb_arg, struct mlx5_fpga_dma_buf *buf);
|
||||
|
||||
#endif /* __MLX_FPGA_TRANS_H__ */
|
42
sys/dev/mlx5/mlx5_fpga/xfer.h
Normal file
42
sys/dev/mlx5/mlx5_fpga/xfer.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* 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 __MLX5_FPGA_XFER_H__
|
||||
#define __MLX5_FPGA_XFER_H__
|
||||
|
||||
#include <dev/mlx5/mlx5_fpga/trans.h>
|
||||
|
||||
int mlx5_fpga_xfer_exec(const struct mlx5_fpga_transaction *xfer);
|
||||
|
||||
#endif /* __MLX5_FPGA_XFER_H__ */
|
@ -28,6 +28,8 @@
|
||||
#ifndef MLX5_IFC_H
|
||||
#define MLX5_IFC_H
|
||||
|
||||
#include <dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h>
|
||||
|
||||
enum {
|
||||
MLX5_EVENT_TYPE_COMP = 0x0,
|
||||
MLX5_EVENT_TYPE_PATH_MIG = 0x1,
|
||||
@ -58,7 +60,9 @@ enum {
|
||||
MLX5_EVENT_TYPE_DROPPED_PACKET_LOGGED_EVENT = 0x1f,
|
||||
MLX5_EVENT_TYPE_CMD = 0xa,
|
||||
MLX5_EVENT_TYPE_PAGE_REQUEST = 0xb,
|
||||
MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd
|
||||
MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd,
|
||||
MLX5_EVENT_TYPE_FPGA_ERROR = 0x20,
|
||||
MLX5_EVENT_TYPE_FPGA_QP_ERROR = 0x21,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -242,6 +246,11 @@ enum {
|
||||
MLX5_CMD_OP_MODIFY_FLOW_TABLE = 0x93c,
|
||||
MLX5_CMD_OP_ALLOC_ENCAP_HEADER = 0x93d,
|
||||
MLX5_CMD_OP_DEALLOC_ENCAP_HEADER = 0x93e,
|
||||
MLX5_CMD_OP_FPGA_CREATE_QP = 0x960,
|
||||
MLX5_CMD_OP_FPGA_MODIFY_QP = 0x961,
|
||||
MLX5_CMD_OP_FPGA_QUERY_QP = 0x962,
|
||||
MLX5_CMD_OP_FPGA_DESTROY_QP = 0x963,
|
||||
MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS = 0x964,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -998,7 +1007,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
|
||||
u8 max_tc[0x4];
|
||||
u8 temp_warn_event[0x1];
|
||||
u8 dcbx[0x1];
|
||||
u8 reserved_22[0x4];
|
||||
u8 general_notification_event[0x1];
|
||||
u8 reserved_at_1d3[0x2];
|
||||
u8 fpga[0x1];
|
||||
u8 rol_s[0x1];
|
||||
u8 rol_g[0x1];
|
||||
u8 reserved_23[0x1];
|
||||
|
45
sys/dev/mlx5/mlx5_lib/mlx5.h
Normal file
45
sys/dev/mlx5/mlx5_lib/mlx5.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (c) 2017, Mellanox Technologies, Ltd. 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 __LIB_MLX5_H__
|
||||
#define __LIB_MLX5_H__
|
||||
|
||||
void mlx5_init_reserved_gids(struct mlx5_core_dev *dev);
|
||||
void mlx5_cleanup_reserved_gids(struct mlx5_core_dev *dev);
|
||||
int mlx5_core_reserve_gids(struct mlx5_core_dev *dev, unsigned int count);
|
||||
void mlx5_core_unreserve_gids(struct mlx5_core_dev *dev, unsigned int count);
|
||||
int mlx5_core_reserved_gid_alloc(struct mlx5_core_dev *dev, int *gid_index);
|
||||
void mlx5_core_reserved_gid_free(struct mlx5_core_dev *dev, int gid_index);
|
||||
|
||||
#endif
|
156
sys/dev/mlx5/mlx5_lib/mlx5_gid.c
Normal file
156
sys/dev/mlx5/mlx5_lib/mlx5_gid.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*-
|
||||
* 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/etherdevice.h>
|
||||
#include <dev/mlx5/driver.h>
|
||||
#include <dev/mlx5/mlx5_core/mlx5_core.h>
|
||||
#include <dev/mlx5/mlx5_lib/mlx5.h>
|
||||
|
||||
void mlx5_init_reserved_gids(struct mlx5_core_dev *dev)
|
||||
{
|
||||
unsigned int tblsz = MLX5_CAP_ROCE(dev, roce_address_table_size);
|
||||
|
||||
ida_init(&dev->roce.reserved_gids.ida);
|
||||
dev->roce.reserved_gids.start = tblsz;
|
||||
dev->roce.reserved_gids.count = 0;
|
||||
}
|
||||
|
||||
void mlx5_cleanup_reserved_gids(struct mlx5_core_dev *dev)
|
||||
{
|
||||
WARN_ON(!ida_is_empty(&dev->roce.reserved_gids.ida));
|
||||
dev->roce.reserved_gids.start = 0;
|
||||
dev->roce.reserved_gids.count = 0;
|
||||
ida_destroy(&dev->roce.reserved_gids.ida);
|
||||
}
|
||||
|
||||
int mlx5_core_reserve_gids(struct mlx5_core_dev *dev, unsigned int count)
|
||||
{
|
||||
if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
|
||||
mlx5_core_err(dev, "Cannot reserve GIDs when interfaces are up\n");
|
||||
return -EPERM;
|
||||
}
|
||||
if (dev->roce.reserved_gids.start < count) {
|
||||
mlx5_core_warn(dev, "GID table exhausted attempting to reserve %d more GIDs\n",
|
||||
count);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (dev->roce.reserved_gids.count + count > MLX5_MAX_RESERVED_GIDS) {
|
||||
mlx5_core_warn(dev, "Unable to reserve %d more GIDs\n", count);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev->roce.reserved_gids.start -= count;
|
||||
dev->roce.reserved_gids.count += count;
|
||||
mlx5_core_dbg(dev, "Reserved %u GIDs starting at %u\n",
|
||||
dev->roce.reserved_gids.count,
|
||||
dev->roce.reserved_gids.start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_core_unreserve_gids(struct mlx5_core_dev *dev, unsigned int count)
|
||||
{
|
||||
WARN(test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state), "Unreserving GIDs when interfaces are up");
|
||||
WARN(count > dev->roce.reserved_gids.count, "Unreserving %u GIDs when only %u reserved",
|
||||
count, dev->roce.reserved_gids.count);
|
||||
|
||||
dev->roce.reserved_gids.start += count;
|
||||
dev->roce.reserved_gids.count -= count;
|
||||
mlx5_core_dbg(dev, "%u GIDs starting at %u left reserved\n",
|
||||
dev->roce.reserved_gids.count,
|
||||
dev->roce.reserved_gids.start);
|
||||
}
|
||||
|
||||
int mlx5_core_reserved_gid_alloc(struct mlx5_core_dev *dev, int *gid_index)
|
||||
{
|
||||
int end = dev->roce.reserved_gids.start +
|
||||
dev->roce.reserved_gids.count;
|
||||
int index = 0;
|
||||
|
||||
index = ida_simple_get(&dev->roce.reserved_gids.ida,
|
||||
dev->roce.reserved_gids.start, end,
|
||||
GFP_KERNEL);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
mlx5_core_dbg(dev, "Allocating reserved GID %u\n", index);
|
||||
*gid_index = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_core_reserved_gid_free(struct mlx5_core_dev *dev, int gid_index)
|
||||
{
|
||||
mlx5_core_dbg(dev, "Freeing reserved GID %u\n", gid_index);
|
||||
ida_simple_remove(&dev->roce.reserved_gids.ida, gid_index);
|
||||
}
|
||||
|
||||
unsigned int mlx5_core_reserved_gids_count(struct mlx5_core_dev *dev)
|
||||
{
|
||||
return dev->roce.reserved_gids.count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_core_reserved_gids_count);
|
||||
|
||||
int mlx5_core_roce_gid_set(struct mlx5_core_dev *dev, unsigned int index,
|
||||
u8 roce_version, u8 roce_l3_type, const u8 *gid,
|
||||
const u8 *mac, bool vlan, u16 vlan_id)
|
||||
{
|
||||
#define MLX5_SET_RA(p, f, v) MLX5_SET(roce_addr_layout, p, f, v)
|
||||
u32 in[MLX5_ST_SZ_DW(set_roce_address_in)] = {0};
|
||||
u32 out[MLX5_ST_SZ_DW(set_roce_address_out)] = {0};
|
||||
void *in_addr = MLX5_ADDR_OF(set_roce_address_in, in, roce_address);
|
||||
char *addr_l3_addr = MLX5_ADDR_OF(roce_addr_layout, in_addr,
|
||||
source_l3_address);
|
||||
void *addr_mac = MLX5_ADDR_OF(roce_addr_layout, in_addr,
|
||||
source_mac_47_32);
|
||||
int gidsz = MLX5_FLD_SZ_BYTES(roce_addr_layout, source_l3_address);
|
||||
|
||||
if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
|
||||
return -EINVAL;
|
||||
|
||||
if (gid) {
|
||||
if (vlan) {
|
||||
MLX5_SET_RA(in_addr, vlan_valid, 1);
|
||||
MLX5_SET_RA(in_addr, vlan_id, vlan_id);
|
||||
}
|
||||
|
||||
ether_addr_copy(addr_mac, mac);
|
||||
MLX5_SET_RA(in_addr, roce_version, roce_version);
|
||||
MLX5_SET_RA(in_addr, roce_l3_type, roce_l3_type);
|
||||
memcpy(addr_l3_addr, gid, gidsz);
|
||||
}
|
||||
|
||||
MLX5_SET(set_roce_address_in, in, roce_address_index, index);
|
||||
MLX5_SET(set_roce_address_in, in, opcode, MLX5_CMD_OP_SET_ROCE_ADDRESS);
|
||||
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_core_roce_gid_set);
|
@ -57,4 +57,44 @@ struct mlx5_fwdump_get {
|
||||
#define MLX5_DEV_PATH _PATH_DEV"mlx5ctl"
|
||||
#endif
|
||||
|
||||
enum mlx5_fpga_id {
|
||||
MLX5_FPGA_NEWTON = 0,
|
||||
MLX5_FPGA_EDISON = 1,
|
||||
MLX5_FPGA_MORSE = 2,
|
||||
};
|
||||
|
||||
enum mlx5_fpga_image {
|
||||
MLX5_FPGA_IMAGE_USER = 0,
|
||||
MLX5_FPGA_IMAGE_FACTORY = 1,
|
||||
MLX5_FPGA_IMAGE_MAX = MLX5_FPGA_IMAGE_FACTORY,
|
||||
MLX5_FPGA_IMAGE_FACTORY_FAILOVER = 2,
|
||||
};
|
||||
|
||||
enum mlx5_fpga_status {
|
||||
MLX5_FPGA_STATUS_SUCCESS = 0,
|
||||
MLX5_FPGA_STATUS_FAILURE = 1,
|
||||
MLX5_FPGA_STATUS_IN_PROGRESS = 2,
|
||||
MLX5_FPGA_STATUS_DISCONNECTED = 3,
|
||||
};
|
||||
|
||||
struct mlx5_fpga_query {
|
||||
enum mlx5_fpga_image admin_image;
|
||||
enum mlx5_fpga_image oper_image;
|
||||
enum mlx5_fpga_status image_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mlx5_fpga_access_type - Enumerated the different methods possible for
|
||||
* accessing the device memory address space
|
||||
*/
|
||||
enum mlx5_fpga_access_type {
|
||||
/** Use the slow CX-FPGA I2C bus*/
|
||||
MLX5_FPGA_ACCESS_TYPE_I2C = 0x0,
|
||||
/** Use the fast 'shell QP' */
|
||||
MLX5_FPGA_ACCESS_TYPE_RDMA,
|
||||
/** Use the fastest available method */
|
||||
MLX5_FPGA_ACCESS_TYPE_DONTCARE,
|
||||
MLX5_FPGA_ACCESS_TYPE_MAX = MLX5_FPGA_ACCESS_TYPE_DONTCARE,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
# $FreeBSD$
|
||||
.PATH: ${SRCTOP}/sys/dev/mlx5/mlx5_core
|
||||
.PATH: ${SRCTOP}/sys/dev/mlx5/mlx5_core \
|
||||
${SRCTOP}/sys/dev/mlx5/mlx5_lib \
|
||||
${SRCTOP}/sys/dev/mlx5/mlx5_fpga
|
||||
|
||||
KMOD=mlx5
|
||||
SRCS= \
|
||||
@ -29,12 +31,23 @@ mlx5_uar.c \
|
||||
mlx5_vport.c \
|
||||
mlx5_vsc.c \
|
||||
mlx5_wq.c \
|
||||
mlx5_gid.c \
|
||||
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
|
||||
|
||||
.if defined(CONFIG_BUILD_FPGA)
|
||||
SRCS+= \
|
||||
mlx5fpga_cmd.c \
|
||||
mlx5fpga_core.c \
|
||||
mlx5fpga_sdk.c \
|
||||
mlx5fpga_trans.c \
|
||||
mlx5fpga_xfer.c \
|
||||
mlx5fpga_ipsec.c
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
||||
CFLAGS+= -Wno-cast-qual -Wno-pointer-arith ${GCC_MS_EXTENSIONS}
|
||||
|
@ -21,6 +21,10 @@ CFLAGS+= -DHAVE_PER_CQ_EVENT_PACKET
|
||||
CFLAGS+= -DHAVE_TCP_LRO_RX
|
||||
.endif
|
||||
|
||||
.if defined(CONFIG_BUILD_FPGA)
|
||||
CFLAGS+= -DCONFIG_MLX5_FPGA
|
||||
.endif
|
||||
|
||||
CFLAGS+= -I${SRCTOP}/sys/ofed/include
|
||||
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
|
||||
|
||||
|
@ -23,6 +23,10 @@ CFLAGS+= -I${SRCTOP}/sys/ofed/include/uapi
|
||||
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
|
||||
CFLAGS+= -DCONFIG_INFINIBAND_USER_MEM
|
||||
|
||||
.if defined(CONFIG_BUILD_FPGA)
|
||||
CFLAGS+= -DCONFIG_MLX5_FPGA
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
||||
CFLAGS+= -Wno-cast-qual -Wno-pointer-arith ${GCC_MS_EXTENSIONS}
|
||||
|
Loading…
Reference in New Issue
Block a user