@@ -1157,12 +1157,11 @@ static inline void reclaim_free_desc(struct q_inval *qi)
1157
1157
}
1158
1158
}
1159
1159
1160
- static int qi_check_fault (struct intel_iommu * iommu , int index )
1160
+ static int qi_check_fault (struct intel_iommu * iommu , int index , int wait_index )
1161
1161
{
1162
1162
u32 fault ;
1163
1163
int head , tail ;
1164
1164
struct q_inval * qi = iommu -> qi ;
1165
- int wait_index = (index + 1 ) % QI_LENGTH ;
1166
1165
int shift = qi_shift (iommu );
1167
1166
1168
1167
if (qi -> desc_status [wait_index ] == QI_ABORT )
@@ -1225,17 +1224,21 @@ static int qi_check_fault(struct intel_iommu *iommu, int index)
1225
1224
}
1226
1225
1227
1226
/*
1228
- * Submit the queued invalidation descriptor to the remapping
1229
- * hardware unit and wait for its completion.
1227
+ * Function to submit invalidation descriptors of all types to the queued
1228
+ * invalidation interface(QI). Multiple descriptors can be submitted at a
1229
+ * time, a wait descriptor will be appended to each submission to ensure
1230
+ * hardware has completed the invalidation before return. Wait descriptors
1231
+ * can be part of the submission but it will not be polled for completion.
1230
1232
*/
1231
- int qi_submit_sync (struct qi_desc * desc , struct intel_iommu * iommu )
1233
+ int qi_submit_sync (struct intel_iommu * iommu , struct qi_desc * desc ,
1234
+ unsigned int count , unsigned long options )
1232
1235
{
1233
- int rc ;
1234
1236
struct q_inval * qi = iommu -> qi ;
1235
- int offset , shift , length ;
1236
1237
struct qi_desc wait_desc ;
1237
1238
int wait_index , index ;
1238
1239
unsigned long flags ;
1240
+ int offset , shift ;
1241
+ int rc , i ;
1239
1242
1240
1243
if (!qi )
1241
1244
return 0 ;
@@ -1244,32 +1247,41 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
1244
1247
rc = 0 ;
1245
1248
1246
1249
raw_spin_lock_irqsave (& qi -> q_lock , flags );
1247
- while (qi -> free_cnt < 3 ) {
1250
+ /*
1251
+ * Check if we have enough empty slots in the queue to submit,
1252
+ * the calculation is based on:
1253
+ * # of desc + 1 wait desc + 1 space between head and tail
1254
+ */
1255
+ while (qi -> free_cnt < count + 2 ) {
1248
1256
raw_spin_unlock_irqrestore (& qi -> q_lock , flags );
1249
1257
cpu_relax ();
1250
1258
raw_spin_lock_irqsave (& qi -> q_lock , flags );
1251
1259
}
1252
1260
1253
1261
index = qi -> free_head ;
1254
- wait_index = (index + 1 ) % QI_LENGTH ;
1262
+ wait_index = (index + count ) % QI_LENGTH ;
1255
1263
shift = qi_shift (iommu );
1256
- length = 1 << shift ;
1257
1264
1258
- qi -> desc_status [index ] = qi -> desc_status [wait_index ] = QI_IN_USE ;
1265
+ for (i = 0 ; i < count ; i ++ ) {
1266
+ offset = ((index + i ) % QI_LENGTH ) << shift ;
1267
+ memcpy (qi -> desc + offset , & desc [i ], 1 << shift );
1268
+ qi -> desc_status [(index + i ) % QI_LENGTH ] = QI_IN_USE ;
1269
+ }
1270
+ qi -> desc_status [wait_index ] = QI_IN_USE ;
1259
1271
1260
- offset = index << shift ;
1261
- memcpy (qi -> desc + offset , desc , length );
1262
1272
wait_desc .qw0 = QI_IWD_STATUS_DATA (QI_DONE ) |
1263
1273
QI_IWD_STATUS_WRITE | QI_IWD_TYPE ;
1274
+ if (options & QI_OPT_WAIT_DRAIN )
1275
+ wait_desc .qw0 |= QI_IWD_PRQ_DRAIN ;
1264
1276
wait_desc .qw1 = virt_to_phys (& qi -> desc_status [wait_index ]);
1265
1277
wait_desc .qw2 = 0 ;
1266
1278
wait_desc .qw3 = 0 ;
1267
1279
1268
1280
offset = wait_index << shift ;
1269
- memcpy (qi -> desc + offset , & wait_desc , length );
1281
+ memcpy (qi -> desc + offset , & wait_desc , 1 << shift );
1270
1282
1271
- qi -> free_head = (qi -> free_head + 2 ) % QI_LENGTH ;
1272
- qi -> free_cnt -= 2 ;
1283
+ qi -> free_head = (qi -> free_head + count + 1 ) % QI_LENGTH ;
1284
+ qi -> free_cnt -= count + 1 ;
1273
1285
1274
1286
/*
1275
1287
* update the HW tail register indicating the presence of
@@ -1285,7 +1297,7 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
1285
1297
* a deadlock where the interrupt context can wait indefinitely
1286
1298
* for free slots in the queue.
1287
1299
*/
1288
- rc = qi_check_fault (iommu , index );
1300
+ rc = qi_check_fault (iommu , index , wait_index );
1289
1301
if (rc )
1290
1302
break ;
1291
1303
@@ -1294,7 +1306,8 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
1294
1306
raw_spin_lock (& qi -> q_lock );
1295
1307
}
1296
1308
1297
- qi -> desc_status [index ] = QI_DONE ;
1309
+ for (i = 0 ; i < count ; i ++ )
1310
+ qi -> desc_status [(index + i ) % QI_LENGTH ] = QI_DONE ;
1298
1311
1299
1312
reclaim_free_desc (qi );
1300
1313
raw_spin_unlock_irqrestore (& qi -> q_lock , flags );
@@ -1318,7 +1331,7 @@ void qi_global_iec(struct intel_iommu *iommu)
1318
1331
desc .qw3 = 0 ;
1319
1332
1320
1333
/* should never fail */
1321
- qi_submit_sync (& desc , iommu );
1334
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1322
1335
}
1323
1336
1324
1337
void qi_flush_context (struct intel_iommu * iommu , u16 did , u16 sid , u8 fm ,
@@ -1332,7 +1345,7 @@ void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
1332
1345
desc .qw2 = 0 ;
1333
1346
desc .qw3 = 0 ;
1334
1347
1335
- qi_submit_sync (& desc , iommu );
1348
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1336
1349
}
1337
1350
1338
1351
void qi_flush_iotlb (struct intel_iommu * iommu , u16 did , u64 addr ,
@@ -1356,7 +1369,7 @@ void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
1356
1369
desc .qw2 = 0 ;
1357
1370
desc .qw3 = 0 ;
1358
1371
1359
- qi_submit_sync (& desc , iommu );
1372
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1360
1373
}
1361
1374
1362
1375
void qi_flush_dev_iotlb (struct intel_iommu * iommu , u16 sid , u16 pfsid ,
@@ -1378,7 +1391,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
1378
1391
desc .qw2 = 0 ;
1379
1392
desc .qw3 = 0 ;
1380
1393
1381
- qi_submit_sync (& desc , iommu );
1394
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1382
1395
}
1383
1396
1384
1397
/* PASID-based IOTLB invalidation */
@@ -1419,7 +1432,7 @@ void qi_flush_piotlb(struct intel_iommu *iommu, u16 did, u32 pasid, u64 addr,
1419
1432
QI_EIOTLB_AM (mask );
1420
1433
}
1421
1434
1422
- qi_submit_sync (& desc , iommu );
1435
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1423
1436
}
1424
1437
1425
1438
/* PASID-based device IOTLB Invalidate */
@@ -1448,7 +1461,7 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
1448
1461
if (size_order )
1449
1462
desc .qw1 |= QI_DEV_EIOTLB_SIZE ;
1450
1463
1451
- qi_submit_sync (& desc , iommu );
1464
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1452
1465
}
1453
1466
1454
1467
void qi_flush_pasid_cache (struct intel_iommu * iommu , u16 did ,
@@ -1458,7 +1471,7 @@ void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did,
1458
1471
1459
1472
desc .qw0 = QI_PC_PASID (pasid ) | QI_PC_DID (did ) |
1460
1473
QI_PC_GRAN (granu ) | QI_PC_TYPE ;
1461
- qi_submit_sync (& desc , iommu );
1474
+ qi_submit_sync (iommu , & desc , 1 , 0 );
1462
1475
}
1463
1476
1464
1477
/*
0 commit comments