diff options
author | Or Gerlitz <ogerlitz@mellanox.com> | 2017-11-12 08:15:10 -0500 |
---|---|---|
committer | Saeed Mahameed <saeedm@mellanox.com> | 2018-01-09 00:40:48 -0500 |
commit | 18e568c390c61682e747178f136bcbc45c707882 (patch) | |
tree | b0df11b1703e5ebf62b49819f99c5231fb74b1b7 | |
parent | 40817cdbb695de49fb1bfe857b0f440541cb22d8 (diff) |
net/mlx5: Hairpin pair core object setup
Low level code to setup hairpin pair core object, deals with:
- create hairpin RQs/SQs
- destroy hairpin RQs/SQs
- modifying hairpin RQs/SQs - pairing (rst2rdy) and unpairing (rdy2rst)
Unlike conventional RQs/SQs, the memory used for the packet and descriptor
buffers is allocated by the firmware and not the driver. The driver sets
the overall data size (log).
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/transobj.c | 184 | ||||
-rw-r--r-- | include/linux/mlx5/transobj.h | 19 |
2 files changed, 203 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c index 5e128d7a9ffd..a09ebbaf3b68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c | |||
@@ -398,3 +398,187 @@ void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn) | |||
398 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); | 398 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
399 | } | 399 | } |
400 | EXPORT_SYMBOL(mlx5_core_destroy_rqt); | 400 | EXPORT_SYMBOL(mlx5_core_destroy_rqt); |
401 | |||
402 | static int mlx5_hairpin_create_rq(struct mlx5_core_dev *mdev, | ||
403 | struct mlx5_hairpin_params *params, u32 *rqn) | ||
404 | { | ||
405 | u32 in[MLX5_ST_SZ_DW(create_rq_in)] = {0}; | ||
406 | void *rqc, *wq; | ||
407 | |||
408 | rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); | ||
409 | wq = MLX5_ADDR_OF(rqc, rqc, wq); | ||
410 | |||
411 | MLX5_SET(rqc, rqc, hairpin, 1); | ||
412 | MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST); | ||
413 | MLX5_SET(rqc, rqc, counter_set_id, params->q_counter); | ||
414 | |||
415 | MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size); | ||
416 | |||
417 | return mlx5_core_create_rq(mdev, in, MLX5_ST_SZ_BYTES(create_rq_in), rqn); | ||
418 | } | ||
419 | |||
420 | static int mlx5_hairpin_create_sq(struct mlx5_core_dev *mdev, | ||
421 | struct mlx5_hairpin_params *params, u32 *sqn) | ||
422 | { | ||
423 | u32 in[MLX5_ST_SZ_DW(create_sq_in)] = {0}; | ||
424 | void *sqc, *wq; | ||
425 | |||
426 | sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); | ||
427 | wq = MLX5_ADDR_OF(sqc, sqc, wq); | ||
428 | |||
429 | MLX5_SET(sqc, sqc, hairpin, 1); | ||
430 | MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST); | ||
431 | |||
432 | MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size); | ||
433 | |||
434 | return mlx5_core_create_sq(mdev, in, MLX5_ST_SZ_BYTES(create_sq_in), sqn); | ||
435 | } | ||
436 | |||
437 | static int mlx5_hairpin_create_queues(struct mlx5_hairpin *hp, | ||
438 | struct mlx5_hairpin_params *params) | ||
439 | { | ||
440 | int err; | ||
441 | |||
442 | err = mlx5_hairpin_create_rq(hp->func_mdev, params, &hp->rqn); | ||
443 | if (err) | ||
444 | goto out_err_rq; | ||
445 | |||
446 | err = mlx5_hairpin_create_sq(hp->peer_mdev, params, &hp->sqn); | ||
447 | if (err) | ||
448 | goto out_err_sq; | ||
449 | |||
450 | return 0; | ||
451 | |||
452 | out_err_sq: | ||
453 | mlx5_core_destroy_rq(hp->func_mdev, hp->rqn); | ||
454 | out_err_rq: | ||
455 | return err; | ||
456 | } | ||
457 | |||
458 | static void mlx5_hairpin_destroy_queues(struct mlx5_hairpin *hp) | ||
459 | { | ||
460 | mlx5_core_destroy_rq(hp->func_mdev, hp->rqn); | ||
461 | mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn); | ||
462 | } | ||
463 | |||
464 | static int mlx5_hairpin_modify_rq(struct mlx5_core_dev *func_mdev, u32 rqn, | ||
465 | int curr_state, int next_state, | ||
466 | u16 peer_vhca, u32 peer_sq) | ||
467 | { | ||
468 | u32 in[MLX5_ST_SZ_DW(modify_rq_in)] = {0}; | ||
469 | void *rqc; | ||
470 | |||
471 | rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx); | ||
472 | |||
473 | if (next_state == MLX5_RQC_STATE_RDY) { | ||
474 | MLX5_SET(rqc, rqc, hairpin_peer_sq, peer_sq); | ||
475 | MLX5_SET(rqc, rqc, hairpin_peer_vhca, peer_vhca); | ||
476 | } | ||
477 | |||
478 | MLX5_SET(modify_rq_in, in, rq_state, curr_state); | ||
479 | MLX5_SET(rqc, rqc, state, next_state); | ||
480 | |||
481 | return mlx5_core_modify_rq(func_mdev, rqn, | ||
482 | in, MLX5_ST_SZ_BYTES(modify_rq_in)); | ||
483 | } | ||
484 | |||
485 | static int mlx5_hairpin_modify_sq(struct mlx5_core_dev *peer_mdev, u32 sqn, | ||
486 | int curr_state, int next_state, | ||
487 | u16 peer_vhca, u32 peer_rq) | ||
488 | { | ||
489 | u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0}; | ||
490 | void *sqc; | ||
491 | |||
492 | sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx); | ||
493 | |||
494 | if (next_state == MLX5_RQC_STATE_RDY) { | ||
495 | MLX5_SET(sqc, sqc, hairpin_peer_rq, peer_rq); | ||
496 | MLX5_SET(sqc, sqc, hairpin_peer_vhca, peer_vhca); | ||
497 | } | ||
498 | |||
499 | MLX5_SET(modify_sq_in, in, sq_state, curr_state); | ||
500 | MLX5_SET(sqc, sqc, state, next_state); | ||
501 | |||
502 | return mlx5_core_modify_sq(peer_mdev, sqn, | ||
503 | in, MLX5_ST_SZ_BYTES(modify_sq_in)); | ||
504 | } | ||
505 | |||
506 | static int mlx5_hairpin_pair_queues(struct mlx5_hairpin *hp) | ||
507 | { | ||
508 | int err; | ||
509 | |||
510 | /* set peer SQ */ | ||
511 | err = mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn, | ||
512 | MLX5_SQC_STATE_RST, MLX5_SQC_STATE_RDY, | ||
513 | MLX5_CAP_GEN(hp->func_mdev, vhca_id), hp->rqn); | ||
514 | if (err) | ||
515 | goto err_modify_sq; | ||
516 | |||
517 | /* set func RQ */ | ||
518 | err = mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn, | ||
519 | MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY, | ||
520 | MLX5_CAP_GEN(hp->peer_mdev, vhca_id), hp->sqn); | ||
521 | |||
522 | if (err) | ||
523 | goto err_modify_rq; | ||
524 | |||
525 | return 0; | ||
526 | |||
527 | err_modify_rq: | ||
528 | mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn, MLX5_SQC_STATE_RDY, | ||
529 | MLX5_SQC_STATE_RST, 0, 0); | ||
530 | err_modify_sq: | ||
531 | return err; | ||
532 | } | ||
533 | |||
534 | static void mlx5_hairpin_unpair_queues(struct mlx5_hairpin *hp) | ||
535 | { | ||
536 | /* unset func RQ */ | ||
537 | mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn, MLX5_RQC_STATE_RDY, | ||
538 | MLX5_RQC_STATE_RST, 0, 0); | ||
539 | |||
540 | /* unset peer SQ */ | ||
541 | mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn, MLX5_SQC_STATE_RDY, | ||
542 | MLX5_SQC_STATE_RST, 0, 0); | ||
543 | } | ||
544 | |||
545 | struct mlx5_hairpin * | ||
546 | mlx5_core_hairpin_create(struct mlx5_core_dev *func_mdev, | ||
547 | struct mlx5_core_dev *peer_mdev, | ||
548 | struct mlx5_hairpin_params *params) | ||
549 | { | ||
550 | struct mlx5_hairpin *hp; | ||
551 | int size, err; | ||
552 | |||
553 | size = sizeof(*hp); | ||
554 | hp = kzalloc(size, GFP_KERNEL); | ||
555 | if (!hp) | ||
556 | return ERR_PTR(-ENOMEM); | ||
557 | |||
558 | hp->func_mdev = func_mdev; | ||
559 | hp->peer_mdev = peer_mdev; | ||
560 | |||
561 | /* alloc and pair func --> peer hairpin */ | ||
562 | err = mlx5_hairpin_create_queues(hp, params); | ||
563 | if (err) | ||
564 | goto err_create_queues; | ||
565 | |||
566 | err = mlx5_hairpin_pair_queues(hp); | ||
567 | if (err) | ||
568 | goto err_pair_queues; | ||
569 | |||
570 | return hp; | ||
571 | |||
572 | err_pair_queues: | ||
573 | mlx5_hairpin_destroy_queues(hp); | ||
574 | err_create_queues: | ||
575 | kfree(hp); | ||
576 | return ERR_PTR(err); | ||
577 | } | ||
578 | |||
579 | void mlx5_core_hairpin_destroy(struct mlx5_hairpin *hp) | ||
580 | { | ||
581 | mlx5_hairpin_unpair_queues(hp); | ||
582 | mlx5_hairpin_destroy_queues(hp); | ||
583 | kfree(hp); | ||
584 | } | ||
diff --git a/include/linux/mlx5/transobj.h b/include/linux/mlx5/transobj.h index 88441f5ece25..a228310c1968 100644 --- a/include/linux/mlx5/transobj.h +++ b/include/linux/mlx5/transobj.h | |||
@@ -75,4 +75,23 @@ int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in, | |||
75 | int inlen); | 75 | int inlen); |
76 | void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn); | 76 | void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn); |
77 | 77 | ||
78 | struct mlx5_hairpin_params { | ||
79 | u8 log_data_size; | ||
80 | u16 q_counter; | ||
81 | }; | ||
82 | |||
83 | struct mlx5_hairpin { | ||
84 | struct mlx5_core_dev *func_mdev; | ||
85 | struct mlx5_core_dev *peer_mdev; | ||
86 | |||
87 | u32 rqn; | ||
88 | u32 sqn; | ||
89 | }; | ||
90 | |||
91 | struct mlx5_hairpin * | ||
92 | mlx5_core_hairpin_create(struct mlx5_core_dev *func_mdev, | ||
93 | struct mlx5_core_dev *peer_mdev, | ||
94 | struct mlx5_hairpin_params *params); | ||
95 | |||
96 | void mlx5_core_hairpin_destroy(struct mlx5_hairpin *pair); | ||
78 | #endif /* __TRANSOBJ_H__ */ | 97 | #endif /* __TRANSOBJ_H__ */ |