aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ehea/ehea_qmr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ehea/ehea_qmr.c')
-rw-r--r--drivers/net/ehea/ehea_qmr.c156
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
35struct ehea_busmap ehea_bmap = { 0, 0, NULL };
36extern u64 ehea_driver_flags;
37extern struct workqueue_struct *ehea_driver_wq;
38extern struct work_struct ehea_rereg_mr_task;
39
40
34static void *hw_qpageit_get_inc(struct hw_queue *queue) 41static 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
557int 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
597void ehea_destroy_busmap( void )
598{
599 vfree(ehea_bmap.vaddr);
600}
601
602u64 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
550int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) 624int 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;
623out: 691out: