@@ -795,17 +795,10 @@ static int __init disable_ddw_setup(char *str)
795
795
796
796
early_param ("disable_ddw" , disable_ddw_setup );
797
797
798
- static void remove_dma_window (struct device_node * np , u32 * ddw_avail ,
799
- struct property * win )
798
+ static void clean_dma_window (struct device_node * np , struct dynamic_dma_window_prop * dwp )
800
799
{
801
- struct dynamic_dma_window_prop * dwp ;
802
- u64 liobn ;
803
800
int ret ;
804
801
805
- dwp = win -> value ;
806
- liobn = (u64 )be32_to_cpu (dwp -> liobn );
807
-
808
- /* clear the whole window, note the arg is in kernel pages */
809
802
ret = tce_clearrange_multi_pSeriesLP (0 ,
810
803
1ULL << (be32_to_cpu (dwp -> window_shift ) - PAGE_SHIFT ), dwp );
811
804
if (ret )
@@ -814,18 +807,39 @@ static void remove_dma_window(struct device_node *np, u32 *ddw_avail,
814
807
else
815
808
pr_debug ("%pOF successfully cleared tces in window.\n" ,
816
809
np );
810
+ }
811
+
812
+ /*
813
+ * Call only if DMA window is clean.
814
+ */
815
+ static void __remove_dma_window (struct device_node * np , u32 * ddw_avail , u64 liobn )
816
+ {
817
+ int ret ;
817
818
818
819
ret = rtas_call (ddw_avail [DDW_REMOVE_PE_DMA_WIN ], 1 , 1 , NULL , liobn );
819
820
if (ret )
820
- pr_warn ("%pOF: failed to remove direct window: rtas returned "
821
+ pr_warn ("%pOF: failed to remove DMA window: rtas returned "
821
822
"%d to ibm,remove-pe-dma-window(%x) %llx\n" ,
822
823
np , ret , ddw_avail [DDW_REMOVE_PE_DMA_WIN ], liobn );
823
824
else
824
- pr_debug ("%pOF: successfully removed direct window: rtas returned "
825
+ pr_debug ("%pOF: successfully removed DMA window: rtas returned "
825
826
"%d to ibm,remove-pe-dma-window(%x) %llx\n" ,
826
827
np , ret , ddw_avail [DDW_REMOVE_PE_DMA_WIN ], liobn );
827
828
}
828
829
830
+ static void remove_dma_window (struct device_node * np , u32 * ddw_avail ,
831
+ struct property * win )
832
+ {
833
+ struct dynamic_dma_window_prop * dwp ;
834
+ u64 liobn ;
835
+
836
+ dwp = win -> value ;
837
+ liobn = (u64 )be32_to_cpu (dwp -> liobn );
838
+
839
+ clean_dma_window (np , dwp );
840
+ __remove_dma_window (np , ddw_avail , liobn );
841
+ }
842
+
829
843
static void remove_ddw (struct device_node * np , bool remove_prop )
830
844
{
831
845
struct property * win ;
@@ -1153,6 +1167,35 @@ static int iommu_get_page_shift(u32 query_page_size)
1153
1167
return 0 ;
1154
1168
}
1155
1169
1170
+ static struct property * ddw_property_create (const char * propname , u32 liobn , u64 dma_addr ,
1171
+ u32 page_shift , u32 window_shift )
1172
+ {
1173
+ struct dynamic_dma_window_prop * ddwprop ;
1174
+ struct property * win64 ;
1175
+
1176
+ win64 = kzalloc (sizeof (* win64 ), GFP_KERNEL );
1177
+ if (!win64 )
1178
+ return NULL ;
1179
+
1180
+ win64 -> name = kstrdup (propname , GFP_KERNEL );
1181
+ ddwprop = kzalloc (sizeof (* ddwprop ), GFP_KERNEL );
1182
+ win64 -> value = ddwprop ;
1183
+ win64 -> length = sizeof (* ddwprop );
1184
+ if (!win64 -> name || !win64 -> value ) {
1185
+ kfree (win64 -> name );
1186
+ kfree (win64 -> value );
1187
+ kfree (win64 );
1188
+ return NULL ;
1189
+ }
1190
+
1191
+ ddwprop -> liobn = cpu_to_be32 (liobn );
1192
+ ddwprop -> dma_base = cpu_to_be64 (dma_addr );
1193
+ ddwprop -> tce_shift = cpu_to_be32 (page_shift );
1194
+ ddwprop -> window_shift = cpu_to_be32 (window_shift );
1195
+
1196
+ return win64 ;
1197
+ }
1198
+
1156
1199
/*
1157
1200
* If the PE supports dynamic dma windows, and there is space for a table
1158
1201
* that can map all pages in a linear offset, then setup such a table,
@@ -1171,12 +1214,12 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
1171
1214
struct ddw_query_response query ;
1172
1215
struct ddw_create_response create ;
1173
1216
int page_shift ;
1217
+ u64 win_addr ;
1174
1218
struct device_node * dn ;
1175
1219
u32 ddw_avail [DDW_APPLICABLE_SIZE ];
1176
1220
struct direct_window * window ;
1177
1221
struct property * win64 ;
1178
1222
bool ddw_enabled = false;
1179
- struct dynamic_dma_window_prop * ddwprop ;
1180
1223
struct failed_ddw_pdn * fpdn ;
1181
1224
bool default_win_removed = false;
1182
1225
bool pmem_present ;
@@ -1293,72 +1336,68 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
1293
1336
1ULL << page_shift );
1294
1337
goto out_failed ;
1295
1338
}
1296
- win64 = kzalloc (sizeof (struct property ), GFP_KERNEL );
1297
- if (!win64 ) {
1298
- dev_info (& dev -> dev ,
1299
- "couldn't allocate property for 64bit dma window\n" );
1300
- goto out_failed ;
1301
- }
1302
- win64 -> name = kstrdup (DIRECT64_PROPNAME , GFP_KERNEL );
1303
- win64 -> value = ddwprop = kmalloc (sizeof (* ddwprop ), GFP_KERNEL );
1304
- win64 -> length = sizeof (* ddwprop );
1305
- if (!win64 -> name || !win64 -> value ) {
1306
- dev_info (& dev -> dev ,
1307
- "couldn't allocate property name and value\n" );
1308
- goto out_free_prop ;
1309
- }
1310
1339
1311
1340
ret = create_ddw (dev , ddw_avail , & create , page_shift , len );
1312
1341
if (ret != 0 )
1313
- goto out_free_prop ;
1314
-
1315
- ddwprop -> liobn = cpu_to_be32 (create .liobn );
1316
- ddwprop -> dma_base = cpu_to_be64 (((u64 )create .addr_hi << 32 ) |
1317
- create .addr_lo );
1318
- ddwprop -> tce_shift = cpu_to_be32 (page_shift );
1319
- ddwprop -> window_shift = cpu_to_be32 (len );
1342
+ goto out_failed ;
1320
1343
1321
1344
dev_dbg (& dev -> dev , "created tce table LIOBN 0x%x for %pOF\n" ,
1322
1345
create .liobn , dn );
1323
1346
1324
- window = ddw_list_new_entry (pdn , ddwprop );
1347
+ win_addr = ((u64 )create .addr_hi << 32 ) | create .addr_lo ;
1348
+ win64 = ddw_property_create (DIRECT64_PROPNAME , create .liobn , win_addr ,
1349
+ page_shift , len );
1350
+ if (!win64 ) {
1351
+ dev_info (& dev -> dev ,
1352
+ "couldn't allocate property, property name, or value\n" );
1353
+ goto out_remove_win ;
1354
+ }
1355
+
1356
+ ret = of_add_property (pdn , win64 );
1357
+ if (ret ) {
1358
+ dev_err (& dev -> dev , "unable to add dma window property for %pOF: %d" ,
1359
+ pdn , ret );
1360
+ goto out_free_prop ;
1361
+ }
1362
+
1363
+ window = ddw_list_new_entry (pdn , win64 -> value );
1325
1364
if (!window )
1326
- goto out_clear_window ;
1365
+ goto out_del_prop ;
1327
1366
1328
1367
ret = walk_system_ram_range (0 , memblock_end_of_DRAM () >> PAGE_SHIFT ,
1329
1368
win64 -> value , tce_setrange_multi_pSeriesLP_walk );
1330
1369
if (ret ) {
1331
1370
dev_info (& dev -> dev , "failed to map direct window for %pOF: %d\n" ,
1332
1371
dn , ret );
1333
- goto out_free_window ;
1334
- }
1335
1372
1336
- ret = of_add_property (pdn , win64 );
1337
- if (ret ) {
1338
- dev_err (& dev -> dev , "unable to add dma window property for %pOF: %d" ,
1339
- pdn , ret );
1340
- goto out_free_window ;
1373
+ /* Make sure to clean DDW if any TCE was set*/
1374
+ clean_dma_window (pdn , win64 -> value );
1375
+ goto out_del_list ;
1341
1376
}
1342
1377
1343
1378
spin_lock (& direct_window_list_lock );
1344
1379
list_add (& window -> list , & direct_window_list );
1345
1380
spin_unlock (& direct_window_list_lock );
1346
1381
1347
- dev -> dev .archdata .dma_offset = be64_to_cpu ( ddwprop -> dma_base ) ;
1382
+ dev -> dev .archdata .dma_offset = win_addr ;
1348
1383
ddw_enabled = true;
1349
1384
goto out_unlock ;
1350
1385
1351
- out_free_window :
1386
+ out_del_list :
1352
1387
kfree (window );
1353
1388
1354
- out_clear_window :
1355
- remove_ddw (pdn , true );
1389
+ out_del_prop :
1390
+ of_remove_property (pdn , win64 );
1356
1391
1357
1392
out_free_prop :
1358
1393
kfree (win64 -> name );
1359
1394
kfree (win64 -> value );
1360
1395
kfree (win64 );
1361
1396
1397
+ out_remove_win :
1398
+ /* DDW is clean, so it's ok to call this directly. */
1399
+ __remove_dma_window (pdn , ddw_avail , create .liobn );
1400
+
1362
1401
out_failed :
1363
1402
if (default_win_removed )
1364
1403
reset_dma_window (dev , pdn );
0 commit comments