fe449c4e722520e050eb8a0819637cb29269d89c
[mirror/winof/.git] / hw / mlx4 / kernel / bus / core / l2w_umem.c
1
2 #include "l2w.h"
3 #include "ib_verbs.h"
4
5 /**
6  * ib_umem_release - release memory pinned with ib_umem_get
7  * @umem: umem struct to release
8  */
9 void ib_umem_release(struct ib_umem *p_ib_umem)
10 {
11         MLX4_ENTER(MLX4_DBG_MEMORY);
12         if (p_ib_umem->secure_handle)
13                 MmUnsecureVirtualMemory( p_ib_umem->secure_handle );
14         if (p_ib_umem->iobuf_used)
15                 iobuf_deregister_with_cash(&p_ib_umem->iobuf);
16         kfree(p_ib_umem);
17         MLX4_EXIT(MLX4_DBG_MEMORY);
18 }
19
20
21 /**
22  * ib_umem_get - Pin and DMA map userspace memory.
23  * @context: userspace context to pin memory for
24  * @addr: userspace virtual address to start at
25  * @size: length of region to pin
26  * @access: IB_ACCESS_xxx flags for memory being pinned
27  */
28 struct ib_umem *ib_umem_get(struct ib_ucontext *context, u64 addr,
29                             size_t size, enum ib_access_flags access)
30 {
31         int err;
32         struct ib_umem *p_ib_umem;
33
34         MLX4_ENTER(MLX4_DBG_MEMORY);
35
36         // create the object
37         p_ib_umem = kzalloc(sizeof *p_ib_umem, GFP_KERNEL);
38         if (!p_ib_umem)
39                 goto done;
40
41         p_ib_umem->p_uctx = context;
42         p_ib_umem->page_size = PAGE_SIZE;
43         
44         // register the memory 
45         iobuf_init( addr, (u64)size, !!context, &p_ib_umem->iobuf);
46         err =  iobuf_register_with_cash( addr, (u64)size, !!context, 
47                 &access, &p_ib_umem->iobuf );
48         if (err)
49                 goto err_reg_mem;
50         p_ib_umem->iobuf_used = TRUE;
51
52         // TODO: map the memory for DMA
53         
54         // secure memory
55         if (!context)
56                 goto done;
57         __try {
58                 p_ib_umem->secure_handle = MmSecureVirtualMemory ( 
59                         (PVOID)(ULONG_PTR)addr, size,
60                         (access & IB_ACCESS_LOCAL_WRITE) ? PAGE_READWRITE : PAGE_READONLY );
61                 if (p_ib_umem->secure_handle == NULL) 
62                         goto err_secure;
63         }
64         __except (EXCEPTION_EXECUTE_HANDLER) {
65                 NTSTATUS Status = GetExceptionCode();
66                 UNUSED_PARAM_WOWPP(Status);
67                 MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_MEMORY ,
68                         ("Exception 0x%x on MmSecureVirtualMemory(), addr %I64x, size %I64x, access %#x\n", 
69                         Status, addr, (u64)size, access ));
70                 goto err_secure;
71         }
72         goto done;
73
74 err_secure:
75         iobuf_deregister(&p_ib_umem->iobuf);
76
77 err_reg_mem:    
78         kfree(p_ib_umem);
79         p_ib_umem = NULL;
80
81 done:   
82         MLX4_EXIT(MLX4_DBG_MEMORY);
83         return p_ib_umem;
84 }
85
86 int ib_umem_page_count(struct ib_umem *p_ib_umem)
87 {
88         return (int)p_ib_umem->iobuf.nr_pages;
89 }
90
91 dma_addr_t ib_umem_get_dma(struct ib_umem *p_ib_umem)
92 {
93         u64 pages[1] = { 0 };
94         iobuf_iter_t iobuf_iter;
95         dma_addr_t dma_addr = { 0, 0 , 0 };
96
97         iobuf_iter_init( &p_ib_umem->iobuf, &iobuf_iter );
98         iobuf_get_tpt_seg( &p_ib_umem->iobuf, &iobuf_iter, 1, pages );
99         // TODO: convert phys address to DMA one
100         dma_addr.da = pages[0];
101
102         return dma_addr;
103 }
104
105
106 // Returns: 0 on success, -ENOMEM or -EACCESS or -EFAULT on error
107 int ib_umem_map(
108         IN              u64 va,
109         IN              u64 size,
110         IN              ib_access_t acc,
111         OUT             PMDL *mdl,
112         OUT             void **kva)
113 {
114         PMDL p_mdl;
115         int rc = 0;
116         LOCK_OPERATION lock_op = (acc & IB_AC_LOCAL_WRITE) ? IoModifyAccess : IoReadAccess;
117
118         p_mdl = IoAllocateMdl( (PVOID)(ULONG_PTR)va, (ULONG)size, FALSE,FALSE,NULL);
119         if (p_mdl == NULL) {
120                 rc = -ENOMEM;
121                 goto err_alloc_mdl;
122         }
123
124         __try { 
125                 MmProbeAndLockPages( p_mdl, UserMode, lock_op );   /* lock memory */
126         } 
127         __except (EXCEPTION_EXECUTE_HANDLER)    {
128                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_MEMORY, 
129                         ("MOSAL_iobuf_register: Exception 0x%x on MmProbeAndLockPages(), va %I64d, sz %I64d\n", 
130                         GetExceptionCode(), va, size));
131                 rc = -EACCES;
132                 goto err_probe;
133         }
134
135         *kva = MmMapLockedPagesSpecifyCache( p_mdl, 
136                 KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority );
137         if (*kva == NULL) {
138                 MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_MEMORY ,("MmMapLockedPagesSpecifyCache failed\n"));
139                 rc = -EFAULT;
140                 goto err_map;
141         }
142         
143         *mdl = p_mdl;
144         return 0;
145
146 err_map:
147         MmUnlockPages(p_mdl);
148 err_probe:
149         IoFreeMdl(p_mdl);
150 err_alloc_mdl:  
151         return rc;
152 }
153
154 void ib_umem_unmap(
155         IN PMDL p_mdl,
156         IN void *kva)
157 {
158         if (kva) {
159                 MmUnmapLockedPages( kva, p_mdl );
160                 MmUnlockPages(p_mdl);
161                 IoFreeMdl(p_mdl);
162         }
163 }
164