Re: [PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
On 09/24/2014 06:42 AM, Alex Williamson wrote: > On Tue, 2014-09-23 at 13:00 +1000, Alexey Kardashevskiy wrote: >> Modern IBM POWERPC systems support multiple IOMMU tables per PE >> so we need a more reliable way (compared to container_of()) to get >> a PE pointer from the iommu_table struct pointer used in IOMMU functions. >> >> At the moment IOMMU group data points to an iommu_table struct. This >> introduces a spapr_tce_iommu_group struct which keeps an iommu_owner >> and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to >> the pnv_ioda_pe struct, for others it is still a pointer to >> the iommu_table struct. The ops structs correspond to the type which >> iommu_owner points to. >> >> This defines a get_table() callback which returns an iommu_table >> by its number. >> >> As the IOMMU group data pointer points to variable type instead of >> iommu_table, VFIO SPAPR TCE driver is updated to use the new type. >> This changes the tce_container struct to store iommu_group instead of >> iommu_table. >> >> So, it was: >> - iommu_table points to iommu_group via iommu_table::it_group; >> - iommu_group points to iommu_table via iommu_group_get_iommudata(); >> >> now it is: >> - iommu_table points to iommu_group via iommu_table::it_group; >> - iommu_group points to spapr_tce_iommu_group via >> iommu_group_get_iommudata(); >> - spapr_tce_iommu_group points to either (depending on .get_table()): >> - iommu_table; >> - pnv_ioda_pe; >> >> This uses pnv_ioda1_iommu_get_table for both IODA1&2 but IODA2 will >> have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table >> will only be used for IODA1. >> >> Signed-off-by: Alexey Kardashevskiy >> --- >> arch/powerpc/include/asm/iommu.h| 6 ++ >> arch/powerpc/include/asm/tce.h | 13 +++ >> arch/powerpc/kernel/iommu.c | 35 ++- >> arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- >> arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + >> arch/powerpc/platforms/powernv/pci.c| 2 +- >> arch/powerpc/platforms/pseries/iommu.c | 10 +- >> drivers/vfio/vfio_iommu_spapr_tce.c | 148 >> ++-- >> 8 files changed, 208 insertions(+), 38 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/iommu.h >> b/arch/powerpc/include/asm/iommu.h >> index 42632c7..84ee339 100644 >> --- a/arch/powerpc/include/asm/iommu.h >> +++ b/arch/powerpc/include/asm/iommu.h >> @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, >> const char *node_name); >> */ >> extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, >> int nid); >> + >> +struct spapr_tce_iommu_ops; >> #ifdef CONFIG_IOMMU_API >> extern void iommu_register_group(struct iommu_table *tbl, >> + void *iommu_owner, >> + struct spapr_tce_iommu_ops *ops, >> int pci_domain_number, unsigned long pe_num); >> extern int iommu_add_device(struct device *dev); >> extern void iommu_del_device(struct device *dev); >> #else >> static inline void iommu_register_group(struct iommu_table *tbl, >> +void *iommu_owner, >> +struct spapr_tce_iommu_ops *ops, >> int pci_domain_number, >> unsigned long pe_num) >> { >> diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h >> index 743f36b..9f159eb 100644 >> --- a/arch/powerpc/include/asm/tce.h >> +++ b/arch/powerpc/include/asm/tce.h >> @@ -50,5 +50,18 @@ >> #define TCE_PCI_READ0x1 /* read from PCI >> allowed */ >> #define TCE_VB_WRITE0x1 /* write from VB >> allowed */ >> >> +struct spapr_tce_iommu_group; >> + >> +struct spapr_tce_iommu_ops { >> +struct iommu_table *(*get_table)( >> +struct spapr_tce_iommu_group *data, >> +int num); >> +}; >> + >> +struct spapr_tce_iommu_group { >> +void *iommu_owner; >> +struct spapr_tce_iommu_ops *ops; >> +}; >> + >> #endif /* __KERNEL__ */ >> #endif /* _ASM_POWERPC_TCE_H */ >> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c >> index b378f78..1c5dae7 100644 >> --- a/arch/powerpc/kernel/iommu.c >> +++ b/arch/powerpc/kernel/iommu.c >> @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, >> size_t size, >> */ >> static void group_release(void *iommu_data) >> { >> -struct iommu_table *tbl = iommu_data; >> -tbl->it_group = NULL; >> +kfree(iommu_data); >> } >> >> +static struct iommu_table *spapr_tce_default_get_table( >> +struct spapr_tce_iommu_group *data, int num) >> +{ >> +struct iommu_table *tbl = data->iommu_owner; >> + >> +switch (num) { >> +case 0: >> +if (tbl->it_size) >> +
Re: [PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
On 09/24/2014 06:42 AM, Alex Williamson wrote: On Tue, 2014-09-23 at 13:00 +1000, Alexey Kardashevskiy wrote: Modern IBM POWERPC systems support multiple IOMMU tables per PE so we need a more reliable way (compared to container_of()) to get a PE pointer from the iommu_table struct pointer used in IOMMU functions. At the moment IOMMU group data points to an iommu_table struct. This introduces a spapr_tce_iommu_group struct which keeps an iommu_owner and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to the pnv_ioda_pe struct, for others it is still a pointer to the iommu_table struct. The ops structs correspond to the type which iommu_owner points to. This defines a get_table() callback which returns an iommu_table by its number. As the IOMMU group data pointer points to variable type instead of iommu_table, VFIO SPAPR TCE driver is updated to use the new type. This changes the tce_container struct to store iommu_group instead of iommu_table. So, it was: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to iommu_table via iommu_group_get_iommudata(); now it is: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to spapr_tce_iommu_group via iommu_group_get_iommudata(); - spapr_tce_iommu_group points to either (depending on .get_table()): - iommu_table; - pnv_ioda_pe; This uses pnv_ioda1_iommu_get_table for both IODA12 but IODA2 will have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table will only be used for IODA1. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- arch/powerpc/include/asm/iommu.h| 6 ++ arch/powerpc/include/asm/tce.h | 13 +++ arch/powerpc/kernel/iommu.c | 35 ++- arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + arch/powerpc/platforms/powernv/pci.c| 2 +- arch/powerpc/platforms/pseries/iommu.c | 10 +- drivers/vfio/vfio_iommu_spapr_tce.c | 148 ++-- 8 files changed, 208 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 42632c7..84ee339 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); */ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, int nid); + +struct spapr_tce_iommu_ops; #ifdef CONFIG_IOMMU_API extern void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, + struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num); extern int iommu_add_device(struct device *dev); extern void iommu_del_device(struct device *dev); #else static inline void iommu_register_group(struct iommu_table *tbl, +void *iommu_owner, +struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num) { diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h index 743f36b..9f159eb 100644 --- a/arch/powerpc/include/asm/tce.h +++ b/arch/powerpc/include/asm/tce.h @@ -50,5 +50,18 @@ #define TCE_PCI_READ0x1 /* read from PCI allowed */ #define TCE_VB_WRITE0x1 /* write from VB allowed */ +struct spapr_tce_iommu_group; + +struct spapr_tce_iommu_ops { +struct iommu_table *(*get_table)( +struct spapr_tce_iommu_group *data, +int num); +}; + +struct spapr_tce_iommu_group { +void *iommu_owner; +struct spapr_tce_iommu_ops *ops; +}; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TCE_H */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b378f78..1c5dae7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, */ static void group_release(void *iommu_data) { -struct iommu_table *tbl = iommu_data; -tbl-it_group = NULL; +kfree(iommu_data); } +static struct iommu_table *spapr_tce_default_get_table( +struct spapr_tce_iommu_group *data, int num) +{ +struct iommu_table *tbl = data-iommu_owner; + +switch (num) { +case 0: +if (tbl-it_size) +return tbl; +/* fallthru */ +default: +return NULL; +} +} + +static struct spapr_tce_iommu_ops spapr_tce_default_ops = { +.get_table = spapr_tce_default_get_table +}; + void
Re: [PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
On Tue, 2014-09-23 at 13:00 +1000, Alexey Kardashevskiy wrote: > Modern IBM POWERPC systems support multiple IOMMU tables per PE > so we need a more reliable way (compared to container_of()) to get > a PE pointer from the iommu_table struct pointer used in IOMMU functions. > > At the moment IOMMU group data points to an iommu_table struct. This > introduces a spapr_tce_iommu_group struct which keeps an iommu_owner > and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to > the pnv_ioda_pe struct, for others it is still a pointer to > the iommu_table struct. The ops structs correspond to the type which > iommu_owner points to. > > This defines a get_table() callback which returns an iommu_table > by its number. > > As the IOMMU group data pointer points to variable type instead of > iommu_table, VFIO SPAPR TCE driver is updated to use the new type. > This changes the tce_container struct to store iommu_group instead of > iommu_table. > > So, it was: > - iommu_table points to iommu_group via iommu_table::it_group; > - iommu_group points to iommu_table via iommu_group_get_iommudata(); > > now it is: > - iommu_table points to iommu_group via iommu_table::it_group; > - iommu_group points to spapr_tce_iommu_group via > iommu_group_get_iommudata(); > - spapr_tce_iommu_group points to either (depending on .get_table()): > - iommu_table; > - pnv_ioda_pe; > > This uses pnv_ioda1_iommu_get_table for both IODA1&2 but IODA2 will > have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table > will only be used for IODA1. > > Signed-off-by: Alexey Kardashevskiy > --- > arch/powerpc/include/asm/iommu.h| 6 ++ > arch/powerpc/include/asm/tce.h | 13 +++ > arch/powerpc/kernel/iommu.c | 35 ++- > arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- > arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + > arch/powerpc/platforms/powernv/pci.c| 2 +- > arch/powerpc/platforms/pseries/iommu.c | 10 +- > drivers/vfio/vfio_iommu_spapr_tce.c | 148 > ++-- > 8 files changed, 208 insertions(+), 38 deletions(-) > > diff --git a/arch/powerpc/include/asm/iommu.h > b/arch/powerpc/include/asm/iommu.h > index 42632c7..84ee339 100644 > --- a/arch/powerpc/include/asm/iommu.h > +++ b/arch/powerpc/include/asm/iommu.h > @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, > const char *node_name); > */ > extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, > int nid); > + > +struct spapr_tce_iommu_ops; > #ifdef CONFIG_IOMMU_API > extern void iommu_register_group(struct iommu_table *tbl, > + void *iommu_owner, > + struct spapr_tce_iommu_ops *ops, >int pci_domain_number, unsigned long pe_num); > extern int iommu_add_device(struct device *dev); > extern void iommu_del_device(struct device *dev); > #else > static inline void iommu_register_group(struct iommu_table *tbl, > + void *iommu_owner, > + struct spapr_tce_iommu_ops *ops, > int pci_domain_number, > unsigned long pe_num) > { > diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h > index 743f36b..9f159eb 100644 > --- a/arch/powerpc/include/asm/tce.h > +++ b/arch/powerpc/include/asm/tce.h > @@ -50,5 +50,18 @@ > #define TCE_PCI_READ 0x1 /* read from PCI allowed */ > #define TCE_VB_WRITE 0x1 /* write from VB allowed */ > > +struct spapr_tce_iommu_group; > + > +struct spapr_tce_iommu_ops { > + struct iommu_table *(*get_table)( > + struct spapr_tce_iommu_group *data, > + int num); > +}; > + > +struct spapr_tce_iommu_group { > + void *iommu_owner; > + struct spapr_tce_iommu_ops *ops; > +}; > + > #endif /* __KERNEL__ */ > #endif /* _ASM_POWERPC_TCE_H */ > diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c > index b378f78..1c5dae7 100644 > --- a/arch/powerpc/kernel/iommu.c > +++ b/arch/powerpc/kernel/iommu.c > @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, > size_t size, > */ > static void group_release(void *iommu_data) > { > - struct iommu_table *tbl = iommu_data; > - tbl->it_group = NULL; > + kfree(iommu_data); > } > > +static struct iommu_table *spapr_tce_default_get_table( > + struct spapr_tce_iommu_group *data, int num) > +{ > + struct iommu_table *tbl = data->iommu_owner; > + > + switch (num) { > + case 0: > + if (tbl->it_size) > + return tbl; > + /* fallthru */ > + default: > + return NULL; > + } > +} > + > +static struct spapr_tce_iommu_ops
Re: [PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
On Tue, 2014-09-23 at 13:00 +1000, Alexey Kardashevskiy wrote: Modern IBM POWERPC systems support multiple IOMMU tables per PE so we need a more reliable way (compared to container_of()) to get a PE pointer from the iommu_table struct pointer used in IOMMU functions. At the moment IOMMU group data points to an iommu_table struct. This introduces a spapr_tce_iommu_group struct which keeps an iommu_owner and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to the pnv_ioda_pe struct, for others it is still a pointer to the iommu_table struct. The ops structs correspond to the type which iommu_owner points to. This defines a get_table() callback which returns an iommu_table by its number. As the IOMMU group data pointer points to variable type instead of iommu_table, VFIO SPAPR TCE driver is updated to use the new type. This changes the tce_container struct to store iommu_group instead of iommu_table. So, it was: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to iommu_table via iommu_group_get_iommudata(); now it is: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to spapr_tce_iommu_group via iommu_group_get_iommudata(); - spapr_tce_iommu_group points to either (depending on .get_table()): - iommu_table; - pnv_ioda_pe; This uses pnv_ioda1_iommu_get_table for both IODA12 but IODA2 will have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table will only be used for IODA1. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- arch/powerpc/include/asm/iommu.h| 6 ++ arch/powerpc/include/asm/tce.h | 13 +++ arch/powerpc/kernel/iommu.c | 35 ++- arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + arch/powerpc/platforms/powernv/pci.c| 2 +- arch/powerpc/platforms/pseries/iommu.c | 10 +- drivers/vfio/vfio_iommu_spapr_tce.c | 148 ++-- 8 files changed, 208 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 42632c7..84ee339 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); */ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, int nid); + +struct spapr_tce_iommu_ops; #ifdef CONFIG_IOMMU_API extern void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, + struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num); extern int iommu_add_device(struct device *dev); extern void iommu_del_device(struct device *dev); #else static inline void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, + struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num) { diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h index 743f36b..9f159eb 100644 --- a/arch/powerpc/include/asm/tce.h +++ b/arch/powerpc/include/asm/tce.h @@ -50,5 +50,18 @@ #define TCE_PCI_READ 0x1 /* read from PCI allowed */ #define TCE_VB_WRITE 0x1 /* write from VB allowed */ +struct spapr_tce_iommu_group; + +struct spapr_tce_iommu_ops { + struct iommu_table *(*get_table)( + struct spapr_tce_iommu_group *data, + int num); +}; + +struct spapr_tce_iommu_group { + void *iommu_owner; + struct spapr_tce_iommu_ops *ops; +}; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TCE_H */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b378f78..1c5dae7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, */ static void group_release(void *iommu_data) { - struct iommu_table *tbl = iommu_data; - tbl-it_group = NULL; + kfree(iommu_data); } +static struct iommu_table *spapr_tce_default_get_table( + struct spapr_tce_iommu_group *data, int num) +{ + struct iommu_table *tbl = data-iommu_owner; + + switch (num) { + case 0: + if (tbl-it_size) + return tbl; + /* fallthru */ + default: + return NULL; + } +} + +static struct spapr_tce_iommu_ops spapr_tce_default_ops = { + .get_table = spapr_tce_default_get_table +}; + void iommu_register_group(struct
[PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
Modern IBM POWERPC systems support multiple IOMMU tables per PE so we need a more reliable way (compared to container_of()) to get a PE pointer from the iommu_table struct pointer used in IOMMU functions. At the moment IOMMU group data points to an iommu_table struct. This introduces a spapr_tce_iommu_group struct which keeps an iommu_owner and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to the pnv_ioda_pe struct, for others it is still a pointer to the iommu_table struct. The ops structs correspond to the type which iommu_owner points to. This defines a get_table() callback which returns an iommu_table by its number. As the IOMMU group data pointer points to variable type instead of iommu_table, VFIO SPAPR TCE driver is updated to use the new type. This changes the tce_container struct to store iommu_group instead of iommu_table. So, it was: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to iommu_table via iommu_group_get_iommudata(); now it is: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to spapr_tce_iommu_group via iommu_group_get_iommudata(); - spapr_tce_iommu_group points to either (depending on .get_table()): - iommu_table; - pnv_ioda_pe; This uses pnv_ioda1_iommu_get_table for both IODA1&2 but IODA2 will have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table will only be used for IODA1. Signed-off-by: Alexey Kardashevskiy --- arch/powerpc/include/asm/iommu.h| 6 ++ arch/powerpc/include/asm/tce.h | 13 +++ arch/powerpc/kernel/iommu.c | 35 ++- arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + arch/powerpc/platforms/powernv/pci.c| 2 +- arch/powerpc/platforms/pseries/iommu.c | 10 +- drivers/vfio/vfio_iommu_spapr_tce.c | 148 ++-- 8 files changed, 208 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 42632c7..84ee339 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); */ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, int nid); + +struct spapr_tce_iommu_ops; #ifdef CONFIG_IOMMU_API extern void iommu_register_group(struct iommu_table *tbl, +void *iommu_owner, +struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num); extern int iommu_add_device(struct device *dev); extern void iommu_del_device(struct device *dev); #else static inline void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, + struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num) { diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h index 743f36b..9f159eb 100644 --- a/arch/powerpc/include/asm/tce.h +++ b/arch/powerpc/include/asm/tce.h @@ -50,5 +50,18 @@ #define TCE_PCI_READ 0x1 /* read from PCI allowed */ #define TCE_VB_WRITE 0x1 /* write from VB allowed */ +struct spapr_tce_iommu_group; + +struct spapr_tce_iommu_ops { + struct iommu_table *(*get_table)( + struct spapr_tce_iommu_group *data, + int num); +}; + +struct spapr_tce_iommu_group { + void *iommu_owner; + struct spapr_tce_iommu_ops *ops; +}; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TCE_H */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b378f78..1c5dae7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, */ static void group_release(void *iommu_data) { - struct iommu_table *tbl = iommu_data; - tbl->it_group = NULL; + kfree(iommu_data); } +static struct iommu_table *spapr_tce_default_get_table( + struct spapr_tce_iommu_group *data, int num) +{ + struct iommu_table *tbl = data->iommu_owner; + + switch (num) { + case 0: + if (tbl->it_size) + return tbl; + /* fallthru */ + default: + return NULL; + } +} + +static struct spapr_tce_iommu_ops spapr_tce_default_ops = { + .get_table = spapr_tce_default_get_table +}; + void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num) {
[PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops
Modern IBM POWERPC systems support multiple IOMMU tables per PE so we need a more reliable way (compared to container_of()) to get a PE pointer from the iommu_table struct pointer used in IOMMU functions. At the moment IOMMU group data points to an iommu_table struct. This introduces a spapr_tce_iommu_group struct which keeps an iommu_owner and a spapr_tce_iommu_ops struct. For IODA, iommu_owner is a pointer to the pnv_ioda_pe struct, for others it is still a pointer to the iommu_table struct. The ops structs correspond to the type which iommu_owner points to. This defines a get_table() callback which returns an iommu_table by its number. As the IOMMU group data pointer points to variable type instead of iommu_table, VFIO SPAPR TCE driver is updated to use the new type. This changes the tce_container struct to store iommu_group instead of iommu_table. So, it was: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to iommu_table via iommu_group_get_iommudata(); now it is: - iommu_table points to iommu_group via iommu_table::it_group; - iommu_group points to spapr_tce_iommu_group via iommu_group_get_iommudata(); - spapr_tce_iommu_group points to either (depending on .get_table()): - iommu_table; - pnv_ioda_pe; This uses pnv_ioda1_iommu_get_table for both IODA12 but IODA2 will have own pnv_ioda2_iommu_get_table soon and pnv_ioda1_iommu_get_table will only be used for IODA1. Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- arch/powerpc/include/asm/iommu.h| 6 ++ arch/powerpc/include/asm/tce.h | 13 +++ arch/powerpc/kernel/iommu.c | 35 ++- arch/powerpc/platforms/powernv/pci-ioda.c | 31 +- arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 + arch/powerpc/platforms/powernv/pci.c| 2 +- arch/powerpc/platforms/pseries/iommu.c | 10 +- drivers/vfio/vfio_iommu_spapr_tce.c | 148 ++-- 8 files changed, 208 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 42632c7..84ee339 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -108,13 +108,19 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); */ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, int nid); + +struct spapr_tce_iommu_ops; #ifdef CONFIG_IOMMU_API extern void iommu_register_group(struct iommu_table *tbl, +void *iommu_owner, +struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num); extern int iommu_add_device(struct device *dev); extern void iommu_del_device(struct device *dev); #else static inline void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, + struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long pe_num) { diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h index 743f36b..9f159eb 100644 --- a/arch/powerpc/include/asm/tce.h +++ b/arch/powerpc/include/asm/tce.h @@ -50,5 +50,18 @@ #define TCE_PCI_READ 0x1 /* read from PCI allowed */ #define TCE_VB_WRITE 0x1 /* write from VB allowed */ +struct spapr_tce_iommu_group; + +struct spapr_tce_iommu_ops { + struct iommu_table *(*get_table)( + struct spapr_tce_iommu_group *data, + int num); +}; + +struct spapr_tce_iommu_group { + void *iommu_owner; + struct spapr_tce_iommu_ops *ops; +}; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TCE_H */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index b378f78..1c5dae7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -878,24 +878,53 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, */ static void group_release(void *iommu_data) { - struct iommu_table *tbl = iommu_data; - tbl-it_group = NULL; + kfree(iommu_data); } +static struct iommu_table *spapr_tce_default_get_table( + struct spapr_tce_iommu_group *data, int num) +{ + struct iommu_table *tbl = data-iommu_owner; + + switch (num) { + case 0: + if (tbl-it_size) + return tbl; + /* fallthru */ + default: + return NULL; + } +} + +static struct spapr_tce_iommu_ops spapr_tce_default_ops = { + .get_table = spapr_tce_default_get_table +}; + void iommu_register_group(struct iommu_table *tbl, + void *iommu_owner, struct spapr_tce_iommu_ops *ops, int pci_domain_number, unsigned long