aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ehea/ehea_qmr.c
diff options
context:
space:
mode:
authorThomas Klein <osstklei@de.ibm.com>2007-07-11 10:32:00 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-16 17:59:50 -0400
commit44c821525778c5d2e81da293195d5d589e8ad845 (patch)
tree7996d9d180023c752b61e2fcfe96a42a00a1510f /drivers/net/ehea/ehea_qmr.c
parent5be808467347fc99bdd216883c5dbd123d6ad9d6 (diff)
eHEA: Introducing support vor DLPAR memory add
This patch adds support for DLPAR memory add to the eHEA driver. To detect whether memory was added the driver uses its own memory mapping table and checks for kernel addresses whether they're located in already known memory sections. If not the function ehea_rereg_mrs() is triggered which performs a rebuild of the mapping table and a re-registration of the global memory region. Signed-off-by: Thomas Klein <tklein@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
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: