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