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:
Jon Hunter 2016-05-10 16:14:44 +01:00 committed by Marc Zyngier
parent 6e5b5924d9
commit f673b9b5cb
1 changed files with 65 additions and 49 deletions

View File

@ -72,6 +72,9 @@ struct gic_chip_data {
struct irq_chip chip;
union gic_base dist_base;
union gic_base cpu_base;
void __iomem *raw_dist_base;
void __iomem *raw_cpu_base;
u32 percpu_offset;
#ifdef CONFIG_CPU_PM
u32 saved_spi_enable[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,
};
static int __init __gic_init_bases(unsigned int gic_nr, int irq_start,
void __iomem *dist_base, void __iomem *cpu_base,
u32 percpu_offset, struct fwnode_handle *handle)
static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
struct fwnode_handle *handle)
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
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 = &gic_data[gic_nr];
/* Initialize irq_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_eoi = gic_eoimode1_eoi_irq;
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
} 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
if (gic_nr == 0)
if (gic == &gic_data[0])
gic->chip.irq_set_affinity = gic_set_affinity;
#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... */
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) {
u32 mpidr = cpu_logical_map(cpu);
u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
unsigned long offset = percpu_offset * core_id;
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
unsigned long offset = gic->percpu_offset * core_id;
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) =
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);
} else {
/* Normal, sane GIC... */
WARN(percpu_offset,
WARN(gic->percpu_offset,
"GIC_NON_BANKED not enabled, ignoring %08x offset!",
percpu_offset);
gic->dist_base.common_base = dist_base;
gic->cpu_base.common_base = cpu_base;
gic->percpu_offset);
gic->dist_base.common_base = gic->raw_dist_base;
gic->cpu_base.common_base = gic->raw_cpu_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 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;
if (irq_start != -1)
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;
}
if (gic_nr == 0) {
if (gic == &gic_data[0]) {
/*
* Initialize the CPU interface map to all CPUs.
* 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;
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->cpu_base.percpu_base);
}
@ -1176,12 +1179,22 @@ error:
void __init gic_init(unsigned int gic_nr, int irq_start,
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
* bother with these...
*/
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
@ -1228,21 +1241,24 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
int __init
gic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *cpu_base;
void __iomem *dist_base;
u32 percpu_offset;
struct gic_chip_data *gic;
int irq, ret;
if (WARN_ON(!node))
return -ENODEV;
dist_base = of_iomap(node, 0);
if (WARN(!dist_base, "unable to map gic dist registers\n"))
if (WARN_ON(gic_cnt >= CONFIG_ARM_GIC_MAX_NR))
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;
cpu_base = of_iomap(node, 1);
if (WARN(!cpu_base, "unable to map gic cpu registers\n")) {
iounmap(dist_base);
gic->raw_cpu_base = of_iomap(node, 1);
if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n")) {
iounmap(gic->raw_dist_base);
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
* 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);
if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
percpu_offset = 0;
if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
gic->percpu_offset = 0;
ret = __gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
&node->fwnode);
ret = __gic_init_bases(gic, -1, &node->fwnode);
if (ret) {
iounmap(dist_base);
iounmap(cpu_base);
iounmap(gic->raw_dist_base);
iounmap(gic->raw_cpu_base);
return ret;
}
@ -1350,8 +1365,8 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_madt_generic_distributor *dist;
void __iomem *cpu_base, *dist_base;
struct fwnode_handle *domain_handle;
struct gic_chip_data *gic = &gic_data[0];
int count, ret;
/* Collect CPU base addresses */
@ -1362,17 +1377,18 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
return -EINVAL;
}
cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
if (!cpu_base) {
gic->raw_cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
if (!gic->raw_cpu_base) {
pr_err("Unable to map GICC registers\n");
return -ENOMEM;
}
dist = (struct acpi_madt_generic_distributor *)header;
dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE);
if (!dist_base) {
gic->raw_dist_base = ioremap(dist->base_address,
ACPI_GICV2_DIST_MEM_SIZE);
if (!gic->raw_dist_base) {
pr_err("Unable to map GICD registers\n");
iounmap(cpu_base);
iounmap(gic->raw_cpu_base);
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).
*/
domain_handle = irq_domain_alloc_fwnode(dist_base);
domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
if (!domain_handle) {
pr_err("Unable to allocate domain handle\n");
iounmap(cpu_base);
iounmap(dist_base);
iounmap(gic->raw_cpu_base);
iounmap(gic->raw_dist_base);
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) {
pr_err("Failed to initialise GIC\n");
irq_domain_free_fwnode(domain_handle);
iounmap(cpu_base);
iounmap(dist_base);
iounmap(gic->raw_cpu_base);
iounmap(gic->raw_dist_base);
return ret;
}