Skip to content

Commit c4e9d3c

Browse files
aikmpe
authored andcommitted
powerpc/powernv/pseries: Rework device adding to IOMMU groups
The powernv platform registers IOMMU groups and adds devices to them from the pci_controller_ops::setup_bridge() hook except one case when virtual functions (SRIOV VFs) are added from a bus notifier. The pseries platform registers IOMMU groups from the pci_controller_ops::dma_bus_setup() hook and adds devices from the pci_controller_ops::dma_dev_setup() hook. The very same bus notifier used for powernv does not add devices for pseries though as __of_scan_bus() adds devices first, then it does the bus/dev DMA setup. Both platforms use iommu_add_device() which takes a device and expects it to have a valid IOMMU table struct with an iommu_table_group pointer which in turn points the iommu_group struct (which represents an IOMMU group). Although the helper seems easy to use, it relies on some pre-existing device configuration and associated data structures which it does not really need. This simplifies iommu_add_device() to take the table_group pointer directly. Pseries already has a table_group pointer handy and the bus notified is not used anyway. For powernv, this copies the existing bus notifier, makes it work for powernv only which means an easy way of getting to the table_group pointer. This was tested on VFs but should also support physical PCI hotplug. Since iommu_add_device() receives the table_group pointer directly, pseries does not do TCE cache invalidation (the hypervisor does) nor allow multiple groups per a VFIO container (in other words sharing an IOMMU table between partitionable endpoints), this removes iommu_table_group_link from pseries. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent c409c63 commit c4e9d3c

File tree

5 files changed

+74
-95
lines changed

5 files changed

+74
-95
lines changed

arch/powerpc/include/asm/iommu.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ struct iommu_table_group {
215215

216216
extern void iommu_register_group(struct iommu_table_group *table_group,
217217
int pci_domain_number, unsigned long pe_num);
218-
extern int iommu_add_device(struct device *dev);
218+
extern int iommu_add_device(struct iommu_table_group *table_group,
219+
struct device *dev);
219220
extern void iommu_del_device(struct device *dev);
220-
extern int __init tce_iommu_bus_notifier_init(void);
221221
extern long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,
222222
unsigned long entry, unsigned long *hpa,
223223
enum dma_data_direction *direction);
@@ -228,19 +228,15 @@ static inline void iommu_register_group(struct iommu_table_group *table_group,
228228
{
229229
}
230230

231-
static inline int iommu_add_device(struct device *dev)
231+
static inline int iommu_add_device(struct iommu_table_group *table_group,
232+
struct device *dev)
232233
{
233234
return 0;
234235
}
235236

236237
static inline void iommu_del_device(struct device *dev)
237238
{
238239
}
239-
240-
static inline int __init tce_iommu_bus_notifier_init(void)
241-
{
242-
return 0;
243-
}
244240
#endif /* !CONFIG_IOMMU_API */
245241

246242
int dma_iommu_mapping_error(struct device *dev, dma_addr_t dma_addr);

arch/powerpc/kernel/iommu.c

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,11 +1078,8 @@ void iommu_release_ownership(struct iommu_table *tbl)
10781078
}
10791079
EXPORT_SYMBOL_GPL(iommu_release_ownership);
10801080

