@@ -15,11 +15,51 @@
enum acpi_irq_model_id acpi_irq_model;
-static struct irq_domain *acpi_irq_domain __read_mostly;
+struct gsi_cfg_data {
+ struct list_head list;
+ u32 gsi_base;
+ u32 gsi_end;
+ struct irq_domain *domain;
+};
-void set_acpi_irq_domain(struct irq_domain *domain)
+static LIST_HEAD(gsi_cfg_data_list);
+static DEFINE_MUTEX(gsi_mutex);
+
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end)
+{
+ struct gsi_cfg_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domain = domain;
+ data->gsi_base = gsi_base;
+ data->gsi_end = gsi_end;
+
+ mutex_lock(&gsi_mutex);
+ list_add(&data->list, &gsi_cfg_data_list);
+ mutex_unlock(&gsi_mutex);
+
+ return 0;
+}
+
+/* Find irqdomain with GSI (hwirq number) */
+static struct irq_domain *acpi_find_irqdomain(u32 gsi)
{
- acpi_irq_domain = domain;
+ struct gsi_cfg_data *data;
+ struct irq_domain *domain = NULL;
+
+ mutex_lock(&gsi_mutex);
+ list_for_each_entry(data, &gsi_cfg_data_list, list) {
+ if (gsi >= data->gsi_base && gsi <= data->gsi_end) {
+ domain = data->domain;
+ break;
+ }
+ }
+ mutex_unlock(&gsi_mutex);
+
+ return domain;
}
static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
@@ -53,7 +93,9 @@ static unsigned int acpi_gsi_get_irq_type(int trigger,
int polarity)
*/
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
- *irq = irq_find_mapping(acpi_irq_domain, gsi);
+ struct irq_domain *domain = acpi_find_irqdomain(gsi);
+
+ *irq = irq_find_mapping(domain, gsi);
/*
* *irq == 0 means no mapping, that should
* be reported as a failure
@@ -77,12 +119,13 @@ int acpi_register_gsi(struct device *dev, u32 gsi,
int trigger,
{
int irq;
unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+ struct irq_domain *domain = acpi_find_irqdomain(gsi);
- irq = irq_find_mapping(acpi_irq_domain, gsi);
+ irq = irq_find_mapping(domain, gsi);
if (irq > 0)
return irq;
- irq = irq_domain_alloc_irqs(acpi_irq_domain, 1, dev_to_node(dev),
+ irq = irq_domain_alloc_irqs(domain, 1, dev_to_node(dev),
&gsi);
if (irq <= 0)
return -EINVAL;
@@ -101,7 +144,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
*/
void acpi_unregister_gsi(u32 gsi)
{
- int irq = irq_find_mapping(acpi_irq_domain, gsi);
+ struct irq_domain *domain = acpi_find_irqdomain(gsi);
+ int irq = irq_find_mapping(domain, gsi);
irq_dispose_mapping(irq);
}
@@ -947,6 +947,7 @@ static LIST_HEAD(redist_list);
static struct redist_region *redist_regs __initdata;
static u32 nr_redist_regions __initdata;
static phys_addr_t dist_phy_base __initdata;
+static u32 gsi_base __initdata;
static int __init
gic_acpi_register_redist(u64 phys_base, u64 size)
@@ -1014,6 +1015,7 @@ gic_acpi_parse_madt_distributor(struct
acpi_subtable_header *header,
if (BAD_MADT_ENTRY(dist, end))
return -EINVAL;
+ gsi_base = dist->global_irq_base;
dist_phy_base = dist->base_address;
return 0;
}
@@ -1168,7 +1170,7 @@ init_base:
if (err)
goto out_release_redist;
- set_acpi_irq_domain(gic_data.domain);
+ gsi_cfg_data_add(gic_data.domain, gsi_base, gsi_base +
gic_data.irq_nr);
return 0;
out_release_redist:
@@ -1051,6 +1051,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2",
gic_of_init);
#ifdef CONFIG_ACPI
static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+static u32 gsi_base __initdata;
static int __init
gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1089,6 +1090,7 @@ gic_acpi_parse_madt_distributor(struct
acpi_subtable_header *header,
if (BAD_MADT_ENTRY(dist, end))
return -EINVAL;
+ gsi_base = dist->global_irq_base;
dist_phy_base = dist->base_address;
return 0;
}
@@ -1139,7 +1141,10 @@ gic_v2_acpi_init(struct acpi_table_header *table)
}
gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
- set_acpi_irq_domain(gic_data[0].domain);
+
+ /* since we have only one GICD, we can safely use gic_data[0]
here */
+ gsi_cfg_data_add(gic_data[0].domain, gsi_base,
+ gsi_base + gic_data[0].gic_irqs);
acpi_irq_model = ACPI_IRQ_MODEL_GIC;
return 0;
@@ -223,7 +223,7 @@ void acpi_unregister_gsi (u32 gsi);
#ifdef CONFIG_ACPI_GENERIC_GSI
struct irq_domain;
-void set_acpi_irq_domain(struct irq_domain *domain);
+int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end);
#endif
struct pci_dev;