diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/mr.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mr.c | 186 |
1 files changed, 141 insertions, 45 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index c202d3ad2a0e..602ca9bf78e4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c | |||
@@ -44,20 +44,6 @@ | |||
44 | #include "mlx4.h" | 44 | #include "mlx4.h" |
45 | #include "icm.h" | 45 | #include "icm.h" |
46 | 46 | ||
47 | #define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) | ||
48 | #define MLX4_MPT_FLAG_FREE (0x3UL << 28) | ||
49 | #define MLX4_MPT_FLAG_MIO (1 << 17) | ||
50 | #define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15) | ||
51 | #define MLX4_MPT_FLAG_PHYSICAL (1 << 9) | ||
52 | #define MLX4_MPT_FLAG_REGION (1 << 8) | ||
53 | |||
54 | #define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27) | ||
55 | #define MLX4_MPT_PD_FLAG_RAE (1 << 28) | ||
56 | #define MLX4_MPT_PD_FLAG_EN_INV (3 << 24) | ||
57 | |||
58 | #define MLX4_MPT_STATUS_SW 0xF0 | ||
59 | #define MLX4_MPT_STATUS_HW 0x00 | ||
60 | |||
61 | static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) | 47 | static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) |
62 | { | 48 | { |
63 | int o; | 49 | int o; |
@@ -321,7 +307,7 @@ static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd, | |||
321 | mr->size = size; | 307 | mr->size = size; |
322 | mr->pd = pd; | 308 | mr->pd = pd; |
323 | mr->access = access; | 309 | mr->access = access; |
324 | mr->enabled = MLX4_MR_DISABLED; | 310 | mr->enabled = MLX4_MPT_DISABLED; |
325 | mr->key = hw_index_to_key(mridx); | 311 | mr->key = hw_index_to_key(mridx); |
326 | 312 | ||
327 | return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); | 313 | return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); |
@@ -335,14 +321,14 @@ static int mlx4_WRITE_MTT(struct mlx4_dev *dev, | |||
335 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | 321 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); |
336 | } | 322 | } |
337 | 323 | ||
338 | int __mlx4_mr_reserve(struct mlx4_dev *dev) | 324 | int __mlx4_mpt_reserve(struct mlx4_dev *dev) |
339 | { | 325 | { |
340 | struct mlx4_priv *priv = mlx4_priv(dev); | 326 | struct mlx4_priv *priv = mlx4_priv(dev); |
341 | 327 | ||
342 | return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); | 328 | return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); |
343 | } | 329 | } |
344 | 330 | ||
345 | static int mlx4_mr_reserve(struct mlx4_dev *dev) | 331 | static int mlx4_mpt_reserve(struct mlx4_dev *dev) |
346 | { | 332 | { |
347 | u64 out_param; | 333 | u64 out_param; |
348 | 334 | ||
@@ -353,17 +339,17 @@ static int mlx4_mr_reserve(struct mlx4_dev *dev) | |||
353 | return -1; | 339 | return -1; |
354 | return get_param_l(&out_param); | 340 | return get_param_l(&out_param); |
355 | } | 341 | } |
356 | return __mlx4_mr_reserve(dev); | 342 | return __mlx4_mpt_reserve(dev); |
357 | } | 343 | } |
358 | 344 | ||
359 | void __mlx4_mr_release(struct mlx4_dev *dev, u32 index) | 345 | void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index) |
360 | { | 346 | { |
361 | struct mlx4_priv *priv = mlx4_priv(dev); | 347 | struct mlx4_priv *priv = mlx4_priv(dev); |
362 | 348 | ||
363 | mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); | 349 | mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); |
364 | } | 350 | } |
365 | 351 | ||
366 | static void mlx4_mr_release(struct mlx4_dev *dev, u32 index) | 352 | static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index) |
367 | { | 353 | { |
368 | u64 in_param; | 354 | u64 in_param; |
369 | 355 | ||
@@ -376,17 +362,17 @@ static void mlx4_mr_release(struct mlx4_dev *dev, u32 index) | |||
376 | index); | 362 | index); |
377 | return; | 363 | return; |
378 | } | 364 | } |
379 | __mlx4_mr_release(dev, index); | 365 | __mlx4_mpt_release(dev, index); |
380 | } | 366 | } |
381 | 367 | ||
382 | int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index) | 368 | int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index) |
383 | { | 369 | { |
384 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; | 370 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; |
385 | 371 | ||
386 | return mlx4_table_get(dev, &mr_table->dmpt_table, index); | 372 | return mlx4_table_get(dev, &mr_table->dmpt_table, index); |
387 | } | 373 | } |
388 | 374 | ||
389 | static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index) | 375 | static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index) |
390 | { | 376 | { |
391 | u64 param; | 377 | u64 param; |
392 | 378 | ||
@@ -397,17 +383,17 @@ static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index) | |||
397 | MLX4_CMD_TIME_CLASS_A, | 383 | MLX4_CMD_TIME_CLASS_A, |
398 | MLX4_CMD_WRAPPED); | 384 | MLX4_CMD_WRAPPED); |
399 | } | 385 | } |
400 | return __mlx4_mr_alloc_icm(dev, index); | 386 | return __mlx4_mpt_alloc_icm(dev, index); |
401 | } | 387 | } |
402 | 388 | ||
403 | void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index) | 389 | void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index) |
404 | { | 390 | { |
405 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; | 391 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; |
406 | 392 | ||
407 | mlx4_table_put(dev, &mr_table->dmpt_table, index); | 393 | mlx4_table_put(dev, &mr_table->dmpt_table, index); |
408 | } | 394 | } |
409 | 395 | ||
410 | static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index) | 396 | static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index) |
411 | { | 397 | { |
412 | u64 in_param; | 398 | u64 in_param; |
413 | 399 | ||
@@ -420,7 +406,7 @@ static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index) | |||
420 | index); | 406 | index); |
421 | return; | 407 | return; |
422 | } | 408 | } |
423 | return __mlx4_mr_free_icm(dev, index); | 409 | return __mlx4_mpt_free_icm(dev, index); |
424 | } | 410 | } |
425 | 411 | ||
426 | int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, | 412 | int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, |
@@ -429,41 +415,52 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, | |||
429 | u32 index; | 415 | u32 index; |
430 | int err; | 416 | int err; |
431 | 417 | ||
432 | index = mlx4_mr_reserve(dev); | 418 | index = mlx4_mpt_reserve(dev); |
433 | if (index == -1) | 419 | if (index == -1) |
434 | return -ENOMEM; | 420 | return -ENOMEM; |
435 | 421 | ||
436 | err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size, | 422 | err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size, |
437 | access, npages, page_shift, mr); | 423 | access, npages, page_shift, mr); |
438 | if (err) | 424 | if (err) |
439 | mlx4_mr_release(dev, index); | 425 | mlx4_mpt_release(dev, index); |
440 | 426 | ||
441 | return err; | 427 | return err; |
442 | } | 428 | } |
443 | EXPORT_SYMBOL_GPL(mlx4_mr_alloc); | 429 | EXPORT_SYMBOL_GPL(mlx4_mr_alloc); |
444 | 430 | ||
445 | static void mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr) | 431 | static int mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr) |
446 | { | 432 | { |
447 | int err; | 433 | int err; |
448 | 434 | ||
449 | if (mr->enabled == MLX4_MR_EN_HW) { | 435 | if (mr->enabled == MLX4_MPT_EN_HW) { |
450 | err = mlx4_HW2SW_MPT(dev, NULL, | 436 | err = mlx4_HW2SW_MPT(dev, NULL, |
451 | key_to_hw_index(mr->key) & | 437 | key_to_hw_index(mr->key) & |
452 | (dev->caps.num_mpts - 1)); | 438 | (dev->caps.num_mpts - 1)); |
453 | if (err) | 439 | if (err) { |
454 | mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err); | 440 | mlx4_warn(dev, "HW2SW_MPT failed (%d),", err); |
441 | mlx4_warn(dev, "MR has MWs bound to it.\n"); | ||
442 | return err; | ||
443 | } | ||
455 | 444 | ||
456 | mr->enabled = MLX4_MR_EN_SW; | 445 | mr->enabled = MLX4_MPT_EN_SW; |
457 | } | 446 | } |
458 | mlx4_mtt_cleanup(dev, &mr->mtt); | 447 | mlx4_mtt_cleanup(dev, &mr->mtt); |
448 | |||
449 | return 0; | ||
459 | } | 450 | } |
460 | 451 | ||
461 | void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) | 452 | int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) |
462 | { | 453 | { |
463 | mlx4_mr_free_reserved(dev, mr); | 454 | int ret; |
455 | |||
456 | ret = mlx4_mr_free_reserved(dev, mr); | ||
457 | if (ret) | ||
458 | return ret; | ||
464 | if (mr->enabled) | 459 | if (mr->enabled) |
465 | mlx4_mr_free_icm(dev, key_to_hw_index(mr->key)); | 460 | mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key)); |
466 | mlx4_mr_release(dev, key_to_hw_index(mr->key)); | 461 | mlx4_mpt_release(dev, key_to_hw_index(mr->key)); |
462 | |||
463 | return 0; | ||
467 | } | 464 | } |
468 | EXPORT_SYMBOL_GPL(mlx4_mr_free); | 465 | EXPORT_SYMBOL_GPL(mlx4_mr_free); |
469 | 466 | ||
@@ -473,7 +470,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) | |||
473 | struct mlx4_mpt_entry *mpt_entry; | 470 | struct mlx4_mpt_entry *mpt_entry; |
474 | int err; | 471 | int err; |
475 | 472 | ||
476 | err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key)); | 473 | err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mr->key)); |
477 | if (err) | 474 | if (err) |
478 | return err; | 475 | return err; |
479 | 476 | ||
@@ -520,7 +517,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) | |||
520 | mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); | 517 | mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); |
521 | goto err_cmd; | 518 | goto err_cmd; |
522 | } | 519 | } |
523 | mr->enabled = MLX4_MR_EN_HW; | 520 | mr->enabled = MLX4_MPT_EN_HW; |
524 | 521 | ||
525 | mlx4_free_cmd_mailbox(dev, mailbox); | 522 | mlx4_free_cmd_mailbox(dev, mailbox); |
526 | 523 | ||
@@ -530,7 +527,7 @@ err_cmd: | |||
530 | mlx4_free_cmd_mailbox(dev, mailbox); | 527 | mlx4_free_cmd_mailbox(dev, mailbox); |
531 | 528 | ||
532 | err_table: | 529 | err_table: |
533 | mlx4_mr_free_icm(dev, key_to_hw_index(mr->key)); | 530 | mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key)); |
534 | return err; | 531 | return err; |
535 | } | 532 | } |
536 | EXPORT_SYMBOL_GPL(mlx4_mr_enable); | 533 | EXPORT_SYMBOL_GPL(mlx4_mr_enable); |
@@ -657,6 +654,101 @@ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | |||
657 | } | 654 | } |
658 | EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); | 655 | EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); |
659 | 656 | ||
657 | int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type, | ||
658 | struct mlx4_mw *mw) | ||
659 | { | ||
660 | u32 index; | ||
661 | |||
662 | if ((type == MLX4_MW_TYPE_1 && | ||
663 | !(dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW)) || | ||
664 | (type == MLX4_MW_TYPE_2 && | ||
665 | !(dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN))) | ||
666 | return -ENOTSUPP; | ||
667 | |||
668 | index = mlx4_mpt_reserve(dev); | ||
669 | if (index == -1) | ||
670 | return -ENOMEM; | ||
671 | |||
672 | mw->key = hw_index_to_key(index); | ||
673 | mw->pd = pd; | ||
674 | mw->type = type; | ||
675 | mw->enabled = MLX4_MPT_DISABLED; | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | EXPORT_SYMBOL_GPL(mlx4_mw_alloc); | ||
680 | |||
681 | int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw) | ||
682 | { | ||
683 | struct mlx4_cmd_mailbox *mailbox; | ||
684 | struct mlx4_mpt_entry *mpt_entry; | ||
685 | int err; | ||
686 | |||
687 | err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mw->key)); | ||
688 | if (err) | ||
689 | return err; | ||
690 | |||
691 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
692 | if (IS_ERR(mailbox)) { | ||
693 | err = PTR_ERR(mailbox); | ||
694 | goto err_table; | ||
695 | } | ||
696 | mpt_entry = mailbox->buf; | ||
697 | |||
698 | memset(mpt_entry, 0, sizeof(*mpt_entry)); | ||
699 | |||
700 | /* Note that the MLX4_MPT_FLAG_REGION bit in mpt_entry->flags is turned | ||
701 | * off, thus creating a memory window and not a memory region. | ||
702 | */ | ||
703 | mpt_entry->key = cpu_to_be32(key_to_hw_index(mw->key)); | ||
704 | mpt_entry->pd_flags = cpu_to_be32(mw->pd); | ||
705 | if (mw->type == MLX4_MW_TYPE_2) { | ||
706 | mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE); | ||
707 | mpt_entry->qpn = cpu_to_be32(MLX4_MPT_QP_FLAG_BOUND_QP); | ||
708 | mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_EN_INV); | ||
709 | } | ||
710 | |||
711 | err = mlx4_SW2HW_MPT(dev, mailbox, | ||
712 | key_to_hw_index(mw->key) & | ||
713 | (dev->caps.num_mpts - 1)); | ||
714 | if (err) { | ||
715 | mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); | ||
716 | goto err_cmd; | ||
717 | } | ||
718 | mw->enabled = MLX4_MPT_EN_HW; | ||
719 | |||
720 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
721 | |||
722 | return 0; | ||
723 | |||
724 | err_cmd: | ||
725 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
726 | |||
727 | err_table: | ||
728 | mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key)); | ||
729 | return err; | ||
730 | } | ||
731 | EXPORT_SYMBOL_GPL(mlx4_mw_enable); | ||
732 | |||
733 | void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw) | ||
734 | { | ||
735 | int err; | ||
736 | |||
737 | if (mw->enabled == MLX4_MPT_EN_HW) { | ||
738 | err = mlx4_HW2SW_MPT(dev, NULL, | ||
739 | key_to_hw_index(mw->key) & | ||
740 | (dev->caps.num_mpts - 1)); | ||
741 | if (err) | ||
742 | mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err); | ||
743 | |||
744 | mw->enabled = MLX4_MPT_EN_SW; | ||
745 | } | ||
746 | if (mw->enabled) | ||
747 | mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key)); | ||
748 | mlx4_mpt_release(dev, key_to_hw_index(mw->key)); | ||
749 | } | ||
750 | EXPORT_SYMBOL_GPL(mlx4_mw_free); | ||
751 | |||
660 | int mlx4_init_mr_table(struct mlx4_dev *dev) | 752 | int mlx4_init_mr_table(struct mlx4_dev *dev) |
661 | { | 753 | { |
662 | struct mlx4_priv *priv = mlx4_priv(dev); | 754 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -831,7 +923,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, | |||
831 | return 0; | 923 | return 0; |
832 | 924 | ||
833 | err_free: | 925 | err_free: |
834 | mlx4_mr_free(dev, &fmr->mr); | 926 | (void) mlx4_mr_free(dev, &fmr->mr); |
835 | return err; | 927 | return err; |
836 | } | 928 | } |
837 | EXPORT_SYMBOL_GPL(mlx4_fmr_alloc); | 929 | EXPORT_SYMBOL_GPL(mlx4_fmr_alloc); |
@@ -882,17 +974,21 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, | |||
882 | err); | 974 | err); |
883 | return; | 975 | return; |
884 | } | 976 | } |
885 | fmr->mr.enabled = MLX4_MR_EN_SW; | 977 | fmr->mr.enabled = MLX4_MPT_EN_SW; |
886 | } | 978 | } |
887 | EXPORT_SYMBOL_GPL(mlx4_fmr_unmap); | 979 | EXPORT_SYMBOL_GPL(mlx4_fmr_unmap); |
888 | 980 | ||
889 | int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr) | 981 | int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr) |
890 | { | 982 | { |
983 | int ret; | ||
984 | |||
891 | if (fmr->maps) | 985 | if (fmr->maps) |
892 | return -EBUSY; | 986 | return -EBUSY; |
893 | 987 | ||
894 | mlx4_mr_free(dev, &fmr->mr); | 988 | ret = mlx4_mr_free(dev, &fmr->mr); |
895 | fmr->mr.enabled = MLX4_MR_DISABLED; | 989 | if (ret) |
990 | return ret; | ||
991 | fmr->mr.enabled = MLX4_MPT_DISABLED; | ||
896 | 992 | ||
897 | return 0; | 993 | return 0; |
898 | } | 994 | } |