@@ -1234,19 +1234,19 @@ static dma_addr_t arm_smmu_cd_l1_get_desc(const struct arm_smmu_cdtab_l1 *src)
12341234struct arm_smmu_cd * arm_smmu_get_cd_ptr (struct arm_smmu_master * master ,
12351235 u32 ssid )
12361236{
1237- struct arm_smmu_l1_ctx_desc * l1_desc ;
1237+ struct arm_smmu_cdtab_l2 * l2 ;
12381238 struct arm_smmu_ctx_desc_cfg * cd_table = & master -> cd_table ;
12391239
1240- if (!cd_table -> cdtab )
1240+ if (!arm_smmu_cdtab_allocated ( cd_table ) )
12411241 return NULL ;
12421242
12431243 if (cd_table -> s1fmt == STRTAB_STE_0_S1FMT_LINEAR )
1244- return & (( struct arm_smmu_cd * ) cd_table -> cdtab ) [ssid ];
1244+ return & cd_table -> linear . table [ssid ];
12451245
1246- l1_desc = & cd_table -> l1_desc [arm_smmu_cdtab_l1_idx (ssid )];
1247- if (!l1_desc -> l2ptr )
1246+ l2 = cd_table -> l2 . l2ptrs [arm_smmu_cdtab_l1_idx (ssid )];
1247+ if (!l2 )
12481248 return NULL ;
1249- return & l1_desc -> l2ptr -> cds [arm_smmu_cdtab_l2_idx (ssid )];
1249+ return & l2 -> cds [arm_smmu_cdtab_l2_idx (ssid )];
12501250}
12511251
12521252static struct arm_smmu_cd * arm_smmu_alloc_cd_ptr (struct arm_smmu_master * master ,
@@ -1258,30 +1258,25 @@ static struct arm_smmu_cd *arm_smmu_alloc_cd_ptr(struct arm_smmu_master *master,
12581258 might_sleep ();
12591259 iommu_group_mutex_assert (master -> dev );
12601260
1261- if (!cd_table -> cdtab ) {
1261+ if (!arm_smmu_cdtab_allocated ( cd_table ) ) {
12621262 if (arm_smmu_alloc_cd_tables (master ))
12631263 return NULL ;
12641264 }
12651265
12661266 if (cd_table -> s1fmt == STRTAB_STE_0_S1FMT_64K_L2 ) {
12671267 unsigned int idx = arm_smmu_cdtab_l1_idx (ssid );
1268- struct arm_smmu_l1_ctx_desc * l1_desc ;
1268+ struct arm_smmu_cdtab_l2 * * l2ptr = & cd_table -> l2 . l2ptrs [ idx ] ;
12691269
1270- l1_desc = & cd_table -> l1_desc [idx ];
1271- if (!l1_desc -> l2ptr ) {
1272- struct arm_smmu_cdtab_l1 * dst ;
1270+ if (!* l2ptr ) {
12731271 dma_addr_t l2ptr_dma ;
1274- size_t size ;
12751272
1276- size = CTXDESC_L2_ENTRIES * sizeof (struct arm_smmu_cd );
1277- l1_desc -> l2ptr = dma_alloc_coherent (smmu -> dev , size ,
1278- & l2ptr_dma ,
1279- GFP_KERNEL );
1280- if (!l1_desc -> l2ptr )
1273+ * l2ptr = dma_alloc_coherent (smmu -> dev , sizeof (* * l2ptr ),
1274+ & l2ptr_dma , GFP_KERNEL );
1275+ if (!* l2ptr )
12811276 return NULL ;
12821277
1283- dst = & (( struct arm_smmu_cdtab_l1 * ) cd_table -> cdtab ) [idx ];
1284- arm_smmu_write_cd_l1_desc ( dst , l2ptr_dma );
1278+ arm_smmu_write_cd_l1_desc ( & cd_table -> l2 . l1tab [idx ],
1279+ l2ptr_dma );
12851280 /* An invalid L1CD can be cached */
12861281 arm_smmu_sync_cd (master , ssid , false);
12871282 }
@@ -1401,7 +1396,7 @@ void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)
14011396 struct arm_smmu_cd target = {};
14021397 struct arm_smmu_cd * cdptr ;
14031398
1404- if (!master -> cd_table . cdtab )
1399+ if (!arm_smmu_cdtab_allocated ( & master -> cd_table ) )
14051400 return ;
14061401 cdptr = arm_smmu_get_cd_ptr (master , ssid );
14071402 if (WARN_ON (!cdptr ))
@@ -1423,70 +1418,70 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
14231418 if (!(smmu -> features & ARM_SMMU_FEAT_2_LVL_CDTAB ) ||
14241419 max_contexts <= CTXDESC_L2_ENTRIES ) {
14251420 cd_table -> s1fmt = STRTAB_STE_0_S1FMT_LINEAR ;
1426- cd_table -> num_l1_ents = max_contexts ;
1421+ cd_table -> linear . num_ents = max_contexts ;
14271422
1428- l1size = max_contexts * sizeof (struct arm_smmu_cd );
1423+ l1size = max_contexts * sizeof (struct arm_smmu_cd ),
1424+ cd_table -> linear .table = dma_alloc_coherent (smmu -> dev , l1size ,
1425+ & cd_table -> cdtab_dma ,
1426+ GFP_KERNEL );
1427+ if (!cd_table -> linear .table )
1428+ return - ENOMEM ;
14291429 } else {
14301430 cd_table -> s1fmt = STRTAB_STE_0_S1FMT_64K_L2 ;
1431- cd_table -> num_l1_ents = DIV_ROUND_UP ( max_contexts ,
1432- CTXDESC_L2_ENTRIES );
1431+ cd_table -> l2 . num_l1_ents =
1432+ DIV_ROUND_UP ( max_contexts , CTXDESC_L2_ENTRIES );
14331433
1434- cd_table -> l1_desc = kcalloc (cd_table -> num_l1_ents ,
1435- sizeof (* cd_table -> l1_desc ),
1436- GFP_KERNEL );
1437- if (!cd_table -> l1_desc )
1434+ cd_table -> l2 . l2ptrs = kcalloc (cd_table -> l2 . num_l1_ents ,
1435+ sizeof (* cd_table -> l2 . l2ptrs ),
1436+ GFP_KERNEL );
1437+ if (!cd_table -> l2 . l2ptrs )
14381438 return - ENOMEM ;
14391439
1440- l1size = cd_table -> num_l1_ents * sizeof (struct arm_smmu_cdtab_l1 );
1441- }
1442-
1443- cd_table -> cdtab = dma_alloc_coherent (smmu -> dev , l1size ,
1444- & cd_table -> cdtab_dma , GFP_KERNEL );
1445- if (!cd_table -> cdtab ) {
1446- dev_warn (smmu -> dev , "failed to allocate context descriptor\n" );
1447- ret = - ENOMEM ;
1448- goto err_free_l1 ;
1440+ l1size = cd_table -> l2 .num_l1_ents * sizeof (struct arm_smmu_cdtab_l1 );
1441+ cd_table -> l2 .l1tab = dma_alloc_coherent (smmu -> dev , l1size ,
1442+ & cd_table -> cdtab_dma ,
1443+ GFP_KERNEL );
1444+ if (!cd_table -> l2 .l2ptrs ) {
1445+ ret = - ENOMEM ;
1446+ goto err_free_l2ptrs ;
1447+ }
14491448 }
1450-
14511449 return 0 ;
14521450
1453- err_free_l1 :
1454- if (cd_table -> l1_desc ) {
1455- kfree (cd_table -> l1_desc );
1456- cd_table -> l1_desc = NULL ;
1457- }
1451+ err_free_l2ptrs :
1452+ kfree (cd_table -> l2 .l2ptrs );
1453+ cd_table -> l2 .l2ptrs = NULL ;
14581454 return ret ;
14591455}
14601456
14611457static void arm_smmu_free_cd_tables (struct arm_smmu_master * master )
14621458{
14631459 int i ;
1464- size_t l1size ;
14651460 struct arm_smmu_device * smmu = master -> smmu ;
14661461 struct arm_smmu_ctx_desc_cfg * cd_table = & master -> cd_table ;
14671462
1468- if (cd_table -> l1_desc ) {
1469- for (i = 0 ; i < cd_table -> num_l1_ents ; i ++ ) {
1470- dma_addr_t dma_handle ;
1471-
1472- if (!cd_table -> l1_desc [i ].l2ptr )
1463+ if (cd_table -> s1fmt != STRTAB_STE_0_S1FMT_LINEAR ) {
1464+ for (i = 0 ; i < cd_table -> l2 .num_l1_ents ; i ++ ) {
1465+ if (!cd_table -> l2 .l2ptrs [i ])
14731466 continue ;
14741467
1475- dma_handle = arm_smmu_cd_l1_get_desc (& (
1476- (struct arm_smmu_cdtab_l1 * )cd_table -> cdtab )[i ]);
14771468 dma_free_coherent (smmu -> dev ,
1478- sizeof (* cd_table -> l1_desc [i ]. l2ptr ),
1479- cd_table -> l1_desc [i ]. l2ptr ,
1480- dma_handle );
1469+ sizeof (* cd_table -> l2 . l2ptrs [i ]),
1470+ cd_table -> l2 . l2ptrs [i ],
1471+ arm_smmu_cd_l1_get_desc ( & cd_table -> l2 . l1tab [ i ]) );
14811472 }
1482- kfree (cd_table -> l1_desc );
1473+ kfree (cd_table -> l2 . l2ptrs );
14831474
1484- l1size = cd_table -> num_l1_ents * sizeof (struct arm_smmu_cdtab_l1 );
1475+ dma_free_coherent (smmu -> dev ,
1476+ cd_table -> l2 .num_l1_ents *
1477+ sizeof (struct arm_smmu_cdtab_l1 ),
1478+ cd_table -> l2 .l1tab , cd_table -> cdtab_dma );
14851479 } else {
1486- l1size = cd_table -> num_l1_ents * sizeof (struct arm_smmu_cd );
1480+ dma_free_coherent (smmu -> dev ,
1481+ cd_table -> linear .num_ents *
1482+ sizeof (struct arm_smmu_cd ),
1483+ cd_table -> linear .table , cd_table -> cdtab_dma );
14871484 }
1488-
1489- dma_free_coherent (smmu -> dev , l1size , cd_table -> cdtab , cd_table -> cdtab_dma );
14901485}
14911486
14921487/* Stream table manipulation functions */
@@ -3334,7 +3329,7 @@ static void arm_smmu_release_device(struct device *dev)
33343329
33353330 arm_smmu_disable_pasid (master );
33363331 arm_smmu_remove_master (master );
3337- if (master -> cd_table . cdtab )
3332+ if (arm_smmu_cdtab_allocated ( & master -> cd_table ) )
33383333 arm_smmu_free_cd_tables (master );
33393334 kfree (master );
33403335}
0 commit comments