Re: [PATCH v2 03/13] powerpc/spapr: vfio: Implement spapr_tce_iommu_ops

2014-09-24 Thread Alexey Kardashevskiy
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

2014-09-24 Thread Alexey Kardashevskiy
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

2014-09-23 Thread Alex Williamson
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

2014-09-23 Thread Alex Williamson
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

2014-09-22 Thread Alexey Kardashevskiy
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

2014-09-22 Thread Alexey Kardashevskiy
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