aboutsummaryrefslogtreecommitdiffstats
path: root/meta-seattle/recipes-kernel/linux/files/412-5-styx-linux-tracking.git-2a80b31ff435cd274a61d685a4861bf0da461c90.patch
blob: 47ca0ef185bca52596a8f101e01c001d25eb1e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
From 4343fa95a5f0e2e9c32faecc05e4aa1e12e27f72 Mon Sep 17 00:00:00 2001
From: Adrian Calianu <adrian.calianu@enea.com>
Date: Tue, 11 Aug 2015 13:21:33 +0200
Subject: [PATCH] [PATCH] DO NOT UPSTREAM YET: Clean up GIC irq domain for ACPI

From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Date: Tue, 20 Jan 2015 20:02:28 -0600

Instead of using the irq_default_domain, define the acpi_irq_domain.
This still have the same assumption that ACPI only support a single
GIC domain.

Also, rename acpi_gic_init() to acpi_irq_init()

Upstream-Status: Pending

Ported from 3.19 kernel, patch provided by AMD.

Signed-off-by: Adrian Calianu <adrian.calianu@enea.com>
---
 arch/arm64/kernel/acpi.c             | 14 ++++--
 drivers/acpi/gsi.c                   | 31 ++++++++++----
 drivers/irqchip/irq-gic.c            | 83 ++++++++++++++++++++++++++++++------
 drivers/irqchip/irqchip.c            |  2 +-
 drivers/pci/pci-acpi.c               | 25 +++++++++++
 include/linux/irqchip/arm-gic-acpi.h |  6 ++-
 include/linux/irqchip/arm-gic.h      | 17 ++++++++
 7 files changed, 151 insertions(+), 27 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 8b83955..ea80ce2 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -319,7 +319,7 @@ void __init acpi_boot_table_init(void)
 	}
 }
 
-void __init acpi_gic_init(void)
+void __init acpi_irq_init(void)
 {
 	struct acpi_table_header *table;
 	acpi_status status;
@@ -329,6 +329,14 @@ void __init acpi_gic_init(void)
 	if (acpi_disabled)
 		return;
 
+    /**
+     * NOTE: We need to declare this before we initialize the GIC
+     *       so that we can use pointers to MADT table and MSI_FRAME sub-table
+     *       for reference.
+     */
+    acpi_gbl_permanent_mmap = 1;
+
+
 	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
 	if (ACPI_FAILURE(status)) {
 		const char *msg = acpi_format_exception(status);
@@ -337,8 +345,8 @@ void __init acpi_gic_init(void)
 		return;
 	}
 
-	err = gic_v2_acpi_init(table);
-	if (err)
+    err = gic_v2_acpi_init(table, &acpi_irq_domain);
+    if (err || !acpi_irq_domain)
 		pr_err("Failed to initialize GIC IRQ controller");
 
 	early_acpi_os_unmap_memory((char *)table, tbl_size);
diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
index 38208f2..7f1b8a0 100644
--- a/drivers/acpi/gsi.c
+++ b/drivers/acpi/gsi.c
@@ -11,6 +11,7 @@
 #include <linux/acpi.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
 
 enum acpi_irq_model_id acpi_irq_model;
 
@@ -43,6 +44,8 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
  * Returns: linux IRQ number on success (>0)
  *          -EINVAL on failure
  */
+static struct irq_domain *acpi_irq_domain;
+
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
 	/*
@@ -50,7 +53,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 	 * the mapping corresponding to default domain by passing NULL
 	 * as irq_domain parameter
 	 */
-	*irq = irq_find_mapping(NULL, gsi);
+	*irq = irq_find_mapping(acpi_irq_domain, gsi);
 	/*
 	 * *irq == 0 means no mapping, that should
 	 * be reported as a failure
@@ -74,20 +77,32 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 {
 	unsigned int irq;
 	unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+    struct gic_irq_alloc_info info;
+    struct irq_data *d;
 
 	/*
 	 * There is no way at present to look-up the IRQ domain on ACPI,
 	 * hence always create mapping referring to the default domain
 	 * by passing NULL as irq_domain parameter
 	 */
-	irq = irq_create_mapping(NULL, gsi);
-	if (!irq)
-		return -EINVAL;
+    if (!acpi_irq_domain)
+        BUG();
+
+    if (gic_init_irq_alloc_info(GIC_INT_TYPE_NONE,
+                    gsi, irq_type, NULL, &info) < 0)
+        return -EINVAL;
+
+    irq = __irq_domain_alloc_irqs(acpi_irq_domain, -1, 1,
+                      dev_to_node(dev), &info, false);
+    if (irq < 0)
+        return -ENOSPC;
+
+    d = irq_domain_get_irq_data(acpi_irq_domain, irq);
+    if (!d)
+        return -EFAULT;
+
+    d->chip->irq_set_type(d, irq_type);
 
-	/* Set irq type if specified and different than the current one */
-	if (irq_type != IRQ_TYPE_NONE &&
-		irq_type != irq_get_trigger_type(irq))
-		irq_set_irq_type(irq, irq_type);
 	return irq;
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 01999d7..997d073 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -854,10 +854,13 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int i, ret;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
-	struct of_phandle_args *irq_data = arg;
+	struct gic_irq_alloc_info *info = arg;
+	u32 intspec[3];
 
-	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
-				   irq_data->args_count, &hwirq, &type);
+   intspec[0] = info->gic_int_type;
+   intspec[1] = info->hwirq;
+   intspec[2] = info->irq_type;
+   ret = gic_irq_domain_xlate(domain, info->ref, intspec, 3, &hwirq, &type);
 	if (ret)
 		return ret;
 
