Gaurav Batra <[email protected]> writes:

Thanks for the v2 patch. My review comments below:

General comment. I see some issues in the patch that checkpatch would
have flagged. Can you please also ensure that there are no checkpatch
related warning before you send the patch

Optional comment:
Please split the patch into 2 , moving the DOC changes into separate
patch.

> Export PowerPC DMA window information (both default 2GB and Dynamic
> larger window) to user space via sysfs. Each of these DMA windows has
> attributes like size of the window, page size backing the window, mode,
> etc. Each of these atributes is exported for user space consumption as a
> file.
>
> PowerPC Host Bridge (PHB) can have multiple devices/functions sharing
> the same DMA window. For each PHB, iommu registration creates an iommu
> device under "/sys/devices/virtual/iommu".
>
> These devices will have 2 groups created to export Default and DDW
> attributes.
>
> Reviewed-by: Brian King <[email protected]>
> Reviewed-by: Vaibhav Jain <[email protected]>

Thanks for incorporating my review comments from the previous
iteration. However I dont remember reviewing the v2 of this patch
before. Can you please avoid presumptively adding my R-b until I have a
chance to review the patch.

> Reviewed-by: Shivaprasad G Bhat <[email protected]>
> Signed-off-by: Gaurav Batra <[email protected]>
> ---
> V1 -> V2 change log:
>
> 1. Shiva: "weight" the it_map for the bitmap. This avoids using an extra
>    counter in the table. Please look into how iommu_debugfs_weight_get()
>    does this
>
>    Response: Incorporated changes
>
> 2. Vaibhav: If the DMA window is not available, show function should just
>    return ENOENT so that userspace know the error instantly instead of
>    having to parse the sysfs contents.
>
>    Response: Incorporated changes, returning ENODATA
>
> 3. Vaibhav: All the show functions have similar template. Please convert
>    them to macros expansion to reduce code volume.
>
>    Response: Incorporated changes
>
> 4. Vaibhav: These new attributes are PSeries specific but they are being
>    setup in ppc generic iommu code at arch/powerpc/kernel/iommu.c. Can
>    you move these attributes to arch/powerpc/platforms/pseries/iommu.c
>
>    Response: I have split the attributes and moved them to pseries specific
>    files. The original group "spapr-tce-iommu", is moved to PowerNV code
>    base to retain the legacy functionality.
>
>    I tested the changes both on Pseries and PowerNV.
>
> 5. Vaibhav: It would be better to use function iommu_table_inuse_tces() as
>    a callback in iommu_table_ops which can be implemented by pseries and
>    powernv code differently.
>
>    Response: the function is no longer needed after changes in #1
>
> 6. Vaibhav: Since sysfs is ABI can you propose appropriate entries under
>    Documentation/ABI/testing
>
>    Response: Added documentation
>
>  ...sfs-devices-virtual-iommu-dma_window_attrs |  21 ++
>  .../arch/powerpc/dma_window_attributes.rst    |  65 +++++
>  arch/powerpc/include/asm/pci-bridge.h         |   4 +
>  arch/powerpc/kernel/iommu.c                   |  16 +-
>  arch/powerpc/platforms/powernv/pci-ioda.c     |  16 ++
>  arch/powerpc/platforms/pseries/iommu.c        | 261 ++++++++++++++++++
>  arch/powerpc/platforms/pseries/pci_dlpar.c    |   2 +
>  arch/powerpc/platforms/pseries/pseries.h      |   1 +
>  arch/powerpc/platforms/pseries/setup.c        |   2 +
>  9 files changed, 373 insertions(+), 15 deletions(-)
>  create mode 100644 
> Documentation/ABI/testing/sysfs-devices-virtual-iommu-dma_window_attrs
>  create mode 100644 Documentation/arch/powerpc/dma_window_attributes.rst
>
> diff --git 
> a/Documentation/ABI/testing/sysfs-devices-virtual-iommu-dma_window_attrs 
> b/Documentation/ABI/testing/sysfs-devices-virtual-iommu-dma_window_attrs
> new file mode 100644
> index 000000000000..18ba63874276
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-devices-virtual-iommu-dma_window_attrs
> @@ -0,0 +1,21 @@
> +What:
> /sys/devices/virtual/iommu/<iommu-isolation>/spapr-tce-ddw/*
Suggested:
s/iommu-isolation/iommu-group/
> +Date:       Oct 2025
> +Contact:    [email protected]
> +Description:    read only
> +    For each IOMMU isolation unit spapr-tce-ddw sub-directory provides
> +    attributes to query information related to the bigger Dynamic DMA
> +    window (DDW) in the PowerPC virtualized platforms.
> +
> +    See Documentation/arch/powerpc/dma_window_attributes.rst for more
> +    information.
> +
> +What:       /sys/devices/virtual/iommu/<iommu-isolation>/spapr-tce-dma/*
> +Date:       Oct 2025
> +Contact:    [email protected]
> +Description:    read only
> +    For each IOMMU isolation unit spapr-tce-dma sub-directory provides
> +    attributes to query information related to the default 2GB DMA
> +    window in the PowerPC virtualized platforms.
> +
> +    See Documentation/arch/powerpc/dma_window_attributes.rst for more
> +    information.
sysfs ABI documentation typically describes all the attribute files rather
then directory. Please add details of the individual attributes that you
are adding here.

> diff --git a/Documentation/arch/powerpc/dma_window_attributes.rst 
> b/Documentation/arch/powerpc/dma_window_attributes.rst
> new file mode 100644
> index 000000000000..8bd9aec8539d
> --- /dev/null
> +++ b/Documentation/arch/powerpc/dma_window_attributes.rst
> @@ -0,0 +1,65 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=====================
> +DMA Window Attributes
> +=====================
> +
> +In PowerPC architecture there are 2 types of DMA windows -
> +
This is only true for PPC64-PSeries not for PPC64-PowerNV

> +1. Default 2GB DMA window which is backed by 4K page size
> +2. A bigger Dynamic DMA Window (DDW) which is backed by larger page size
> +   (64K or 2MB)
> +
> +A dedicated device will have both the DMA windows instantiated but an SR-IOV
> +device will only have the bigger Dynamic DMA Window.
In context of PSeries please give some context abt 'dedicated device'

> +
> +The attributes of these 2 DMA windows are exported to user space via sysfs.
> +Each IOMMU isolation unit will have its directory created under
> +/sys/devices/virtual/iommu.
> +
> +As an exapmple, iommu-phb0001
> +
> +Under each IOMMU isolation unit, there will be a group of attributes for
> +"Default 2GB DMA Window" and "Dynamic DMA Window" - spapr-tce-dma and
> +spapr-tce-ddw respectively.
> +
> +Attributes under each group
> +
> +spapr-tce-ddw:
> +direct_address  dynamic_address       dynamic_size  window_type
> +direct_size     dynamic_pages_mapped  page_size
> +
> +spapr-tce-dma:
> +dynamic_address  dynamic_pages_mapped  dynamic_size  page_size
> +
> +
> +The bigger Dynamic DMA Window is configured into pre-mapped and/or 
> dynamically
> +allocated TCEs. If the DDW is in "Hybrid" mode, then both the Direct
> +(pre-mapped) and Dynamic part of the DMA window will have valid values. 
> Hybrid
> +mode is valid only for SR-IOV devices.
> +
> +DMA Window properties:
> +
> +direct_address              Starting address of the pre-mapped DMA window
> +direct_size                 Size of the pre-mapped DMA Window
> +dynamic_address             Starting address of the dynamic allocations
> +dynamic_size                Size of the dynamic allocation window
> +dynamic_pages_mapped        Pages mapped for DMA by dynamic allocations
> +page_size                   Page size backing the DMA window
> +window_type                 Type of the DMA Window (Direct/Dynamic/Hybrid)
> +

these attributes should also be documented in the sysfs/ABI 

> +
> +An example of DDW attributes for an SR-IOV device::
> +
> +    $ cd /sys/devices/virtual/iommu/iommu-phb0001/spapr-tce-ddw
> +
> +    $ grep . *
> +
> +    direct_address:0x800000000000000   <-- Starting addr of pre-mapped Window
> +    direct_size:137438953472           <-- Size of pre-mapped Window (128GB)
> +    dynamic_address:0x800002000000000  <-- Starting addr of Dynamic 
> allocations
> +    dynamic_size:412316860416          <-- Size of dynamic allocation window 
> (384GB)
> +    dynamic_pages_mapped:270           <-- Pages mapped by dynamic 
> allocations
> +    page_size:2097152                  <-- DMA window page size (2MB)
> +    window_type:Hybrid                 <-- window has both pre-mapped and
> +                                           dynamic sections
Suggested:
This documentation can be improved by moving details on sysfs attrs and
adding details on how 2 different types of DMA windows are allocated and 
managed.

> diff --git a/arch/powerpc/include/asm/pci-bridge.h 
> b/arch/powerpc/include/asm/pci-bridge.h
> index 1dae53130782..9b09178aca5e 100644
> --- a/arch/powerpc/include/asm/pci-bridge.h
> +++ b/arch/powerpc/include/asm/pci-bridge.h
> @@ -124,6 +124,10 @@ struct pci_controller {
>       resource_size_t dma_window_base_cur;
>       resource_size_t dma_window_size;
>  
> +#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
> +     const struct attribute_group **iommu_groups;
> +#endif
Ideally addition of new members to a struct should be done at the end
to preserve KABI.
Naming issue: s/iommu_groups/iommu_group_attrs/

> +
>  #ifdef CONFIG_PPC64
>       unsigned long buid;
>       struct pci_dn *pci_data;
> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
> index 0ce71310b7d9..d6242e3f77da 100644
> --- a/arch/powerpc/kernel/iommu.c
> +++ b/arch/powerpc/kernel/iommu.c
> @@ -1269,24 +1269,10 @@ static const struct iommu_ops spapr_tce_iommu_ops = {
>       .device_group = spapr_tce_iommu_device_group,
>  };
>


> -static struct attribute *spapr_tce_iommu_attrs[] = {
> -     NULL,
> -};
> -
> -static struct attribute_group spapr_tce_iommu_group = {
> -     .name = "spapr-tce-iommu",
> -     .attrs = spapr_tce_iommu_attrs,
> -};
> -
> -static const struct attribute_group *spapr_tce_iommu_groups[] = {
> -     &spapr_tce_iommu_group,
> -     NULL,
> -};
> -
>  void ppc_iommu_register_device(struct pci_controller *phb)
>  {
>       iommu_device_sysfs_add(&phb->iommu, phb->parent,
> -                             spapr_tce_iommu_groups, "iommu-phb%04x",
> +                             phb->iommu_groups, "iommu-phb%04x",
>                               phb->global_number);
>       iommu_device_register(&phb->iommu, &spapr_tce_iommu_ops,
>                               phb->parent);
Since you are changing this code, can you check for NULL
phb->iommu_groups and also check for returned errors from these two
functions().
In case phb->iommu_groups == NULL you can ignore registering sysfs. That
will take care of POWERNV case.

> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
> b/arch/powerpc/platforms/powernv/pci-ioda.c
> index 1c78fdfb7b03..0887f154955e 100644
> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
> @@ -2493,6 +2493,20 @@ static const struct pci_controller_ops 
> pnv_npu_ocapi_ioda_controller_ops = {
>       .shutdown               = pnv_pci_ioda_shutdown,
>  };
>  
> +static struct attribute *pnv_tce_iommu_attrs[] = {
> +     NULL,
> +};
> +
> +static struct attribute_group pnv_tce_iommu_group = {
> +     .name = "spapr-tce-iommu",
> +     .attrs = pnv_tce_iommu_attrs,
> +};
> +
> +static const struct attribute_group *pnv_tce_iommu_groups[] = {
> +     &pnv_tce_iommu_group,
> +     NULL,
> +};
> +
>  static void __init pnv_pci_init_ioda_phb(struct device_node *np,
>                                        u64 hub_id, int ioda_type)
>  {
> @@ -2697,6 +2711,8 @@ static void __init pnv_pci_init_ioda_phb(struct 
> device_node *np,
>               hose->controller_ops = pnv_pci_ioda_controller_ops;
>       }
>  
> +     hose->iommu_groups = pnv_tce_iommu_groups;
> +
See the previous comment for optimization. This  proposed hunk can be
removed.

>       ppc_md.pcibios_default_alignment = pnv_pci_default_alignment;
>  
>  #ifdef CONFIG_PCI_IOV
> diff --git a/arch/powerpc/platforms/pseries/iommu.c 
> b/arch/powerpc/platforms/pseries/iommu.c
> index 5497b130e026..28be7a45761d 100644
> --- a/arch/powerpc/platforms/pseries/iommu.c
> +++ b/arch/powerpc/platforms/pseries/iommu.c
> @@ -56,6 +56,20 @@ enum {
>       DDW_EXT_LIMITED_ADDR_MODE = 3
>  };
>  
> +/* used by sysfs when querying Dynamic/Default DMA Window data */
> +struct dma_win_data {
> +     u32     page_size;
> +     u64     direct_address;
> +     u64     direct_size;
> +     u64     dynamic_address;
> +     u64     dynamic_size;
> +     u32     dynamic_pages_mapped;
> +     char    window_type[15];
Why do you need to hold a string representation of the window_type. Can
this be replaced by an enum that holds much smaller space.

> +};
> +
> +#define SPAPR_SUCCESS                0
> +#define SPAPR_ERROR                  -1

Returning 0 or -1 are common and well known return values from kernel
functions and as such you need not create seperate macros for them.

Also Indentation looks strange.
> +
>  static struct iommu_table *iommu_pseries_alloc_table(int node)
>  {
>       struct iommu_table *tbl;
> @@ -837,6 +851,253 @@ static struct device_node *pci_dma_find(struct 
> device_node *dn,
>       return rdn;
>  }
>  
> +/* Get DDW information for the device */
> +static int gather_ddw_info(struct device *dev, struct dma_win_data *data)
> +{
> +     struct iommu_device *iommu;
> +     struct pci_controller *phb;
> +     struct device_node *dn;
> +     struct pci_dn *pci;
> +     const __be32 *prop = NULL;
> +     bool ddw_direct = false;
> +     bool found = false;
> +     struct iommu_table *tbl;
> +     u32 pgshift;
> +     struct dynamic_dma_window_prop *p;
> +
> +     memset(data, 0, sizeof(*data));
> +
> +     iommu = dev_get_drvdata(dev);
> +     phb = container_of(iommu, struct pci_controller, iommu);
> +     dn = phb->dn;
> +
> +     if (!dn)
> +             return SPAPR_ERROR;
> +
> +     pci = PCI_DN(dn);
> +     if (!pci || !pci->table_group)
> +             return SPAPR_ERROR;
> +
> +     /* Find DDW */
> +     prop = of_get_property(dn, DIRECT64_PROPNAME, NULL);
> +     if (prop) {
> +             ddw_direct = true;
> +             found = true;
> +     } else {
> +             prop = of_get_property(dn, DMA64_PROPNAME, NULL);
> +             if (prop)
> +                     found = true;
> +     }
> +
> +     /* NO DDW */
> +     if (!found)
> +             return SPAPR_ERROR;
> +
> +     p = (struct dynamic_dma_window_prop *)prop;
> +
> +     pgshift = be32_to_cpu(p->tce_shift);
> +     if (pgshift != 0xc && pgshift != 0x10 && pgshift != 0x15)
> +             data->page_size = 0;
> +     else
> +             data->page_size = 1 << pgshift;
> +
> +     /* Check if DDW has table associated with it. Having a table associated 
> with
> +      * DDW is indicative that is has some dynamic TCE allocations. In this 
> case the
> +      * DDW can be fully Dynamic or in Hybrid mode. For SR-IOV DDW is on 
> index 0,
> +      * for dedicated adapter on index 1.
> +      */
> +     found = false;
> +     for (int i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
Variable Naming: avoid 'i' . Also please hoist the loop variable
> +             tbl = pci->table_group->tables[i];
> +
> +             if (tbl && tbl->it_index == be32_to_cpu(p->liobn)) {
> +                     found = true;
> +                     break;
> +             }
> +     }
> +
> +     /* set the parameters depnding on the DDW type */
> +     if (ddw_direct && found) {          /* Hybrid */
> +             data->direct_address = be64_to_cpu(p->dma_base);
> +             data->dynamic_size = (u64)(tbl->it_size <<
> tbl->it_page_shift);
May want to check for possible overflow

> +
> +             data->dynamic_address = data->direct_address
> +                                                             + (u64)(1UL << 
> be32_to_cpu(p->window_shift))
> +                                                             -
> data->dynamic_size;
May want to check for possible overflow


> +
> +             data->direct_size = data->dynamic_address - 
> data->direct_address;
> +             data->dynamic_pages_mapped = bitmap_weight(tbl->it_map, 
> tbl->it_size);
> +
> +             sprintf(data->window_type, "%s", "Hybrid");
> +     } else if (ddw_direct && !found) {    /* Direct */
> +             data->direct_address = be64_to_cpu(p->dma_base);
> +             data->direct_size = (u64)(1UL << be32_to_cpu(p->window_shift));
> +
> +             sprintf(data->window_type, "%s", "Direct");
> +     } else {                              /* Dynamic */
> +             data->dynamic_address = be64_to_cpu(p->dma_base);
> +             data->dynamic_size = (u64)(1UL << be32_to_cpu(p->window_shift));
> +             data->dynamic_pages_mapped = bitmap_weight(tbl->it_map, 
> tbl->it_size);
> +
> +             sprintf(data->window_type, "%s", "Dynamic");
> +     }
> +
> +     return SPAPR_SUCCESS;
> +}
> +
> +/* Get DDW information for the device */
> +static int gather_dma_info(struct device *dev, struct dma_win_data *data)
> +{
> +     struct iommu_device *iommu;
> +     struct pci_controller *phb;
> +     struct device_node *dn;
> +     struct pci_dn *pci;
> +     const __be32 *prop = NULL;
> +     struct iommu_table *tbl;
> +     unsigned long offset, size, liobn;
> +
> +     memset(data, 0, sizeof(*data));
> +
> +     iommu = dev_get_drvdata(dev);
> +     phb = container_of(iommu, struct pci_controller, iommu);
> +     dn = phb->dn;
> +
> +     if (!dn)
> +             return SPAPR_ERROR;
> +
> +     pci = PCI_DN(dn);
> +     if (!pci || !pci->table_group)
> +             return SPAPR_ERROR;
> +
> +     /* search for default DMA window */
> +     prop = of_get_property(dn, "ibm,dma-window", NULL);
> +
> +     if (!prop)
> +             return SPAPR_ERROR;
> +
> +     /* default DMA Window is always at index 0 */
> +     tbl = pci->table_group->tables[0];
> +     if (!tbl)
> +             return SPAPR_ERROR;
> +
> +     of_parse_dma_window(dn, prop, &liobn, &offset, &size);
> +
> +     data->dynamic_address = offset;
> +     data->dynamic_size = size;
> +     data->page_size = 1ULL << IOMMU_PAGE_SHIFT_4K;
> +     data->dynamic_pages_mapped = bitmap_weight(tbl->it_map, tbl->it_size);
> +
> +     return SPAPR_SUCCESS;
> +}
> +
> +#define DEVICE_SHOW_DDW(_name, _fmt)                                         
>         \
> +ssize_t ddw_##_name##_show(struct device *dev,                               
>         \
> +                                                               struct 
> device_attribute *attr,\
> +                                                               char *buf)    
>                                 \
> +{                                                                            
>                                                 \
> +     int rc = 0;                                                             
>                                         \
> +     struct dma_win_data data;                                               
>                         \
> +                                                                             
>                                                 \
> +     rc = gather_ddw_info(dev, &data);                                       
>                 \
> +                                                                             
>                                                 \
> +     if (rc == SPAPR_SUCCESS)                                                
>                         \
> +             return sysfs_emit(buf, _fmt, data._name);                       
>         \
> +     else                                                                    
>                                         \
> +             return -ENODATA;                                                
>                                 \
> +}                                                                            
>                                                 \
All the device tree data that gather_{ddw dma}_info() collects except
bitmap_weight is static in nature and need not be refreshed at each call
to xx_show(). This can be optimized.

> +
> +#define DEVICE_SHOW_DMA(_name, _fmt)                                         
>         \
> +ssize_t dma_##_name##_show(struct device *dev,                               
>         \
> +                                                               struct 
> device_attribute *attr,\
> +                                                               char *buf)    
>                                 \
> +{                                                                            
>                                                 \
> +     int rc = 0;                                                             
>                                         \
> +     struct dma_win_data data;                                               
>                         \
> +                                                                             
>                                                 \
> +     rc = gather_dma_info(dev, &data);                                       
>                 \
> +                                                                             
>                                                 \
> +     if (rc == SPAPR_SUCCESS)                                                
>                         \
> +             return sysfs_emit(buf, _fmt, data._name);                       
>         \
> +     else                                                                    
>                                         \
> +             return -ENODATA;                                                
>                                 \
> +}                                                                            
>                                                 \
> +

Indentation looks strange.
Also can you just return the 'rc' from gather_{ddw dma}_info back from
xx_show rather then ENODATA

> +static DEVICE_SHOW_DDW(direct_address, "%#llx\n");
> +static DEVICE_SHOW_DDW(direct_size, "%lld\n");
> +static DEVICE_SHOW_DDW(page_size, "%d\n");
> +static DEVICE_SHOW_DDW(window_type, "%s\n");
> +static DEVICE_SHOW_DDW(dynamic_address, "%#llx\n");
> +static DEVICE_SHOW_DDW(dynamic_size, "%lld\n");
> +static DEVICE_SHOW_DDW(dynamic_pages_mapped, "%d\n");
> +static DEVICE_SHOW_DMA(dynamic_address, "%#llx\n");
> +static DEVICE_SHOW_DMA(dynamic_size, "%lld\n");
> +static DEVICE_SHOW_DMA(page_size, "%d\n");
> +static DEVICE_SHOW_DMA(dynamic_pages_mapped, "%d\n");
Avoid putting '\n's at the end of strings. Makes parsing contents
tricky.

