diff options
Diffstat (limited to 'recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch')
-rw-r--r-- | recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch b/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch new file mode 100644 index 0000000..16c2dbd --- /dev/null +++ b/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch | |||
@@ -0,0 +1,418 @@ | |||
1 | From 6082a087207706d5951768d2d48aaa2d21fc2c0d Mon Sep 17 00:00:00 2001 | ||
2 | From: Adrian Calianu <adrian.calianu@enea.com> | ||
3 | Date: Tue, 11 Aug 2015 15:09:19 +0200 | ||
4 | Subject: [PATCH] DO NOT UPSTREAM YET: Introducing ACPI support for GICv2m | ||
5 | |||
6 | From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> | ||
7 | Date: Tue, 20 Jan 2015 23:21:20 -0600 | ||
8 | |||
9 | Signed-off-by: Adrian Calianu <adrian.calianu@enea.com> | ||
10 | --- | ||
11 | drivers/irqchip/irq-gic-v2m.c | 193 ++++++++++++++++++++++++++--------- | ||
12 | drivers/pci/pci-acpi.c | 55 ++++++---- | ||
13 | include/linux/irqchip/arm-gic-acpi.h | 1 + | ||
14 | include/linux/pci-acpi.h | 3 + | ||
15 | 4 files changed, 185 insertions(+), 67 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c | ||
18 | index fdf7065..c32eb55 100644 | ||
19 | --- a/drivers/irqchip/irq-gic-v2m.c | ||
20 | +++ b/drivers/irqchip/irq-gic-v2m.c | ||
21 | @@ -15,6 +15,7 @@ | ||
22 | |||
23 | #define pr_fmt(fmt) "GICv2m: " fmt | ||
24 | |||
25 | +#include <linux/acpi.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | #include <linux/kernel.h> | ||
29 | @@ -22,6 +23,7 @@ | ||
30 | #include <linux/of_pci.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | +#include <linux/irqchip/arm-gic.h> | ||
34 | |||
35 | /* | ||
36 | * MSI_TYPER: | ||
37 | @@ -45,7 +47,6 @@ | ||
38 | |||
39 | struct v2m_data { | ||
40 | spinlock_t msi_cnt_lock; | ||
41 | - struct msi_controller mchip; | ||
42 | struct resource res; /* GICv2m resource */ | ||
43 | void __iomem *base; /* GICv2m virt address */ | ||
44 | u32 spi_start; /* The SPI number that MSIs start */ | ||
45 | @@ -115,17 +116,17 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain, | ||
46 | unsigned int virq, | ||
47 | irq_hw_number_t hwirq) | ||
48 | { | ||
49 | - struct of_phandle_args args; | ||
50 | + struct gic_irq_alloc_info info; | ||
51 | struct irq_data *d; | ||
52 | int err; | ||
53 | |||
54 | - args.np = domain->parent->of_node; | ||
55 | - args.args_count = 3; | ||
56 | - args.args[0] = 0; | ||
57 | - args.args[1] = hwirq - 32; | ||
58 | - args.args[2] = IRQ_TYPE_EDGE_RISING; | ||
59 | + err = gic_init_irq_alloc_info(GIC_INT_TYPE_NONE, hwirq, | ||
60 | + IRQ_TYPE_EDGE_RISING, | ||
61 | + domain->parent->of_node, &info); | ||
62 | + if (err) | ||
63 | + return err; | ||
64 | |||
65 | - err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args); | ||
66 | + err = irq_domain_alloc_irqs_parent(domain, virq, 1, &info); | ||
67 | if (err) | ||
68 | return err; | ||
69 | |||
70 | @@ -192,7 +193,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *domain, | ||
71 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); | ||
72 | } | ||
73 | |||
74 | -static const struct irq_domain_ops gicv2m_domain_ops = { | ||
75 | +static struct irq_domain_ops gicv2m_domain_ops = { | ||
76 | .alloc = gicv2m_irq_domain_alloc, | ||
77 | .free = gicv2m_irq_domain_free, | ||
78 | }; | ||
79 | @@ -213,11 +214,18 @@ static bool is_msi_spi_valid(u32 base, u32 num) | ||
80 | return true; | ||
81 | } | ||
82 | |||
83 | -static int __init gicv2m_init_one(struct device_node *node, | ||
84 | - struct irq_domain *parent) | ||
85 | +char gicv2m_msi_domain_name[] = "V2M-MSI"; | ||
86 | +char gicv2m_domain_name[] = "GICV2M"; | ||
87 | + | ||
88 | +static int __init gicv2m_init_one(struct irq_domain *parent, | ||
89 | + u32 *spi_start, u32 *nr_spis, | ||
90 | + struct resource *res, | ||
91 | + enum irq_domain_ref_type type, | ||
92 | + void *ref) | ||
93 | { | ||
94 | int ret; | ||
95 | struct v2m_data *v2m; | ||
96 | + struct irq_domain *inner_domain; | ||
97 | |||
98 | v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL); | ||
99 | if (!v2m) { | ||
100 | @@ -225,23 +233,17 @@ static int __init gicv2m_init_one(struct device_node *node, | ||
101 | return -ENOMEM; | ||
102 | } | ||
103 | |||
104 | - ret = of_address_to_resource(node, 0, &v2m->res); | ||
105 | - if (ret) { | ||
106 | - pr_err("Failed to allocate v2m resource.\n"); | ||
107 | - goto err_free_v2m; | ||
108 | - } | ||
109 | - | ||
110 | - v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res)); | ||
111 | + v2m->base = ioremap(res->start, resource_size(res)); | ||
112 | if (!v2m->base) { | ||
113 | pr_err("Failed to map GICv2m resource\n"); | ||
114 | ret = -ENOMEM; | ||
115 | goto err_free_v2m; | ||
116 | } | ||
117 | + memcpy(&v2m->res,res, sizeof(struct resource)); | ||
118 | |||
119 | - if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) && | ||
120 | - !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) { | ||
121 | - pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n", | ||
122 | - v2m->spi_start, v2m->nr_spis); | ||
123 | + if (*spi_start && *nr_spis) { | ||
124 | + v2m->spi_start = *spi_start; | ||
125 | + v2m->nr_spis = *nr_spis; | ||
126 | } else { | ||
127 | u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER); | ||
128 | |||
129 | @@ -261,43 +263,50 @@ static int __init gicv2m_init_one(struct device_node *node, | ||
130 | goto err_iounmap; | ||
131 | } | ||
132 | |||
133 | - v2m->domain = irq_domain_add_tree(NULL, &gicv2m_domain_ops, v2m); | ||
134 | - if (!v2m->domain) { | ||
135 | + inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m); | ||
136 | + if (!inner_domain) { | ||
137 | pr_err("Failed to create GICv2m domain\n"); | ||
138 | ret = -ENOMEM; | ||
139 | goto err_free_bm; | ||
140 | } | ||
141 | |||
142 | - v2m->domain->parent = parent; | ||
143 | - v2m->mchip.of_node = node; | ||
144 | - v2m->mchip.domain = pci_msi_create_irq_domain(node, | ||
145 | - &gicv2m_msi_domain_info, | ||
146 | - v2m->domain); | ||
147 | - if (!v2m->mchip.domain) { | ||
148 | - pr_err("Failed to create MSI domain\n"); | ||
149 | - ret = -ENOMEM; | ||
150 | - goto err_free_domains; | ||
151 | - } | ||
152 | - | ||
153 | - spin_lock_init(&v2m->msi_cnt_lock); | ||
154 | - | ||
155 | - ret = of_pci_msi_chip_add(&v2m->mchip); | ||
156 | - if (ret) { | ||
157 | - pr_err("Failed to add msi_chip.\n"); | ||
158 | - goto err_free_domains; | ||
159 | - } | ||
160 | - | ||
161 | - pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name, | ||
162 | - (unsigned long)v2m->res.start, (unsigned long)v2m->res.end, | ||
163 | - v2m->spi_start, (v2m->spi_start + v2m->nr_spis)); | ||
164 | + inner_domain->bus_token = DOMAIN_BUS_PLATFORM_MSI; | ||
165 | + inner_domain->name = gicv2m_domain_name; | ||
166 | + | ||
167 | + ret = -ENOMEM; | ||
168 | + if (type == IRQ_DOMAIN_REF_OF_DEV_NODE) { | ||
169 | + v2m->domain = pci_msi_create_irq_domain( | ||
170 | + (struct device_node *)ref, | ||
171 | + &gicv2m_msi_domain_info, | ||
172 | + inner_domain); | ||
173 | + if (!v2m->domain) { | ||
174 | + pr_err("Failed to create MSI domain\n"); | ||
175 | + goto err_free_domains; | ||
176 | + } | ||
177 | + } else { | ||
178 | + v2m->domain = pci_msi_create_irq_domain( NULL, | ||
179 | + &gicv2m_msi_domain_info, | ||
180 | + inner_domain); | ||
181 | + if (!v2m->domain) { | ||
182 | + pr_err("Failed to create MSI domain\n"); | ||
183 | + goto err_free_domains; | ||
184 | + } | ||
185 | + | ||
186 | + v2m->domain->type = type; | ||
187 | + v2m->domain->acpi_ref = ref; | ||
188 | + } | ||
189 | + | ||
190 | + v2m->domain->name = gicv2m_msi_domain_name; | ||
191 | + | ||
192 | + spin_lock_init(&v2m->msi_cnt_lock); | ||
193 | |||
194 | return 0; | ||
195 | |||
196 | err_free_domains: | ||
197 | - if (v2m->mchip.domain) | ||
198 | - irq_domain_remove(v2m->mchip.domain); | ||
199 | if (v2m->domain) | ||
200 | irq_domain_remove(v2m->domain); | ||
201 | + if (inner_domain) | ||
202 | + irq_domain_remove(inner_domain); | ||
203 | err_free_bm: | ||
204 | kfree(v2m->bm); | ||
205 | err_iounmap: | ||
206 | @@ -319,15 +328,101 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent) | ||
207 | |||
208 | for (child = of_find_matching_node(node, gicv2m_device_id); child; | ||
209 | child = of_find_matching_node(child, gicv2m_device_id)) { | ||
210 | + u32 spi_start = 0, nr_spis = 0; | ||
211 | + struct resource res; | ||
212 | + | ||
213 | if (!of_find_property(child, "msi-controller", NULL)) | ||
214 | continue; | ||
215 | |||
216 | - ret = gicv2m_init_one(child, parent); | ||
217 | + ret = of_address_to_resource(child, 0, &res); | ||
218 | + if (ret) { | ||
219 | + pr_err("Failed to allocate v2m resource.\n"); | ||
220 | + break; | ||
221 | + } | ||
222 | + | ||
223 | + if (!of_property_read_u32(child, "arm,msi-base-spi", &spi_start) && | ||
224 | + !of_property_read_u32(child, "arm,msi-num-spis", &nr_spis)) | ||
225 | + pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n", | ||
226 | + spi_start, nr_spis); | ||
227 | + | ||
228 | + ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res, | ||
229 | + IRQ_DOMAIN_REF_OF_DEV_NODE, child); | ||
230 | + | ||
231 | if (ret) { | ||
232 | of_node_put(node); | ||
233 | break; | ||
234 | } | ||
235 | + pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", child->name, | ||
236 | + (unsigned long)res.start, (unsigned long)res.end, | ||
237 | + spi_start, (spi_start + nr_spis)); | ||
238 | } | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | + | ||
243 | +#ifdef CONFIG_ACPI | ||
244 | +static struct acpi_madt_generic_msi_frame *msi_frame; | ||
245 | + | ||
246 | +static int __init | ||
247 | +gicv2m_acpi_parse_madt_msi(struct acpi_subtable_header *header, | ||
248 | + const unsigned long end) | ||
249 | +{ | ||
250 | + struct acpi_madt_generic_msi_frame *frame; | ||
251 | + | ||
252 | + frame = (struct acpi_madt_generic_msi_frame *)header; | ||
253 | + if (BAD_MADT_ENTRY(frame, end)) | ||
254 | + return -EINVAL; | ||
255 | + | ||
256 | + if (msi_frame) | ||
257 | + pr_warn("Only one GIC MSI FRAME supported.\n"); | ||
258 | + else | ||
259 | + msi_frame = frame; | ||
260 | + | ||
261 | + return 0; | ||
262 | +} | ||
263 | + | ||
264 | +int __init gicv2m_acpi_init(struct acpi_table_header *table, | ||
265 | + struct irq_domain *parent) | ||
266 | +{ | ||
267 | + int ret = 0; | ||
268 | + int count, i; | ||
269 | + struct acpi_madt_generic_msi_frame *cur; | ||
270 | + | ||
271 | + count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), | ||
272 | + gicv2m_acpi_parse_madt_msi, table, | ||
273 | + ACPI_MADT_TYPE_GENERIC_MSI_FRAME, 0); | ||
274 | + | ||
275 | + if ((count <= 0) || !msi_frame) { | ||
276 | + pr_debug("No valid ACPI GIC MSI FRAME exist\n"); | ||
277 | + return 0; | ||
278 | + } | ||
279 | + | ||
280 | + for (i = 0, cur = msi_frame; i < count; i++, cur++) { | ||
281 | + struct resource res; | ||
282 | + u32 spi_start = 0, nr_spis = 0; | ||
283 | + | ||
284 | + res.start = cur->base_address; | ||
285 | + res.end = cur->base_address + 0x1000; | ||
286 | + | ||
287 | + if (cur->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) { | ||
288 | + spi_start = cur->spi_base; | ||
289 | + nr_spis = cur->spi_count; | ||
290 | + | ||
291 | + pr_info("ACPI overriding V2M MSI_TYPER (base:%u, num:%u)\n", | ||
292 | + spi_start, nr_spis); | ||
293 | + } | ||
294 | + | ||
295 | + ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res, | ||
296 | + IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame); | ||
297 | + if (ret) | ||
298 | + break; | ||
299 | + | ||
300 | + pr_info("MSI frame ID %u: range[%#lx:%#lx], SPI[%d:%d]\n", | ||
301 | + cur->msi_frame_id, | ||
302 | + (unsigned long)res.start, (unsigned long)res.end, | ||
303 | + spi_start, (spi_start + nr_spis)); | ||
304 | + } | ||
305 | + return ret; | ||
306 | +} | ||
307 | + | ||
308 | +#endif /* CONFIG_ACPI */ | ||
309 | diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c | ||
310 | index fe42097..fa0d8ec 100644 | ||
311 | --- a/drivers/pci/pci-acpi.c | ||
312 | +++ b/drivers/pci/pci-acpi.c | ||
313 | @@ -9,6 +9,7 @@ | ||
314 | |||
315 | #include <linux/delay.h> | ||
316 | #include <linux/init.h> | ||
317 | +#include <linux/irqdomain.h> | ||
318 | #include <linux/pci.h> | ||
319 | #include <linux/pci_hotplug.h> | ||
320 | #include <linux/module.h> | ||
321 | @@ -717,25 +718,43 @@ static int __init acpi_pci_init(void) | ||
322 | arch_initcall(acpi_pci_init); | ||
323 | |||
324 | #ifdef CONFIG_PCI_MSI | ||
325 | -void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) { | ||
326 | +static struct acpi_madt_generic_msi_frame *msi_frame; | ||
327 | +static int | ||
328 | +pci_acpi_parse_madt_msi(struct acpi_subtable_header *header, | ||
329 | + const unsigned long end) | ||
330 | +{ | ||
331 | + struct acpi_madt_generic_msi_frame *frame; | ||
332 | + frame = (struct acpi_madt_generic_msi_frame *)header; | ||
333 | + if (BAD_MADT_ENTRY(frame, end)) | ||
334 | + return -EINVAL; | ||
335 | + | ||
336 | + /* We currently support one MSI frame only */ | ||
337 | + if (!msi_frame) | ||
338 | + msi_frame = frame; | ||
339 | + | ||
340 | + return 0; | ||
341 | +} | ||
342 | + | ||
343 | +void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) | ||
344 | +{ | ||
345 | + int count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_MSI_FRAME, | ||
346 | + pci_acpi_parse_madt_msi, 0); | ||
347 | + if (count > 0) { | ||
348 | #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN | ||
349 | - u32 msi_frame_id = 0; | ||
350 | - int num; | ||
351 | - | ||
352 | - if (acpi_disabled) | ||
353 | - return; | ||
354 | - | ||
355 | - /** | ||
356 | - * Since ACPI 5.1 currently does not define | ||
357 | - * a way to associate MSI frame ID to a device, | ||
358 | - * we can only support single MSI frame at the moment. | ||
359 | - * Therefore, the id 0 is used as a default. | ||
360 | - */ | ||
361 | - num = msi_get_num_irq_domain(); | ||
362 | - if (num <= 0 || num > 1) | ||
363 | - return; | ||
364 | - | ||
365 | - dev_set_msi_domain(&bus->dev, irq_find_acpi_msi_domain(msi_frame_id)); | ||
366 | + struct irq_domain *domain; | ||
367 | + /** | ||
368 | + * Since ACPI 5.1 currently does not define | ||
369 | + * a way to associate MSI frame ID to a device, | ||
370 | + * we can only support single MSI frame at the moment. | ||
371 | + */ | ||
372 | + domain = irq_find_domain(IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame); | ||
373 | + if (!domain) { | ||
374 | + pr_debug("Fail to find domain for MSI\n"); | ||
375 | + return; | ||
376 | + } | ||
377 | + | ||
378 | + dev_set_msi_domain(&bus->dev, domain); | ||
379 | #endif | ||
380 | + } | ||
381 | } | ||
382 | #endif /* CONFIG_PCI_MSI */ | ||
383 | diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h | ||
384 | index fa8033b..b02f065 100644 | ||
385 | --- a/include/linux/irqchip/arm-gic-acpi.h | ||
386 | +++ b/include/linux/irqchip/arm-gic-acpi.h | ||
387 | @@ -26,6 +26,7 @@ struct acpi_table_header; | ||
388 | |||
389 | void acpi_irq_init(void); | ||
390 | int gic_v2_acpi_init(struct acpi_table_header *table, struct irq_domain **domain); | ||
391 | +int gicv2m_acpi_init(struct acpi_table_header *table, struct irq_domain *parent); | ||
392 | #else | ||
393 | static inline void acpi_gic_init(void) { } | ||
394 | #endif | ||
395 | diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h | ||
396 | index a965efa..759916d 100644 | ||
397 | --- a/include/linux/pci-acpi.h | ||
398 | +++ b/include/linux/pci-acpi.h | ||
399 | @@ -77,6 +77,8 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { } | ||
400 | static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { } | ||
401 | #endif | ||
402 | |||
403 | +void pci_acpi_set_phb_msi_domain(struct pci_bus *bus); | ||
404 | + | ||
405 | extern const u8 pci_acpi_dsm_uuid[]; | ||
406 | #define DEVICE_LABEL_DSM 0x07 | ||
407 | #define RESET_DELAY_DSM 0x08 | ||
408 | @@ -85,6 +87,7 @@ extern const u8 pci_acpi_dsm_uuid[]; | ||
409 | #else /* CONFIG_ACPI */ | ||
410 | static inline void acpi_pci_add_bus(struct pci_bus *bus) { } | ||
411 | static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } | ||
412 | +static inline void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) { }; | ||
413 | #endif /* CONFIG_ACPI */ | ||
414 | |||
415 | #ifdef CONFIG_ACPI_APEI | ||
416 | -- | ||
417 | 1.9.1 | ||
418 | |||