Index: stable/12/sys/dev/mlx5/mlx5_fpga/cmd.h =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/cmd.h (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/cmd.h (revision 341965) @@ -1,84 +1,86 @@ /*- * 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 #include #include 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_query_mtmp(struct mlx5_core_dev *dev, struct mlx5_fpga_temperature *temp); 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_ctrl_connect(struct mlx5_core_dev *dev, + enum mlx5_fpga_connect *connect); 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__ */ Index: stable/12/sys/dev/mlx5/mlx5_fpga/core.h =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/core.h (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/core.h (revision 341965) @@ -1,140 +1,141 @@ /*- * 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 #include /* 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_DISCONNECTED = 3, 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__ */ Index: stable/12/sys/dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/mlx5_ifc_fpga.h (revision 341965) @@ -1,500 +1,502 @@ /*- * 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, + MLX5_FPGA_CTRL_OPERATION_DISCONNECT = 0x9, + MLX5_FPGA_CTRL_OPERATION_CONNECT = 0xA, }; 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 */ Index: stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_cmd.c =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_cmd.c (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_cmd.c (revision 341965) @@ -1,321 +1,349 @@ /*- * Copyright (c) 2017, Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $FreeBSD$ */ #include #include #include #include #include +#include #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_ctrl_connect(struct mlx5_core_dev *dev, + enum mlx5_fpga_connect *connect) +{ + u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0}; + u32 out[MLX5_ST_SZ_DW(fpga_ctrl)]; + int status; + int err; + + if (*connect == MLX5_FPGA_CONNECT_QUERY) { + err = mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_FPGA_CTRL, + 0, false); + if (err) + return err; + status = MLX5_GET(fpga_ctrl, out, status); + *connect = (status == MLX5_FDEV_STATE_DISCONNECTED) ? + MLX5_FPGA_CONNECT_DISCONNECT : + MLX5_FPGA_CONNECT_CONNECT; + } else { + MLX5_SET(fpga_ctrl, in, operation, *connect); + err = mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_FPGA_CTRL, + 0, true); + } + return err; } int mlx5_fpga_query_mtmp(struct mlx5_core_dev *dev, struct mlx5_fpga_temperature *temp) { u32 in[MLX5_ST_SZ_DW(mtmp_reg)] = {0}; u32 out[MLX5_ST_SZ_DW(mtmp_reg)] = {0}; int err; MLX5_SET(mtmp_reg, in, sensor_index, temp->index); MLX5_SET(mtmp_reg, in, i, ((temp->index < MLX5_FPGA_INTERNAL_SENSORS_LOW) || (temp->index > MLX5_FPGA_INTERNAL_SENSORS_HIGH)) ? 1 : 0); err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MTMP, 0, false); if (err) return err; temp->index = MLX5_GET(mtmp_reg, out, sensor_index); temp->temperature = MLX5_GET(mtmp_reg, out, temperature); temp->mte = MLX5_GET(mtmp_reg, out, mte); temp->max_temperature = MLX5_GET(mtmp_reg, out, max_temperature); temp->tee = MLX5_GET(mtmp_reg, out, tee); temp->temperature_threshold_hi = MLX5_GET(mtmp_reg, out, temperature_threshold_hi); temp->temperature_threshold_lo = MLX5_GET(mtmp_reg, out, temperature_threshold_lo); memcpy(temp->sensor_name, MLX5_ADDR_OF(mtmp_reg, out, sensor_name), MLX5_FLD_SZ_BYTES(mtmp_reg, sensor_name)); 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; } Index: stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c (revision 341965) @@ -1,466 +1,494 @@ /*- * Copyright (c) 2017 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include /* #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: + case MLX5_FDEV_STATE_DISCONNECTED: 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_DISCONNECTED: 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); + +int mlx5_fpga_connectdisconnect(struct mlx5_fpga_device *fdev, + enum mlx5_fpga_connect *connect) +{ + 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: + case MLX5_FDEV_STATE_DISCONNECTED: + break; + } + spin_unlock_irqrestore(&fdev->state_lock, flags); + + err = mlx5_fpga_ctrl_connect(fdev->mdev, connect); + if (err) + mlx5_fpga_err(fdev, "Failed to connect/disconnect: %d\n", err); + return err; +} +EXPORT_SYMBOL(mlx5_fpga_connectdisconnect); int mlx5_fpga_temperature(struct mlx5_fpga_device *fdev, struct mlx5_fpga_temperature *temp) { return mlx5_fpga_query_mtmp(fdev->mdev, temp); } EXPORT_SYMBOL(mlx5_fpga_temperature); 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); Index: stable/12/sys/dev/mlx5/mlx5_fpga/sdk.h =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga/sdk.h (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga/sdk.h (revision 341965) @@ -1,378 +1,388 @@ /*- * 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 #include #include /* #include */ #include #include /** * 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_temperature() - Retrieve FPGA sensor of temperature * @fdev: The FPGA device * Return: 0 if successful * or any other error value otherwise. */ int mlx5_fpga_temperature(struct mlx5_fpga_device *fdev, struct mlx5_fpga_temperature *temp); /** + * mlx5_fpga_connectdisconnect() - Connect/disconnect ConnectX to FPGA + * @fdev: The FPGA device + + * Return: 0 if successful + * or any other error value otherwise. + */ +int mlx5_fpga_connectdisconnect(struct mlx5_fpga_device *fdev, + enum mlx5_fpga_connect *connect); + +/** * 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 */ Index: stable/12/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c =================================================================== --- stable/12/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5_fpga_tools/mlx5fpga_tools_char.c (revision 341965) @@ -1,331 +1,337 @@ /*- * Copyright (c) 2017 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $FreeBSD$ */ #include #include #include #include #include #define CHUNK_SIZE (128 * 1024) struct tools_context { struct mlx5_fpga_tools_dev *tdev; enum mlx5_fpga_access_type access_type; }; static void tools_char_ctx_dtor(void *data) { free(data, M_DEVBUF); } static int tools_char_open(struct cdev *dev, int oflags, int devtype, struct thread *td) { struct tools_context *context; context = malloc(sizeof(*context), M_DEVBUF, M_WAITOK); context->tdev = dev->si_drv1; context->access_type = MLX5_FPGA_ACCESS_TYPE_DONTCARE; devfs_set_cdevpriv(context, tools_char_ctx_dtor); return (0); } static int mem_read(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count, u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt) { int ret; ret = sx_xlock_sig(&tdev->lock); if (ret != 0) return (ret); ret = mlx5_fpga_mem_read(tdev->fdev, count, address, buf, access_type); sx_xunlock(&tdev->lock); if (ret < 0) { dev_dbg(mlx5_fpga_dev(tdev->fdev), "Failed to read %zu bytes at address 0x%jx: %d\n", count, (uintmax_t)address, ret); return (-ret); } *retcnt = ret; return (0); } static int mem_write(struct mlx5_fpga_tools_dev *tdev, void *buf, size_t count, u64 address, enum mlx5_fpga_access_type access_type, size_t *retcnt) { int ret; ret = sx_xlock_sig(&tdev->lock); if (ret != 0) return (ret); ret = mlx5_fpga_mem_write(tdev->fdev, count, address, buf, access_type); sx_xunlock(&tdev->lock); if (ret < 0) { dev_dbg(mlx5_fpga_dev(tdev->fdev), "Failed to write %zu bytes at address 0x%jx: %d\n", count, (uintmax_t)address, ret); return (-ret); } *retcnt = ret; return (0); } static void tools_char_llseek(struct tools_context *context, struct uio *uio, ssize_t *len) { uint64_t fbase, fsize; size_t llen; llen = uio->uio_resid; if (llen < 1) { *len = 0; return; } if (llen > CHUNK_SIZE) llen = CHUNK_SIZE; fbase = mlx5_fpga_ddr_base_get(context->tdev->fdev); fsize = mlx5_fpga_ddr_size_get(context->tdev->fdev); if (uio->uio_offset > fbase) *len = 0; else if (uio->uio_offset + *len > fbase + fsize) *len = fbase + fsize - uio->uio_offset; else *len = llen; } static int tools_char_read(struct cdev *dev, struct uio *uio, int ioflag) { struct tools_context *context; void *kbuf; size_t len, len1; int ret; ret = devfs_get_cdevpriv((void **)&context); if (ret != 0) return (ret); dev_dbg(mlx5_fpga_dev(context->tdev->fdev), "tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid, (uintmax_t)uio->uio_offset); tools_char_llseek(context, uio, &len); if (len == 0) return (0); kbuf = malloc(len, M_DEVBUF, M_WAITOK); ret = mem_read(context->tdev, kbuf, len, uio->uio_offset, context->access_type, &len1); if (ret == 0) ret = uiomove(kbuf, len1, uio); free(kbuf, M_DEVBUF); return (ret); } static int tools_char_write(struct cdev *dev, struct uio *uio, int ioflag) { struct tools_context *context; void *kbuf; off_t of; size_t len, len1; int ret; ret = devfs_get_cdevpriv((void **)&context); if (ret != 0) return (ret); dev_dbg(mlx5_fpga_dev(context->tdev->fdev), "tools char device reading %zu bytes at 0x%jx\n", uio->uio_resid, (uintmax_t)uio->uio_offset); tools_char_llseek(context, uio, &len); if (len == 0) return (0); kbuf = malloc(len, M_DEVBUF, M_WAITOK); len1 = uio->uio_resid; of = uio->uio_offset; ret = uiomove(kbuf, len, uio); if (ret == 0) { len1 -= uio->uio_resid; ret = mem_write(context->tdev, kbuf, len, of, context->access_type, &len1); } free(kbuf, M_DEVBUF); return (ret); } CTASSERT(MLX5_FPGA_CAP_ARR_SZ == MLX5_ST_SZ_DW(fpga_cap)); static int tools_char_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { struct tools_context *context; struct mlx5_fpga_device *fdev; struct mlx5_fpga_query query; struct mlx5_fpga_temperature *temperature; + enum mlx5_fpga_connect *connect; u32 fpga_cap[MLX5_ST_SZ_DW(fpga_cap)] = {0}; int arg, err; err = devfs_get_cdevpriv((void **)&context); if (err != 0) return (err); fdev = context->tdev->fdev; if (fdev == NULL) return (ENXIO); switch (cmd) { case MLX5_FPGA_ACCESS_TYPE: arg = *(int *)data; if (arg > MLX5_FPGA_ACCESS_TYPE_MAX) { dev_err(mlx5_fpga_dev(fdev), "unknown access type %u\n", arg); err = EINVAL; break; } context->access_type = arg; break; case MLX5_FPGA_LOAD: arg = *(int *)data; if (arg > MLX5_FPGA_IMAGE_MAX) { dev_err(mlx5_fpga_dev(fdev), "unknown image type %u\n", arg); err = EINVAL; break; } err = mlx5_fpga_device_reload(fdev, arg); break; case MLX5_FPGA_RESET: err = mlx5_fpga_device_reload(fdev, MLX5_FPGA_IMAGE_MAX + 1); break; case MLX5_FPGA_IMAGE_SEL: arg = *(int *)data; if (arg > MLX5_FPGA_IMAGE_MAX) { dev_err(mlx5_fpga_dev(fdev), "unknown image type %u\n", arg); err = EINVAL; break; } err = mlx5_fpga_flash_select(fdev, arg); break; case MLX5_FPGA_QUERY: mlx5_fpga_device_query(fdev, &query); bcopy(&query, data, sizeof(query)); err = 0; break; case MLX5_FPGA_CAP: mlx5_fpga_get_cap(fdev, fpga_cap); bcopy(&fpga_cap, data, sizeof(fpga_cap)); err = 0; break; case MLX5_FPGA_TEMPERATURE: temperature = (struct mlx5_fpga_temperature *)data; mlx5_fpga_temperature(fdev, temperature); err = 0; /* XXXKIB */ break; + case MLX5_FPGA_CONNECT: + connect = (enum mlx5_fpga_connect *)data; + mlx5_fpga_connectdisconnect(fdev, connect); + err = 0; /* XXXKIB */ + break; default: dev_err(mlx5_fpga_dev(fdev), "unknown ioctl command %#08lx\n", cmd); err = ENOTTY; } return (err); } static struct cdevsw mlx5_tools_char_cdevsw = { .d_version = D_VERSION, .d_name = "mlx5_tools_char", .d_open = tools_char_open, .d_read = tools_char_read, .d_write = tools_char_write, .d_ioctl = tools_char_ioctl, }; int mlx5_fpga_tools_char_add_one(struct mlx5_fpga_tools_dev *tdev) { struct make_dev_args mda; struct cdev *cd; device_t bdev; int ret; make_dev_args_init(&mda); mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME; mda.mda_devsw = &mlx5_tools_char_cdevsw; mda.mda_uid = UID_ROOT; mda.mda_gid = GID_OPERATOR; mda.mda_mode = 0660; mda.mda_si_drv1 = tdev; bdev = mlx5_fpga_dev(tdev->fdev)->bsddev; ret = make_dev_s(&mda, &cd, "%04x:%02x:%02x.%x" MLX5_FPGA_TOOLS_NAME_SUFFIX, pci_get_domain(bdev), pci_get_bus(bdev), pci_get_slot(bdev), pci_get_function(bdev)); if (ret != 0) { tdev->char_device = NULL; dev_err(mlx5_fpga_dev(tdev->fdev), "Failed to create a char device: %d\n", ret); return (-ret); } tdev->char_device = cd; dev_dbg(mlx5_fpga_dev(tdev->fdev), "tools char device %s created\n", cd->si_name); return (0); } void mlx5_fpga_tools_char_remove_one(struct mlx5_fpga_tools_dev *tdev) { dev_err(mlx5_fpga_dev(tdev->fdev), "tools char device %s destroyed\n", ((struct cdev *)(tdev->char_device))->si_name); destroy_dev((struct cdev *)(tdev->char_device)); } int mlx5_fpga_tools_char_init(void) { return (0); } void mlx5_fpga_tools_char_deinit(void) { } Index: stable/12/sys/dev/mlx5/mlx5io.h =================================================================== --- stable/12/sys/dev/mlx5/mlx5io.h (revision 341964) +++ stable/12/sys/dev/mlx5/mlx5io.h (revision 341965) @@ -1,134 +1,141 @@ /*- * Copyright (c) 2018, Mellanox Technologies, Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_MLX5_MLX5IO_H_ #define _DEV_MLX5_MLX5IO_H_ #include struct mlx5_fwdump_reg { uint32_t addr; uint32_t val; }; struct mlx5_fwdump_addr { uint32_t domain; uint8_t bus; uint8_t slot; uint8_t func; }; struct mlx5_fwdump_get { struct mlx5_fwdump_addr devaddr; struct mlx5_fwdump_reg *buf; size_t reg_cnt; size_t reg_filled; /* out */ }; #define MLX5_FWDUMP_GET _IOWR('m', 1, struct mlx5_fwdump_get) #define MLX5_FWDUMP_RESET _IOW('m', 2, struct mlx5_fwdump_addr) #define MLX5_FWDUMP_FORCE _IOW('m', 3, struct mlx5_fwdump_addr) #ifndef _KERNEL #define MLX5_DEV_PATH _PATH_DEV"mlx5ctl" #endif enum mlx5_fpga_id { MLX5_FPGA_NEWTON = 0, MLX5_FPGA_EDISON = 1, MLX5_FPGA_MORSE = 2, MLX5_FPGA_MORSEQ = 3, }; 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_tee { MLX5_FPGA_TEE_DISABLE = 0, MLX5_FPGA_TEE_GENERATE_EVENT = 1, MLX5_FPGA_TEE_GENERATE_SINGLE_EVENT = 2, }; +enum mlx5_fpga_connect { + MLX5_FPGA_CONNECT_QUERY = 0, + MLX5_FPGA_CONNECT_DISCONNECT = 0x9, + MLX5_FPGA_CONNECT_CONNECT = 0xA, +}; + /** * 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, }; #define MLX5_FPGA_INTERNAL_SENSORS_LOW 63 #define MLX5_FPGA_INTERNAL_SENSORS_HIGH 63 struct mlx5_fpga_temperature { uint32_t temperature; uint32_t index; uint32_t tee; uint32_t max_temperature; uint32_t temperature_threshold_hi; uint32_t temperature_threshold_lo; uint32_t mte; uint32_t mtr; char sensor_name[16]; }; #define MLX5_FPGA_CAP_ARR_SZ 0x40 #define MLX5_FPGA_ACCESS_TYPE _IOWINT('m', 0x80) #define MLX5_FPGA_LOAD _IOWINT('m', 0x81) #define MLX5_FPGA_RESET _IO('m', 0x82) #define MLX5_FPGA_IMAGE_SEL _IOWINT('m', 0x83) #define MLX5_FPGA_QUERY _IOR('m', 0x84, struct mlx5_fpga_query) #define MLX5_FPGA_CAP _IOR('m', 0x85, uint32_t[MLX5_FPGA_CAP_ARR_SZ]) #define MLX5_FPGA_TEMPERATURE _IOWR('m', 0x86, struct mlx5_fpga_temperature) +#define MLX5_FPGA_CONNECT _IOWR('m', 0x87, enum mlx5_fpga_connect) #define MLX5_FPGA_TOOLS_NAME_SUFFIX "_mlx5_fpga_tools" #endif Index: stable/12 =================================================================== --- stable/12 (revision 341964) +++ stable/12 (revision 341965) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r341576