diff options
Diffstat (limited to 'drivers/net/ehea/ehea_qmr.c')
-rw-r--r-- | drivers/net/ehea/ehea_qmr.c | 156 |
1 files changed, 112 insertions, 44 deletions
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 29eaa46948b0..a36fa6c23fdf 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c | |||
@@ -31,6 +31,13 @@ | |||
31 | #include "ehea_phyp.h" | 31 | #include "ehea_phyp.h" |
32 | #include "ehea_qmr.h" | 32 | #include "ehea_qmr.h" |
33 | 33 | ||
34 | |||
35 | struct ehea_busmap ehea_bmap = { 0, 0, NULL }; | ||
36 | extern u64 ehea_driver_flags; | ||
37 | extern struct workqueue_struct *ehea_driver_wq; | ||
38 | extern struct work_struct ehea_rereg_mr_task; | ||
39 | |||
40 | |||
34 | static void *hw_qpageit_get_inc(struct hw_queue *queue) | 41 | static void *hw_qpageit_get_inc(struct hw_queue *queue) |
35 | { | 42 | { |
36 | void *retvalue = hw_qeit_get(queue); | 43 | void *retvalue = hw_qeit_get(queue); |
@@ -547,18 +554,84 @@ int ehea_destroy_qp(struct ehea_qp *qp) | |||
547 | return 0; | 554 | return 0; |
548 | } | 555 | } |
549 | 556 | ||
557 | int ehea_create_busmap( void ) | ||
558 | { | ||
559 | u64 vaddr = EHEA_BUSMAP_START; | ||
560 | unsigned long abs_max_pfn = 0; | ||
561 | unsigned long sec_max_pfn; | ||
562 | int i; | ||
563 | |||
564 | /* | ||
565 | * Sections are not in ascending order -> Loop over all sections and | ||
566 | * find the highest PFN to compute the required map size. | ||
567 | */ | ||
568 | ehea_bmap.valid_sections = 0; | ||
569 | |||
570 | for (i = 0; i < NR_MEM_SECTIONS; i++) | ||
571 | if (valid_section_nr(i)) { | ||
572 | sec_max_pfn = section_nr_to_pfn(i); | ||
573 | if (sec_max_pfn > abs_max_pfn) | ||
574 | abs_max_pfn = sec_max_pfn; | ||
575 | ehea_bmap.valid_sections++; | ||
576 | } | ||
577 | |||
578 | ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1; | ||
579 | ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr)); | ||
580 | |||
581 | if (!ehea_bmap.vaddr) | ||
582 | return -ENOMEM; | ||
583 | |||
584 | for (i = 0 ; i < ehea_bmap.entries; i++) { | ||
585 | unsigned long pfn = section_nr_to_pfn(i); | ||
586 | |||
587 | if (pfn_valid(pfn)) { | ||
588 | ehea_bmap.vaddr[i] = vaddr; | ||
589 | vaddr += EHEA_SECTSIZE; | ||
590 | } else | ||
591 | ehea_bmap.vaddr[i] = 0; | ||
592 | } | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | void ehea_destroy_busmap( void ) | ||
598 | { | ||
599 | vfree(ehea_bmap.vaddr); | ||
600 | } | ||
601 | |||
602 | u64 ehea_map_vaddr(void *caddr) | ||
603 | { | ||
604 | u64 mapped_addr; | ||
605 | unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS; | ||
606 | |||
607 | if (likely(index < ehea_bmap.entries)) { | ||
608 | mapped_addr = ehea_bmap.vaddr[index]; | ||
609 | if (likely(mapped_addr)) | ||
610 | mapped_addr |= (((unsigned long)caddr) | ||
611 | & (EHEA_SECTSIZE - 1)); | ||
612 | else | ||
613 | mapped_addr = -1; | ||
614 | } else | ||
615 | mapped_addr = -1; | ||
616 | |||
617 | if (unlikely(mapped_addr == -1)) | ||
618 | if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) | ||
619 | queue_work(ehea_driver_wq, &ehea_rereg_mr_task); | ||
620 | |||
621 | return mapped_addr; | ||
622 | } | ||
623 | |||
550 | int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) | 624 | int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) |
551 | { | 625 | { |
552 | int i, k, ret; | 626 | int ret; |
553 | u64 hret, pt_abs, start, end, nr_pages; | ||
554 | u32 acc_ctrl = EHEA_MR_ACC_CTRL; | ||
555 | u64 *pt; | 627 | u64 *pt; |
628 | void *pg; | ||
629 | u64 hret, pt_abs, i, j, m, mr_len; | ||
630 | u32 acc_ctrl = EHEA_MR_ACC_CTRL; | ||
556 | 631 | ||
557 | start = KERNELBASE; | 632 | mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE; |
558 | end = (u64)high_memory; | ||
559 | nr_pages = (end - start) / EHEA_PAGESIZE; | ||
560 | 633 | ||
561 | pt = kzalloc(PAGE_SIZE, GFP_KERNEL); | 634 | pt = kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL); |
562 | if (!pt) { | 635 | if (!pt) { |
563 | ehea_error("no mem"); | 636 | ehea_error("no mem"); |
564 | ret = -ENOMEM; | 637 | ret = -ENOMEM; |
@@ -566,7 +639,8 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) | |||
566 | } | 639 | } |
567 | pt_abs = virt_to_abs(pt); | 640 | pt_abs = virt_to_abs(pt); |
568 | 641 | ||
569 | hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start, | 642 | hret = ehea_h_alloc_resource_mr(adapter->handle, |
643 | EHEA_BUSMAP_START, mr_len, | ||
570 | acc_ctrl, adapter->pd, | 644 | acc_ctrl, adapter->pd, |
571 | &mr->handle, &mr->lkey); | 645 | &mr->handle, &mr->lkey); |
572 | if (hret != H_SUCCESS) { | 646 | if (hret != H_SUCCESS) { |
@@ -575,49 +649,43 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) | |||
575 | goto out; | 649 | goto out; |
576 | } | 650 | } |
577 | 651 | ||
578 | mr->vaddr = KERNELBASE; | 652 | for (i = 0 ; i < ehea_bmap.entries; i++) |
579 | k = 0; | 653 | if (ehea_bmap.vaddr[i]) { |
580 | 654 | void *sectbase = __va(i << SECTION_SIZE_BITS); | |
581 | while (nr_pages > 0) { | 655 | unsigned long k = 0; |
582 | if (nr_pages > 1) { | 656 | |
583 | u64 num_pages = min(nr_pages, (u64)512); | 657 | for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE); |
584 | for (i = 0; i < num_pages; i++) | 658 | j++) { |
585 | pt[i] = virt_to_abs((void*)(((u64)start) + | 659 | |
586 | ((k++) * | 660 | for (m = 0; m < EHEA_MAX_RPAGE; m++) { |
587 | EHEA_PAGESIZE))); | 661 | pg = sectbase + ((k++) * EHEA_PAGESIZE); |
588 | 662 | pt[m] = virt_to_abs(pg); | |
589 | hret = ehea_h_register_rpage_mr(adapter->handle, | 663 | } |
590 | mr->handle, 0, | 664 | |
591 | 0, (u64)pt_abs, | 665 | hret = ehea_h_register_rpage_mr(adapter->handle, |
592 | num_pages); | 666 | mr->handle, |
593 | nr_pages -= num_pages; | 667 | 0, 0, pt_abs, |
594 | } else { | 668 | EHEA_MAX_RPAGE); |
595 | u64 abs_adr = virt_to_abs((void*)(((u64)start) + | 669 | if ((hret != H_SUCCESS) |
596 | (k * EHEA_PAGESIZE))); | 670 | && (hret != H_PAGE_REGISTERED)) { |
597 | 671 | ehea_h_free_resource(adapter->handle, | |
598 | hret = ehea_h_register_rpage_mr(adapter->handle, | 672 | mr->handle, |
599 | mr->handle, 0, | 673 | FORCE_FREE); |
600 | 0, abs_adr,1); | 674 | ehea_error("register_rpage_mr failed"); |
601 | nr_pages--; | 675 | ret = -EIO; |
602 | } | 676 | goto out; |
603 | 677 | } | |
604 | if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) { | 678 | } |
605 | ehea_h_free_resource(adapter->handle, | ||
606 | mr->handle, FORCE_FREE); | ||
607 | ehea_error("register_rpage_mr failed"); | ||
608 | ret = -EIO; | ||
609 | goto out; | ||
610 | } | 679 | } |
611 | } | ||
612 | 680 | ||
613 | if (hret != H_SUCCESS) { | 681 | if (hret != H_SUCCESS) { |
614 | ehea_h_free_resource(adapter->handle, mr->handle, | 682 | ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE); |
615 | FORCE_FREE); | 683 | ehea_error("registering mr failed"); |
616 | ehea_error("register_rpage failed for last page"); | ||
617 | ret = -EIO; | 684 | ret = -EIO; |
618 | goto out; | 685 | goto out; |
619 | } | 686 | } |
620 | 687 | ||
688 | mr->vaddr = EHEA_BUSMAP_START; | ||
621 | mr->adapter = adapter; | 689 | mr->adapter = adapter; |
622 | ret = 0; | 690 | ret = 0; |
623 | out: | 691 | out: |