diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_verbs.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 170 |
1 files changed, 63 insertions, 107 deletions
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 44cb513f9a87..137880a19ebe 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -51,6 +51,7 @@ atomic_t qps_created; | |||
51 | atomic_t sw_qps_destroyed; | 51 | atomic_t sw_qps_destroyed; |
52 | 52 | ||
53 | static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev); | 53 | static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev); |
54 | static int nes_dereg_mr(struct ib_mr *ib_mr); | ||
54 | 55 | ||
55 | /** | 56 | /** |
56 | * nes_alloc_mw | 57 | * nes_alloc_mw |
@@ -443,79 +444,46 @@ static struct ib_mr *nes_alloc_mr(struct ib_pd *ibpd, | |||
443 | } else { | 444 | } else { |
444 | kfree(nesmr); | 445 | kfree(nesmr); |
445 | nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); | 446 | nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); |
446 | ibmr = ERR_PTR(-ENOMEM); | 447 | return ERR_PTR(-ENOMEM); |
447 | } | 448 | } |
449 | |||
450 | nesmr->pages = pci_alloc_consistent(nesdev->pcidev, | ||
451 | max_num_sg * sizeof(u64), | ||
452 | &nesmr->paddr); | ||
453 | if (!nesmr->paddr) | ||
454 | goto err; | ||
455 | |||
456 | nesmr->max_pages = max_num_sg; | ||
457 | |||
448 | return ibmr; | 458 | return ibmr; |
459 | |||
460 | err: | ||
461 | nes_dereg_mr(ibmr); | ||
462 | |||
463 | return ERR_PTR(-ENOMEM); | ||
449 | } | 464 | } |
450 | 465 | ||
451 | /* | 466 | static int nes_set_page(struct ib_mr *ibmr, u64 addr) |
452 | * nes_alloc_fast_reg_page_list | ||
453 | */ | ||
454 | static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list( | ||
455 | struct ib_device *ibdev, | ||
456 | int page_list_len) | ||
457 | { | 467 | { |
458 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); | 468 | struct nes_mr *nesmr = to_nesmr(ibmr); |
459 | struct nes_device *nesdev = nesvnic->nesdev; | ||
460 | struct ib_fast_reg_page_list *pifrpl; | ||
461 | struct nes_ib_fast_reg_page_list *pnesfrpl; | ||
462 | 469 | ||
463 | if (page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) | 470 | if (unlikely(nesmr->npages == nesmr->max_pages)) |
464 | return ERR_PTR(-E2BIG); | 471 | return -ENOMEM; |
465 | /* | ||
466 | * Allocate the ib_fast_reg_page_list structure, the | ||
467 | * nes_fast_bpl structure, and the PLB table. | ||
468 | */ | ||
469 | pnesfrpl = kmalloc(sizeof(struct nes_ib_fast_reg_page_list) + | ||
470 | page_list_len * sizeof(u64), GFP_KERNEL); | ||
471 | |||
472 | if (!pnesfrpl) | ||
473 | return ERR_PTR(-ENOMEM); | ||
474 | 472 | ||
475 | pifrpl = &pnesfrpl->ibfrpl; | 473 | nesmr->pages[nesmr->npages++] = cpu_to_le64(addr); |
476 | pifrpl->page_list = &pnesfrpl->pbl; | ||
477 | pifrpl->max_page_list_len = page_list_len; | ||
478 | /* | ||
479 | * Allocate the WQE PBL | ||
480 | */ | ||
481 | pnesfrpl->nes_wqe_pbl.kva = pci_alloc_consistent(nesdev->pcidev, | ||
482 | page_list_len * sizeof(u64), | ||
483 | &pnesfrpl->nes_wqe_pbl.paddr); | ||
484 | 474 | ||
485 | if (!pnesfrpl->nes_wqe_pbl.kva) { | 475 | return 0; |
486 | kfree(pnesfrpl); | ||
487 | return ERR_PTR(-ENOMEM); | ||
488 | } | ||
489 | nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, " | ||
490 | "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, " | ||
491 | "pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl, | ||
492 | pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva, | ||
493 | (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr); | ||
494 | |||
495 | return pifrpl; | ||
496 | } | 476 | } |
497 | 477 | ||
498 | /* | 478 | static int nes_map_mr_sg(struct ib_mr *ibmr, |
499 | * nes_free_fast_reg_page_list | 479 | struct scatterlist *sg, |
500 | */ | 480 | int sg_nents) |
501 | static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl) | ||
502 | { | 481 | { |
503 | struct nes_vnic *nesvnic = to_nesvnic(pifrpl->device); | 482 | struct nes_mr *nesmr = to_nesmr(ibmr); |
504 | struct nes_device *nesdev = nesvnic->nesdev; | ||
505 | struct nes_ib_fast_reg_page_list *pnesfrpl; | ||
506 | 483 | ||
507 | pnesfrpl = container_of(pifrpl, struct nes_ib_fast_reg_page_list, ibfrpl); | 484 | nesmr->npages = 0; |
508 | /* | 485 | |
509 | * Free the WQE PBL. | 486 | return ib_sg_to_pages(ibmr, sg, sg_nents, nes_set_page); |
510 | */ | ||
511 | pci_free_consistent(nesdev->pcidev, | ||
512 | pifrpl->max_page_list_len * sizeof(u64), | ||
513 | pnesfrpl->nes_wqe_pbl.kva, | ||
514 | pnesfrpl->nes_wqe_pbl.paddr); | ||
515 | /* | ||
516 | * Free the PBL structure | ||
517 | */ | ||
518 | kfree(pnesfrpl); | ||
519 | } | 487 | } |
520 | 488 | ||
521 | /** | 489 | /** |
@@ -2683,6 +2651,13 @@ static int nes_dereg_mr(struct ib_mr *ib_mr) | |||
2683 | u16 major_code; | 2651 | u16 major_code; |
2684 | u16 minor_code; | 2652 | u16 minor_code; |
2685 | 2653 | ||
2654 | |||
2655 | if (nesmr->pages) | ||
2656 | pci_free_consistent(nesdev->pcidev, | ||
2657 | nesmr->max_pages * sizeof(u64), | ||
2658 | nesmr->pages, | ||
2659 | nesmr->paddr); | ||
2660 | |||
2686 | if (nesmr->region) { | 2661 | if (nesmr->region) { |
2687 | ib_umem_release(nesmr->region); | 2662 | ib_umem_release(nesmr->region); |
2688 | } | 2663 | } |
@@ -3372,9 +3347,9 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3372 | wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; | 3347 | wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; |
3373 | 3348 | ||
3374 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, | 3349 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, |
3375 | ib_wr->wr.rdma.rkey); | 3350 | rdma_wr(ib_wr)->rkey); |
3376 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, | 3351 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, |
3377 | ib_wr->wr.rdma.remote_addr); | 3352 | rdma_wr(ib_wr)->remote_addr); |
3378 | 3353 | ||
3379 | if ((ib_wr->send_flags & IB_SEND_INLINE) && | 3354 | if ((ib_wr->send_flags & IB_SEND_INLINE) && |
3380 | ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) && | 3355 | ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) && |
@@ -3409,9 +3384,9 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3409 | } | 3384 | } |
3410 | 3385 | ||
3411 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, | 3386 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, |
3412 | ib_wr->wr.rdma.remote_addr); | 3387 | rdma_wr(ib_wr)->remote_addr); |
3413 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, | 3388 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, |
3414 | ib_wr->wr.rdma.rkey); | 3389 | rdma_wr(ib_wr)->rkey); |
3415 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX, | 3390 | set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX, |
3416 | ib_wr->sg_list->length); | 3391 | ib_wr->sg_list->length); |
3417 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, | 3392 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, |
@@ -3425,19 +3400,13 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3425 | NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX, | 3400 | NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX, |
3426 | ib_wr->ex.invalidate_rkey); | 3401 | ib_wr->ex.invalidate_rkey); |
3427 | break; | 3402 | break; |
3428 | case IB_WR_FAST_REG_MR: | 3403 | case IB_WR_REG_MR: |
3429 | { | 3404 | { |
3430 | int i; | 3405 | struct nes_mr *mr = to_nesmr(reg_wr(ib_wr)->mr); |
3431 | int flags = ib_wr->wr.fast_reg.access_flags; | 3406 | int page_shift = ilog2(reg_wr(ib_wr)->mr->page_size); |
3432 | struct nes_ib_fast_reg_page_list *pnesfrpl = | 3407 | int flags = reg_wr(ib_wr)->access; |
3433 | container_of(ib_wr->wr.fast_reg.page_list, | 3408 | |
3434 | struct nes_ib_fast_reg_page_list, | 3409 | if (mr->npages > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) { |
3435 | ibfrpl); | ||
3436 | u64 *src_page_list = pnesfrpl->ibfrpl.page_list; | ||
3437 | u64 *dst_page_list = pnesfrpl->nes_wqe_pbl.kva; | ||
3438 | |||
3439 | if (ib_wr->wr.fast_reg.page_list_len > | ||
3440 | (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) { | ||
3441 | nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n"); | 3410 | nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n"); |
3442 | err = -EINVAL; | 3411 | err = -EINVAL; |
3443 | break; | 3412 | break; |
@@ -3445,19 +3414,19 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3445 | wqe_misc = NES_IWARP_SQ_OP_FAST_REG; | 3414 | wqe_misc = NES_IWARP_SQ_OP_FAST_REG; |
3446 | set_wqe_64bit_value(wqe->wqe_words, | 3415 | set_wqe_64bit_value(wqe->wqe_words, |
3447 | NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX, | 3416 | NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX, |
3448 | ib_wr->wr.fast_reg.iova_start); | 3417 | mr->ibmr.iova); |
3449 | set_wqe_32bit_value(wqe->wqe_words, | 3418 | set_wqe_32bit_value(wqe->wqe_words, |
3450 | NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX, | 3419 | NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX, |
3451 | ib_wr->wr.fast_reg.length); | 3420 | mr->ibmr.length); |
3452 | set_wqe_32bit_value(wqe->wqe_words, | 3421 | set_wqe_32bit_value(wqe->wqe_words, |
3453 | NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0); | 3422 | NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0); |
3454 | set_wqe_32bit_value(wqe->wqe_words, | 3423 | set_wqe_32bit_value(wqe->wqe_words, |
3455 | NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX, | 3424 | NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX, |
3456 | ib_wr->wr.fast_reg.rkey); | 3425 | reg_wr(ib_wr)->key); |
3457 | /* Set page size: */ | 3426 | |
3458 | if (ib_wr->wr.fast_reg.page_shift == 12) { | 3427 | if (page_shift == 12) { |
3459 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K; | 3428 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K; |
3460 | } else if (ib_wr->wr.fast_reg.page_shift == 21) { | 3429 | } else if (page_shift == 21) { |
3461 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M; | 3430 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M; |
3462 | } else { | 3431 | } else { |
3463 | nes_debug(NES_DBG_IW_TX, "Invalid page shift," | 3432 | nes_debug(NES_DBG_IW_TX, "Invalid page shift," |
@@ -3465,6 +3434,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3465 | err = -EINVAL; | 3434 | err = -EINVAL; |
3466 | break; | 3435 | break; |
3467 | } | 3436 | } |
3437 | |||
3468 | /* Set access_flags */ | 3438 | /* Set access_flags */ |
3469 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ; | 3439 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ; |
3470 | if (flags & IB_ACCESS_LOCAL_WRITE) | 3440 | if (flags & IB_ACCESS_LOCAL_WRITE) |
@@ -3480,35 +3450,22 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3480 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND; | 3450 | wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND; |
3481 | 3451 | ||
3482 | /* Fill in PBL info: */ | 3452 | /* Fill in PBL info: */ |
3483 | if (ib_wr->wr.fast_reg.page_list_len > | ||
3484 | pnesfrpl->ibfrpl.max_page_list_len) { | ||
3485 | nes_debug(NES_DBG_IW_TX, "Invalid page list length," | ||
3486 | " ib_wr=%p, value=%u, max=%u\n", | ||
3487 | ib_wr, ib_wr->wr.fast_reg.page_list_len, | ||
3488 | pnesfrpl->ibfrpl.max_page_list_len); | ||
3489 | err = -EINVAL; | ||
3490 | break; | ||
3491 | } | ||
3492 | |||
3493 | set_wqe_64bit_value(wqe->wqe_words, | 3453 | set_wqe_64bit_value(wqe->wqe_words, |
3494 | NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX, | 3454 | NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX, |
3495 | pnesfrpl->nes_wqe_pbl.paddr); | 3455 | mr->paddr); |
3496 | 3456 | ||
3497 | set_wqe_32bit_value(wqe->wqe_words, | 3457 | set_wqe_32bit_value(wqe->wqe_words, |
3498 | NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX, | 3458 | NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX, |
3499 | ib_wr->wr.fast_reg.page_list_len * 8); | 3459 | mr->npages * 8); |
3500 | |||
3501 | for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++) | ||
3502 | dst_page_list[i] = cpu_to_le64(src_page_list[i]); | ||
3503 | 3460 | ||
3504 | nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, " | 3461 | nes_debug(NES_DBG_IW_TX, "SQ_REG_MR: iova_start: %llx, " |
3505 | "length: %d, rkey: %0x, pgl_paddr: %llx, " | 3462 | "length: %d, rkey: %0x, pgl_paddr: %llx, " |
3506 | "page_list_len: %u, wqe_misc: %x\n", | 3463 | "page_list_len: %u, wqe_misc: %x\n", |
3507 | (unsigned long long) ib_wr->wr.fast_reg.iova_start, | 3464 | (unsigned long long) mr->ibmr.iova, |
3508 | ib_wr->wr.fast_reg.length, | 3465 | mr->ibmr.length, |
3509 | ib_wr->wr.fast_reg.rkey, | 3466 | reg_wr(ib_wr)->key, |
3510 | (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr, | 3467 | (unsigned long long) mr->paddr, |
3511 | ib_wr->wr.fast_reg.page_list_len, | 3468 | mr->npages, |
3512 | wqe_misc); | 3469 | wqe_misc); |
3513 | break; | 3470 | break; |
3514 | } | 3471 | } |
@@ -3751,7 +3708,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
3751 | entry->opcode = IB_WC_LOCAL_INV; | 3708 | entry->opcode = IB_WC_LOCAL_INV; |
3752 | break; | 3709 | break; |
3753 | case NES_IWARP_SQ_OP_FAST_REG: | 3710 | case NES_IWARP_SQ_OP_FAST_REG: |
3754 | entry->opcode = IB_WC_FAST_REG_MR; | 3711 | entry->opcode = IB_WC_REG_MR; |
3755 | break; | 3712 | break; |
3756 | } | 3713 | } |
3757 | 3714 | ||
@@ -3939,8 +3896,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) | |||
3939 | nesibdev->ibdev.bind_mw = nes_bind_mw; | 3896 | nesibdev->ibdev.bind_mw = nes_bind_mw; |
3940 | 3897 | ||
3941 | nesibdev->ibdev.alloc_mr = nes_alloc_mr; | 3898 | nesibdev->ibdev.alloc_mr = nes_alloc_mr; |
3942 | nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list; | 3899 | nesibdev->ibdev.map_mr_sg = nes_map_mr_sg; |
3943 | nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list; | ||
3944 | 3900 | ||
3945 | nesibdev->ibdev.attach_mcast = nes_multicast_attach; | 3901 | nesibdev->ibdev.attach_mcast = nes_multicast_attach; |
3946 | nesibdev->ibdev.detach_mcast = nes_multicast_detach; | 3902 | nesibdev->ibdev.detach_mcast = nes_multicast_detach; |