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