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