@@ -867,6 +870,51 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	return 0;
 }
 
+int gic_init_irq_alloc_info(unsigned int gic_int_type, unsigned int irq,
+               unsigned int irq_type, void *ref,
+               struct gic_irq_alloc_info *info)
+{
+   if (!info)
+       return -EINVAL;
+
+   if ((irq_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_HIGH &&
+       (irq_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_EDGE_RISING)
+       return -EINVAL;
+
+   info->ref = ref;
+   info->irq_type = irq_type;
+
+   /*
+    * ACPI have no bindings to indicate SPI or PPI, so we
+    * use different mappings from DT in ACPI.
+    *
+    * For FDT
+    * PPI interrupt: in the range [0, 15];
+    * SPI interrupt: in the range [0, 987];
+    *
+    * For ACPI, GSI should be unique so using
+    * the hwirq directly for the mapping:
+    * PPI interrupt: in the range [16, 31];
+    * SPI interrupt: in the range [32, 1019];
+    */
+
+   if (gic_int_type != ~0U) {
+       info->gic_int_type = gic_int_type;
+       info->hwirq = irq;
+
+   } else {
+       if (irq < 32) {
+           info->gic_int_type = GIC_INT_TYPE_PPI;
+           info->hwirq = irq - 16;
+       } else {
+           info->gic_int_type = GIC_INT_TYPE_SPI;
+           info->hwirq = irq - 32;
+       }
+   }
+
+   return 0;
+}
+
 static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
 	.xlate = gic_irq_domain_xlate,
 	.alloc = gic_irq_domain_alloc,
@@ -945,7 +993,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_irqs = 1020;
 	gic->gic_irqs = gic_irqs;
 
-	if (node) {		/* DT case */
+    if (!acpi_disabled) {   /* ACPI case */
+        gic->domain = irq_domain_add_linear(node, gic_irqs,
+                        &gic_irq_domain_hierarchy_ops, gic);
+    } else if (node) {  /* DT case */
 		gic->domain = irq_domain_add_linear(node, gic_irqs,
 						    &gic_irq_domain_hierarchy_ops,
 						    gic);
@@ -992,9 +1043,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic_pm_init(gic);
 }
 
-#ifdef CONFIG_OF
 static int gic_cnt __initdata;
 
+#ifdef CONFIG_OF
 static int __init
 gic_of_init(struct device_node *node, struct device_node *parent)
 {
@@ -1086,7 +1137,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
 }
 
 int __init
-gic_v2_acpi_init(struct acpi_table_header *table)
+gic_v2_acpi_init(struct acpi_table_header *table, struct irq_domain **domain)
 {
 	void __iomem *cpu_base, *dist_base;
 	int count;
@@ -1130,13 +1181,19 @@ gic_v2_acpi_init(struct acpi_table_header *table)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
-	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
-	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
-	 */
-	gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
-	irq_set_default_host(gic_data[0].domain);
+    gic_init_bases(gic_cnt, -1, dist_base, cpu_base, 0, NULL);
+    *domain = gic_data[gic_cnt].domain;
+
+    if (!*domain) {
+        pr_err("Unable to create domain\n");
+        return -EFAULT;
+    }
+
+    if (IS_ENABLED(CONFIG_ARM_GIC_V2M)) {
+        gicv2m_acpi_init(table, gic_data[gic_cnt].domain);
+    }
+
+    gic_cnt++;
 
 	acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 	return 0;
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
index afd1af3..0d3a8b1 100644
--- a/drivers/irqchip/irqchip.c
+++ b/drivers/irqchip/irqchip.c
@@ -28,5 +28,5 @@ void __init irqchip_init(void)
 {
 	of_irq_init(__irqchip_of_table);
 
-	acpi_irq_init();
+    acpi_irq_init();
 }
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 6f6f175..fe42097 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/module.h>
+#include <linux/msi.h>
 #include <linux/pci-aspm.h>
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
@@ -714,3 +715,27 @@ static int __init acpi_pci_init(void)
 	return 0;
 }
 arch_initcall(acpi_pci_init);
+
+#ifdef CONFIG_PCI_MSI
+void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) {
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+   u32 msi_frame_id = 0;
+   int num;
+
+   if (acpi_disabled)
+       return;
+
+   /**
+    * Since ACPI 5.1 currently does not define
+    * a way to associate MSI frame ID to a device,
+    * we can only support single MSI frame at the moment.
+    * Therefore, the id 0 is used as a default.
+    */
+   num = msi_get_num_irq_domain();
+   if (num <= 0 || num > 1)
+       return;
+
+        dev_set_msi_domain(&bus->dev, irq_find_acpi_msi_domain(msi_frame_id));
+#endif
+}
+#endif /* CONFIG_PCI_MSI */
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
index de3419e..fa8033b 100644
--- a/include/linux/irqchip/arm-gic-acpi.h
+++ b/include/linux/irqchip/arm-gic-acpi.h
@@ -10,6 +10,8 @@
 #ifndef ARM_GIC_ACPI_H_
 #define ARM_GIC_ACPI_H_
 
+#include <linux/irqchip/arm-gic.h>
+
 #ifdef CONFIG_ACPI
 
 /*
@@ -22,8 +24,8 @@
 
 struct acpi_table_header;
 
-int gic_v2_acpi_init(struct acpi_table_header *table);
-void acpi_gic_init(void);
+void acpi_irq_init(void);
+int gic_v2_acpi_init(struct acpi_table_header *table, struct irq_domain **domain);
 #else
 static inline void acpi_gic_init(void) { }
 #endif
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9de976b..f490f26 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -89,12 +89,25 @@
 #define GICH_MISR_EOI			(1 << 0)
 #define GICH_MISR_U			(1 << 1)
 
+#define GIC_INT_TYPE_SPI       0
+#define GIC_INT_TYPE_PPI       1
+#define GIC_INT_TYPE_NONE      ~0U
+
 #ifndef __ASSEMBLY__
 
 #include <linux/irqdomain.h>
 
 struct device_node;
 
+struct gic_irq_alloc_info {
+
+   enum irq_domain_ref_type ref_type;
+   void *ref;
+   unsigned int irq_type;
+   unsigned int gic_int_type;
+   unsigned int hwirq;
+};
+
 void gic_set_irqchip_flags(unsigned long flags);
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
 		    u32 offset, struct device_node *);
@@ -114,5 +127,9 @@ int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
 unsigned long gic_get_sgir_physaddr(void);
 
+extern int gic_init_irq_alloc_info(unsigned int gic_int_type, unsigned int irq,
+                  unsigned int irq_type, void *ref,
+                  struct gic_irq_alloc_info *info);
+
 #endif /* __ASSEMBLY */
 #endif
-- 
1.9.1