|
35 | 35 | #include <asm/vio.h> |
36 | 36 | #include <asm/tce.h> |
37 | 37 | #include <asm/mmu_context.h> |
| 38 | +#include <asm/ppc-pci.h> |
38 | 39 |
|
39 | 40 | #define DBG(...) |
40 | 41 |
|
@@ -1156,8 +1157,14 @@ int iommu_add_device(struct iommu_table_group *table_group, struct device *dev) |
1156 | 1157 |
|
1157 | 1158 | pr_debug("%s: Adding %s to iommu group %d\n", |
1158 | 1159 | __func__, dev_name(dev), iommu_group_id(table_group->group)); |
1159 | | - |
1160 | | - return iommu_group_add_device(table_group->group, dev); |
| 1160 | + /* |
| 1161 | + * This is still not adding devices via the IOMMU bus notifier because |
| 1162 | + * of pcibios_init() from arch/powerpc/kernel/pci_64.c which calls |
| 1163 | + * pcibios_scan_phb() first (and this guy adds devices and triggers |
| 1164 | + * the notifier) and only then it calls pci_bus_add_devices() which |
| 1165 | + * configures DMA for buses which also creates PEs and IOMMU groups. |
| 1166 | + */ |
| 1167 | + return iommu_probe_device(dev); |
1161 | 1168 | } |
1162 | 1169 | EXPORT_SYMBOL_GPL(iommu_add_device); |
1163 | 1170 |
|
@@ -1237,6 +1244,7 @@ static long spapr_tce_take_ownership(struct iommu_table_group *table_group) |
1237 | 1244 | rc = iommu_take_ownership(tbl); |
1238 | 1245 | if (!rc) |
1239 | 1246 | continue; |
| 1247 | + |
1240 | 1248 | for (j = 0; j < i; ++j) |
1241 | 1249 | iommu_release_ownership(table_group->tables[j]); |
1242 | 1250 | return rc; |
@@ -1269,4 +1277,140 @@ struct iommu_table_group_ops spapr_tce_table_group_ops = { |
1269 | 1277 | .release_ownership = spapr_tce_release_ownership, |
1270 | 1278 | }; |
1271 | 1279 |
|
| 1280 | +/* |
| 1281 | + * A simple iommu_ops to allow less cruft in generic VFIO code. |
| 1282 | + */ |
| 1283 | +static int spapr_tce_blocking_iommu_attach_dev(struct iommu_domain *dom, |
| 1284 | + struct device *dev) |
| 1285 | +{ |
| 1286 | + struct iommu_group *grp = iommu_group_get(dev); |
| 1287 | + struct iommu_table_group *table_group; |
| 1288 | + int ret = -EINVAL; |
| 1289 | + |
| 1290 | + if (!grp) |
| 1291 | + return -ENODEV; |
| 1292 | + |
| 1293 | + table_group = iommu_group_get_iommudata(grp); |
| 1294 | + ret = table_group->ops->take_ownership(table_group); |
| 1295 | + iommu_group_put(grp); |
| 1296 | + |
| 1297 | + return ret; |
| 1298 | +} |
| 1299 | + |
| 1300 | +static void spapr_tce_blocking_iommu_set_platform_dma(struct device *dev) |
| 1301 | +{ |
| 1302 | + struct iommu_group *grp = iommu_group_get(dev); |
| 1303 | + struct iommu_table_group *table_group; |
| 1304 | + |
| 1305 | + table_group = iommu_group_get_iommudata(grp); |
| 1306 | + table_group->ops->release_ownership(table_group); |
| 1307 | +} |
| 1308 | + |
| 1309 | +static const struct iommu_domain_ops spapr_tce_blocking_domain_ops = { |
| 1310 | + .attach_dev = spapr_tce_blocking_iommu_attach_dev, |
| 1311 | +}; |
| 1312 | + |
| 1313 | +static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap) |
| 1314 | +{ |
| 1315 | + switch (cap) { |
| 1316 | + case IOMMU_CAP_CACHE_COHERENCY: |
| 1317 | + return true; |
| 1318 | + default: |
| 1319 | + break; |
| 1320 | + } |
| 1321 | + |
| 1322 | + return false; |
| 1323 | +} |
| 1324 | + |
| 1325 | +static struct iommu_domain *spapr_tce_iommu_domain_alloc(unsigned int type) |
| 1326 | +{ |
| 1327 | + struct iommu_domain *dom; |
| 1328 | + |
| 1329 | + if (type != IOMMU_DOMAIN_BLOCKED) |
| 1330 | + return NULL; |
| 1331 | + |
| 1332 | + dom = kzalloc(sizeof(*dom), GFP_KERNEL); |
| 1333 | + if (!dom) |
| 1334 | + return NULL; |
| 1335 | + |
| 1336 | + dom->ops = &spapr_tce_blocking_domain_ops; |
| 1337 | + |
| 1338 | + return dom; |
| 1339 | +} |
| 1340 | + |
| 1341 | +static struct iommu_device *spapr_tce_iommu_probe_device(struct device *dev) |
| 1342 | +{ |
| 1343 | + struct pci_dev *pdev; |
| 1344 | + struct pci_controller *hose; |
| 1345 | + |
| 1346 | + if (!dev_is_pci(dev)) |
| 1347 | + return ERR_PTR(-EPERM); |
| 1348 | + |
| 1349 | + pdev = to_pci_dev(dev); |
| 1350 | + hose = pdev->bus->sysdata; |
| 1351 | + |
| 1352 | + return &hose->iommu; |
| 1353 | +} |
| 1354 | + |
| 1355 | +static void spapr_tce_iommu_release_device(struct device *dev) |
| 1356 | +{ |
| 1357 | +} |
| 1358 | + |
| 1359 | +static struct iommu_group *spapr_tce_iommu_device_group(struct device *dev) |
| 1360 | +{ |
| 1361 | + struct pci_controller *hose; |
| 1362 | + struct pci_dev *pdev; |
| 1363 | + |
| 1364 | + pdev = to_pci_dev(dev); |
| 1365 | + hose = pdev->bus->sysdata; |
| 1366 | + |
| 1367 | + if (!hose->controller_ops.device_group) |
| 1368 | + return ERR_PTR(-ENOENT); |
| 1369 | + |
| 1370 | + return hose->controller_ops.device_group(hose, pdev); |
| 1371 | +} |
| 1372 | + |
| 1373 | +static const struct iommu_ops spapr_tce_iommu_ops = { |
| 1374 | + .capable = spapr_tce_iommu_capable, |
| 1375 | + .domain_alloc = spapr_tce_iommu_domain_alloc, |
| 1376 | + .probe_device = spapr_tce_iommu_probe_device, |
| 1377 | + .release_device = spapr_tce_iommu_release_device, |
| 1378 | + .device_group = spapr_tce_iommu_device_group, |
| 1379 | + .set_platform_dma_ops = spapr_tce_blocking_iommu_set_platform_dma, |
| 1380 | +}; |
| 1381 | + |
| 1382 | +static struct attribute *spapr_tce_iommu_attrs[] = { |
| 1383 | + NULL, |
| 1384 | +}; |
| 1385 | + |
| 1386 | +static struct attribute_group spapr_tce_iommu_group = { |
| 1387 | + .name = "spapr-tce-iommu", |
| 1388 | + .attrs = spapr_tce_iommu_attrs, |
| 1389 | +}; |
| 1390 | + |
| 1391 | +static const struct attribute_group *spapr_tce_iommu_groups[] = { |
| 1392 | + &spapr_tce_iommu_group, |
| 1393 | + NULL, |
| 1394 | +}; |
| 1395 | + |
| 1396 | +/* |
| 1397 | + * This registers IOMMU devices of PHBs. This needs to happen |
| 1398 | + * after core_initcall(iommu_init) + postcore_initcall(pci_driver_init) and |
| 1399 | + * before subsys_initcall(iommu_subsys_init). |
| 1400 | + */ |
| 1401 | +static int __init spapr_tce_setup_phb_iommus_initcall(void) |
| 1402 | +{ |
| 1403 | + struct pci_controller *hose; |
| 1404 | + |
| 1405 | + list_for_each_entry(hose, &hose_list, list_node) { |
| 1406 | + iommu_device_sysfs_add(&hose->iommu, hose->parent, |
| 1407 | + spapr_tce_iommu_groups, "iommu-phb%04x", |
| 1408 | + hose->global_number); |
| 1409 | + iommu_device_register(&hose->iommu, &spapr_tce_iommu_ops, |
| 1410 | + hose->parent); |
| 1411 | + } |
| 1412 | + return 0; |
| 1413 | +} |
| 1414 | +postcore_initcall_sync(spapr_tce_setup_phb_iommus_initcall); |
| 1415 | + |
1272 | 1416 | #endif /* CONFIG_IOMMU_API */ |
0 commit comments