mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-12 06:26:42 +07:00
irqchip/gic: Store GIC configuration parameters
Store the GIC configuration parameters in the GIC chip data structure. This will allow us to simplify the code by reducing the number of parameters passed between functions. Update the __gic_init_bases() function so that we only need to pass a pointer to the GIC chip data structure and no longer need to pass the GIC index in order to look-up the chip data. Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
6e5b5924d9
commit
f673b9b5cb
@ -72,6 +72,9 @@ struct gic_chip_data {
|
|||||||
struct irq_chip chip;
|
struct irq_chip chip;
|
||||||
union gic_base dist_base;
|
union gic_base dist_base;
|
||||||
union gic_base cpu_base;
|
union gic_base cpu_base;
|
||||||
|
void __iomem *raw_dist_base;
|
||||||
|
void __iomem *raw_cpu_base;
|
||||||
|
u32 percpu_offset;
|
||||||
#ifdef CONFIG_CPU_PM
|
#ifdef CONFIG_CPU_PM
|
||||||
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
|
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
|
||||||
u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
|
u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
|
||||||
@ -1026,38 +1029,36 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
|
|||||||
.unmap = gic_irq_domain_unmap,
|
.unmap = gic_irq_domain_unmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
|
||||||
void __iomem *dist_base, void __iomem *cpu_base,
|
struct fwnode_handle *handle)
|
||||||
u32 percpu_offset, struct fwnode_handle *handle)
|
|
||||||
{
|
{
|
||||||
irq_hw_number_t hwirq_base;
|
irq_hw_number_t hwirq_base;
|
||||||
struct gic_chip_data *gic;
|
|
||||||
int gic_irqs, irq_base, i, ret;
|
int gic_irqs, irq_base, i, ret;
|
||||||
|
|
||||||
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
if (WARN_ON(!gic || gic->domain))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
gic_check_cpu_features();
|
gic_check_cpu_features();
|
||||||
|
|
||||||
gic = &gic_data[gic_nr];
|
|
||||||
|
|
||||||
/* Initialize irq_chip */
|
/* Initialize irq_chip */
|
||||||
gic->chip = gic_chip;
|
gic->chip = gic_chip;
|
||||||
|
|
||||||
if (static_key_true(&supports_deactivate) && gic_nr == 0) {
|
if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
|
||||||
gic->chip.irq_mask = gic_eoimode1_mask_irq;
|
gic->chip.irq_mask = gic_eoimode1_mask_irq;
|
||||||
gic->chip.irq_eoi = gic_eoimode1_eoi_irq;
|
gic->chip.irq_eoi = gic_eoimode1_eoi_irq;
|
||||||
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
|
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
|
||||||
gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
|
gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
|
||||||
} else {
|
} else {
|
||||||
gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
|
gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d",
|
||||||
|
(int)(gic - &gic_data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
if (gic_nr == 0)
|
if (gic == &gic_data[0])
|
||||||
gic->chip.irq_set_affinity = gic_set_affinity;
|
gic->chip.irq_set_affinity = gic_set_affinity;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && percpu_offset) {
|
if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
|
||||||
/* Frankein-GIC without banked registers... */
|
/* Frankein-GIC without banked registers... */
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
|
||||||
@ -1072,19 +1073,21 @@ static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
|||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
u32 mpidr = cpu_logical_map(cpu);
|
u32 mpidr = cpu_logical_map(cpu);
|
||||||
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||||
unsigned long offset = percpu_offset * core_id;
|
unsigned long offset = gic->percpu_offset * core_id;
|
||||||
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
|
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) =
|
||||||
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
|
gic->raw_dist_base + offset;
|
||||||
|
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) =
|
||||||
|
gic->raw_cpu_base + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
gic_set_base_accessor(gic, gic_get_percpu_base);
|
gic_set_base_accessor(gic, gic_get_percpu_base);
|
||||||
} else {
|
} else {
|
||||||
/* Normal, sane GIC... */
|
/* Normal, sane GIC... */
|
||||||
WARN(percpu_offset,
|
WARN(gic->percpu_offset,
|
||||||
"GIC_NON_BANKED not enabled, ignoring %08x offset!",
|
"GIC_NON_BANKED not enabled, ignoring %08x offset!",
|
||||||
percpu_offset);
|
gic->percpu_offset);
|
||||||
gic->dist_base.common_base = dist_base;
|
gic->dist_base.common_base = gic->raw_dist_base;
|
||||||
gic->cpu_base.common_base = cpu_base;
|
gic->cpu_base.common_base = gic->raw_cpu_base;
|
||||||
gic_set_base_accessor(gic, gic_get_common_base);
|
gic_set_base_accessor(gic, gic_get_common_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,7 +1110,7 @@ static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
|||||||
* For primary GICs, skip over SGIs.
|
* For primary GICs, skip over SGIs.
|
||||||
* For secondary GICs, skip over PPIs, too.
|
* For secondary GICs, skip over PPIs, too.
|
||||||
*/
|
*/
|
||||||
if (gic_nr == 0 && (irq_start & 31) > 0) {
|
if (gic == &gic_data[0] && (irq_start & 31) > 0) {
|
||||||
hwirq_base = 16;
|
hwirq_base = 16;
|
||||||
if (irq_start != -1)
|
if (irq_start != -1)
|
||||||
irq_start = (irq_start & ~31) + 16;
|
irq_start = (irq_start & ~31) + 16;
|
||||||
@ -1134,7 +1137,7 @@ static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gic_nr == 0) {
|
if (gic == &gic_data[0]) {
|
||||||
/*
|
/*
|
||||||
* Initialize the CPU interface map to all CPUs.
|
* Initialize the CPU interface map to all CPUs.
|
||||||
* It will be refined as each CPU probes its ID.
|
* It will be refined as each CPU probes its ID.
|
||||||
@ -1163,7 +1166,7 @@ static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && percpu_offset) {
|
if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
|
||||||
free_percpu(gic->dist_base.percpu_base);
|
free_percpu(gic->dist_base.percpu_base);
|
||||||
free_percpu(gic->cpu_base.percpu_base);
|
free_percpu(gic->cpu_base.percpu_base);
|
||||||
}
|
}
|
||||||
@ -1176,12 +1179,22 @@ static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
|||||||
void __init gic_init(unsigned int gic_nr, int irq_start,
|
void __init gic_init(unsigned int gic_nr, int irq_start,
|
||||||
void __iomem *dist_base, void __iomem *cpu_base)
|
void __iomem *dist_base, void __iomem *cpu_base)
|
||||||
{
|
{
|
||||||
|
struct gic_chip_data *gic;
|
||||||
|
|
||||||
|
if (WARN_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR))
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Non-DT/ACPI systems won't run a hypervisor, so let's not
|
* Non-DT/ACPI systems won't run a hypervisor, so let's not
|
||||||
* bother with these...
|
* bother with these...
|
||||||
*/
|
*/
|
||||||
static_key_slow_dec(&supports_deactivate);
|
static_key_slow_dec(&supports_deactivate);
|
||||||
__gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
|
|
||||||
|
gic = &gic_data[gic_nr];
|
||||||
|
gic->raw_dist_base = dist_base;
|
||||||
|
gic->raw_cpu_base = cpu_base;
|
||||||
|
|
||||||
|
__gic_init_bases(gic, irq_start, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
@ -1228,21 +1241,24 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
|
|||||||
int __init
|
int __init
|
||||||
gic_of_init(struct device_node *node, struct device_node *parent)
|
gic_of_init(struct device_node *node, struct device_node *parent)
|
||||||
{
|
{
|
||||||
void __iomem *cpu_base;
|
struct gic_chip_data *gic;
|
||||||
void __iomem *dist_base;
|
|
||||||
u32 percpu_offset;
|
|
||||||
int irq, ret;
|
int irq, ret;
|
||||||
|
|
||||||
if (WARN_ON(!node))
|
if (WARN_ON(!node))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
dist_base = of_iomap(node, 0);
|
if (WARN_ON(gic_cnt >= CONFIG_ARM_GIC_MAX_NR))
|
||||||
if (WARN(!dist_base, "unable to map gic dist registers\n"))
|
return -EINVAL;
|
||||||
|
|
||||||
|
gic = &gic_data[gic_cnt];
|
||||||
|
|
||||||
|
gic->raw_dist_base = of_iomap(node, 0);
|
||||||
|
if (WARN(!gic->raw_dist_base, "unable to map gic dist registers\n"))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
cpu_base = of_iomap(node, 1);
|
gic->raw_cpu_base = of_iomap(node, 1);
|
||||||
if (WARN(!cpu_base, "unable to map gic cpu registers\n")) {
|
if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n")) {
|
||||||
iounmap(dist_base);
|
iounmap(gic->raw_dist_base);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1250,17 +1266,16 @@ gic_of_init(struct device_node *node, struct device_node *parent)
|
|||||||
* Disable split EOI/Deactivate if either HYP is not available
|
* Disable split EOI/Deactivate if either HYP is not available
|
||||||
* or the CPU interface is too small.
|
* or the CPU interface is too small.
|
||||||
*/
|
*/
|
||||||
if (gic_cnt == 0 && !gic_check_eoimode(node, &cpu_base))
|
if (gic_cnt == 0 && !gic_check_eoimode(node, &gic->raw_cpu_base))
|
||||||
static_key_slow_dec(&supports_deactivate);
|
static_key_slow_dec(&supports_deactivate);
|
||||||
|
|
||||||
if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
|
if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
|
||||||
percpu_offset = 0;
|
gic->percpu_offset = 0;
|
||||||
|
|
||||||
ret = __gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
|
ret = __gic_init_bases(gic, -1, &node->fwnode);
|
||||||
&node->fwnode);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
iounmap(dist_base);
|
iounmap(gic->raw_dist_base);
|
||||||
iounmap(cpu_base);
|
iounmap(gic->raw_cpu_base);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1350,8 +1365,8 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
|
|||||||
const unsigned long end)
|
const unsigned long end)
|
||||||
{
|
{
|
||||||
struct acpi_madt_generic_distributor *dist;
|
struct acpi_madt_generic_distributor *dist;
|
||||||
void __iomem *cpu_base, *dist_base;
|
|
||||||
struct fwnode_handle *domain_handle;
|
struct fwnode_handle *domain_handle;
|
||||||
|
struct gic_chip_data *gic = &gic_data[0];
|
||||||
int count, ret;
|
int count, ret;
|
||||||
|
|
||||||
/* Collect CPU base addresses */
|
/* Collect CPU base addresses */
|
||||||
@ -1362,17 +1377,18 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
|
gic->raw_cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
|
||||||
if (!cpu_base) {
|
if (!gic->raw_cpu_base) {
|
||||||
pr_err("Unable to map GICC registers\n");
|
pr_err("Unable to map GICC registers\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
dist = (struct acpi_madt_generic_distributor *)header;
|
dist = (struct acpi_madt_generic_distributor *)header;
|
||||||
dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE);
|
gic->raw_dist_base = ioremap(dist->base_address,
|
||||||
if (!dist_base) {
|
ACPI_GICV2_DIST_MEM_SIZE);
|
||||||
|
if (!gic->raw_dist_base) {
|
||||||
pr_err("Unable to map GICD registers\n");
|
pr_err("Unable to map GICD registers\n");
|
||||||
iounmap(cpu_base);
|
iounmap(gic->raw_cpu_base);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1387,20 +1403,20 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
|
|||||||
/*
|
/*
|
||||||
* Initialize GIC instance zero (no multi-GIC support).
|
* Initialize GIC instance zero (no multi-GIC support).
|
||||||
*/
|
*/
|
||||||
domain_handle = irq_domain_alloc_fwnode(dist_base);
|
domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
|
||||||
if (!domain_handle) {
|
if (!domain_handle) {
|
||||||
pr_err("Unable to allocate domain handle\n");
|
pr_err("Unable to allocate domain handle\n");
|
||||||
iounmap(cpu_base);
|
iounmap(gic->raw_cpu_base);
|
||||||
iounmap(dist_base);
|
iounmap(gic->raw_dist_base);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = __gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
|
ret = __gic_init_bases(gic, -1, domain_handle);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Failed to initialise GIC\n");
|
pr_err("Failed to initialise GIC\n");
|
||||||
irq_domain_free_fwnode(domain_handle);
|
irq_domain_free_fwnode(domain_handle);
|
||||||
iounmap(cpu_base);
|
iounmap(gic->raw_cpu_base);
|
||||||
iounmap(dist_base);
|
iounmap(gic->raw_dist_base);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user