mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 08:49:45 +00:00
of/device: Add input id to of_dma_configure()
Devices sitting on proprietary busses have a device ID space that is owned by the respective bus and related firmware bindings. In order to let the generic OF layer handle the input translations to an IOMMU id, for such busses the current of_dma_configure() interface should be extended in order to allow the bus layer to provide the device input id parameter - that is retrieved/assigned in bus specific code and firmware. Augment of_dma_configure() to add an optional input_id parameter, leaving current functionality unchanged. Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Rob Herring <robh@kernel.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Robin Murphy <robin.murphy@arm.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Laurentiu Tudor <laurentiu.tudor@nxp.com> Link: https://lore.kernel.org/r/20200619082013.13661-8-lorenzo.pieralisi@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
746a71d02b
commit
a081bd4af4
5 changed files with 72 additions and 47 deletions
|
@ -118,11 +118,13 @@ static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
static int fsl_mc_dma_configure(struct device *dev)
|
||||
{
|
||||
struct device *dma_dev = dev;
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
u32 input_id = mc_dev->icid;
|
||||
|
||||
while (dev_is_fsl_mc(dma_dev))
|
||||
dma_dev = dma_dev->parent;
|
||||
|
||||
return of_dma_configure(dev, dma_dev->of_node, 0);
|
||||
return of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id);
|
||||
}
|
||||
|
||||
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
|
||||
|
|
|
@ -118,6 +118,43 @@ static int of_iommu_xlate(struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int of_iommu_configure_dev_id(struct device_node *master_np,
|
||||
struct device *dev,
|
||||
const u32 *id)
|
||||
{
|
||||
struct of_phandle_args iommu_spec = { .args_count = 1 };
|
||||
int err;
|
||||
|
||||
err = of_map_id(master_np, *id, "iommu-map",
|
||||
"iommu-map-mask", &iommu_spec.np,
|
||||
iommu_spec.args);
|
||||
if (err)
|
||||
return err == -ENODEV ? NO_IOMMU : err;
|
||||
|
||||
err = of_iommu_xlate(dev, &iommu_spec);
|
||||
of_node_put(iommu_spec.np);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int of_iommu_configure_dev(struct device_node *master_np,
|
||||
struct device *dev)
|
||||
{
|
||||
struct of_phandle_args iommu_spec;
|
||||
int err = NO_IOMMU, idx = 0;
|
||||
|
||||
while (!of_parse_phandle_with_args(master_np, "iommus",
|
||||
"#iommu-cells",
|
||||
idx, &iommu_spec)) {
|
||||
err = of_iommu_xlate(dev, &iommu_spec);
|
||||
of_node_put(iommu_spec.np);
|
||||
idx++;
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct of_pci_iommu_alias_info {
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
|
@ -126,38 +163,21 @@ struct of_pci_iommu_alias_info {
|
|||
static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
|
||||
{
|
||||
struct of_pci_iommu_alias_info *info = data;
|
||||
struct of_phandle_args iommu_spec = { .args_count = 1 };
|
||||
int err;
|
||||
u32 input_id = alias;
|
||||
|
||||
err = of_map_id(info->np, alias, "iommu-map", "iommu-map-mask",
|
||||
&iommu_spec.np, iommu_spec.args);
|
||||
if (err)
|
||||
return err == -ENODEV ? NO_IOMMU : err;
|
||||
|
||||
err = of_iommu_xlate(info->dev, &iommu_spec);
|
||||
of_node_put(iommu_spec.np);
|
||||
return err;
|
||||
return of_iommu_configure_dev_id(info->np, info->dev, &input_id);
|
||||
}
|
||||
|
||||
static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
|
||||
struct device_node *master_np)
|
||||
static int of_iommu_configure_device(struct device_node *master_np,
|
||||
struct device *dev, const u32 *id)
|
||||
{
|
||||
struct of_phandle_args iommu_spec = { .args_count = 1 };
|
||||
int err;
|
||||
|
||||
err = of_map_id(master_np, mc_dev->icid, "iommu-map",
|
||||
"iommu-map-mask", &iommu_spec.np,
|
||||
iommu_spec.args);
|
||||
if (err)
|
||||
return err == -ENODEV ? NO_IOMMU : err;
|
||||
|
||||
err = of_iommu_xlate(&mc_dev->dev, &iommu_spec);
|
||||
of_node_put(iommu_spec.np);
|
||||
return err;
|
||||
return (id) ? of_iommu_configure_dev_id(master_np, dev, id) :
|
||||
of_iommu_configure_dev(master_np, dev);
|
||||
}
|
||||
|
||||
const struct iommu_ops *of_iommu_configure(struct device *dev,
|
||||
struct device_node *master_np)
|
||||
struct device_node *master_np,
|
||||
const u32 *id)
|
||||
{
|
||||
const struct iommu_ops *ops = NULL;
|
||||
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
|
||||
|
@ -188,21 +208,8 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
|
|||
pci_request_acs();
|
||||
err = pci_for_each_dma_alias(to_pci_dev(dev),
|
||||
of_pci_iommu_init, &info);
|
||||
} else if (dev_is_fsl_mc(dev)) {
|
||||
err = of_fsl_mc_iommu_init(to_fsl_mc_device(dev), master_np);
|
||||
} else {
|
||||
struct of_phandle_args iommu_spec;
|
||||
int idx = 0;
|
||||
|
||||
while (!of_parse_phandle_with_args(master_np, "iommus",
|
||||
"#iommu-cells",
|
||||
idx, &iommu_spec)) {
|
||||
err = of_iommu_xlate(dev, &iommu_spec);
|
||||
of_node_put(iommu_spec.np);
|
||||
idx++;
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
err = of_iommu_configure_device(master_np, dev, id);
|
||||
|
||||
fwspec = dev_iommu_fwspec_get(dev);
|
||||
if (!err && fwspec)
|
||||
|
|
|
@ -78,6 +78,7 @@ int of_device_add(struct platform_device *ofdev)
|
|||
* @np: Pointer to OF node having DMA configuration
|
||||
* @force_dma: Whether device is to be set up by of_dma_configure() even if
|
||||
* DMA capability is not explicitly described by firmware.
|
||||
* @id: Optional const pointer value input id
|
||||
*
|
||||
* Try to get devices's DMA configuration from DT and update it
|
||||
* accordingly.
|
||||
|
@ -86,7 +87,8 @@ int of_device_add(struct platform_device *ofdev)
|
|||
* can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
|
||||
* to fix up DMA configuration.
|
||||
*/
|
||||
int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
|
||||
int of_dma_configure_id(struct device *dev, struct device_node *np,
|
||||
bool force_dma, const u32 *id)
|
||||
{
|
||||
u64 dma_addr, paddr, size = 0;
|
||||
int ret;
|
||||
|
@ -160,7 +162,7 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
|
|||
dev_dbg(dev, "device is%sdma coherent\n",
|
||||
coherent ? " " : " not ");
|
||||
|
||||
iommu = of_iommu_configure(dev, np);
|
||||
iommu = of_iommu_configure(dev, np, id);
|
||||
if (PTR_ERR(iommu) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
|
@ -171,7 +173,7 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_dma_configure);
|
||||
EXPORT_SYMBOL_GPL(of_dma_configure_id);
|
||||
|
||||
int of_device_register(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -55,9 +55,15 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
|
|||
return of_node_get(cpu_dev->of_node);
|
||||
}
|
||||
|
||||
int of_dma_configure(struct device *dev,
|
||||
int of_dma_configure_id(struct device *dev,
|
||||
struct device_node *np,
|
||||
bool force_dma);
|
||||
bool force_dma, const u32 *id);
|
||||
static inline int of_dma_configure(struct device *dev,
|
||||
struct device_node *np,
|
||||
bool force_dma)
|
||||
{
|
||||
return of_dma_configure_id(dev, np, force_dma, NULL);
|
||||
}
|
||||
#else /* CONFIG_OF */
|
||||
|
||||
static inline int of_driver_match_device(struct device *dev,
|
||||
|
@ -106,6 +112,12 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline int of_dma_configure_id(struct device *dev,
|
||||
struct device_node *np,
|
||||
bool force_dma)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int of_dma_configure(struct device *dev,
|
||||
struct device_node *np,
|
||||
bool force_dma)
|
||||
|
|
|
@ -13,7 +13,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
|
|||
size_t *size);
|
||||
|
||||
extern const struct iommu_ops *of_iommu_configure(struct device *dev,
|
||||
struct device_node *master_np);
|
||||
struct device_node *master_np,
|
||||
const u32 *id);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -25,7 +26,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
|
|||
}
|
||||
|
||||
static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
|
||||
struct device_node *master_np)
|
||||
struct device_node *master_np,
|
||||
const u32 *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue