Hi Stefano, > -----Original Message----- > From: Stefano Stabellini [mailto:sstabell...@kernel.org] > Sent: 2017年7月7日 4:26 > To: Wei Chen <wei.c...@arm.com> > Cc: xen-devel@lists.xen.org; sstabell...@kernel.org; Julien Grall > <julien.gr...@arm.com>; Steve Capper <steve.cap...@arm.com>; Kaly Xin > <kaly....@arm.com>; nd <n...@arm.com> > Subject: Re: [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/driver > s/of/of_pci.c > > The commit id is: 987068fcbdb7a085bb11151b91dc6f4c956c4a1b > > > > Signed-off-by: Wei Chen <wei.c...@arm.com> > > --- > > 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. >
Ok, I will cleanup it. > > > +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 ) Oh, it's code-style mistake, I will fix it. > > > > + 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@lists.xen.org https://lists.xen.org/xen-devel