[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 1/2] xen: devicetree: Introduce a helper to translate PCI requester ID



On Fri, 30 Jun 2017, Wei Chen wrote:
> Each PCI(e) device under a root complex is uniquely identified by its
> Requester ID (AKA RID). A Requester ID is a triplet of a Bus number,
> Device number, and Function number. IOMMUs may distinguish PCI devices
> through sideband data derived from the Requester ID. While a given PCI
> device can only master through one IOMMU, a root complex may split
> masters across a set of IOMMUs.
> 
> The generic 'iommus' property is using to describe this relationship.
> This helper will be used to parse and map PCI Requester ID to IOMMU
> match ID in later patches.
> 
> This patch is based on Linux of_pci.c:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/of/of_pci.c
> The commit id is: 987068fcbdb7a085bb11151b91dc6f4c956c4a1b
> 
> Signed-off-by: Wei Chen <Wei.Chen@xxxxxxx>
> ---
>  xen/common/device_tree.c      | 89 
> +++++++++++++++++++++++++++++++++++++++++++
>  xen/include/xen/device_tree.h | 23 +++++++++++
>  2 files changed, 112 insertions(+)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 7b009ea..bf95cda 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -1663,6 +1663,95 @@ int dt_parse_phandle_with_args(const struct 
> dt_device_node *np,
>                                          index, out_args);
>  }
>  
> +#define pr_err(fmt, ...) printk(XENLOG_ERR fmt, ## __VA_ARGS__)
> +#define pr_info(fmt, ...) printk(XENLOG_INFO fmt, ## __VA_ARGS__)
> +#define pr_debug(fmt, ...) printk(XENLOG_DEBUG fmt, ## __VA_ARGS__)

I wouldn't define pr_* in device_tree.c just for this function. I would
use printk(XENLOG_* directly and dt_dprintk.


> +int dt_pci_map_rid(struct dt_device_node *np, u32 rid,
> +           const char *map_name, const char *map_mask_name,
> +           struct dt_device_node **target, u32 *id_out)
> +{
> +    u32 map_mask, masked_rid, map_len;
> +    const __be32 *map = NULL;
> +
> +    if ( !np || !map_name || (!target && !id_out) )
> +        return -EINVAL;
> +
> +    map = dt_get_property(np, map_name, &map_len);
> +    if ( !map )
> +    {
> +        if (target)

if ( target )


> +            return -ENODEV;
> +        /* Otherwise, no map implies no translation */
> +        *id_out = rid;
> +        return 0;
> +    }
> +
> +    if ( !map_len || map_len % (4 * sizeof(*map)) )
> +    {
> +        pr_err("%s: Error: Bad %s length: %d\n", np->full_name,
> +               map_name, map_len);
> +        return -EINVAL;
> +    }
> +
> +    /*
> +     * Can be overridden by "{iommu,msi}-map-mask" property.
> +     * If of_property_read_u32() fails, the default is used.
> +     */
> +    if ( !map_mask_name ||
> +         !dt_property_read_u32(np, map_mask_name, &map_mask) )
> +        /* The default is to select all bits. */
> +        map_mask = 0xffffffff;
> +
> +    masked_rid = map_mask & rid;
> +    for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4 )
> +    {
> +        struct dt_device_node *phandle_node;
> +        u32 rid_base = be32_to_cpup(map + 0);
> +        u32 phandle = be32_to_cpup(map + 1);
> +        u32 out_base = be32_to_cpup(map + 2);
> +        u32 rid_len = be32_to_cpup(map + 3);
> +
> +        if ( rid_base & ~map_mask )
> +        {
> +            pr_err("%s: Invalid %s translation - %s-mask (0x%x) ignores 
> rid-base (0x%x)\n",
> +                    np->full_name, map_name, map_name,
> +                    map_mask, rid_base);
> +            return -EFAULT;
> +        }
> +
> +        if ( masked_rid < rid_base || masked_rid >= rid_base + rid_len )
> +            continue;
> +
> +        phandle_node = dt_find_node_by_phandle(phandle);
> +        if ( !phandle_node )
> +            return -ENODEV;
> +
> +        if ( target )
> +        {
> +            if ( *target == NULL )
> +                *target = phandle_node;
> +
> +            if ( *target != phandle_node )
> +                continue;
> +        }
> +
> +        if ( id_out )
> +            *id_out = masked_rid - rid_base + out_base;
> +
> +        pr_info("%s: %s, using mask %08x, rid-base: %08x, out-base: %08x, 
> length: %08x, rid: %08x -> %08x\n",
> +                np->full_name, map_name, map_mask, rid_base, out_base,
> +                rid_len, rid, *id_out);
> +        return 0;
> +    }
> +
> +    pr_err("%s: Invalid %s translation - no match for rid 0x%x on %s\n",
> +           np->full_name, map_name, rid,
> +           target && *target ? (*target)->full_name : "any target");
> +
> +    return -EFAULT;
> +}
> +
>  /**
>   * unflatten_dt_node - Alloc and populate a device_node from the flat tree
>   * @fdt: The parent device tree blob
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 0aecbe0..0bddd7f 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -486,6 +486,29 @@ int dt_find_node_by_gpath(XEN_GUEST_HANDLE(char) u_path, 
> uint32_t u_plen,
>                            struct dt_device_node **node);
>  
>  /**
> + * dt_pci_map_rid - Translate a requester ID through a downstream mapping.
> + * @np: root complex device node.
> + * @rid: PCI requester ID to map.
> + * @map_name: property name of the map to use.
> + * @map_mask_name: optional property name of the mask to use.
> + * @target: optional pointer to a target device node.
> + * @id_out: optional pointer to receive the translated ID.
> + *
> + * Given a PCI requester ID, look up the appropriate implementation-defined
> + * platform ID and/or the target device which receives transactions on that
> + * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
> + * @id_out may be NULL if only the other is required. If @target points to
> + * a non-NULL device node pointer, only entries targeting that node will be
> + * matched; if it points to a NULL value, it will receive the device node of
> + * the first matching target phandle, with a reference held.
> + *
> + * Return: 0 on success or a standard error code on failure.
> + */
> +int dt_pci_map_rid(struct dt_device_node *np, u32 rid,
> +           const char *map_name, const char *map_mask_name,
> +           struct dt_device_node **target, u32 *id_out);
> +
> +/**
>   * dt_get_parent - Get a node's parent if any
>   * @node: Node to get parent
>   *
> -- 
> 2.7.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.