mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arm/asm/setup.h: Update struct map_range_data to add rangeset.
Add rangesets for IRQs and IOMEMs. This was done to accommodate dynamic overlay node addition/removal operations. With overlay operations, new IRQs and IOMEMs are added in dt_host and routed. While removing overlay nodes, nodes are removed from dt_host and their IRQs and IOMEMs routing is also removed. Storing IRQs and IOMEMs in the rangeset will avoid re-parsing the device tree nodes to get the IOMEM and IRQ ranges for overlay remove ops. Dynamic overlay node add/remove will be introduced in follow-up patches. Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com> Acked-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
b8de00ff7a
commit
57d4d7d4e8
3 files changed
+42
-14
No files matched your search
+34
-9
@@ -165,6 +165,15 @@ int map_range_to_domain(const struct dt_device_node *dev,
|
||||
dt_dprintk(" - MMIO: %010"PRIx64" - %010"PRIx64" P2MType=%x\n",
|
||||
addr, addr + len, mr_data->p2mt);
|
||||
|
||||
if ( mr_data->iomem_ranges )
|
||||
{
|
||||
res = rangeset_add_range(mr_data->iomem_ranges,
|
||||
paddr_to_pfn(addr),
|
||||
paddr_to_pfn_aligned(addr + len - 1));
|
||||
if ( res )
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -178,10 +187,11 @@ int map_range_to_domain(const struct dt_device_node *dev,
|
||||
*/
|
||||
int map_device_irqs_to_domain(struct domain *d,
|
||||
struct dt_device_node *dev,
|
||||
bool need_mapping)
|
||||
bool need_mapping,
|
||||
struct rangeset *irq_ranges)
|
||||
{
|
||||
unsigned int i, nirq;
|
||||
int res;
|
||||
int res, irq;
|
||||
struct dt_raw_irq rirq;
|
||||
|
||||
nirq = dt_number_of_irq(dev);
|
||||
@@ -208,17 +218,24 @@ int map_device_irqs_to_domain(struct domain *d,
|
||||
continue;
|
||||
}
|
||||
|
||||
res = platform_get_irq(dev, i);
|
||||
if ( res < 0 )
|
||||
irq = platform_get_irq(dev, i);
|
||||
if ( irq < 0 )
|
||||
{
|
||||
printk(XENLOG_ERR "Unable to get irq %u for %s\n",
|
||||
i, dt_node_full_name(dev));
|
||||
return res;
|
||||
return irq;
|
||||
}
|
||||
|
||||
res = map_irq_to_domain(d, res, need_mapping, dt_node_name(dev));
|
||||
res = map_irq_to_domain(d, irq, need_mapping, dt_node_name(dev));
|
||||
if ( res )
|
||||
return res;
|
||||
|
||||
if ( irq_ranges )
|
||||
{
|
||||
res = rangeset_add_singleton(irq_ranges, irq);
|
||||
if ( res )
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -249,6 +266,11 @@ static int map_dt_irq_to_domain(const struct dt_device_node *dev,
|
||||
}
|
||||
|
||||
res = map_irq_to_domain(d, irq, !mr_data->skip_mapping, dt_node_name(dev));
|
||||
if ( res )
|
||||
return res;
|
||||
|
||||
if ( mr_data->irq_ranges )
|
||||
res = rangeset_add_singleton(mr_data->irq_ranges, irq);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -289,7 +311,8 @@ static int map_device_children(const struct dt_device_node *dev,
|
||||
* - Assign the device to the guest if it's protected by an IOMMU
|
||||
* - Map the IRQs and iomem regions to DOM0
|
||||
*/
|
||||
int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt)
|
||||
int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
|
||||
struct rangeset *iomem_ranges, struct rangeset *irq_ranges)
|
||||
{
|
||||
unsigned int naddr;
|
||||
unsigned int i;
|
||||
@@ -308,7 +331,9 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt)
|
||||
.p2mt = p2mt,
|
||||
.skip_mapping = !own_device ||
|
||||
(is_pci_passthrough_enabled() &&
|
||||
(device_get_class(dev) == DEVICE_PCI_HOSTBRIDGE))
|
||||
(device_get_class(dev) == DEVICE_PCI_HOSTBRIDGE)),
|
||||
.iomem_ranges = iomem_ranges,
|
||||
.irq_ranges = irq_ranges
|
||||
};
|
||||
|
||||
naddr = dt_number_of_address(dev);
|
||||
@@ -342,7 +367,7 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt)
|
||||
}
|
||||
}
|
||||
|
||||
res = map_device_irqs_to_domain(d, dev, own_device);
|
||||
res = map_device_irqs_to_domain(d, dev, own_device, irq_ranges);
|
||||
if ( res < 0 )
|
||||
return res;
|
||||
|
||||
|
||||
@@ -2402,7 +2402,7 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
|
||||
"WARNING: Path %s is reserved, skip the node as we may re-use the path.\n",
|
||||
path);
|
||||
|
||||
res = handle_device(d, node, p2mt);
|
||||
res = handle_device(d, node, p2mt, NULL, NULL);
|
||||
if ( res)
|
||||
return res;
|
||||
|
||||
@@ -2745,7 +2745,7 @@ static int __init handle_passthrough_prop(struct kernel_info *kinfo,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = map_device_irqs_to_domain(kinfo->d, node, true);
|
||||
res = map_device_irqs_to_domain(kinfo->d, node, true, NULL);
|
||||
if ( res < 0 )
|
||||
return res;
|
||||
|
||||
|
||||
@@ -113,6 +113,9 @@ struct map_range_data
|
||||
p2m_type_t p2mt;
|
||||
/* Set if mapping of the memory ranges must be skipped. */
|
||||
bool skip_mapping;
|
||||
/* Rangeset to store IRQs and IOMEM for overlay nodes. */
|
||||
struct rangeset *iomem_ranges;
|
||||
struct rangeset *irq_ranges;
|
||||
};
|
||||
|
||||
extern struct bootinfo bootinfo;
|
||||
@@ -165,11 +168,11 @@ void device_tree_get_reg(const __be32 **cell, uint32_t address_cells,
|
||||
u32 device_tree_get_u32(const void *fdt, int node,
|
||||
const char *prop_name, u32 dflt);
|
||||
|
||||
int handle_device(struct domain *d, struct dt_device_node *dev,
|
||||
p2m_type_t p2mt);
|
||||
int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
|
||||
struct rangeset *iomem_ranges, struct rangeset *irq_ranges);
|
||||
|
||||
int map_device_irqs_to_domain(struct domain *d, struct dt_device_node *dev,
|
||||
bool need_mapping);
|
||||
bool need_mapping, struct rangeset *irq_ranges);
|
||||
|
||||
int map_irq_to_domain(struct domain *d, unsigned int irq,
|
||||
bool need_mapping, const char *devname);
|
||||
|
||||