]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/ehea/ehea_qmr.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh64-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / ehea / ehea_qmr.c
index f24a8862977ddda82589dc17c75fb4232f204dec..83b76432b41a8cc6c299ad3530b4e4bd98b5ac2a 100644 (file)
 #include "ehea_phyp.h"
 #include "ehea_qmr.h"
 
+
+struct ehea_busmap ehea_bmap = { 0, 0, NULL };
+extern u64 ehea_driver_flags;
+extern struct work_struct ehea_rereg_mr_task;
+
+
 static void *hw_qpageit_get_inc(struct hw_queue *queue)
 {
        void *retvalue = hw_qeit_get(queue);
@@ -211,7 +217,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
        u64 hret;
        u64 adapter_handle = cq->adapter->handle;
 
-        /* deregister all previous registered pages */
+       /* deregister all previous registered pages */
        hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
        if (hret != H_SUCCESS)
                return hret;
@@ -228,6 +234,8 @@ int ehea_destroy_cq(struct ehea_cq *cq)
        if (!cq)
                return 0;
 
+       hcp_epas_dtor(&cq->epas);
+
        if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) {
                ehea_error_data(cq->adapter, cq->fw_handle);
                hret = ehea_destroy_cq_res(cq, FORCE_FREE);
@@ -354,6 +362,8 @@ int ehea_destroy_eq(struct ehea_eq *eq)
        if (!eq)
                return 0;
 
+       hcp_epas_dtor(&eq->epas);
+
        if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) {
                ehea_error_data(eq->adapter, eq->fw_handle);
                hret = ehea_destroy_eq_res(eq, FORCE_FREE);
@@ -362,7 +372,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
        if (hret != H_SUCCESS) {
                ehea_error("destroy EQ failed");
                return -EIO;
-        }
+       }
 
        return 0;
 }
@@ -507,56 +517,120 @@ out_freemem:
 
 u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
 {
-        u64 hret;
-        struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+       u64 hret;
+       struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
 
 
-        ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
-        hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
-        if (hret != H_SUCCESS)
-                return hret;
+       ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+       hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+       if (hret != H_SUCCESS)
+               return hret;
 
-        hw_queue_dtor(&qp->hw_squeue);
-        hw_queue_dtor(&qp->hw_rqueue1);
+       hw_queue_dtor(&qp->hw_squeue);
+       hw_queue_dtor(&qp->hw_rqueue1);
 
-        if (qp_attr->rq_count > 1)
-                hw_queue_dtor(&qp->hw_rqueue2);
-        if (qp_attr->rq_count > 2)
-                hw_queue_dtor(&qp->hw_rqueue3);
-        kfree(qp);
+       if (qp_attr->rq_count > 1)
+               hw_queue_dtor(&qp->hw_rqueue2);
+       if (qp_attr->rq_count > 2)
+               hw_queue_dtor(&qp->hw_rqueue3);
+       kfree(qp);
 
-        return hret;
+       return hret;
 }
 
 int ehea_destroy_qp(struct ehea_qp *qp)
 {
-        u64 hret;
-        if (!qp)
-                return 0;
+       u64 hret;
+       if (!qp)
+               return 0;
+
+       hcp_epas_dtor(&qp->epas);
+
+       if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+               ehea_error_data(qp->adapter, qp->fw_handle);
+               hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+       }
+
+       if (hret != H_SUCCESS) {
+               ehea_error("destroy QP failed");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int ehea_create_busmap( void )
+{
+       u64 vaddr = EHEA_BUSMAP_START;
+       unsigned long high_section_index = 0;
+       int i;
+
+       /*
+        * Sections are not in ascending order -> Loop over all sections and
+        * find the highest PFN to compute the required map size.
+       */
+       ehea_bmap.valid_sections = 0;
 
-        if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
-                ehea_error_data(qp->adapter, qp->fw_handle);
-                hret = ehea_destroy_qp_res(qp, FORCE_FREE);
-        }
+       for (i = 0; i < NR_MEM_SECTIONS; i++)
+               if (valid_section_nr(i))
+                       high_section_index = i;
+
+       ehea_bmap.entries = high_section_index + 1;
+       ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr));
+
+       if (!ehea_bmap.vaddr)
+               return -ENOMEM;
 
