1dc7e38acSHans Petter Selasky /*- 2b633e08cSHans Petter Selasky * Copyright (c) 2013-2020, Mellanox Technologies, Ltd. All rights reserved. 3dc7e38acSHans Petter Selasky * 4dc7e38acSHans Petter Selasky * Redistribution and use in source and binary forms, with or without 5dc7e38acSHans Petter Selasky * modification, are permitted provided that the following conditions 6dc7e38acSHans Petter Selasky * are met: 7dc7e38acSHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 8dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer. 9dc7e38acSHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 10dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 11dc7e38acSHans Petter Selasky * documentation and/or other materials provided with the distribution. 12dc7e38acSHans Petter Selasky * 13dc7e38acSHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14dc7e38acSHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15dc7e38acSHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16dc7e38acSHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17dc7e38acSHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18dc7e38acSHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19dc7e38acSHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20dc7e38acSHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21dc7e38acSHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22dc7e38acSHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23dc7e38acSHans Petter Selasky * SUCH DAMAGE. 24dc7e38acSHans Petter Selasky */ 25dc7e38acSHans Petter Selasky 26ee9d634bSKonstantin Belousov #include "opt_rss.h" 27ee9d634bSKonstantin Belousov #include "opt_ratelimit.h" 28ee9d634bSKonstantin Belousov 29dc7e38acSHans Petter Selasky #include <dev/mlx5/driver.h> 30dc7e38acSHans Petter Selasky #include <linux/module.h> 3112c56d7dSHans Petter Selasky #include <dev/mlx5/mlx5_core/mlx5_core.h> 32dc7e38acSHans Petter Selasky 33dc7e38acSHans Petter Selasky static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out, 34dc7e38acSHans Petter Selasky int outlen) 35dc7e38acSHans Petter Selasky { 36dc7e38acSHans Petter Selasky u32 in[MLX5_ST_SZ_DW(query_adapter_in)]; 37dc7e38acSHans Petter Selasky int err; 38dc7e38acSHans Petter Selasky 39dc7e38acSHans Petter Selasky memset(in, 0, sizeof(in)); 40dc7e38acSHans Petter Selasky 41dc7e38acSHans Petter Selasky MLX5_SET(query_adapter_in, in, opcode, MLX5_CMD_OP_QUERY_ADAPTER); 42dc7e38acSHans Petter Selasky 43788333d9SHans Petter Selasky err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 44dc7e38acSHans Petter Selasky return err; 45dc7e38acSHans Petter Selasky } 46dc7e38acSHans Petter Selasky 47dc7e38acSHans Petter Selasky int mlx5_query_board_id(struct mlx5_core_dev *dev) 48dc7e38acSHans Petter Selasky { 49dc7e38acSHans Petter Selasky u32 *out; 50dc7e38acSHans Petter Selasky int outlen = MLX5_ST_SZ_BYTES(query_adapter_out); 51dc7e38acSHans Petter Selasky int err; 52dc7e38acSHans Petter Selasky 53dc7e38acSHans Petter Selasky out = kzalloc(outlen, GFP_KERNEL); 54dc7e38acSHans Petter Selasky 55dc7e38acSHans Petter Selasky err = mlx5_cmd_query_adapter(dev, out, outlen); 56dc7e38acSHans Petter Selasky if (err) 57dc7e38acSHans Petter Selasky goto out_out; 58dc7e38acSHans Petter Selasky 59dc7e38acSHans Petter Selasky memcpy(dev->board_id, 60dc7e38acSHans Petter Selasky MLX5_ADDR_OF(query_adapter_out, out, 61dc7e38acSHans Petter Selasky query_adapter_struct.vsd_contd_psid), 62dc7e38acSHans Petter Selasky MLX5_FLD_SZ_BYTES(query_adapter_out, 63dc7e38acSHans Petter Selasky query_adapter_struct.vsd_contd_psid)); 64dc7e38acSHans Petter Selasky 65dc7e38acSHans Petter Selasky out_out: 66dc7e38acSHans Petter Selasky kfree(out); 67dc7e38acSHans Petter Selasky 68dc7e38acSHans Petter Selasky return err; 69dc7e38acSHans Petter Selasky } 70dc7e38acSHans Petter Selasky 71dc7e38acSHans Petter Selasky int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id) 72dc7e38acSHans Petter Selasky { 73dc7e38acSHans Petter Selasky u32 *out; 74dc7e38acSHans Petter Selasky int outlen = MLX5_ST_SZ_BYTES(query_adapter_out); 75dc7e38acSHans Petter Selasky int err; 76dc7e38acSHans Petter Selasky 77dc7e38acSHans Petter Selasky out = kzalloc(outlen, GFP_KERNEL); 78dc7e38acSHans Petter Selasky 79dc7e38acSHans Petter Selasky err = mlx5_cmd_query_adapter(mdev, out, outlen); 80dc7e38acSHans Petter Selasky if (err) 81dc7e38acSHans Petter Selasky goto out_out; 82dc7e38acSHans Petter Selasky 83dc7e38acSHans Petter Selasky *vendor_id = MLX5_GET(query_adapter_out, out, 84dc7e38acSHans Petter Selasky query_adapter_struct.ieee_vendor_id); 85dc7e38acSHans Petter Selasky 86dc7e38acSHans Petter Selasky out_out: 87dc7e38acSHans Petter Selasky kfree(out); 88dc7e38acSHans Petter Selasky 89dc7e38acSHans Petter Selasky return err; 90dc7e38acSHans Petter Selasky } 91dc7e38acSHans Petter Selasky EXPORT_SYMBOL(mlx5_core_query_vendor_id); 92dc7e38acSHans Petter Selasky 93dc7e38acSHans Petter Selasky static int mlx5_core_query_special_contexts(struct mlx5_core_dev *dev) 94dc7e38acSHans Petter Selasky { 95dc7e38acSHans Petter Selasky u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)]; 96dc7e38acSHans Petter Selasky u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)]; 97dc7e38acSHans Petter Selasky int err; 98dc7e38acSHans Petter Selasky 99dc7e38acSHans Petter Selasky memset(in, 0, sizeof(in)); 100dc7e38acSHans Petter Selasky memset(out, 0, sizeof(out)); 101dc7e38acSHans Petter Selasky 102dc7e38acSHans Petter Selasky MLX5_SET(query_special_contexts_in, in, opcode, 103dc7e38acSHans Petter Selasky MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS); 104788333d9SHans Petter Selasky err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 105dc7e38acSHans Petter Selasky if (err) 106dc7e38acSHans Petter Selasky return err; 107dc7e38acSHans Petter Selasky 108dc7e38acSHans Petter Selasky dev->special_contexts.resd_lkey = MLX5_GET(query_special_contexts_out, 109dc7e38acSHans Petter Selasky out, resd_lkey); 110dc7e38acSHans Petter Selasky 111dc7e38acSHans Petter Selasky return err; 112dc7e38acSHans Petter Selasky } 113dc7e38acSHans Petter Selasky 114ed0cee0bSHans Petter Selasky static int mlx5_get_qcam_reg(struct mlx5_core_dev *dev) 115ed0cee0bSHans Petter Selasky { 116ed0cee0bSHans Petter Selasky return mlx5_query_qcam_reg(dev, dev->caps.qcam, 117ed0cee0bSHans Petter Selasky MLX5_QCAM_FEATURE_ENHANCED_FEATURES, 118ed0cee0bSHans Petter Selasky MLX5_QCAM_REGS_FIRST_128); 119ed0cee0bSHans Petter Selasky } 120ed0cee0bSHans Petter Selasky 1215a8145f6SHans Petter Selasky static int mlx5_get_pcam_reg(struct mlx5_core_dev *dev) 1225a8145f6SHans Petter Selasky { 1235a8145f6SHans Petter Selasky return mlx5_query_pcam_reg(dev, dev->caps.pcam, 1245a8145f6SHans Petter Selasky MLX5_PCAM_FEATURE_ENHANCED_FEATURES, 1255a8145f6SHans Petter Selasky MLX5_PCAM_REGS_5000_TO_507F); 1265a8145f6SHans Petter Selasky } 1275a8145f6SHans Petter Selasky 1285a8145f6SHans Petter Selasky static int mlx5_get_mcam_reg(struct mlx5_core_dev *dev) 1295a8145f6SHans Petter Selasky { 1305a8145f6SHans Petter Selasky return mlx5_query_mcam_reg(dev, dev->caps.mcam, 1315a8145f6SHans Petter Selasky MLX5_MCAM_FEATURE_ENHANCED_FEATURES, 1325a8145f6SHans Petter Selasky MLX5_MCAM_REGS_FIRST_128); 1335a8145f6SHans Petter Selasky } 1345a8145f6SHans Petter Selasky 135dc7e38acSHans Petter Selasky int mlx5_query_hca_caps(struct mlx5_core_dev *dev) 136dc7e38acSHans Petter Selasky { 137dc7e38acSHans Petter Selasky int err; 138dc7e38acSHans Petter Selasky 139788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL); 140dc7e38acSHans Petter Selasky if (err) 141dc7e38acSHans Petter Selasky return err; 142dc7e38acSHans Petter Selasky 143dc7e38acSHans Petter Selasky if (MLX5_CAP_GEN(dev, eth_net_offloads)) { 144788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS); 145dc7e38acSHans Petter Selasky if (err) 146dc7e38acSHans Petter Selasky return err; 147dc7e38acSHans Petter Selasky } 148dc7e38acSHans Petter Selasky 149dc7e38acSHans Petter Selasky if (MLX5_CAP_GEN(dev, pg)) { 150788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ODP); 151dc7e38acSHans Petter Selasky if (err) 152dc7e38acSHans Petter Selasky return err; 153dc7e38acSHans Petter Selasky } 154dc7e38acSHans Petter Selasky 155dc7e38acSHans Petter Selasky if (MLX5_CAP_GEN(dev, atomic)) { 156788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ATOMIC); 157dc7e38acSHans Petter Selasky if (err) 158dc7e38acSHans Petter Selasky return err; 159dc7e38acSHans Petter Selasky } 160dc7e38acSHans Petter Selasky 161dc7e38acSHans Petter Selasky if (MLX5_CAP_GEN(dev, roce)) { 162788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ROCE); 163dc7e38acSHans Petter Selasky if (err) 164dc7e38acSHans Petter Selasky return err; 165dc7e38acSHans Petter Selasky } 166dc7e38acSHans Petter Selasky 167627ef61aSHans Petter Selasky if ((MLX5_CAP_GEN(dev, port_type) == 168627ef61aSHans Petter Selasky MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET && 169627ef61aSHans Petter Selasky MLX5_CAP_GEN(dev, nic_flow_table)) || 170627ef61aSHans Petter Selasky (MLX5_CAP_GEN(dev, port_type) == MLX5_CMD_HCA_CAP_PORT_TYPE_IB && 171627ef61aSHans Petter Selasky MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) { 172788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE); 173dc7e38acSHans Petter Selasky if (err) 174dc7e38acSHans Petter Selasky return err; 175dc7e38acSHans Petter Selasky } 176dc7e38acSHans Petter Selasky 1779fc929d2SHans Petter Selasky if (MLX5_CAP_GEN(dev, eswitch_flow_table)) { 178788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE); 179dc7e38acSHans Petter Selasky if (err) 180dc7e38acSHans Petter Selasky return err; 181dc7e38acSHans Petter Selasky } 182dc7e38acSHans Petter Selasky 183dc7e38acSHans Petter Selasky if (MLX5_CAP_GEN(dev, vport_group_manager)) { 184788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH); 185dc7e38acSHans Petter Selasky if (err) 186dc7e38acSHans Petter Selasky return err; 187dc7e38acSHans Petter Selasky } 188dc7e38acSHans Petter Selasky 189cb4e4a6eSHans Petter Selasky if (MLX5_CAP_GEN(dev, snapshot)) { 190788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_SNAPSHOT); 191cb4e4a6eSHans Petter Selasky if (err) 192cb4e4a6eSHans Petter Selasky return err; 193cb4e4a6eSHans Petter Selasky } 194cb4e4a6eSHans Petter Selasky 195cb4e4a6eSHans Petter Selasky if (MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { 196788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_EOIB_OFFLOADS); 197cb4e4a6eSHans Petter Selasky if (err) 198cb4e4a6eSHans Petter Selasky return err; 199cb4e4a6eSHans Petter Selasky } 200cb4e4a6eSHans Petter Selasky 201cb4e4a6eSHans Petter Selasky if (MLX5_CAP_GEN(dev, debug)) { 202788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_DEBUG); 203cb4e4a6eSHans Petter Selasky if (err) 204cb4e4a6eSHans Petter Selasky return err; 205cb4e4a6eSHans Petter Selasky } 206cb4e4a6eSHans Petter Selasky 207cb4e4a6eSHans Petter Selasky if (MLX5_CAP_GEN(dev, qos)) { 208788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_QOS); 209cb4e4a6eSHans Petter Selasky if (err) 210cb4e4a6eSHans Petter Selasky return err; 211cb4e4a6eSHans Petter Selasky } 212cb4e4a6eSHans Petter Selasky 213ed0cee0bSHans Petter Selasky if (MLX5_CAP_GEN(dev, qcam_reg)) { 214ed0cee0bSHans Petter Selasky err = mlx5_get_qcam_reg(dev); 215ed0cee0bSHans Petter Selasky if (err) 216ed0cee0bSHans Petter Selasky return err; 217ed0cee0bSHans Petter Selasky } 218ed0cee0bSHans Petter Selasky 21958e63779SHans Petter Selasky if (MLX5_CAP_GEN(dev, mcam_reg)) { 22058e63779SHans Petter Selasky err = mlx5_get_mcam_reg(dev); 22158e63779SHans Petter Selasky if (err) 22258e63779SHans Petter Selasky return err; 22358e63779SHans Petter Selasky } 22458e63779SHans Petter Selasky 225ac87880aSHans Petter Selasky if (MLX5_CAP_GEN(dev, pcam_reg)) { 226ac87880aSHans Petter Selasky err = mlx5_get_pcam_reg(dev); 227ac87880aSHans Petter Selasky if (err) 228ac87880aSHans Petter Selasky return err; 229ac87880aSHans Petter Selasky } 230ac87880aSHans Petter Selasky 2319550e340SHans Petter Selasky if (MLX5_CAP_GEN(dev, tls_tx)) { 23204f1690bSHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_TLS); 23304f1690bSHans Petter Selasky if (err) 23404f1690bSHans Petter Selasky return err; 23504f1690bSHans Petter Selasky } 23604f1690bSHans Petter Selasky 237b633e08cSHans Petter Selasky if (MLX5_CAP_GEN(dev, event_cap)) { 238b633e08cSHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_EVENT); 239b633e08cSHans Petter Selasky if (err) 240b633e08cSHans Petter Selasky return err; 241b633e08cSHans Petter Selasky } 242b633e08cSHans Petter Selasky 243*e23731dbSKonstantin Belousov if (MLX5_CAP_GEN(dev, ipsec_offload)) { 244*e23731dbSKonstantin Belousov err = mlx5_core_get_caps(dev, MLX5_CAP_IPSEC); 245*e23731dbSKonstantin Belousov if (err) 246*e23731dbSKonstantin Belousov return err; 247*e23731dbSKonstantin Belousov } 248*e23731dbSKonstantin Belousov 249dc7e38acSHans Petter Selasky err = mlx5_core_query_special_contexts(dev); 250dc7e38acSHans Petter Selasky if (err) 251dc7e38acSHans Petter Selasky return err; 252dc7e38acSHans Petter Selasky 253dc7e38acSHans Petter Selasky return 0; 254dc7e38acSHans Petter Selasky } 255dc7e38acSHans Petter Selasky 256dc7e38acSHans Petter Selasky int mlx5_cmd_init_hca(struct mlx5_core_dev *dev) 257dc7e38acSHans Petter Selasky { 258dc7e38acSHans Petter Selasky u32 in[MLX5_ST_SZ_DW(init_hca_in)]; 259dc7e38acSHans Petter Selasky u32 out[MLX5_ST_SZ_DW(init_hca_out)]; 260dc7e38acSHans Petter Selasky 261dc7e38acSHans Petter Selasky memset(in, 0, sizeof(in)); 262dc7e38acSHans Petter Selasky 263dc7e38acSHans Petter Selasky MLX5_SET(init_hca_in, in, opcode, MLX5_CMD_OP_INIT_HCA); 264dc7e38acSHans Petter Selasky 265dc7e38acSHans Petter Selasky memset(out, 0, sizeof(out)); 266788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 267dc7e38acSHans Petter Selasky } 268dc7e38acSHans Petter Selasky 269dc7e38acSHans Petter Selasky int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev) 270dc7e38acSHans Petter Selasky { 271788333d9SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0}; 272788333d9SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0}; 273dc7e38acSHans Petter Selasky 274dc7e38acSHans Petter Selasky MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA); 275788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 276dc7e38acSHans Petter Selasky } 277cb4e4a6eSHans Petter Selasky 278c0902569SHans Petter Selasky int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev) 279c0902569SHans Petter Selasky { 280c0902569SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0}; 281c0902569SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0}; 282c0902569SHans Petter Selasky int force_state; 283c0902569SHans Petter Selasky int ret; 284c0902569SHans Petter Selasky 285c0902569SHans Petter Selasky if (!MLX5_CAP_GEN(dev, force_teardown)) { 286c0902569SHans Petter Selasky mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n"); 287c0902569SHans Petter Selasky return -EOPNOTSUPP; 288c0902569SHans Petter Selasky } 289c0902569SHans Petter Selasky 290c0902569SHans Petter Selasky MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA); 291c0902569SHans Petter Selasky MLX5_SET(teardown_hca_in, in, profile, MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE); 292c0902569SHans Petter Selasky 293c0902569SHans Petter Selasky ret = mlx5_cmd_exec_polling(dev, in, sizeof(in), out, sizeof(out)); 294c0902569SHans Petter Selasky if (ret) 295c0902569SHans Petter Selasky return ret; 296c0902569SHans Petter Selasky 297a4130a34SHans Petter Selasky force_state = MLX5_GET(teardown_hca_out, out, state); 298c0902569SHans Petter Selasky if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) { 299c0902569SHans Petter Selasky mlx5_core_err(dev, "teardown with force mode failed\n"); 300c0902569SHans Petter Selasky return -EIO; 301c0902569SHans Petter Selasky } 302c0902569SHans Petter Selasky 303c0902569SHans Petter Selasky return 0; 304c0902569SHans Petter Selasky } 305c0902569SHans Petter Selasky 306a4130a34SHans Petter Selasky #define MLX5_FAST_TEARDOWN_WAIT_MS 3000 307a4130a34SHans Petter Selasky int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev) 308a4130a34SHans Petter Selasky { 309a4130a34SHans Petter Selasky int end, delay_ms = MLX5_FAST_TEARDOWN_WAIT_MS; 310a4130a34SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {}; 311a4130a34SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {}; 312a4130a34SHans Petter Selasky int state; 313a4130a34SHans Petter Selasky int ret; 314a4130a34SHans Petter Selasky 315a4130a34SHans Petter Selasky if (!MLX5_CAP_GEN(dev, fast_teardown)) { 316a4130a34SHans Petter Selasky mlx5_core_dbg(dev, "fast teardown is not supported in the firmware\n"); 317a4130a34SHans Petter Selasky return -EOPNOTSUPP; 318a4130a34SHans Petter Selasky } 319a4130a34SHans Petter Selasky 320a4130a34SHans Petter Selasky MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA); 321a4130a34SHans Petter Selasky MLX5_SET(teardown_hca_in, in, profile, 322a4130a34SHans Petter Selasky MLX5_TEARDOWN_HCA_IN_PROFILE_PREPARE_FAST_TEARDOWN); 323a4130a34SHans Petter Selasky 324a4130a34SHans Petter Selasky ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 325a4130a34SHans Petter Selasky if (ret) 326a4130a34SHans Petter Selasky return ret; 327a4130a34SHans Petter Selasky 328a4130a34SHans Petter Selasky state = MLX5_GET(teardown_hca_out, out, state); 329a4130a34SHans Petter Selasky if (state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) { 330a4130a34SHans Petter Selasky mlx5_core_warn(dev, "teardown with fast mode failed\n"); 331a4130a34SHans Petter Selasky return -EIO; 332a4130a34SHans Petter Selasky } 333a4130a34SHans Petter Selasky 334a4130a34SHans Petter Selasky mlx5_set_nic_state(dev, MLX5_NIC_IFC_DISABLED); 335a4130a34SHans Petter Selasky 336a4130a34SHans Petter Selasky /* Loop until device state turns to disable */ 337a4130a34SHans Petter Selasky end = jiffies + msecs_to_jiffies(delay_ms); 338a4130a34SHans Petter Selasky do { 339a4130a34SHans Petter Selasky if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED) 340a4130a34SHans Petter Selasky break; 341a4130a34SHans Petter Selasky 342a4130a34SHans Petter Selasky pause("W", 1); 343a4130a34SHans Petter Selasky } while (!time_after(jiffies, end)); 344a4130a34SHans Petter Selasky 345a4130a34SHans Petter Selasky if (mlx5_get_nic_state(dev) != MLX5_NIC_IFC_DISABLED) { 346a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "NIC IFC still %d after %ums.\n", 347a4130a34SHans Petter Selasky mlx5_get_nic_state(dev), delay_ms); 348a4130a34SHans Petter Selasky return -EIO; 349a4130a34SHans Petter Selasky } 350a4130a34SHans Petter Selasky return 0; 351a4130a34SHans Petter Selasky } 352a4130a34SHans Petter Selasky 353cb4e4a6eSHans Petter Selasky int mlx5_core_set_dc_cnak_trace(struct mlx5_core_dev *dev, int enable, 354cb4e4a6eSHans Petter Selasky u64 addr) 355cb4e4a6eSHans Petter Selasky { 356788333d9SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(set_dc_cnak_trace_in)] = {0}; 357788333d9SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(set_dc_cnak_trace_out)] = {0}; 358788333d9SHans Petter Selasky __be64 be_addr; 359788333d9SHans Petter Selasky void *pas; 360cb4e4a6eSHans Petter Selasky 361788333d9SHans Petter Selasky MLX5_SET(set_dc_cnak_trace_in, in, opcode, MLX5_CMD_OP_SET_DC_CNAK_TRACE); 362788333d9SHans Petter Selasky MLX5_SET(set_dc_cnak_trace_in, in, enable, enable); 363788333d9SHans Petter Selasky pas = MLX5_ADDR_OF(set_dc_cnak_trace_in, in, pas); 364788333d9SHans Petter Selasky be_addr = cpu_to_be64(addr); 365788333d9SHans Petter Selasky memcpy(MLX5_ADDR_OF(cmd_pas, pas, pa_h), &be_addr, sizeof(be_addr)); 366cb4e4a6eSHans Petter Selasky 367788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); 368cb4e4a6eSHans Petter Selasky } 369031b1981SHans Petter Selasky 370031b1981SHans Petter Selasky enum mlxsw_reg_mcc_instruction { 371031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE = 0x01, 372031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE = 0x02, 373031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_UPDATE_COMPONENT = 0x03, 374031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_VERIFY_COMPONENT = 0x04, 375031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_ACTIVATE = 0x06, 376031b1981SHans Petter Selasky MLX5_REG_MCC_INSTRUCTION_CANCEL = 0x08, 377031b1981SHans Petter Selasky }; 378031b1981SHans Petter Selasky 379031b1981SHans Petter Selasky static int mlx5_reg_mcc_set(struct mlx5_core_dev *dev, 380031b1981SHans Petter Selasky enum mlxsw_reg_mcc_instruction instr, 381031b1981SHans Petter Selasky u16 component_index, u32 update_handle, 382031b1981SHans Petter Selasky u32 component_size) 383031b1981SHans Petter Selasky { 384031b1981SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(mcc_reg)]; 385031b1981SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(mcc_reg)]; 386031b1981SHans Petter Selasky 387031b1981SHans Petter Selasky memset(in, 0, sizeof(in)); 388031b1981SHans Petter Selasky 389031b1981SHans Petter Selasky MLX5_SET(mcc_reg, in, instruction, instr); 390031b1981SHans Petter Selasky MLX5_SET(mcc_reg, in, component_index, component_index); 391031b1981SHans Petter Selasky MLX5_SET(mcc_reg, in, update_handle, update_handle); 392031b1981SHans Petter Selasky MLX5_SET(mcc_reg, in, component_size, component_size); 393031b1981SHans Petter Selasky 394031b1981SHans Petter Selasky return mlx5_core_access_reg(dev, in, sizeof(in), out, 395031b1981SHans Petter Selasky sizeof(out), MLX5_REG_MCC, 0, 1); 396031b1981SHans Petter Selasky } 397031b1981SHans Petter Selasky 398031b1981SHans Petter Selasky static int mlx5_reg_mcc_query(struct mlx5_core_dev *dev, 399031b1981SHans Petter Selasky u32 *update_handle, u8 *error_code, 400031b1981SHans Petter Selasky u8 *control_state) 401031b1981SHans Petter Selasky { 402031b1981SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(mcc_reg)]; 403031b1981SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(mcc_reg)]; 404031b1981SHans Petter Selasky int err; 405031b1981SHans Petter Selasky 406031b1981SHans Petter Selasky memset(in, 0, sizeof(in)); 407031b1981SHans Petter Selasky memset(out, 0, sizeof(out)); 408031b1981SHans Petter Selasky MLX5_SET(mcc_reg, in, update_handle, *update_handle); 409031b1981SHans Petter Selasky 410031b1981SHans Petter Selasky err = mlx5_core_access_reg(dev, in, sizeof(in), out, 411031b1981SHans Petter Selasky sizeof(out), MLX5_REG_MCC, 0, 0); 412031b1981SHans Petter Selasky if (err) 413031b1981SHans Petter Selasky goto out; 414031b1981SHans Petter Selasky 415031b1981SHans Petter Selasky *update_handle = MLX5_GET(mcc_reg, out, update_handle); 416031b1981SHans Petter Selasky *error_code = MLX5_GET(mcc_reg, out, error_code); 417031b1981SHans Petter Selasky *control_state = MLX5_GET(mcc_reg, out, control_state); 418031b1981SHans Petter Selasky 419031b1981SHans Petter Selasky out: 420031b1981SHans Petter Selasky return err; 421031b1981SHans Petter Selasky } 422031b1981SHans Petter Selasky 423031b1981SHans Petter Selasky static int mlx5_reg_mcda_set(struct mlx5_core_dev *dev, 424031b1981SHans Petter Selasky u32 update_handle, 425031b1981SHans Petter Selasky u32 offset, u16 size, 426031b1981SHans Petter Selasky u8 *data) 427031b1981SHans Petter Selasky { 428031b1981SHans Petter Selasky int err, in_size = MLX5_ST_SZ_BYTES(mcda_reg) + size; 429031b1981SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(mcda_reg)]; 430031b1981SHans Petter Selasky int i, j, dw_size = size >> 2; 431031b1981SHans Petter Selasky __be32 data_element; 432031b1981SHans Petter Selasky u32 *in; 433031b1981SHans Petter Selasky 434031b1981SHans Petter Selasky in = kzalloc(in_size, GFP_KERNEL); 435031b1981SHans Petter Selasky if (!in) 436031b1981SHans Petter Selasky return -ENOMEM; 437031b1981SHans Petter Selasky 438031b1981SHans Petter Selasky MLX5_SET(mcda_reg, in, update_handle, update_handle); 439031b1981SHans Petter Selasky MLX5_SET(mcda_reg, in, offset, offset); 440031b1981SHans Petter Selasky MLX5_SET(mcda_reg, in, size, size); 441031b1981SHans Petter Selasky 442031b1981SHans Petter Selasky for (i = 0; i < dw_size; i++) { 443031b1981SHans Petter Selasky j = i * 4; 444031b1981SHans Petter Selasky data_element = htonl(*(u32 *)&data[j]); 445031b1981SHans Petter Selasky memcpy(MLX5_ADDR_OF(mcda_reg, in, data) + j, &data_element, 4); 446031b1981SHans Petter Selasky } 447031b1981SHans Petter Selasky 448031b1981SHans Petter Selasky err = mlx5_core_access_reg(dev, in, in_size, out, 449031b1981SHans Petter Selasky sizeof(out), MLX5_REG_MCDA, 0, 1); 450031b1981SHans Petter Selasky kfree(in); 451031b1981SHans Petter Selasky return err; 452031b1981SHans Petter Selasky } 453031b1981SHans Petter Selasky 454031b1981SHans Petter Selasky static int mlx5_reg_mcqi_query(struct mlx5_core_dev *dev, 455031b1981SHans Petter Selasky u16 component_index, 456031b1981SHans Petter Selasky u32 *max_component_size, 457031b1981SHans Petter Selasky u8 *log_mcda_word_size, 458031b1981SHans Petter Selasky u16 *mcda_max_write_size) 459031b1981SHans Petter Selasky { 460031b1981SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_ST_SZ_DW(mcqi_cap)]; 461031b1981SHans Petter Selasky int offset = MLX5_ST_SZ_DW(mcqi_reg); 462031b1981SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(mcqi_reg)]; 463031b1981SHans Petter Selasky int err; 464031b1981SHans Petter Selasky 465031b1981SHans Petter Selasky memset(in, 0, sizeof(in)); 466031b1981SHans Petter Selasky memset(out, 0, sizeof(out)); 467031b1981SHans Petter Selasky 468031b1981SHans Petter Selasky MLX5_SET(mcqi_reg, in, component_index, component_index); 469031b1981SHans Petter Selasky MLX5_SET(mcqi_reg, in, data_size, MLX5_ST_SZ_BYTES(mcqi_cap)); 470031b1981SHans Petter Selasky 471031b1981SHans Petter Selasky err = mlx5_core_access_reg(dev, in, sizeof(in), out, 472031b1981SHans Petter Selasky sizeof(out), MLX5_REG_MCQI, 0, 0); 473031b1981SHans Petter Selasky if (err) 474031b1981SHans Petter Selasky goto out; 475031b1981SHans Petter Selasky 476031b1981SHans Petter Selasky *max_component_size = MLX5_GET(mcqi_cap, out + offset, max_component_size); 477031b1981SHans Petter Selasky *log_mcda_word_size = MLX5_GET(mcqi_cap, out + offset, log_mcda_word_size); 478031b1981SHans Petter Selasky *mcda_max_write_size = MLX5_GET(mcqi_cap, out + offset, mcda_max_write_size); 479031b1981SHans Petter Selasky 480031b1981SHans Petter Selasky out: 481031b1981SHans Petter Selasky return err; 482031b1981SHans Petter Selasky } 48320a63539SHans Petter Selasky 48420a63539SHans Petter Selasky struct mlx5_mlxfw_dev { 48520a63539SHans Petter Selasky struct mlxfw_dev mlxfw_dev; 48620a63539SHans Petter Selasky struct mlx5_core_dev *mlx5_core_dev; 48720a63539SHans Petter Selasky }; 48820a63539SHans Petter Selasky 48920a63539SHans Petter Selasky static int mlx5_component_query(struct mlxfw_dev *mlxfw_dev, 49020a63539SHans Petter Selasky u16 component_index, u32 *p_max_size, 49120a63539SHans Petter Selasky u8 *p_align_bits, u16 *p_max_write_size) 49220a63539SHans Petter Selasky { 49320a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 49420a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 49520a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 49620a63539SHans Petter Selasky 49720a63539SHans Petter Selasky return mlx5_reg_mcqi_query(dev, component_index, p_max_size, 49820a63539SHans Petter Selasky p_align_bits, p_max_write_size); 49920a63539SHans Petter Selasky } 50020a63539SHans Petter Selasky 50120a63539SHans Petter Selasky static int mlx5_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle) 50220a63539SHans Petter Selasky { 50320a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 50420a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 50520a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 50620a63539SHans Petter Selasky u8 control_state, error_code; 50720a63539SHans Petter Selasky int err; 50820a63539SHans Petter Selasky 50920a63539SHans Petter Selasky *fwhandle = 0; 51020a63539SHans Petter Selasky err = mlx5_reg_mcc_query(dev, fwhandle, &error_code, &control_state); 51120a63539SHans Petter Selasky if (err) 51220a63539SHans Petter Selasky return err; 51320a63539SHans Petter Selasky 51420a63539SHans Petter Selasky if (control_state != MLXFW_FSM_STATE_IDLE) 51520a63539SHans Petter Selasky return -EBUSY; 51620a63539SHans Petter Selasky 51720a63539SHans Petter Selasky return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE, 51820a63539SHans Petter Selasky 0, *fwhandle, 0); 51920a63539SHans Petter Selasky } 52020a63539SHans Petter Selasky 52120a63539SHans Petter Selasky static int mlx5_fsm_component_update(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 52220a63539SHans Petter Selasky u16 component_index, u32 component_size) 52320a63539SHans Petter Selasky { 52420a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 52520a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 52620a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 52720a63539SHans Petter Selasky 52820a63539SHans Petter Selasky return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_UPDATE_COMPONENT, 52920a63539SHans Petter Selasky component_index, fwhandle, component_size); 53020a63539SHans Petter Selasky } 53120a63539SHans Petter Selasky 53220a63539SHans Petter Selasky static int mlx5_fsm_block_download(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 53320a63539SHans Petter Selasky u8 *data, u16 size, u32 offset) 53420a63539SHans Petter Selasky { 53520a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 53620a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 53720a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 53820a63539SHans Petter Selasky 53920a63539SHans Petter Selasky return mlx5_reg_mcda_set(dev, fwhandle, offset, size, data); 54020a63539SHans Petter Selasky } 54120a63539SHans Petter Selasky 54220a63539SHans Petter Selasky static int mlx5_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 54320a63539SHans Petter Selasky u16 component_index) 54420a63539SHans Petter Selasky { 54520a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 54620a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 54720a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 54820a63539SHans Petter Selasky 54920a63539SHans Petter Selasky return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_VERIFY_COMPONENT, 55020a63539SHans Petter Selasky component_index, fwhandle, 0); 55120a63539SHans Petter Selasky } 55220a63539SHans Petter Selasky 55320a63539SHans Petter Selasky static int mlx5_fsm_activate(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 55420a63539SHans Petter Selasky { 55520a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 55620a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 55720a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 55820a63539SHans Petter Selasky 55920a63539SHans Petter Selasky return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_ACTIVATE, 0, 56020a63539SHans Petter Selasky fwhandle, 0); 56120a63539SHans Petter Selasky } 56220a63539SHans Petter Selasky 56320a63539SHans Petter Selasky static int mlx5_fsm_query_state(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 56420a63539SHans Petter Selasky enum mlxfw_fsm_state *fsm_state, 56520a63539SHans Petter Selasky enum mlxfw_fsm_state_err *fsm_state_err) 56620a63539SHans Petter Selasky { 56720a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 56820a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 56920a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 57020a63539SHans Petter Selasky u8 control_state, error_code; 57120a63539SHans Petter Selasky int err; 57220a63539SHans Petter Selasky 57320a63539SHans Petter Selasky err = mlx5_reg_mcc_query(dev, &fwhandle, &error_code, &control_state); 57420a63539SHans Petter Selasky if (err) 57520a63539SHans Petter Selasky return err; 57620a63539SHans Petter Selasky 57720a63539SHans Petter Selasky *fsm_state = control_state; 57820a63539SHans Petter Selasky *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code, 57920a63539SHans Petter Selasky MLXFW_FSM_STATE_ERR_MAX); 58020a63539SHans Petter Selasky return 0; 58120a63539SHans Petter Selasky } 58220a63539SHans Petter Selasky 58320a63539SHans Petter Selasky static void mlx5_fsm_cancel(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 58420a63539SHans Petter Selasky { 58520a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 58620a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 58720a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 58820a63539SHans Petter Selasky 58920a63539SHans Petter Selasky mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_CANCEL, 0, fwhandle, 0); 59020a63539SHans Petter Selasky } 59120a63539SHans Petter Selasky 59220a63539SHans Petter Selasky static void mlx5_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 59320a63539SHans Petter Selasky { 59420a63539SHans Petter Selasky struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = 59520a63539SHans Petter Selasky container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); 59620a63539SHans Petter Selasky struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; 59720a63539SHans Petter Selasky 59820a63539SHans Petter Selasky mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 0, 59920a63539SHans Petter Selasky fwhandle, 0); 60020a63539SHans Petter Selasky } 60120a63539SHans Petter Selasky 60220a63539SHans Petter Selasky static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = { 60320a63539SHans Petter Selasky .component_query = mlx5_component_query, 60420a63539SHans Petter Selasky .fsm_lock = mlx5_fsm_lock, 60520a63539SHans Petter Selasky .fsm_component_update = mlx5_fsm_component_update, 60620a63539SHans Petter Selasky .fsm_block_download = mlx5_fsm_block_download, 60720a63539SHans Petter Selasky .fsm_component_verify = mlx5_fsm_component_verify, 60820a63539SHans Petter Selasky .fsm_activate = mlx5_fsm_activate, 60920a63539SHans Petter Selasky .fsm_query_state = mlx5_fsm_query_state, 61020a63539SHans Petter Selasky .fsm_cancel = mlx5_fsm_cancel, 61120a63539SHans Petter Selasky .fsm_release = mlx5_fsm_release 61220a63539SHans Petter Selasky }; 61320a63539SHans Petter Selasky 61420a63539SHans Petter Selasky int mlx5_firmware_flash(struct mlx5_core_dev *dev, 61520a63539SHans Petter Selasky const struct firmware *firmware) 61620a63539SHans Petter Selasky { 61720a63539SHans Petter Selasky struct mlx5_mlxfw_dev mlx5_mlxfw_dev = { 61820a63539SHans Petter Selasky .mlxfw_dev = { 61920a63539SHans Petter Selasky .ops = &mlx5_mlxfw_dev_ops, 62020a63539SHans Petter Selasky .psid = dev->board_id, 62120a63539SHans Petter Selasky .psid_size = strlen(dev->board_id), 62220a63539SHans Petter Selasky }, 62320a63539SHans Petter Selasky .mlx5_core_dev = dev 62420a63539SHans Petter Selasky }; 62520a63539SHans Petter Selasky 62620a63539SHans Petter Selasky if (!MLX5_CAP_GEN(dev, mcam_reg) || 62720a63539SHans Petter Selasky !MLX5_CAP_MCAM_REG(dev, mcqi) || 62820a63539SHans Petter Selasky !MLX5_CAP_MCAM_REG(dev, mcc) || 62920a63539SHans Petter Selasky !MLX5_CAP_MCAM_REG(dev, mcda)) { 63020a63539SHans Petter Selasky pr_info("%s flashing isn't supported by the running FW\n", __func__); 63120a63539SHans Petter Selasky return -EOPNOTSUPP; 63220a63539SHans Petter Selasky } 63320a63539SHans Petter Selasky 63420a63539SHans Petter Selasky return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev, firmware); 63520a63539SHans Petter Selasky } 636