@@ -37,13 +37,14 @@ struct nv50_instmem {
3737/******************************************************************************
3838 * instmem object implementation
3939 *****************************************************************************/
40- #define nv50_instobj (p ) container_of((p), struct nv50_instobj, memory)
40+ #define nv50_instobj (p ) container_of((p), struct nv50_instobj, base. memory)
4141
4242struct nv50_instobj {
43- struct nvkm_memory memory ;
43+ struct nvkm_instobj base ;
4444 struct nv50_instmem * imem ;
4545 struct nvkm_mem * mem ;
4646 struct nvkm_vma bar ;
47+ refcount_t maps ;
4748 void * map ;
4849};
4950
@@ -93,31 +94,59 @@ nv50_instobj_slow = {
9394 .wr32 = nv50_instobj_wr32_slow ,
9495};
9596
97+ static void
98+ nv50_instobj_wr32 (struct nvkm_memory * memory , u64 offset , u32 data )
99+ {
100+ iowrite32_native (data , nv50_instobj (memory )-> map + offset );
101+ }
102+
103+ static u32
104+ nv50_instobj_rd32 (struct nvkm_memory * memory , u64 offset )
105+ {
106+ return ioread32_native (nv50_instobj (memory )-> map + offset );
107+ }
108+
109+ static const struct nvkm_memory_ptrs
110+ nv50_instobj_fast = {
111+ .rd32 = nv50_instobj_rd32 ,
112+ .wr32 = nv50_instobj_wr32 ,
113+ };
114+
96115static void
97116nv50_instobj_kmap (struct nv50_instobj * iobj , struct nvkm_vmm * vmm )
98117{
99- struct nvkm_memory * memory = & iobj -> memory ;
100- struct nvkm_subdev * subdev = & iobj -> imem -> base .subdev ;
118+ struct nv50_instmem * imem = iobj -> imem ;
119+ struct nvkm_memory * memory = & iobj -> base .memory ;
120+ struct nvkm_subdev * subdev = & imem -> base .subdev ;
101121 struct nvkm_device * device = subdev -> device ;
122+ struct nvkm_vma bar = {};
102123 u64 size = nvkm_memory_size (memory );
103- void __iomem * map ;
104124 int ret ;
105125
106- iobj -> map = ERR_PTR (- ENOMEM );
107-
108- ret = nvkm_vm_get (vmm , size , 12 , NV_MEM_ACCESS_RW , & iobj -> bar );
109- if (ret == 0 ) {
110- map = ioremap (device -> func -> resource_addr (device , 3 ) +
111- (u32 )iobj -> bar .offset , size );
112- if (map ) {
113- nvkm_memory_map (memory , & iobj -> bar , 0 );
114- iobj -> map = map ;
115- } else {
116- nvkm_warn (subdev , "PRAMIN ioremap failed\n" );
117- nvkm_vm_put (& iobj -> bar );
118- }
119- } else {
120- nvkm_warn (subdev , "PRAMIN exhausted\n" );
126+ /* Attempt to allocate BAR2 address-space and map the object
127+ * into it. The lock has to be dropped while doing this due
128+ * to the possibility of recursion for page table allocation.
129+ */
130+ mutex_unlock (& subdev -> mutex );
131+ ret = nvkm_vm_get (vmm , size , 12 , NV_MEM_ACCESS_RW , & bar );
132+ if (ret == 0 )
133+ nvkm_memory_map (memory , & bar , 0 );
134+ mutex_lock (& subdev -> mutex );
135+ if (ret || iobj -> bar .node ) {
136+ /* We either failed, or another thread beat us. */
137+ mutex_unlock (& subdev -> mutex );
138+ nvkm_vm_put (& bar );
139+ mutex_lock (& subdev -> mutex );
140+ return ;
141+ }
142+
143+ /* Make the mapping visible to the host. */
144+ iobj -> bar = bar ;
145+ iobj -> map = ioremap (device -> func -> resource_addr (device , 3 ) +
146+ (u32 )iobj -> bar .offset , size );
147+ if (!iobj -> map ) {
148+ nvkm_warn (subdev , "PRAMIN ioremap failed\n" );
149+ nvkm_vm_put (& iobj -> bar );
121150 }
122151}
123152
@@ -131,28 +160,66 @@ nv50_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset)
131160static void
132161nv50_instobj_release (struct nvkm_memory * memory )
133162{
163+ struct nv50_instobj * iobj = nv50_instobj (memory );
164+ struct nv50_instmem * imem = iobj -> imem ;
165+ struct nvkm_subdev * subdev = & imem -> base .subdev ;
166+
167+ nvkm_bar_flush (subdev -> device -> bar );
168+
169+ if (refcount_dec_and_mutex_lock (& iobj -> maps , & subdev -> mutex )) {
170+ /* Switch back to NULL accessors when last map is gone. */
171+ iobj -> base .memory .ptrs = & nv50_instobj_slow ;
172+ mutex_unlock (& subdev -> mutex );
173+ }
134174}
135175
136176static void __iomem *
137177nv50_instobj_acquire (struct nvkm_memory * memory )
138178{
139179 struct nv50_instobj * iobj = nv50_instobj (memory );
140- struct nv50_instmem * imem = iobj -> imem ;
141- struct nvkm_vm * vm ;
180+ struct nvkm_instmem * imem = & iobj -> imem -> base ;
181+ struct nvkm_vmm * vmm ;
182+ void __iomem * map = NULL ;
142183
143- if (!iobj -> map && (vm = nvkm_bar_bar2_vmm (imem -> base .subdev .device )))
144- nv50_instobj_kmap (iobj , vm );
145- if (!IS_ERR_OR_NULL (iobj -> map ))
184+ /* Already mapped? */
185+ if (refcount_inc_not_zero (& iobj -> maps ))
146186 return iobj -> map ;
147187
148- return NULL ;
188+ /* Take the lock, and re-check that another thread hasn't
189+ * already mapped the object in the meantime.
190+ */
191+ mutex_lock (& imem -> subdev .mutex );
192+ if (refcount_inc_not_zero (& iobj -> maps )) {
193+ mutex_unlock (& imem -> subdev .mutex );
194+ return iobj -> map ;
195+ }
196+
197+ /* Attempt to get a direct CPU mapping of the object. */
198+ if (!iobj -> map && (vmm = nvkm_bar_bar2_vmm (imem -> subdev .device )))
199+ nv50_instobj_kmap (iobj , vmm );
200+ map = iobj -> map ;
201+
202+ if (!refcount_inc_not_zero (& iobj -> maps )) {
203+ if (map )
204+ iobj -> base .memory .ptrs = & nv50_instobj_fast ;
205+ else
206+ iobj -> base .memory .ptrs = & nv50_instobj_slow ;
207+ refcount_inc (& iobj -> maps );
208+ }
209+
210+ mutex_unlock (& imem -> subdev .mutex );
211+ return map ;
149212}
150213
151214static void
152215nv50_instobj_boot (struct nvkm_memory * memory , struct nvkm_vmm * vmm )
153216{
154217 struct nv50_instobj * iobj = nv50_instobj (memory );
218+ struct nvkm_instmem * imem = & iobj -> imem -> base ;
219+
220+ mutex_lock (& imem -> subdev .mutex );
155221 nv50_instobj_kmap (iobj , vmm );
222+ mutex_unlock (& imem -> subdev .mutex );
156223}
157224
158225static u64
@@ -177,12 +244,14 @@ static void *
177244nv50_instobj_dtor (struct nvkm_memory * memory )
178245{
179246 struct nv50_instobj * iobj = nv50_instobj (memory );
180- struct nvkm_ram * ram = iobj -> imem -> base .subdev .device -> fb -> ram ;
181- if (!IS_ERR_OR_NULL (iobj -> map )) {
247+ struct nvkm_instmem * imem = & iobj -> imem -> base ;
248+ struct nvkm_ram * ram = imem -> subdev .device -> fb -> ram ;
249+ if (iobj -> map ) {
182250 iounmap (iobj -> map );
183251 nvkm_vm_put (& iobj -> bar );
184252 }
185253 ram -> func -> put (ram , & iobj -> mem );
254+ nvkm_instobj_dtor (imem , & iobj -> base );
186255 return iobj ;
187256}
188257
@@ -209,11 +278,12 @@ nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
209278
210279 if (!(iobj = kzalloc (sizeof (* iobj ), GFP_KERNEL )))
211280 return - ENOMEM ;
212- * pmemory = & iobj -> memory ;
281+ * pmemory = & iobj -> base . memory ;
213282
214- nvkm_memory_ctor (& nv50_instobj_func , & iobj -> memory );
215- iobj -> memory .ptrs = & nv50_instobj_slow ;
283+ nvkm_instobj_ctor (& nv50_instobj_func , & imem -> base , & iobj -> base );
284+ iobj -> base . memory .ptrs = & nv50_instobj_slow ;
216285 iobj -> imem = imem ;
286+ refcount_set (& iobj -> maps , 0 );
217287
218288 size = max ((size + 4095 ) & ~4095 , (u32 )4096 );
219289 align = max ((align + 4095 ) & ~4095 , (u32 )4096 );
@@ -240,7 +310,7 @@ static const struct nvkm_instmem_func
240310nv50_instmem = {
241311 .fini = nv50_instmem_fini ,
242312 .memory_new = nv50_instobj_new ,
243- .persistent = false ,
313+ .persistent = true ,
244314 .zero = false,
245315};
246316
0 commit comments