-        if (hret != H_SUCCESS) {
-                ehea_error("destroy QP failed");
-                return -EIO;
-        }
+       for (i = 0 ; i < ehea_bmap.entries; i++) {
+               unsigned long pfn = section_nr_to_pfn(i);
 
-        return 0;
+               if (pfn_valid(pfn)) {
+                       ehea_bmap.vaddr[i] = vaddr;
+                       vaddr += EHEA_SECTSIZE;
+                       ehea_bmap.valid_sections++;
+               } else
+                       ehea_bmap.vaddr[i] = 0;
+       }
+
+       return 0;
+}
+
+void ehea_destroy_busmap( void )
+{
+       vfree(ehea_bmap.vaddr);
+}
+
+u64 ehea_map_vaddr(void *caddr)
+{
+       u64 mapped_addr;
+       unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS;
+
+       if (likely(index < ehea_bmap.entries)) {
+               mapped_addr = ehea_bmap.vaddr[index];
+               if (likely(mapped_addr))
+                       mapped_addr |= (((unsigned long)caddr)
+                                       & (EHEA_SECTSIZE - 1));
+               else
+                       mapped_addr = -1;
+       } else
+               mapped_addr = -1;
+
+       if (unlikely(mapped_addr == -1))
+               if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
+                       schedule_work(&ehea_rereg_mr_task);
+
+       return mapped_addr;
 }
 
 int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
 {
-       int i, k, ret;
-       u64 hret, pt_abs, start, end, nr_pages;
-       u32 acc_ctrl = EHEA_MR_ACC_CTRL;
+       int ret;
        u64 *pt;
+       void *pg;
+       u64 hret, pt_abs, i, j, m, mr_len;
+       u32 acc_ctrl = EHEA_MR_ACC_CTRL;
 
-       start = KERNELBASE;
-       end = (u64)high_memory;
-       nr_pages = (end - start) / EHEA_PAGESIZE;
+       mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE;
 
        pt =  kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!pt) {
@@ -566,7 +640,8 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
        }
        pt_abs = virt_to_abs(pt);
 
-       hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,
+       hret = ehea_h_alloc_resource_mr(adapter->handle,
+                                       EHEA_BUSMAP_START, mr_len,
                                        acc_ctrl, adapter->pd,
                                        &mr->handle, &mr->lkey);
        if (hret != H_SUCCESS) {
@@ -575,49 +650,43 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
                goto out;
        }
 
-       mr->vaddr = KERNELBASE;
-       k = 0;
-
-       while (nr_pages > 0) {
-               if (nr_pages > 1) {
-                       u64 num_pages = min(nr_pages, (u64)512);
-                       for (i = 0; i < num_pages; i++)
-                               pt[i] = virt_to_abs((void*)(((u64)start) +
-                                                           ((k++) *
-                                                            EHEA_PAGESIZE)));
-
-                       hret = ehea_h_register_rpage_mr(adapter->handle,
-                                                       mr->handle, 0,
-                                                       0, (u64)pt_abs,
-                                                       num_pages);
-                       nr_pages -= num_pages;
-               } else {
-                       u64 abs_adr = virt_to_abs((void*)(((u64)start) +
-                                                         (k * EHEA_PAGESIZE)));
-
-                       hret = ehea_h_register_rpage_mr(adapter->handle,
-                                                       mr->handle, 0,
-                                                       0, abs_adr,1);
-                       nr_pages--;
-               }
-
-               if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
-                       ehea_h_free_resource(adapter->handle,
-                                            mr->handle, FORCE_FREE);
-                       ehea_error("register_rpage_mr failed");
-                       ret = -EIO;
-                       goto out;
+       for (i = 0 ; i < ehea_bmap.entries; i++)
+               if (ehea_bmap.vaddr[i]) {
+                       void *sectbase = __va(i << SECTION_SIZE_BITS);
+                       unsigned long k = 0;
+
+                       for (j = 0; j < (EHEA_PAGES_PER_SECTION /
+                                        EHEA_MAX_RPAGE); j++) {
+
+                               for (m = 0; m < EHEA_MAX_RPAGE; m++) {
+                                       pg = sectbase + ((k++) * EHEA_PAGESIZE);
+                                       pt[m] = virt_to_abs(pg);
+                               }
+
+                               hret = ehea_h_register_rpage_mr(adapter->handle,
+                                                               mr->handle,
+                                                               0, 0, pt_abs,
+                                                               EHEA_MAX_RPAGE);
+                               if ((hret != H_SUCCESS)
+                                   && (hret != H_PAGE_REGISTERED)) {
+                                       ehea_h_free_resource(adapter->handle,
+                                                            mr->handle,
+                                                            FORCE_FREE);
+                                       ehea_error("register_rpage_mr failed");
+                                       ret = -EIO;
+                                       goto out;
+                               }
+                       }
                }
-       }
 
        if (hret != H_SUCCESS) {
-               ehea_h_free_resource(adapter->handle, mr->handle,
-                                    FORCE_FREE);
-               ehea_error("register_rpage failed for last page");
+               ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
+               ehea_error("registering mr failed");
                ret = -EIO;
                goto out;
        }
 
+       mr->vaddr = EHEA_BUSMAP_START;
        mr->adapter = adapter;
        ret = 0;
 out: