Hi Zhanpeng,

On Tue, Jul 14, 2026 at 9:08 PM Zhanpeng Zhang
<[email protected]> wrote:
>
> Allow the resctrl devices file to accept iommu_group:<id> tokens on
> RISC-V and map the target resource group's closid and rmid values to
> RCID and MCID.
>
> Record non-default assignments in an RCU-protected binding list rather
> than inferring membership from hardware IDs, which may be shared. Keep a
> parent reference obtained by numeric group lookup so the binding does not
> keep an empty group's devices kobject active, and prune bindings after
> their group becomes inactive.
>
> Publish an explicit UPDATING state while hardware changes. Paging-domain
> attachment rejects that transient state. Static FSC=Bare transitions
> preserve the current IDs so a mandatory release-domain attachment cannot
> fail. After the checked group update succeeds, publish the packed IDs. A
> validation failure restores the previous active state without partially
> changing hardware.
>
> Moving an IOMMU group to the default resource group resets its hardware
> state and removes the software binding. Device contexts created later for
> an assigned group inherit the IDs through the RCU lookup path.
>
> Signed-off-by: Zhanpeng Zhang <[email protected]>
> ---
>  MAINTAINERS                   |   1 +
>  arch/riscv/include/asm/qos.h  |  12 ++
>  drivers/iommu/riscv/iommu.c   |  70 +++++++--
>  drivers/iommu/riscv/iommu.h   |  16 +-
>  drivers/resctrl/Kconfig       |   6 +
>  drivers/resctrl/Makefile      |   1 +
>  drivers/resctrl/cbqri_iommu.c | 276 ++++++++++++++++++++++++++++++++++
>  7 files changed, 369 insertions(+), 13 deletions(-)
>  create mode 100644 drivers/resctrl/cbqri_iommu.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c59be02c8f02..162ad5a1780f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -23288,6 +23288,7 @@ L:      [email protected]
>  L:     [email protected]
>  S:     Maintained
>  F:     Documentation/ABI/testing/sysfs-class-iommu-riscv-iommu
> +F:     drivers/resctrl/cbqri_iommu.c
>
>  RISC-V MICROCHIP SUPPORT
>  M:     Conor Dooley <[email protected]>
> diff --git a/arch/riscv/include/asm/qos.h b/arch/riscv/include/asm/qos.h
> index daa758d4efff..84a93739c6ff 100644
> --- a/arch/riscv/include/asm/qos.h
> +++ b/arch/riscv/include/asm/qos.h
> @@ -8,6 +8,18 @@
>
>  struct iommu_group;
>
> +#ifdef CONFIG_RISCV_CBQRI_IOMMU
> +int riscv_resctrl_iommu_group_get_qosid(struct iommu_group *group,
> +                                       u32 *rcid, u32 *mcid);
> +#else
> +static inline int
> +riscv_resctrl_iommu_group_get_qosid(struct iommu_group *group, u32 *rcid,
> +                                   u32 *mcid)
> +{
> +       return -ENOENT;
> +}
> +#endif
> +
>  #ifdef CONFIG_RISCV_IOMMU
>  int riscv_iommu_group_set_qosid(struct iommu_group *group, u32 rcid,
>                                 u32 mcid);
> diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
> index e85da9eef58e..1a7d8a582959 100644
> --- a/drivers/iommu/riscv/iommu.c
> +++ b/drivers/iommu/riscv/iommu.c
> @@ -1188,16 +1188,50 @@ static void riscv_iommu_iodir_iotinval(struct 
> riscv_iommu_device *iommu,
>   * device is not quiesced might be disruptive, potentially causing
>   * interim translation faults.
>   */
> -static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
> -                                    struct device *dev, u64 fsc, u64 ta)
> +static int riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
> +                                   struct device *dev, u64 fsc, u64 ta)
>  {
>         struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>         struct riscv_iommu_dc *dc;
>         struct riscv_iommu_command cmd;
>         bool sync_required = false;
> +       u64 group_qos_ta = 0;
> +       bool has_group_qos;
> +       u32 group_rcid;
> +       u32 group_mcid;
>         u64 tc;
> +       int ret = 0;
> +       int qos_ret;
>         int i;
>
> +       /* Serialize DC.ta updates with resctrl IOMMU group QoS changes. */
> +       mutex_lock(&iommu->qosid_lock);
> +
> +       qos_ret = riscv_resctrl_iommu_group_get_qosid(dev->iommu_group,
> +                                                     &group_rcid, 
> &group_mcid);
> +       if (qos_ret == -EAGAIN) {
> +               /* Static domain transitions must not fail during device 
> release. */
> +               if (fsc != RISCV_IOMMU_FSC_BARE) {
> +                       ret = -EBUSY;
> +                       goto unlock;
> +               }
> +               qos_ret = -ENOENT;
> +       }
> +       has_group_qos = !qos_ret;
> +       if (has_group_qos) {
> +               if (!(iommu->caps & RISCV_IOMMU_CAPABILITIES_QOSID) ||
> +                   iommu->ddt_mode <= RISCV_IOMMU_DDTP_IOMMU_MODE_BARE) {
> +                       ret = -EOPNOTSUPP;
> +                       goto unlock;
> +               }
> +               if (group_rcid > FIELD_MAX(RISCV_IOMMU_DC_TA_RCID) ||
> +                   group_mcid > FIELD_MAX(RISCV_IOMMU_DC_TA_MCID)) {
> +                       ret = -ERANGE;
> +                       goto unlock;
> +               }
> +               group_qos_ta = riscv_iommu_qosid_ta(group_rcid, group_mcid);
> +       }
> +
>         for (i = 0; i < fwspec->num_ids; i++) {
>                 dc = riscv_iommu_get_dc(iommu, fwspec->ids[i]);
>                 tc = READ_ONCE(dc->tc);
> @@ -1233,11 +1267,12 @@ static void riscv_iommu_iodir_update(struct 
> riscv_iommu_device *iommu,
>                 tc = READ_ONCE(dc->tc);
>                 dc_ta = ta;
>                 if (iommu->caps & RISCV_IOMMU_CAPABILITIES_QOSID) {
> -                       dc_ta |= READ_ONCE(dc->ta) &
> -                                (RISCV_IOMMU_DC_TA_RCID |
> -                                 RISCV_IOMMU_DC_TA_MCID);
> -                       ta_mask |= RISCV_IOMMU_DC_TA_RCID |
> -                                  RISCV_IOMMU_DC_TA_MCID;
> +                       if (has_group_qos)
> +                               dc_ta |= group_qos_ta;
> +                       else
> +                               dc_ta |= READ_ONCE(dc->ta) &
> +                                        RISCV_IOMMU_DC_TA_QOSID;
> +                       ta_mask |= RISCV_IOMMU_DC_TA_QOSID;
>                 }
>                 tc |= dc_ta & RISCV_IOMMU_DC_TC_V;
>
> @@ -1259,6 +1294,9 @@ static void riscv_iommu_iodir_update(struct 
> riscv_iommu_device *iommu,
>         }
>
>         riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
> +unlock:
> +       mutex_unlock(&iommu->qosid_lock);
> +       return ret;
>  }
>
>  /*
> @@ -1324,6 +1362,7 @@ static int riscv_iommu_attach_paging_domain(struct 
> iommu_domain *iommu_domain,
>         struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
>         struct pt_iommu_riscv_64_hw_info pt_info;
>         u64 fsc, ta;
> +       int ret;
>
>         pt_iommu_riscv_64_hw_info(&domain->riscvpt, &pt_info);
>
> @@ -1338,7 +1377,11 @@ static int riscv_iommu_attach_paging_domain(struct 
> iommu_domain *iommu_domain,
>         if (riscv_iommu_bond_link(domain, dev))
>                 return -ENOMEM;
>
> -       riscv_iommu_iodir_update(iommu, dev, fsc, ta);
> +       ret = riscv_iommu_iodir_update(iommu, dev, fsc, ta);
> +       if (ret) {
> +               riscv_iommu_bond_unlink(domain, dev);
> +               return ret;
> +       }
>         riscv_iommu_bond_unlink(info->domain, dev);
>         info->domain = domain;
>
> @@ -1413,9 +1456,12 @@ static int riscv_iommu_attach_blocking_domain(struct 
> iommu_domain *iommu_domain,
>  {
>         struct riscv_iommu_device *iommu = dev_to_iommu(dev);
>         struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
> +       int ret;
>
>         /* Make device context invalid, translation requests will fault w/ 
> #258 */
> -       riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, 0);
> +       ret = riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, 0);
> +       if (ret)
> +               return ret;
>         riscv_iommu_bond_unlink(info->domain, dev);
>         info->domain = NULL;
>
> @@ -1435,8 +1481,12 @@ static int riscv_iommu_attach_identity_domain(struct 
> iommu_domain *iommu_domain,
>  {
>         struct riscv_iommu_device *iommu = dev_to_iommu(dev);
>         struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
> +       u64 ta = RISCV_IOMMU_PC_TA_V;
> +       int ret;
>
> -       riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, 
> RISCV_IOMMU_PC_TA_V);
> +       ret = riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, ta);
> +       if (ret)
> +               return ret;
>         riscv_iommu_bond_unlink(info->domain, dev);
>         info->domain = NULL;
>
> diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h
> index 13ea67b7e42d..e7804ec65647 100644
> --- a/drivers/iommu/riscv/iommu.h
> +++ b/drivers/iommu/riscv/iommu.h
> @@ -11,13 +11,11 @@
>  #ifndef _RISCV_IOMMU_H_
>  #define _RISCV_IOMMU_H_
>
> +#include <linux/errno.h>
>  #include <linux/iommu.h>
>  #include <linux/iopoll.h>
>  #include <linux/mutex.h>
>  #include <linux/types.h>
> -#ifdef CONFIG_RISCV_IOMMU_32BIT
> -#include <linux/spinlock.h>
> -#endif
>
>  #include "iommu-bits.h"
>
> @@ -26,6 +24,18 @@ struct riscv_iommu_device;
>  int riscv_iommu_group_set_qosid(struct iommu_group *group, u32 rcid,
>                                 u32 mcid);
>
> +#ifdef CONFIG_RISCV_CBQRI_IOMMU
> +int riscv_resctrl_iommu_group_get_qosid(struct iommu_group *group,
> +                                       u32 *rcid, u32 *mcid);
> +#else
> +static inline int
> +riscv_resctrl_iommu_group_get_qosid(struct iommu_group *group, u32 *rcid,
> +                                   u32 *mcid)
> +{
> +       return -ENOENT;
> +}
> +#endif
> +
>  struct riscv_iommu_queue {
>         atomic_t prod;                          /* unbounded producer 
> allocation index */
>         atomic_t head;                          /* unbounded shadow ring 
> buffer consumer index */
> diff --git a/drivers/resctrl/Kconfig b/drivers/resctrl/Kconfig
> index b7db6ff9d054..4e10c813e647 100644
> --- a/drivers/resctrl/Kconfig
> +++ b/drivers/resctrl/Kconfig
> @@ -60,3 +60,9 @@ endif
>  config RISCV_CBQRI_RESCTRL_FS
>         bool
>         default y if RISCV_CBQRI && RESCTRL_FS
> +
> +config RISCV_CBQRI_IOMMU
> +       bool
> +       depends on RISCV_CBQRI_RESCTRL_FS && RISCV_IOMMU
> +       select ARCH_HAS_RESCTRL_DEVICES
> +       default y
> diff --git a/drivers/resctrl/Makefile b/drivers/resctrl/Makefile
> index c8339113ef1f..148b2e28c6a3 100644
> --- a/drivers/resctrl/Makefile
> +++ b/drivers/resctrl/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_RISCV_CBQRI)                       += cbqri.o
>  cbqri-y                                                += cbqri_devices.o
>  cbqri-$(CONFIG_RISCV_CBQRI_RESCTRL_FS)         += cbqri_resctrl.o
>  cbqri-$(CONFIG_RISCV_CBQRI_CAPACITY)           += cbqri_capacity.o
> +cbqri-$(CONFIG_RISCV_CBQRI_IOMMU)                      += cbqri_iommu.o
> diff --git a/drivers/resctrl/cbqri_iommu.c b/drivers/resctrl/cbqri_iommu.c
> new file mode 100644
> index 000000000000..4086c32546bd
> --- /dev/null
> +++ b/drivers/resctrl/cbqri_iommu.c
> @@ -0,0 +1,276 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <linux/capability.h>
> +#include <linux/errno.h>
> +#include <linux/iommu.h>
> +#include <linux/kernel.h>
> +#include <linux/limits.h>
> +#include <linux/list.h>
> +#include <linux/rculist.h>
> +#include <linux/rcupdate.h>
> +#include <linux/resctrl.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +
> +#include <asm/qos.h>
> +
> +#define IOMMU_GROUP_TOKEN      "iommu_group:"
> +
> +/*
> + * RISC-V IOMMU RCID and MCID fields are 12 bits each, so an active binding
> + * cannot contain U64_MAX.
> + */
> +#define QOS_IOMMU_BINDING_UPDATING     U64_MAX
> +
> +/* Records the resctrl QoS ID assignment for one IOMMU group. */
> +struct qos_iommu_group_binding {
> +       struct list_head node;
> +       struct rcu_head rcu;
> +       struct iommu_group *group;
> +       int group_id;
> +       /* Packed IDs, or QOS_IOMMU_BINDING_UPDATING during a hardware 
> update. */
> +       u64 state;
> +};
> +
> +/*
> + * resctrl owns IOMMU group membership bookkeeping. Do not infer membership 
> by
> + * reading RCID/MCID back from hardware: the same IDs may be shared by 
> multiple
> + * resctrl users. Writers are serialized by rdtgroup_mutex. IOMMU attach 
> paths
> + * read the list under RCU so newly attached devices can inherit an existing
> + * group assignment without taking locks in the opposite order to resctrl.
> + */
> +static LIST_HEAD(qos_iommu_bindings);
> +
> +static u64 qos_iommu_group_ids_pack(struct resctrl_group_ids ids)
> +{
> +       return (u64)ids.closid << 32 | ids.rmid;
> +}
> +
> +static struct resctrl_group_ids qos_iommu_group_ids_unpack(u64 ids)
> +{
> +       return (struct resctrl_group_ids) {
> +               .closid = upper_32_bits(ids),
> +               .rmid = lower_32_bits(ids),
> +       };
> +}
> +
> +static bool qos_iommu_group_ids_match(u64 packed, struct resctrl_group_ids 
> ids)
> +{
> +       return packed != QOS_IOMMU_BINDING_UPDATING &&
> +              packed == qos_iommu_group_ids_pack(ids);
> +}
> +
> +static bool qos_iommu_group_ids_default(struct resctrl_group_ids ids)
> +{
> +       return ids.closid == RESCTRL_RESERVED_CLOSID &&
> +              ids.rmid == RESCTRL_RESERVED_RMID;
> +}
> +
> +static struct qos_iommu_group_binding *
> +qos_iommu_group_find_binding(int group_id)
> +{
> +       struct qos_iommu_group_binding *binding;
> +
> +       list_for_each_entry(binding, &qos_iommu_bindings, node) {
> +               if (binding->group_id == group_id)
> +                       return binding;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void qos_iommu_group_free_binding(struct qos_iommu_group_binding 
> *binding)
> +{
> +       list_del_rcu(&binding->node);
> +       iommu_group_put_by_id(binding->group);
> +       kfree_rcu(binding, rcu);
> +}
> +
> +static void qos_iommu_group_prune_inactive(void)
> +{
> +       struct qos_iommu_group_binding *binding;
> +       struct qos_iommu_group_binding *tmp;
> +
> +       list_for_each_entry_safe(binding, tmp, &qos_iommu_bindings, node) {
> +               if (!iommu_group_is_active(binding->group))
> +                       qos_iommu_group_free_binding(binding);
> +       }
> +}
> +
> +static int qos_iommu_group_set(struct iommu_group *group,
> +                              struct resctrl_group_ids ids)
> +{
> +       /* RISC-V IOMMU QoS maps closid->rcid and rmid->mcid 1:1. */
> +       return riscv_iommu_group_set_qosid(group, ids.closid, ids.rmid);
> +}
> +
> +int resctrl_arch_devices_write(char *tok, struct resctrl_group_ids ids)
> +{
> +       struct qos_iommu_group_binding *binding;
> +       struct qos_iommu_group_binding *new_binding = NULL;
> +       struct iommu_group *group;
> +       u64 old_state = QOS_IOMMU_BINDING_UPDATING;
> +       bool default_ids;
> +       int group_id;
> +       int ret;
> +
> +       if (strncmp(tok, IOMMU_GROUP_TOKEN, strlen(IOMMU_GROUP_TOKEN))) {
> +               resctrl_last_cmd_printf("Unsupported device token %s\n", tok);
> +               return -EOPNOTSUPP;
> +       }
> +
> +       tok += strlen(IOMMU_GROUP_TOKEN);
> +       if (kstrtoint(tok, 10, &group_id) || group_id < 0) {
> +               resctrl_last_cmd_printf("IOMMU group parsing error %s%s\n",
> +                                       IOMMU_GROUP_TOKEN, tok);
> +               return -EINVAL;
> +       }
> +
> +       if (!capable(CAP_SYS_ADMIN)) {
> +               resctrl_last_cmd_puts("No permission to move IOMMU group\n");
> +               return -EPERM;
> +       }
> +
> +       default_ids = qos_iommu_group_ids_default(ids);
> +       qos_iommu_group_prune_inactive();
> +       binding = qos_iommu_group_find_binding(group_id);
> +       if (!binding) {
> +               group = iommu_group_get_by_id(group_id);
> +               if (!group) {
> +                       resctrl_last_cmd_printf("No IOMMU group %d\n", 
> group_id);
> +                       return -ENOENT;
> +               }
> +
> +               if (default_ids) {
> +                       ret = qos_iommu_group_set(group, ids);
> +                       iommu_group_put_by_id(group);
> +                       if (ret)
> +                               resctrl_last_cmd_printf("Failed to reset 
> IOMMU group %d QoS (%d)\n",
> +                                                       group_id, ret);
> +                       return ret;
> +               }
> +
> +               new_binding = kzalloc_obj(*new_binding, GFP_KERNEL);
> +               if (!new_binding) {
> +                       iommu_group_put_by_id(group);
> +                       resctrl_last_cmd_puts("Unable to allocate IOMMU group 
> QoS binding\n");
> +                       return -ENOMEM;
> +               }
> +               binding = new_binding;
> +               binding->group = group;
> +               binding->group_id = group_id;
> +               binding->state = QOS_IOMMU_BINDING_UPDATING;
> +               list_add_tail_rcu(&binding->node, &qos_iommu_bindings);
> +       } else {
> +               group = binding->group;
> +               old_state = READ_ONCE(binding->state);
> +               WRITE_ONCE(binding->state, QOS_IOMMU_BINDING_UPDATING);
> +       }

Could this make a concurrent paging-domain attachment fail
unnecessarily?

  resctrl_arch_devices_write()
iommu_attach_group()
  --------------------------------
--------------------------------

  WRITE_ONCE(binding->state,
             QOS_IOMMU_BINDING_UPDATING);


mutex_lock(&group->mutex);

__iommu_attach_group()

__iommu_group_set_domain()

__iommu_device_set_domain()

riscv_iommu_attach_paging_domain()

 riscv_iommu_iodir_update()

   riscv_resctrl_iommu_group_get_qosid()

     return -EAGAIN

   return -EBUSY

mutex_unlock(&group->mutex);

  qos_iommu_group_set()
    riscv_iommu_group_set_qosid()
      iommu_group_update_devices()
        mutex_lock(&group->mutex);
        riscv_iommu_qosid_validate_dev()
        riscv_iommu_qosid_apply_dev()
        mutex_unlock(&group->mutex);

Since QOS_IOMMU_BINDING_UPDATING is published before
iommu_group_update_devices() acquires group->mutex, the attachment can
acquire group->mutex first, but still fail with -EBUSY after observing
the transient state.

Should the binding state transition be serialized with the group update
under group->mutex instead?

Thanks,
Yunhui

> +
> +       ret = qos_iommu_group_set(group, ids);
> +       if (ret) {
> +               if (new_binding)
> +                       qos_iommu_group_free_binding(binding);
> +               else
> +                       WRITE_ONCE(binding->state, old_state);
> +               resctrl_last_cmd_printf("Failed to move IOMMU group %d QoS 
> (%d)\n",
> +                                       group_id, ret);
> +               return ret;
> +       }
> +
> +       if (default_ids)
> +               qos_iommu_group_free_binding(binding);
> +       else
> +               WRITE_ONCE(binding->state, qos_iommu_group_ids_pack(ids));
> +
> +       return 0;
> +}
> +
> +int riscv_resctrl_iommu_group_get_qosid(struct iommu_group *group, u32 *rcid,
> +                                       u32 *mcid)
> +{
> +       struct qos_iommu_group_binding *binding;
> +       int ret = -ENOENT;
> +
> +       if (!group)
> +               return -ENODEV;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(binding, &qos_iommu_bindings, node) {
> +               struct resctrl_group_ids ids;
> +               u64 state;
> +
> +               if (binding->group != group)
> +                       continue;
> +               state = READ_ONCE(binding->state);
> +               if (state == QOS_IOMMU_BINDING_UPDATING) {
> +                       ret = -EAGAIN;
> +                       break;
> +               }
> +
> +               ids = qos_iommu_group_ids_unpack(state);
> +               if (rcid)
> +                       *rcid = ids.closid;
> +               if (mcid)
> +                       *mcid = ids.rmid;
> +               ret = 0;
> +               break;
> +       }
> +       rcu_read_unlock();
> +
> +       return ret;
> +}
> +
> +void resctrl_arch_devices_show(struct seq_file *s, struct resctrl_group_ids 
> ids)
> +{
> +       struct qos_iommu_group_binding *binding;
> +
> +       qos_iommu_group_prune_inactive();
> +       list_for_each_entry(binding, &qos_iommu_bindings, node) {
> +               if (qos_iommu_group_ids_match(READ_ONCE(binding->state), ids))
> +                       seq_printf(s, "iommu_group:%d\n", binding->group_id);
> +       }
> +}
> +
> +bool resctrl_arch_devices_assigned(struct resctrl_group_ids ids)
> +{
> +       struct qos_iommu_group_binding *binding;
> +
> +       qos_iommu_group_prune_inactive();
> +       list_for_each_entry(binding, &qos_iommu_bindings, node) {
> +               if (qos_iommu_group_ids_match(READ_ONCE(binding->state), ids))
> +                       return true;
> +       }
> +
> +       return false;
> +}
> +
> +int resctrl_arch_devices_reset_all(struct resctrl_group_ids default_ids)
> +{
> +       struct qos_iommu_group_binding *binding;
> +       struct qos_iommu_group_binding *tmp;
> +       u64 old_state;
> +       int first_ret = 0;
> +       int ret;
> +
> +       qos_iommu_group_prune_inactive();
> +       list_for_each_entry_safe(binding, tmp, &qos_iommu_bindings, node) {
> +               old_state = READ_ONCE(binding->state);
> +               WRITE_ONCE(binding->state, QOS_IOMMU_BINDING_UPDATING);
> +               ret = qos_iommu_group_set(binding->group, default_ids);
> +               if (ret) {
> +                       WRITE_ONCE(binding->state, old_state);
> +                       if (!first_ret)
> +                               first_ret = ret;
> +                       resctrl_last_cmd_printf("Failed to reset IOMMU group 
> %d QoS (%d)\n",
> +                                               binding->group_id, ret);
> +                       continue;
> +               }
> +
> +               qos_iommu_group_free_binding(binding);
> +       }
> +
> +       return first_ret;
> +}
> --
> 2.50.1 (Apple Git-155)
>

Reply via email to