1081-
int iommu_add_device(struct device *dev)
1081+
int iommu_add_device(struct iommu_table_group *table_group, struct device *dev)
10821082
{
1083-
struct iommu_table *tbl;
1084-
struct iommu_table_group_link *tgl;
1085-
10861083
/*
10871084
* The sysfs entries should be populated before
10881085
* binding IOMMU group. If sysfs entries isn't
@@ -1098,32 +1095,10 @@ int iommu_add_device(struct device *dev)
10981095
return -EBUSY;
10991096
}
11001097

1101-
tbl = get_iommu_table_base(dev);
1102-
if (!tbl) {
1103-
pr_debug("%s: Skipping device %s with no tbl\n",
1104-
__func__, dev_name(dev));
1105-
return 0;
1106-
}
1107-
1108-
tgl = list_first_entry_or_null(&tbl->it_group_list,
1109-
struct iommu_table_group_link, next);
1110-
if (!tgl) {
1111-
pr_debug("%s: Skipping device %s with no group\n",
1112-
__func__, dev_name(dev));
1113-
return 0;
1114-
}
11151098
pr_debug("%s: Adding %s to iommu group %d\n",
1116-
__func__, dev_name(dev),
1117-
iommu_group_id(tgl->table_group->group));
1118-
1119-
if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
1120-
pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n",
1121-
__func__, IOMMU_PAGE_SIZE(tbl),
1122-
PAGE_SIZE, dev_name(dev));
1123-
return -EINVAL;
1124-
}
1099+
__func__, dev_name(dev), iommu_group_id(table_group->group));
11251100

1126-
return iommu_group_add_device(tgl->table_group->group, dev);
1101+
return iommu_group_add_device(table_group->group, dev);
11271102
}
11281103
EXPORT_SYMBOL_GPL(iommu_add_device);
11291104

@@ -1143,31 +1118,4 @@ void iommu_del_device(struct device *dev)
11431118
iommu_group_remove_device(dev);
11441119
}
11451120
EXPORT_SYMBOL_GPL(iommu_del_device);
1146-
1147-
static int tce_iommu_bus_notifier(struct notifier_block *nb,
1148-
unsigned long action, void *data)
1149-
{
1150-
struct device *dev = data;
1151-
1152-
switch (action) {
1153-
case BUS_NOTIFY_ADD_DEVICE:
1154-
return iommu_add_device(dev);
1155-
case BUS_NOTIFY_DEL_DEVICE:
1156-
if (dev->iommu_group)
1157-
iommu_del_device(dev);
1158-
return 0;
1159-
default:
1160-
return 0;
1161-
}
1162-
}
1163-
1164-
static struct notifier_block tce_iommu_bus_nb = {
1165-
.notifier_call = tce_iommu_bus_notifier,
1166-
};
1167-
1168-
int __init tce_iommu_bus_notifier_init(void)
1169-
{
1170-
bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
1171-
return 0;
1172-
}
11731121
#endif /* CONFIG_IOMMU_API */

arch/powerpc/platforms/powernv/pci-ioda.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,7 +1935,7 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
19351935
set_iommu_table_base(&dev->dev, pe->table_group.tables[0]);
19361936
set_dma_offset(&dev->dev, pe->tce_bypass_base);
19371937
if (add_to_group)
1938-
iommu_add_device(&dev->dev);
1938+
iommu_add_device(&pe->table_group, &dev->dev);
19391939

19401940
if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
19411941
pnv_ioda_setup_bus_dma(pe, dev->subordinate,
@@ -2521,14 +2521,6 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
25212521
if (!pnv_iommu_bypass_disabled)
25222522
pnv_pci_ioda2_set_bypass(pe, true);
25232523

2524-
/*
2525-
* Setting table base here only for carrying iommu_group
2526-
* further down to let iommu_add_device() do the job.
2527-
* pnv_pci_ioda_dma_dev_setup will override it later anyway.
2528-
*/
2529-
if (pe->flags & PNV_IODA_PE_DEV)
2530-
set_iommu_table_base(&pe->pdev->dev, tbl);
2531-
25322524
return 0;
25332525
}
25342526

arch/powerpc/platforms/powernv/pci.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,4 +1125,45 @@ void __init pnv_pci_init(void)
11251125
set_pci_dma_ops(&dma_iommu_ops);
11261126
}
11271127