> +
> +#define DEVICE_ATTR_DDW(_name)                              \
> +             struct device_attribute dev_attr_ddw_##_name =      \
> +                     __ATTR(_name, 0444, ddw_##_name##_show, NULL)
> +#define DEVICE_ATTR_DMA(_name)                              \
> +             struct device_attribute dev_attr_dma_##_name =      \
> +             __ATTR(_name, 0444, dma_##_name##_show, NULL)
> +
> +static DEVICE_ATTR_DDW(direct_address);
> +static DEVICE_ATTR_DDW(direct_size);
> +static DEVICE_ATTR_DDW(page_size);
> +static DEVICE_ATTR_DDW(window_type);
> +static DEVICE_ATTR_DDW(dynamic_address);
> +static DEVICE_ATTR_DDW(dynamic_size);
> +static DEVICE_ATTR_DDW(dynamic_pages_mapped);
> +static DEVICE_ATTR_DMA(dynamic_address);
> +static DEVICE_ATTR_DMA(dynamic_size);
> +static DEVICE_ATTR_DMA(page_size);
> +static DEVICE_ATTR_DMA(dynamic_pages_mapped);
> +
> +static struct attribute *spapr_tce_ddw_attrs[] = {
> +     &dev_attr_ddw_direct_address.attr,
> +     &dev_attr_ddw_direct_size.attr,
> +     &dev_attr_ddw_page_size.attr,
> +     &dev_attr_ddw_window_type.attr,
> +     &dev_attr_ddw_dynamic_address.attr,
> +     &dev_attr_ddw_dynamic_size.attr,
> +     &dev_attr_ddw_dynamic_pages_mapped.attr,
> +     NULL,
> +};
> +
> +static struct attribute *spapr_tce_dma_attrs[] = {
> +     &dev_attr_dma_dynamic_address.attr,
> +     &dev_attr_dma_dynamic_size.attr,
> +     &dev_attr_dma_page_size.attr,
> +     &dev_attr_dma_dynamic_pages_mapped.attr,
> +     NULL,
> +};
> +
> +static struct attribute_group spapr_tce_ddw_group = {
> +     .name = "spapr-tce-ddw",
> +     .attrs = spapr_tce_ddw_attrs,
> +};
> +
> +static struct attribute_group spapr_tce_dma_group = {
> +     .name = "spapr-tce-dma",
> +     .attrs = spapr_tce_dma_attrs,
> +};
> +
> +static struct attribute *spapr_tce_iommu_attrs[] = {
> +     NULL,
> +};
> +
> +static struct attribute_group spapr_tce_iommu_group = {
> +     .name = "spapr-tce-iommu",
> +     .attrs = spapr_tce_iommu_attrs,
> +};
> +
> +const struct attribute_group *spapr_tce_iommu_groups[] = {
> +     &spapr_tce_iommu_group,
> +     &spapr_tce_ddw_group,
> +     &spapr_tce_dma_group,
> +     NULL,
> +};
> +
>  static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
>  {
>       struct iommu_table *tbl;
> diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c 
> b/arch/powerpc/platforms/pseries/pci_dlpar.c
> index 8c77ec7980de..b457451a2814 100644
> --- a/arch/powerpc/platforms/pseries/pci_dlpar.c
> +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
> @@ -45,6 +45,8 @@ struct pci_controller *init_phb_dynamic(struct device_node 
> *dn)
>       pci_process_bridge_OF_ranges(phb, dn, 0);
>       phb->controller_ops = pseries_pci_controller_ops;
>  
> +     phb->iommu_groups = spapr_tce_iommu_groups;
> +
>       pci_devs_phb_init_dynamic(phb);
>  
>       pseries_msi_allocate_domains(phb);
> diff --git a/arch/powerpc/platforms/pseries/pseries.h 
> b/arch/powerpc/platforms/pseries/pseries.h
> index 3968a6970fa8..4cf0b7a4e96a 100644
> --- a/arch/powerpc/platforms/pseries/pseries.h
> +++ b/arch/powerpc/platforms/pseries/pseries.h
> @@ -128,4 +128,5 @@ struct iommu_group *pSeries_pci_device_group(struct 
> pci_controller *hose,
>                                            struct pci_dev *pdev);
>  #endif
>  
> +extern const struct attribute_group *spapr_tce_iommu_groups[];
>  #endif /* _PSERIES_PSERIES_H */
> diff --git a/arch/powerpc/platforms/pseries/setup.c 
> b/arch/powerpc/platforms/pseries/setup.c
> index 50b26ed8432d..4d877aae0560 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -512,6 +512,8 @@ static void __init pSeries_discover_phbs(void)
>               isa_bridge_find_early(phb);
>               phb->controller_ops = pseries_pci_controller_ops;
>  
> +             phb->iommu_groups = spapr_tce_iommu_groups;
> +
>               /* create pci_dn's for DT nodes under this PHB */
>               pci_devs_phb_init_dynamic(phb);
>  
> base-commit: 192c0159402e6bfbe13de6f8379546943297783d
> -- 
> 2.39.3
>

-- 
Cheers
~ Vaibhav

Reply via email to