@@ -232,20 +232,23 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
232
232
free_pages ((unsigned long )pages , get_order (size ));
233
233
}
234
234
235
- static void __arm_lpae_sync_pte (arm_lpae_iopte * ptep ,
235
+ static void __arm_lpae_sync_pte (arm_lpae_iopte * ptep , int num_entries ,
236
236
struct io_pgtable_cfg * cfg )
237
237
{
238
238
dma_sync_single_for_device (cfg -> iommu_dev , __arm_lpae_dma_addr (ptep ),
239
- sizeof (* ptep ), DMA_TO_DEVICE );
239
+ sizeof (* ptep ) * num_entries , DMA_TO_DEVICE );
240
240
}
241
241
242
242
static void __arm_lpae_set_pte (arm_lpae_iopte * ptep , arm_lpae_iopte pte ,
243
- struct io_pgtable_cfg * cfg )
243
+ int num_entries , struct io_pgtable_cfg * cfg )
244
244
{
245
- * ptep = pte ;
245
+ int i ;
246
+
247
+ for (i = 0 ; i < num_entries ; i ++ )
248
+ ptep [i ] = pte ;
246
249
247
250
if (!cfg -> coherent_walk )
248
- __arm_lpae_sync_pte (ptep , cfg );
251
+ __arm_lpae_sync_pte (ptep , num_entries , cfg );
249
252
}
250
253
251
254
static size_t __arm_lpae_unmap (struct arm_lpae_io_pgtable * data ,
@@ -255,47 +258,54 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
255
258
256
259
static void __arm_lpae_init_pte (struct arm_lpae_io_pgtable * data ,
257
260
phys_addr_t paddr , arm_lpae_iopte prot ,
258
- int lvl , arm_lpae_iopte * ptep )
261
+ int lvl , int num_entries , arm_lpae_iopte * ptep )
259
262
{
260
263
arm_lpae_iopte pte = prot ;
264
+ struct io_pgtable_cfg * cfg = & data -> iop .cfg ;
265
+ size_t sz = ARM_LPAE_BLOCK_SIZE (lvl , data );
266
+ int i ;
261
267
262
268
if (data -> iop .fmt != ARM_MALI_LPAE && lvl == ARM_LPAE_MAX_LEVELS - 1 )
263
269
pte |= ARM_LPAE_PTE_TYPE_PAGE ;
264
270
else
265
271
pte |= ARM_LPAE_PTE_TYPE_BLOCK ;
266
272
267
- pte |= paddr_to_iopte (paddr , data );
273
+ for (i = 0 ; i < num_entries ; i ++ )
274
+ ptep [i ] = pte | paddr_to_iopte (paddr + i * sz , data );
268
275
269
- __arm_lpae_set_pte (ptep , pte , & data -> iop .cfg );
276
+ if (!cfg -> coherent_walk )
277
+ __arm_lpae_sync_pte (ptep , num_entries , cfg );
270
278
}
271
279
272
280
static int arm_lpae_init_pte (struct arm_lpae_io_pgtable * data ,
273
281
unsigned long iova , phys_addr_t paddr ,
274
- arm_lpae_iopte prot , int lvl ,
282
+ arm_lpae_iopte prot , int lvl , int num_entries ,
275
283
arm_lpae_iopte * ptep )
276
284
{
277
- arm_lpae_iopte pte = * ptep ;
278
-
279
- if (iopte_leaf (pte , lvl , data -> iop .fmt )) {
280
- /* We require an unmap first */
281
- WARN_ON (!selftest_running );
282
- return - EEXIST ;
283
- } else if (iopte_type (pte ) == ARM_LPAE_PTE_TYPE_TABLE ) {
284
- /*
285
- * We need to unmap and free the old table before
286
- * overwriting it with a block entry.
287
- */
288
- arm_lpae_iopte * tblp ;
289
- size_t sz = ARM_LPAE_BLOCK_SIZE (lvl , data );
290
-
291
- tblp = ptep - ARM_LPAE_LVL_IDX (iova , lvl , data );
292
- if (__arm_lpae_unmap (data , NULL , iova , sz , lvl , tblp ) != sz ) {
293
- WARN_ON (1 );
294
- return - EINVAL ;
285
+ int i ;
286
+
287
+ for (i = 0 ; i < num_entries ; i ++ )
288
+ if (iopte_leaf (ptep [i ], lvl , data -> iop .fmt )) {
289
+ /* We require an unmap first */
290
+ WARN_ON (!selftest_running );
291
+ return - EEXIST ;
292
+ } else if (iopte_type (ptep [i ]) == ARM_LPAE_PTE_TYPE_TABLE ) {
293
+ /*
294
+ * We need to unmap and free the old table before
295
+ * overwriting it with a block entry.
296
+ */
297
+ arm_lpae_iopte * tblp ;
298
+ size_t sz = ARM_LPAE_BLOCK_SIZE (lvl , data );
299
+
300
+ tblp = ptep - ARM_LPAE_LVL_IDX (iova , lvl , data );
301
+ if (__arm_lpae_unmap (data , NULL , iova + i * sz , sz ,
302
+ lvl , tblp ) != sz ) {
303
+ WARN_ON (1 );
304
+ return - EINVAL ;
305
+ }
295
306
}
296
- }
297
307
298
- __arm_lpae_init_pte (data , paddr , prot , lvl , ptep );
308
+ __arm_lpae_init_pte (data , paddr , prot , lvl , num_entries , ptep );
299
309
return 0 ;
300
310
}
301
311
@@ -323,7 +333,7 @@ static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table,
323
333
return old ;
324
334
325
335
/* Even if it's not ours, there's no point waiting; just kick it */
326
- __arm_lpae_sync_pte (ptep , cfg );
336
+ __arm_lpae_sync_pte (ptep , 1 , cfg );
327
337
if (old == curr )
328
338
WRITE_ONCE (* ptep , new | ARM_LPAE_PTE_SW_SYNC );
329
339
@@ -344,7 +354,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
344
354
345
355
/* If we can install a leaf entry at this level, then do so */
346
356
if (size == block_size )
347
- return arm_lpae_init_pte (data , iova , paddr , prot , lvl , ptep );
357
+ return arm_lpae_init_pte (data , iova , paddr , prot , lvl , 1 , ptep );
348
358
349
359
/* We can't allocate tables at the final level */
350
360
if (WARN_ON (lvl >= ARM_LPAE_MAX_LEVELS - 1 ))
@@ -361,7 +371,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
361
371
if (pte )
362
372
__arm_lpae_free_pages (cptep , tblsz , cfg );
363
373
} else if (!cfg -> coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC )) {
364
- __arm_lpae_sync_pte (ptep , cfg );
374
+ __arm_lpae_sync_pte (ptep , 1 , cfg );
365
375
}
366
376
367
377
if (pte && !iopte_leaf (pte , lvl , data -> iop .fmt )) {
@@ -543,7 +553,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
543
553
if (i == unmap_idx )
544
554
continue ;
545
555
546
- __arm_lpae_init_pte (data , blk_paddr , pte , lvl , & tablep [i ]);
556
+ __arm_lpae_init_pte (data , blk_paddr , pte , lvl , 1 , & tablep [i ]);
547
557
}
548
558
549
559
pte = arm_lpae_install_table (tablep , ptep , blk_pte , cfg );
@@ -585,7 +595,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
585
595
586
596
/* If the size matches this level, we're in the right place */
587
597
if (size == ARM_LPAE_BLOCK_SIZE (lvl , data )) {
588
- __arm_lpae_set_pte (ptep , 0 , & iop -> cfg );
598
+ __arm_lpae_set_pte (ptep , 0 , 1 , & iop -> cfg );
589
599
590
600
if (!iopte_leaf (pte , lvl , iop -> fmt )) {
591
601
/* Also flush any partial walks */
0 commit comments