1128-
machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init);
1128+
static int pnv_tce_iommu_bus_notifier(struct notifier_block *nb,
1129+
unsigned long action, void *data)
1130+
{
1131+
struct device *dev = data;
1132+
struct pci_dev *pdev;
1133+
struct pci_dn *pdn;
1134+
struct pnv_ioda_pe *pe;
1135+
struct pci_controller *hose;
1136+
struct pnv_phb *phb;
1137+
1138+
switch (action) {
1139+
case BUS_NOTIFY_ADD_DEVICE:
1140+
pdev = to_pci_dev(dev);
1141+
pdn = pci_get_pdn(pdev);
1142+
hose = pci_bus_to_host(pdev->bus);
1143+
phb = hose->private_data;
1144+
1145+
WARN_ON_ONCE(!phb);
1146+
if (!pdn || pdn->pe_number == IODA_INVALID_PE || !phb)
1147+
return 0;
1148+
1149+
pe = &phb->ioda.pe_array[pdn->pe_number];
1150+
iommu_add_device(&pe->table_group, dev);
1151+
return 0;
1152+
case BUS_NOTIFY_DEL_DEVICE:
1153+
iommu_del_device(dev);
1154+
return 0;
1155+
default:
1156+
return 0;
1157+
}
1158+
}
1159+
1160+
static struct notifier_block pnv_tce_iommu_bus_nb = {
1161+
.notifier_call = pnv_tce_iommu_bus_notifier,
1162+
};
1163+
1164+
static int __init pnv_tce_iommu_bus_notifier_init(void)
1165+
{
1166+
bus_register_notifier(&pci_bus_type, &pnv_tce_iommu_bus_nb);
1167+
return 0;
1168+
}
1169+
machine_subsys_initcall_sync(powernv, pnv_tce_iommu_bus_notifier_init);

arch/powerpc/platforms/pseries/iommu.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node)
5757
{
5858
struct iommu_table_group *table_group;
5959
struct iommu_table *tbl;
60-
struct iommu_table_group_link *tgl;
6160

6261
table_group = kzalloc_node(sizeof(struct iommu_table_group), GFP_KERNEL,
6362
node);
@@ -68,22 +67,13 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node)
6867
if (!tbl)
6968
goto free_group;
7069

71-
tgl = kzalloc_node(sizeof(struct iommu_table_group_link), GFP_KERNEL,
72-
node);
73-
if (!tgl)
74-
goto free_table;
75-
7670
INIT_LIST_HEAD_RCU(&tbl->it_group_list);
7771
kref_init(&tbl->it_kref);
78-
tgl->table_group = table_group;
79-
list_add_rcu(&tgl->next, &tbl->it_group_list);
8072

8173
table_group->tables[0] = tbl;
8274

8375
return table_group;
8476

85-
free_table:
86-
kfree(tbl);
8777
free_group:
8878
kfree(table_group);
8979
return NULL;
@@ -93,23 +83,12 @@ static void iommu_pseries_free_group(struct iommu_table_group *table_group,
9383
const char *node_name)
9484
{
9585
struct iommu_table *tbl;
96-
#ifdef CONFIG_IOMMU_API
97-
struct iommu_table_group_link *tgl;
98-
#endif
9986

10087
if (!table_group)
10188
return;
10289

10390
tbl = table_group->tables[0];
10491
#ifdef CONFIG_IOMMU_API
105-
tgl = list_first_entry_or_null(&tbl->it_group_list,
106-
struct iommu_table_group_link, next);
107-
108-
WARN_ON_ONCE(!tgl);
109-
if (tgl) {
110-
list_del_rcu(&tgl->next);
111-
kfree(tgl);
112-
}
11392
if (table_group->group) {
11493
iommu_group_put(table_group->group);
11594
BUG_ON(table_group->group);
@@ -1216,7 +1195,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
12161195
}
12171196

12181197
set_iommu_table_base(&dev->dev, pci->table_group->tables[0]);
1219-
iommu_add_device(&dev->dev);
1198+
iommu_add_device(pci->table_group, &dev->dev);
12201199
}
12211200

12221201
static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
@@ -1421,4 +1400,27 @@ static int __init disable_multitce(char *str)
14211400

14221401
__setup("multitce=", disable_multitce);
14231402

1403+
static int tce_iommu_bus_notifier(struct notifier_block *nb,
1404+
unsigned long action, void *data)
1405+
{
1406+
struct device *dev = data;
1407+
1408+
switch (action) {
1409+
case BUS_NOTIFY_DEL_DEVICE:
1410+
iommu_del_device(dev);
1411+
return 0;
1412+
default:
1413+
return 0;
1414+
}
1415+
}
1416+
1417+
static struct notifier_block tce_iommu_bus_nb = {
1418+
.notifier_call = tce_iommu_bus_notifier,
1419+
};
1420+
1421+
static int __init tce_iommu_bus_notifier_init(void)
1422+
{
1423+
bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
1424+
return 0;
1425+
}
14241426
machine_subsys_initcall_sync(pseries, tce_iommu_bus_notifier_init);

0 commit comments

Comments
 (0)