On Fri, 8 Jan 2021 15:52:15 +0100
Jean-Philippe Brucker <[email protected]> wrote:

> When handling faults from the event or PRI queue, we need to find the
> struct device associated with a SID. Add a rb_tree to keep track of
> SIDs.
> 
> Signed-off-by: Jean-Philippe Brucker <[email protected]>
One totally trivial point if you happen to be spinning again.

Acked-by: Jonathan Cameron <[email protected]>
with or without that.

> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  13 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 161 ++++++++++++++++----
>  2 files changed, 144 insertions(+), 30 deletions(-)
> 

...

>  
> +static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
> +                               struct arm_smmu_master *master)
> +{
> +     int i;
> +     int ret = 0;
> +     struct arm_smmu_stream *new_stream, *cur_stream;
> +     struct rb_node **new_node, *parent_node = NULL;
> +     struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
> +
> +     master->streams = kcalloc(fwspec->num_ids,
> +                               sizeof(struct arm_smmu_stream), GFP_KERNEL);
                                  sizeof(*master->streams)

nitpick :) Saves reviewer going to check that master->streams is of the type 
they expect.


> +     if (!master->streams)
> +             return -ENOMEM;
> +     master->num_streams = fwspec->num_ids;
> +
> +     mutex_lock(&smmu->streams_mutex);
> +     for (i = 0; i < fwspec->num_ids && !ret; i++) {
> +             u32 sid = fwspec->ids[i];
> +
> +             new_stream = &master->streams[i];
> +             new_stream->id = sid;
> +             new_stream->master = master;
> +
> +             /*
> +              * Check the SIDs are in range of the SMMU and our stream table
> +              */
> +             if (!arm_smmu_sid_in_range(smmu, sid)) {
> +                     ret = -ERANGE;
> +                     break;
> +             }
> +
> +             /* Ensure l2 strtab is initialised */
> +             if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
> +                     ret = arm_smmu_init_l2_strtab(smmu, sid);
> +                     if (ret)
> +                             break;
> +             }
> +
> +             /* Insert into SID tree */
> +             new_node = &(smmu->streams.rb_node);
> +             while (*new_node) {
> +                     cur_stream = rb_entry(*new_node, struct arm_smmu_stream,
> +                                           node);
> +                     parent_node = *new_node;
> +                     if (cur_stream->id > new_stream->id) {
> +                             new_node = &((*new_node)->rb_left);
> +                     } else if (cur_stream->id < new_stream->id) {
> +                             new_node = &((*new_node)->rb_right);
> +                     } else {
> +                             dev_warn(master->dev,
> +                                      "stream %u already in tree\n",
> +                                      cur_stream->id);
> +                             ret = -EINVAL;
> +                             break;
> +                     }
> +             }
> +
> +             if (!ret) {
> +                     rb_link_node(&new_stream->node, parent_node, new_node);
> +                     rb_insert_color(&new_stream->node, &smmu->streams);
> +             }
> +     }
> +
> +     if (ret) {
> +             for (; i > 0; i--)
> +                     rb_erase(&master->streams[i].node, &smmu->streams);
> +             kfree(master->streams);
> +     }
> +     mutex_unlock(&smmu->streams_mutex);
> +
> +     return ret;
> +}
...
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to