[tip:irq/core] genirq/debugfs: Reinstate full OF path for domain name
Commit-ID: 94967b55ebf3b603f2fe750ecedd896042585a1c Gitweb: https://git.kernel.org/tip/94967b55ebf3b603f2fe750ecedd896042585a1c Author: Marc Zyngier AuthorDate: Mon, 1 Oct 2018 11:05:22 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Oct 2018 12:24:53 +0200 genirq/debugfs: Reinstate full OF path for domain name On a DT based system, we use the of_node full name to name the corresponding irq domain. We expect that name to be unique, so so that domains with the same base name won't clash (this happens on multi-node topologies, for example). Since a7e4cfb0a7ca ("of/fdt: only store the device node basename in full_name"), of_node_full_name() lies and only returns the basename. This breaks the above requirement, and we end-up with only a subset of the domains in /sys/kernel/debug/irq/domains. Let's reinstate the feature by using the fancy new %pOF format specifier, which happens to do the right thing. Fixes: a7e4cfb0a7ca ("of/fdt: only store the device node basename in full_name") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20181001100522.180054-3-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 95a0acbdd4e6..3b30a4aeb0db 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -183,7 +183,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, * unhappy about. Replace them with ':', which does * the trick and is not as offensive as '\'... */ - name = kstrdup(of_node_full_name(of_node), GFP_KERNEL); + name = kasprintf(GFP_KERNEL, "%pOF", of_node); if (!name) { kfree(domain); return NULL;
[tip:irq/core] genirq/debugfs: Reinstate full OF path for domain name
Commit-ID: 94967b55ebf3b603f2fe750ecedd896042585a1c Gitweb: https://git.kernel.org/tip/94967b55ebf3b603f2fe750ecedd896042585a1c Author: Marc Zyngier AuthorDate: Mon, 1 Oct 2018 11:05:22 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Oct 2018 12:24:53 +0200 genirq/debugfs: Reinstate full OF path for domain name On a DT based system, we use the of_node full name to name the corresponding irq domain. We expect that name to be unique, so so that domains with the same base name won't clash (this happens on multi-node topologies, for example). Since a7e4cfb0a7ca ("of/fdt: only store the device node basename in full_name"), of_node_full_name() lies and only returns the basename. This breaks the above requirement, and we end-up with only a subset of the domains in /sys/kernel/debug/irq/domains. Let's reinstate the feature by using the fancy new %pOF format specifier, which happens to do the right thing. Fixes: a7e4cfb0a7ca ("of/fdt: only store the device node basename in full_name") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20181001100522.180054-3-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 95a0acbdd4e6..3b30a4aeb0db 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -183,7 +183,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, * unhappy about. Replace them with ':', which does * the trick and is not as offensive as '\'... */ - name = kstrdup(of_node_full_name(of_node), GFP_KERNEL); + name = kasprintf(GFP_KERNEL, "%pOF", of_node); if (!name) { kfree(domain); return NULL;
[tip:irq/core] genirq/debugfs: Reset domain debugfs_file on removal of the debugfs file
Commit-ID: 513145ea66af95f1a5c744d7b5a4f4a97625e669 Gitweb: https://git.kernel.org/tip/513145ea66af95f1a5c744d7b5a4f4a97625e669 Author: Marc Zyngier AuthorDate: Mon, 1 Oct 2018 11:05:21 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Oct 2018 12:24:53 +0200 genirq/debugfs: Reset domain debugfs_file on removal of the debugfs file When removing a debugfs file for a given irq domain, we fail to clear the corresponding field, meaning that the corresponding domain won't be created again if we need to do so. It turns out that this is exactly what irq_domain_update_bus_token does (delete old file, update domain name, recreate file). This doesn't have any impact other than making debug more difficult, but we do value ease of debugging... So clear the debugfs_file field. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20181001100522.180054-2-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 5d9fc01b60a6..95a0acbdd4e6 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1741,6 +1741,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d) static void debugfs_remove_domain_dir(struct irq_domain *d) { debugfs_remove(d->debugfs_file); + d->debugfs_file = NULL; } void __init irq_domain_debugfs_init(struct dentry *root)
[tip:irq/core] genirq/debugfs: Reset domain debugfs_file on removal of the debugfs file
Commit-ID: 513145ea66af95f1a5c744d7b5a4f4a97625e669 Gitweb: https://git.kernel.org/tip/513145ea66af95f1a5c744d7b5a4f4a97625e669 Author: Marc Zyngier AuthorDate: Mon, 1 Oct 2018 11:05:21 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Oct 2018 12:24:53 +0200 genirq/debugfs: Reset domain debugfs_file on removal of the debugfs file When removing a debugfs file for a given irq domain, we fail to clear the corresponding field, meaning that the corresponding domain won't be created again if we need to do so. It turns out that this is exactly what irq_domain_update_bus_token does (delete old file, update domain name, recreate file). This doesn't have any impact other than making debug more difficult, but we do value ease of debugging... So clear the debugfs_file field. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20181001100522.180054-2-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 5d9fc01b60a6..95a0acbdd4e6 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1741,6 +1741,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d) static void debugfs_remove_domain_dir(struct irq_domain *d) { debugfs_remove(d->debugfs_file); + d->debugfs_file = NULL; } void __init irq_domain_debugfs_init(struct dentry *root)
[tip:irq/urgent] irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug
Commit-ID: 82f499c8811149069ec958b72a86643a7a289b25 Gitweb: https://git.kernel.org/tip/82f499c8811149069ec958b72a86643a7a289b25 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:54 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:02 +0200 irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug Enabling LPIs was made a lot stricter recently, by checking that they are disabled before enabling them. By doing so, the CPU hotplug case was missed altogether, which leaves LPIs enabled on hotplug off (expecting the CPU to eventually come back), and won't write a different value anyway on hotplug on. So skip that check if that particular case is detected Fixes: 6eb486b66a30 ("irqchip/gic-v3: Ensure GICR_CTLR.EnableLPI=0 is observed before enabling") Reported-by: Sumit Garg Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Sumit Garg Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Link: https://lkml.kernel.org/r/20180622095254.5906-8-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0269ffb93f6e..d7842d312d3e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3427,6 +3427,16 @@ static int redist_disable_lpis(void) u64 timeout = USEC_PER_SEC; u64 val; + /* +* If coming via a CPU hotplug event, we don't need to disable +* LPIs before trying to re-enable them. They are already +* configured and all is well in the world. Detect this case +* by checking the allocation of the pending table for the +* current CPU. +*/ + if (gic_data_rdist()->pend_page) + return 0; + if (!gic_rdists_supports_plpis()) { pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); return -ENXIO;
[tip:irq/urgent] irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug
Commit-ID: 82f499c8811149069ec958b72a86643a7a289b25 Gitweb: https://git.kernel.org/tip/82f499c8811149069ec958b72a86643a7a289b25 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:54 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:02 +0200 irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug Enabling LPIs was made a lot stricter recently, by checking that they are disabled before enabling them. By doing so, the CPU hotplug case was missed altogether, which leaves LPIs enabled on hotplug off (expecting the CPU to eventually come back), and won't write a different value anyway on hotplug on. So skip that check if that particular case is detected Fixes: 6eb486b66a30 ("irqchip/gic-v3: Ensure GICR_CTLR.EnableLPI=0 is observed before enabling") Reported-by: Sumit Garg Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Sumit Garg Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Link: https://lkml.kernel.org/r/20180622095254.5906-8-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0269ffb93f6e..d7842d312d3e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3427,6 +3427,16 @@ static int redist_disable_lpis(void) u64 timeout = USEC_PER_SEC; u64 val; + /* +* If coming via a CPU hotplug event, we don't need to disable +* LPIs before trying to re-enable them. They are already +* configured and all is well in the world. Detect this case +* by checking the allocation of the pending table for the +* current CPU. +*/ + if (gic_data_rdist()->pend_page) + return 0; + if (!gic_rdists_supports_plpis()) { pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); return -ENXIO;
[tip:irq/urgent] irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection
Commit-ID: 205e065d91d72e6afad112ea84f0ca60b30bf5ab Gitweb: https://git.kernel.org/tip/205e065d91d72e6afad112ea84f0ca60b30bf5ab Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:53 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:01 +0200 irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection Similarily to the SYNC operation, it must be verified that the VPE targetted by a VLPI is backed by a valid collection in the GIC driver data structures. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-7-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 18 +- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index fcfc96f8e0de..0269ffb93f6e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -190,6 +190,14 @@ static struct its_collection *valid_col(struct its_collection *col) return col; } +static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe) +{ + if (valid_col(its->collections + vpe->col_idx)) + return vpe; + + return NULL; +} + /* * ITS command descriptors - parameters to be encoded in a command * block. @@ -562,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vinvall_cmd.vpe; + return valid_vpe(its, desc->its_vinvall_cmd.vpe); } static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, @@ -584,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmapp_cmd.vpe; + return valid_vpe(its, desc->its_vmapp_cmd.vpe); } static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, @@ -607,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmapti_cmd.vpe; + return valid_vpe(its, desc->its_vmapti_cmd.vpe); } static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, @@ -630,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmovi_cmd.vpe; + return valid_vpe(its, desc->its_vmovi_cmd.vpe); } static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, @@ -648,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmovp_cmd.vpe; + return valid_vpe(its, desc->its_vmovp_cmd.vpe); } static u64 its_cmd_ptr_to_offset(struct its_node *its,
[tip:irq/urgent] irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection
Commit-ID: 205e065d91d72e6afad112ea84f0ca60b30bf5ab Gitweb: https://git.kernel.org/tip/205e065d91d72e6afad112ea84f0ca60b30bf5ab Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:53 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:01 +0200 irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection Similarily to the SYNC operation, it must be verified that the VPE targetted by a VLPI is backed by a valid collection in the GIC driver data structures. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-7-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 18 +- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index fcfc96f8e0de..0269ffb93f6e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -190,6 +190,14 @@ static struct its_collection *valid_col(struct its_collection *col) return col; } +static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe) +{ + if (valid_col(its->collections + vpe->col_idx)) + return vpe; + + return NULL; +} + /* * ITS command descriptors - parameters to be encoded in a command * block. @@ -562,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vinvall_cmd.vpe; + return valid_vpe(its, desc->its_vinvall_cmd.vpe); } static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, @@ -584,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmapp_cmd.vpe; + return valid_vpe(its, desc->its_vmapp_cmd.vpe); } static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, @@ -607,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmapti_cmd.vpe; + return valid_vpe(its, desc->its_vmapti_cmd.vpe); } static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, @@ -630,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmovi_cmd.vpe; + return valid_vpe(its, desc->its_vmovi_cmd.vpe); } static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, @@ -648,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, its_fixup_cmd(cmd); - return desc->its_vmovp_cmd.vpe; + return valid_vpe(its, desc->its_vmovp_cmd.vpe); } static u64 its_cmd_ptr_to_offset(struct its_node *its,
[tip:irq/urgent] irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection
Commit-ID: 83559b47cdc4d396fc1187a13b527d01b55e0fe6 Gitweb: https://git.kernel.org/tip/83559b47cdc4d396fc1187a13b527d01b55e0fe6 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:52 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:01 +0200 irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection It is possible, under obscure circumstances, to convince the ITS driver to emit a SYNC operation that targets a collection that is not bound to any redistributor (and the target_address field is zero) because the corresponding CPU has not been seen yet (the system has been booted with max_cpus="something small"). If the ITS is using the linear CPU number as the target, this is not a big deal, as we just end-up issuing a SYNC to CPU0. But if the ITS requires the physical address of the redistributor (with GITS_TYPER.PTA==1), we end-up asking the ITS to write to the physical address zero, which is not exactly a good idea (there has been report of the ITS locking up). This should of course never happen, but hey, this is SW... In order to avoid the above disaster, let's track which collections have been actually initialized, and let's not generate a SYNC if the collection hasn't been properly bound to a redistributor. Take this opportunity to spit our a warning, in the hope that someone may report the issue if it arrises again. Reported-by: Yang Yingliang Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-6-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 25 +++-- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index cae53937feeb..fcfc96f8e0de 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -182,6 +182,14 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, return its->collections + its_dev->event_map.col_map[event]; } +static struct its_collection *valid_col(struct its_collection *col) +{ + if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15))) + return NULL; + + return col; +} + /* * ITS command descriptors - parameters to be encoded in a command * block. @@ -439,7 +447,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_movi_cmd(struct its_node *its, @@ -458,7 +466,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_discard_cmd(struct its_node *its, @@ -476,7 +484,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_inv_cmd(struct its_node *its, @@ -494,7 +502,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_int_cmd(struct its_node *its, @@ -512,7 +520,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_clear_cmd(struct its_node *its, @@ -530,7 +538,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_invall_cmd(struct its_node *its, @@ -1824,11 +1832,16 @@ static int its_alloc_tables(struct its_node *its) static int its_alloc_collections(struct its_node *its) { + int i; + its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), GFP_KERNEL); if (!its->collections) return -ENOMEM; + for (i = 0; i < nr_cpu_ids; i++) + its->collections[i].target_address = ~0ULL; + return 0; }
[tip:irq/urgent] irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection
Commit-ID: 83559b47cdc4d396fc1187a13b527d01b55e0fe6 Gitweb: https://git.kernel.org/tip/83559b47cdc4d396fc1187a13b527d01b55e0fe6 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:52 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:01 +0200 irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection It is possible, under obscure circumstances, to convince the ITS driver to emit a SYNC operation that targets a collection that is not bound to any redistributor (and the target_address field is zero) because the corresponding CPU has not been seen yet (the system has been booted with max_cpus="something small"). If the ITS is using the linear CPU number as the target, this is not a big deal, as we just end-up issuing a SYNC to CPU0. But if the ITS requires the physical address of the redistributor (with GITS_TYPER.PTA==1), we end-up asking the ITS to write to the physical address zero, which is not exactly a good idea (there has been report of the ITS locking up). This should of course never happen, but hey, this is SW... In order to avoid the above disaster, let's track which collections have been actually initialized, and let's not generate a SYNC if the collection hasn't been properly bound to a redistributor. Take this opportunity to spit our a warning, in the hope that someone may report the issue if it arrises again. Reported-by: Yang Yingliang Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-6-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 25 +++-- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index cae53937feeb..fcfc96f8e0de 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -182,6 +182,14 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, return its->collections + its_dev->event_map.col_map[event]; } +static struct its_collection *valid_col(struct its_collection *col) +{ + if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15))) + return NULL; + + return col; +} + /* * ITS command descriptors - parameters to be encoded in a command * block. @@ -439,7 +447,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_movi_cmd(struct its_node *its, @@ -458,7 +466,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_discard_cmd(struct its_node *its, @@ -476,7 +484,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_inv_cmd(struct its_node *its, @@ -494,7 +502,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_int_cmd(struct its_node *its, @@ -512,7 +520,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_clear_cmd(struct its_node *its, @@ -530,7 +538,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its, its_fixup_cmd(cmd); - return col; + return valid_col(col); } static struct its_collection *its_build_invall_cmd(struct its_node *its, @@ -1824,11 +1832,16 @@ static int its_alloc_tables(struct its_node *its) static int its_alloc_collections(struct its_node *its) { + int i; + its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), GFP_KERNEL); if (!its->collections) return -ENOMEM; + for (i = 0; i < nr_cpu_ids; i++) + its->collections[i].target_address = ~0ULL; + return 0; }
[tip:irq/urgent] irqchip/gic-v2m: Fix SPI release on error path
Commit-ID: cbaf45a6be497c272e80500e4fd9bccdf20d5050 Gitweb: https://git.kernel.org/tip/cbaf45a6be497c272e80500e4fd9bccdf20d5050 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:50 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 irqchip/gic-v2m: Fix SPI release on error path On failing to allocate the required SPIs, the actual number of interrupts should be freed and not its log2 value. Fixes: de337ee30142 ("irqchip/gic-v2m: Add PCI Multi-MSI support") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-4-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 0f52d44b3f69..f5fe0100f9ff 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, fail: irq_domain_free_irqs_parent(domain, virq, nr_irqs); - gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs)); + gicv2m_unalloc_msi(v2m, hwirq, nr_irqs); return err; }
[tip:irq/urgent] irqchip/gic-v2m: Fix SPI release on error path
Commit-ID: cbaf45a6be497c272e80500e4fd9bccdf20d5050 Gitweb: https://git.kernel.org/tip/cbaf45a6be497c272e80500e4fd9bccdf20d5050 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:50 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 irqchip/gic-v2m: Fix SPI release on error path On failing to allocate the required SPIs, the actual number of interrupts should be freed and not its log2 value. Fixes: de337ee30142 ("irqchip/gic-v2m: Add PCI Multi-MSI support") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-4-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 0f52d44b3f69..f5fe0100f9ff 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, fail: irq_domain_free_irqs_parent(domain, virq, nr_irqs); - gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs)); + gicv2m_unalloc_msi(v2m, hwirq, nr_irqs); return err; }
[tip:irq/urgent] irqchip/ls-scfg-msi: Fix MSI affinity handling
Commit-ID: 893fbfff976cd069f2e60c3b186dbe3f85504db2 Gitweb: https://git.kernel.org/tip/893fbfff976cd069f2e60c3b186dbe3f85504db2 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:49 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 irqchip/ls-scfg-msi: Fix MSI affinity handling The ls-scfs-msi driver is not dealing with the effective affinity as it should. Let's fix that, and make it clear that the effective affinity is restricted to a single CPU. Also prevent the driver from messing with the internals of the affinity setting infrastructure. Reported-by: Alexandre Belloni Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Alexandre Belloni Cc: Jason Cooper Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-3-marc.zyng...@arm.com --- drivers/irqchip/irq-ls-scfg-msi.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 1ec3bfe56693..c671b3212010 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c @@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) msg->address_lo = lower_32_bits(msi_data->msiir_addr); msg->data = data->hwirq; - if (msi_affinity_flag) - msg->data |= cpumask_first(data->common->affinity); + if (msi_affinity_flag) { + const struct cpumask *mask; + + mask = irq_data_get_effective_affinity_mask(data); + msg->data |= cpumask_first(mask); + } iommu_dma_map_msi_msg(data->irq, msg); } @@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, return -EINVAL; } - cpumask_copy(irq_data->common->affinity, mask); + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); return IRQ_SET_MASK_OK; }
[tip:irq/urgent] irqchip/ls-scfg-msi: Fix MSI affinity handling
Commit-ID: 893fbfff976cd069f2e60c3b186dbe3f85504db2 Gitweb: https://git.kernel.org/tip/893fbfff976cd069f2e60c3b186dbe3f85504db2 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:49 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 irqchip/ls-scfg-msi: Fix MSI affinity handling The ls-scfs-msi driver is not dealing with the effective affinity as it should. Let's fix that, and make it clear that the effective affinity is restricted to a single CPU. Also prevent the driver from messing with the internals of the affinity setting infrastructure. Reported-by: Alexandre Belloni Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Alexandre Belloni Cc: Jason Cooper Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-3-marc.zyng...@arm.com --- drivers/irqchip/irq-ls-scfg-msi.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 1ec3bfe56693..c671b3212010 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c @@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) msg->address_lo = lower_32_bits(msi_data->msiir_addr); msg->data = data->hwirq; - if (msi_affinity_flag) - msg->data |= cpumask_first(data->common->affinity); + if (msi_affinity_flag) { + const struct cpumask *mask; + + mask = irq_data_get_effective_affinity_mask(data); + msg->data |= cpumask_first(mask); + } iommu_dma_map_msi_msg(data->irq, msg); } @@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, return -EINVAL; } - cpumask_copy(irq_data->common->affinity, mask); + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); return IRQ_SET_MASK_OK; }
[tip:irq/urgent] genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug
Commit-ID: 72a8edc2d9134c2895eac2fec5eecf8230a05c96 Gitweb: https://git.kernel.org/tip/72a8edc2d9134c2895eac2fec5eecf8230a05c96 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:48 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug Debug is missing the IRQCHIP_SUPPORTS_LEVEL_MSI debug entry, making debugfs slightly less useful. Take this opportunity to also add a missing comment in the definition of IRQCHIP_SUPPORTS_LEVEL_MSI. Fixes: 6988e0e0d283 ("genirq/msi: Limit level-triggered MSI to platform devices") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-2-marc.zyng...@arm.com --- include/linux/irq.h | 1 + kernel/irq/debugfs.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/linux/irq.h b/include/linux/irq.h index 4bd2f34947f4..201de12a9957 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -503,6 +503,7 @@ struct irq_chip { * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode + * IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs */ enum { IRQCHIP_SET_TYPE_MASKED = (1 << 0), diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4dadeb3d..6f636136 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = { BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), + BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI), }; static void
[tip:irq/urgent] genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug
Commit-ID: 72a8edc2d9134c2895eac2fec5eecf8230a05c96 Gitweb: https://git.kernel.org/tip/72a8edc2d9134c2895eac2fec5eecf8230a05c96 Author: Marc Zyngier AuthorDate: Fri, 22 Jun 2018 10:52:48 +0100 Committer: Thomas Gleixner CommitDate: Fri, 22 Jun 2018 14:22:00 +0200 genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug Debug is missing the IRQCHIP_SUPPORTS_LEVEL_MSI debug entry, making debugfs slightly less useful. Take this opportunity to also add a missing comment in the definition of IRQCHIP_SUPPORTS_LEVEL_MSI. Fixes: 6988e0e0d283 ("genirq/msi: Limit level-triggered MSI to platform devices") Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Yang Yingliang Cc: Sumit Garg Link: https://lkml.kernel.org/r/20180622095254.5906-2-marc.zyng...@arm.com --- include/linux/irq.h | 1 + kernel/irq/debugfs.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/linux/irq.h b/include/linux/irq.h index 4bd2f34947f4..201de12a9957 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -503,6 +503,7 @@ struct irq_chip { * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode + * IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs */ enum { IRQCHIP_SET_TYPE_MASKED = (1 << 0), diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4dadeb3d..6f636136 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = { BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), + BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI), }; static void
[tip:irq/core] dt-bindings/gic-v3: Add documentation for MBI support
Commit-ID: 53667c670fe00d63246fb3cfb4480bb1ba247bcc Gitweb: https://git.kernel.org/tip/53667c670fe00d63246fb3cfb4480bb1ba247bcc Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:38 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:02 +0200 dt-bindings/gic-v3: Add documentation for MBI support Add the required properties to support the MBI feature on GICv3. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-10-marc.zyng...@arm.com --- .../bindings/interrupt-controller/arm,gic-v3.txt| 17 + 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt index 0a57f2f4167d..3ea78c4ef887 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt @@ -57,6 +57,20 @@ Optional occupied by the redistributors. Required if more than one such region is present. +- msi-controller: Boolean property. Identifies the node as an MSI + controller. Only present if the Message Based Interrupt + functionnality is being exposed by the HW, and the mbi-ranges + property present. + +- mbi-ranges: A list of pairs , where "intid" is the first + SPI of a range that can be used an MBI, and "span" the size of that + range. Multiple ranges can be provided. Requires "msi-controller" to + be set. + +- mbi-alias: Address property. Base address of an alias of the GICD + region containing only the {SET,CLR}SPI registers to be used if + isolation is required, and if supported by the HW. + Sub-nodes: PPI affinity can be expressed as a single "ppi-partitions" node, @@ -99,6 +113,9 @@ Examples: <0x0 0x2c02 0 0x2000>;// GICV interrupts = <1 9 4>; + msi-controller; + mbi-ranges = <256 128>; + gic-its@2c20 { compatible = "arm,gic-v3-its"; msi-controller;
[tip:irq/core] dt-bindings/gic-v3: Add documentation for MBI support
Commit-ID: 53667c670fe00d63246fb3cfb4480bb1ba247bcc Gitweb: https://git.kernel.org/tip/53667c670fe00d63246fb3cfb4480bb1ba247bcc Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:38 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:02 +0200 dt-bindings/gic-v3: Add documentation for MBI support Add the required properties to support the MBI feature on GICv3. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-10-marc.zyng...@arm.com --- .../bindings/interrupt-controller/arm,gic-v3.txt| 17 + 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt index 0a57f2f4167d..3ea78c4ef887 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt @@ -57,6 +57,20 @@ Optional occupied by the redistributors. Required if more than one such region is present. +- msi-controller: Boolean property. Identifies the node as an MSI + controller. Only present if the Message Based Interrupt + functionnality is being exposed by the HW, and the mbi-ranges + property present. + +- mbi-ranges: A list of pairs , where "intid" is the first + SPI of a range that can be used an MBI, and "span" the size of that + range. Multiple ranges can be provided. Requires "msi-controller" to + be set. + +- mbi-alias: Address property. Base address of an alias of the GICD + region containing only the {SET,CLR}SPI registers to be used if + isolation is required, and if supported by the HW. + Sub-nodes: PPI affinity can be expressed as a single "ppi-partitions" node, @@ -99,6 +113,9 @@ Examples: <0x0 0x2c02 0 0x2000>;// GICV interrupts = <1 9 4>; + msi-controller; + mbi-ranges = <256 128>; + gic-its@2c20 { compatible = "arm,gic-v3-its"; msi-controller;
[tip:irq/core] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
Commit-ID: 38985351492b4ef2f63ffe527ef7cdfa66680f94 Gitweb: https://git.kernel.org/tip/38985351492b4ef2f63ffe527ef7cdfa66680f94 Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:37 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver You would hope that if you have a GICv3 in your system, you'd use the ITS, as it provides a large interrupt ID space and device isolation. Sadly, some SoC integrations are less than perfect, and the ITS is not usesable on those. The only solution for these systems is to use the MBI interface, and rely on a very small number of possible vectors. This patch thus adds minimal support for PCI/MSI on top of the GICv3 MBI driver. Please don't use it if you can avoid it. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Ard Biesheuvel Tested-by: Srinivas Kandagatla Cc: Rob Herring Cc: Jason Cooper Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-9-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-mbi.c | 62 ++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c index 2b3b767050aa..ad70e7c416e3 100644 --- a/drivers/irqchip/irq-gic-v3-mbi.c +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -144,6 +145,55 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) iommu_dma_map_msi_msg(data->irq, msg); } +#ifdef CONFIG_PCI_MSI +/* PCI-specific irqchip */ +static void mbi_mask_msi_irq(struct irq_data *d) +{ + pci_msi_mask_irq(d); + irq_chip_mask_parent(d); +} + +static void mbi_unmask_msi_irq(struct irq_data *d) +{ + pci_msi_unmask_irq(d); + irq_chip_unmask_parent(d); +} + +static struct irq_chip mbi_msi_irq_chip = { + .name = "MSI", + .irq_mask = mbi_mask_msi_irq, + .irq_unmask = mbi_unmask_msi_irq, + .irq_eoi= irq_chip_eoi_parent, + .irq_compose_msi_msg= mbi_compose_msi_msg, + .irq_write_msi_msg = pci_msi_domain_write_msg, +}; + +static struct msi_domain_info mbi_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), + .chip = _msi_irq_chip, +}; + +static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, + struct irq_domain **pci_domain) +{ + *pci_domain = pci_msi_create_irq_domain(nexus_domain->parent->fwnode, + _msi_domain_info, + nexus_domain); + if (!*pci_domain) + return -ENOMEM; + + return 0; +} +#else +static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, + struct irq_domain **pci_domain) +{ + *pci_domain = NULL; + return 0; +} +#endif + static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg) { mbi_compose_msi_msg(data, msg); @@ -175,7 +225,8 @@ static struct msi_domain_info mbi_pmsi_domain_info = { static int mbi_allocate_domains(struct irq_domain *parent) { - struct irq_domain *nexus_domain, *plat_domain; + struct irq_domain *nexus_domain, *pci_domain, *plat_domain; + int err; nexus_domain = irq_domain_create_tree(parent->fwnode, _domain_ops, NULL); @@ -185,12 +236,17 @@ static int mbi_allocate_domains(struct irq_domain *parent) irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS); nexus_domain->parent = parent; + err = mbi_allocate_pci_domain(nexus_domain, _domain); + plat_domain = platform_msi_create_irq_domain(parent->fwnode, _pmsi_domain_info, nexus_domain); - if (!plat_domain) { - irq_domain_remove(plat_domain); + if (err || !plat_domain) { + if (plat_domain) + irq_domain_remove(plat_domain); + if (pci_domain) + irq_domain_remove(pci_domain); irq_domain_remove(nexus_domain); return -ENOMEM; }
[tip:irq/core] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller
Commit-ID: 505287525c24d5c78b662fd73721ad9900b91fcc Gitweb: https://git.kernel.org/tip/505287525c24d5c78b662fd73721ad9900b91fcc Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:36 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller GICv3 offers the possibility to signal SPIs using a pair of doorbells (SETPI, CLRSPI) under the name of Message Based Interrupts (MBI). They can be used as either traditional (edge) MSIs, or the more exotic level-triggered flavour. Let's implement support for platform MSI, which is the original intent for this feature. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-8-marc.zyng...@arm.com --- drivers/irqchip/Makefile | 2 +- drivers/irqchip/irq-gic-v3-mbi.c | 275 + drivers/irqchip/irq-gic-v3.c | 6 + include/linux/irqchip/arm-gic-v3.h | 1 + 4 files changed, 283 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5ed465ab1c76..15f268f646bf 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW)+= irq-gic-realview.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o -obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o +obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o obj-$(CONFIG_ARM_GIC_V3_ITS_PCI) += irq-gic-v3-its-pci-msi.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)+= irq-gic-v3-its-fsl-mc-msi.o diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c new file mode 100644 index ..2b3b767050aa --- /dev/null +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 ARM Limited, All Rights Reserved. + * Author: Marc Zyngier + */ + +#define pr_fmt(fmt) "GICv3: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct mbi_range { + u32 spi_start; + u32 nr_spis; + unsigned long *bm; +}; + +static struct mutexmbi_lock; +static phys_addr_t mbi_phys_base; +static struct mbi_range*mbi_ranges; +static unsigned intmbi_range_nr; + +static struct irq_chip mbi_irq_chip = { + .name = "MBI", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi= irq_chip_eoi_parent, + .irq_set_type = irq_chip_set_type_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, +}; + +static int mbi_irq_gic_domain_alloc(struct irq_domain *domain, + unsigned int virq, + irq_hw_number_t hwirq) +{ + struct irq_fwspec fwspec; + struct irq_data *d; + int err; + + /* +* Using ACPI? There is no MBI support in the spec, you +* shouldn't even be here. +*/ + if (!is_of_node(domain->parent->fwnode)) + return -EINVAL; + + /* +* Let's default to edge. This is consistent with traditional +* MSIs, and systems requiring level signaling will just +* enforce the trigger on their own. +*/ + fwspec.fwnode = domain->parent->fwnode; + fwspec.param_count = 3; + fwspec.param[0] = 0; + fwspec.param[1] = hwirq - 32; + fwspec.param[2] = IRQ_TYPE_EDGE_RISING; + + err = irq_domain_alloc_irqs_parent(domain, virq, 1, ); + if (err) + return err; + + d = irq_domain_get_irq_data(domain->parent, virq); + return d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING); +} + +static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq, +int nr_irqs) +{ + mutex_lock(_lock); + bitmap_release_region(mbi->bm, hwirq - mbi->spi_start, + get_count_order(nr_irqs)); + mutex_unlock(_lock); +} + +static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, +
[tip:irq/core] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
Commit-ID: 38985351492b4ef2f63ffe527ef7cdfa66680f94 Gitweb: https://git.kernel.org/tip/38985351492b4ef2f63ffe527ef7cdfa66680f94 Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:37 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver You would hope that if you have a GICv3 in your system, you'd use the ITS, as it provides a large interrupt ID space and device isolation. Sadly, some SoC integrations are less than perfect, and the ITS is not usesable on those. The only solution for these systems is to use the MBI interface, and rely on a very small number of possible vectors. This patch thus adds minimal support for PCI/MSI on top of the GICv3 MBI driver. Please don't use it if you can avoid it. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Ard Biesheuvel Tested-by: Srinivas Kandagatla Cc: Rob Herring Cc: Jason Cooper Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-9-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-mbi.c | 62 ++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c index 2b3b767050aa..ad70e7c416e3 100644 --- a/drivers/irqchip/irq-gic-v3-mbi.c +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -144,6 +145,55 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) iommu_dma_map_msi_msg(data->irq, msg); } +#ifdef CONFIG_PCI_MSI +/* PCI-specific irqchip */ +static void mbi_mask_msi_irq(struct irq_data *d) +{ + pci_msi_mask_irq(d); + irq_chip_mask_parent(d); +} + +static void mbi_unmask_msi_irq(struct irq_data *d) +{ + pci_msi_unmask_irq(d); + irq_chip_unmask_parent(d); +} + +static struct irq_chip mbi_msi_irq_chip = { + .name = "MSI", + .irq_mask = mbi_mask_msi_irq, + .irq_unmask = mbi_unmask_msi_irq, + .irq_eoi= irq_chip_eoi_parent, + .irq_compose_msi_msg= mbi_compose_msi_msg, + .irq_write_msi_msg = pci_msi_domain_write_msg, +}; + +static struct msi_domain_info mbi_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), + .chip = _msi_irq_chip, +}; + +static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, + struct irq_domain **pci_domain) +{ + *pci_domain = pci_msi_create_irq_domain(nexus_domain->parent->fwnode, + _msi_domain_info, + nexus_domain); + if (!*pci_domain) + return -ENOMEM; + + return 0; +} +#else +static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, + struct irq_domain **pci_domain) +{ + *pci_domain = NULL; + return 0; +} +#endif + static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg) { mbi_compose_msi_msg(data, msg); @@ -175,7 +225,8 @@ static struct msi_domain_info mbi_pmsi_domain_info = { static int mbi_allocate_domains(struct irq_domain *parent) { - struct irq_domain *nexus_domain, *plat_domain; + struct irq_domain *nexus_domain, *pci_domain, *plat_domain; + int err; nexus_domain = irq_domain_create_tree(parent->fwnode, _domain_ops, NULL); @@ -185,12 +236,17 @@ static int mbi_allocate_domains(struct irq_domain *parent) irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS); nexus_domain->parent = parent; + err = mbi_allocate_pci_domain(nexus_domain, _domain); + plat_domain = platform_msi_create_irq_domain(parent->fwnode, _pmsi_domain_info, nexus_domain); - if (!plat_domain) { - irq_domain_remove(plat_domain); + if (err || !plat_domain) { + if (plat_domain) + irq_domain_remove(plat_domain); + if (pci_domain) + irq_domain_remove(pci_domain); irq_domain_remove(nexus_domain); return -ENOMEM; }
[tip:irq/core] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller
Commit-ID: 505287525c24d5c78b662fd73721ad9900b91fcc Gitweb: https://git.kernel.org/tip/505287525c24d5c78b662fd73721ad9900b91fcc Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:36 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller GICv3 offers the possibility to signal SPIs using a pair of doorbells (SETPI, CLRSPI) under the name of Message Based Interrupts (MBI). They can be used as either traditional (edge) MSIs, or the more exotic level-triggered flavour. Let's implement support for platform MSI, which is the original intent for this feature. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-8-marc.zyng...@arm.com --- drivers/irqchip/Makefile | 2 +- drivers/irqchip/irq-gic-v3-mbi.c | 275 + drivers/irqchip/irq-gic-v3.c | 6 + include/linux/irqchip/arm-gic-v3.h | 1 + 4 files changed, 283 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5ed465ab1c76..15f268f646bf 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW)+= irq-gic-realview.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o -obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o +obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o obj-$(CONFIG_ARM_GIC_V3_ITS_PCI) += irq-gic-v3-its-pci-msi.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)+= irq-gic-v3-its-fsl-mc-msi.o diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c new file mode 100644 index ..2b3b767050aa --- /dev/null +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 ARM Limited, All Rights Reserved. + * Author: Marc Zyngier + */ + +#define pr_fmt(fmt) "GICv3: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct mbi_range { + u32 spi_start; + u32 nr_spis; + unsigned long *bm; +}; + +static struct mutexmbi_lock; +static phys_addr_t mbi_phys_base; +static struct mbi_range*mbi_ranges; +static unsigned intmbi_range_nr; + +static struct irq_chip mbi_irq_chip = { + .name = "MBI", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi= irq_chip_eoi_parent, + .irq_set_type = irq_chip_set_type_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, +}; + +static int mbi_irq_gic_domain_alloc(struct irq_domain *domain, + unsigned int virq, + irq_hw_number_t hwirq) +{ + struct irq_fwspec fwspec; + struct irq_data *d; + int err; + + /* +* Using ACPI? There is no MBI support in the spec, you +* shouldn't even be here. +*/ + if (!is_of_node(domain->parent->fwnode)) + return -EINVAL; + + /* +* Let's default to edge. This is consistent with traditional +* MSIs, and systems requiring level signaling will just +* enforce the trigger on their own. +*/ + fwspec.fwnode = domain->parent->fwnode; + fwspec.param_count = 3; + fwspec.param[0] = 0; + fwspec.param[1] = hwirq - 32; + fwspec.param[2] = IRQ_TYPE_EDGE_RISING; + + err = irq_domain_alloc_irqs_parent(domain, virq, 1, ); + if (err) + return err; + + d = irq_domain_get_irq_data(domain->parent, virq); + return d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING); +} + +static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq, +int nr_irqs) +{ + mutex_lock(_lock); + bitmap_release_region(mbi->bm, hwirq - mbi->spi_start, + get_count_order(nr_irqs)); + mutex_unlock(_lock); +} + +static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *args) +{ + struct mbi_range *mbi = NULL; + int hwirq, offset, i, err = 0; + + mutex_lock(_lock); + for (i = 0; i < mbi_range_nr; i++) { + offset =
[tip:irq/core] irqchip/gic-v3: Mark the base irq domain as DOMAIN_BUS_WIRED
Commit-ID: b2425b51bed7437c08c11ce71bb0f308f4516451 Gitweb: https://git.kernel.org/tip/b2425b51bed7437c08c11ce71bb0f308f4516451 Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:35 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Mark the base irq domain as DOMAIN_BUS_WIRED As we're about to introduce MSI domains based on top of the GICv3 domain, we must make sure nothing the new domains do not alias with the core domain. So let's tag that core domain with the DOMAIN_BUS_WIRED attribute, ensuring it gets picked up by other drivers that use irq_find_host(). Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-7-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index e5d101418390..94164d7b87a6 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1099,6 +1099,7 @@ static int __init gic_init_bases(void __iomem *dist_base, gic_data.domain = irq_domain_create_tree(handle, _irq_domain_ops, _data); + irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED); gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist)); gic_data.rdists.has_vlpis = true; gic_data.rdists.has_direct_lpi = true;
[tip:irq/core] irqchip/gic-v3: Mark the base irq domain as DOMAIN_BUS_WIRED
Commit-ID: b2425b51bed7437c08c11ce71bb0f308f4516451 Gitweb: https://git.kernel.org/tip/b2425b51bed7437c08c11ce71bb0f308f4516451 Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:35 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:01 +0200 irqchip/gic-v3: Mark the base irq domain as DOMAIN_BUS_WIRED As we're about to introduce MSI domains based on top of the GICv3 domain, we must make sure nothing the new domains do not alias with the core domain. So let's tag that core domain with the DOMAIN_BUS_WIRED attribute, ensuring it gets picked up by other drivers that use irq_find_host(). Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-7-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index e5d101418390..94164d7b87a6 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1099,6 +1099,7 @@ static int __init gic_init_bases(void __iomem *dist_base, gic_data.domain = irq_domain_create_tree(handle, _irq_domain_ops, _data); + irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED); gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist)); gic_data.rdists.has_vlpis = true; gic_data.rdists.has_direct_lpi = true;
[tip:irq/core] irqdomain: Let irq_find_host default to DOMAIN_BUS_WIRED
Commit-ID: 6461934371bfc1bfe6b424b197a546b4effd0a32 Gitweb: https://git.kernel.org/tip/6461934371bfc1bfe6b424b197a546b4effd0a32 Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:34 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 irqdomain: Let irq_find_host default to DOMAIN_BUS_WIRED At the beginning of times, irq_find_host() was simple. Each device node implemented at most one irq domain, and we were happy. Over time, things have become more complex, and we now have nodes implementing a plurality of domains, tagged by "bus_token". Crutially, users of irq_find_host() all expect the most basic domain to be returned, and not any other domain such as a bus-specific MSI domain. So let's change irq_find_host() to first look for a DOMAIN_BUS_WIRED domain, and only if this fails fallback to DOMAIN_BUS_ANY. Note that this is consistent with what irq_create_fwspec_mapping is already doing, see 530cbe100ef7 ("irqdomain: Allow domain lookup with DOMAIN_BUS_WIRED token"). Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-6-marc.zyng...@arm.com --- include/linux/irqdomain.h | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 48c7e86bb556..dccfa65aee96 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -301,7 +301,13 @@ static inline struct irq_domain *irq_find_matching_host(struct device_node *node static inline struct irq_domain *irq_find_host(struct device_node *node) { - return irq_find_matching_host(node, DOMAIN_BUS_ANY); + struct irq_domain *d; + + d = irq_find_matching_host(node, DOMAIN_BUS_WIRED); + if (!d) + d = irq_find_matching_host(node, DOMAIN_BUS_ANY); + + return d; } /**
[tip:irq/core] irqdomain: Let irq_find_host default to DOMAIN_BUS_WIRED
Commit-ID: 6461934371bfc1bfe6b424b197a546b4effd0a32 Gitweb: https://git.kernel.org/tip/6461934371bfc1bfe6b424b197a546b4effd0a32 Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:34 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 irqdomain: Let irq_find_host default to DOMAIN_BUS_WIRED At the beginning of times, irq_find_host() was simple. Each device node implemented at most one irq domain, and we were happy. Over time, things have become more complex, and we now have nodes implementing a plurality of domains, tagged by "bus_token". Crutially, users of irq_find_host() all expect the most basic domain to be returned, and not any other domain such as a bus-specific MSI domain. So let's change irq_find_host() to first look for a DOMAIN_BUS_WIRED domain, and only if this fails fallback to DOMAIN_BUS_ANY. Note that this is consistent with what irq_create_fwspec_mapping is already doing, see 530cbe100ef7 ("irqdomain: Allow domain lookup with DOMAIN_BUS_WIRED token"). Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-6-marc.zyng...@arm.com --- include/linux/irqdomain.h | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 48c7e86bb556..dccfa65aee96 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -301,7 +301,13 @@ static inline struct irq_domain *irq_find_matching_host(struct device_node *node static inline struct irq_domain *irq_find_host(struct device_node *node) { - return irq_find_matching_host(node, DOMAIN_BUS_ANY); + struct irq_domain *d; + + d = irq_find_matching_host(node, DOMAIN_BUS_WIRED); + if (!d) + d = irq_find_matching_host(node, DOMAIN_BUS_ANY); + + return d; } /**
[tip:irq/core] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
Commit-ID: 8a22a3e1e768c309b718f99bd86f9f25a453e0dc Gitweb: https://git.kernel.org/tip/8a22a3e1e768c309b718f99bd86f9f25a453e0dc Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:33 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA Inclusion of include/dma-iommu.h when CONFIG_IOMMU_DMA is not selected results in the following splat: In file included from drivers/irqchip/irq-gic-v3-mbi.c:20:0: ./include/linux/dma-iommu.h:95:69: error: unknown type name ‘dma_addr_t’ static inline int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base) ^~ ./include/linux/dma-iommu.h:108:74: warning: ‘struct list_head’ declared inside parameter list will not be visible outside of this definition or declaration static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list) ^ scripts/Makefile.build:312: recipe for target 'drivers/irqchip/irq-gic-v3-mbi.o' failed Fix it by including linux/types.h. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-5-marc.zyng...@arm.com --- include/linux/dma-iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 92f20832fd28..e8ca5e654277 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -17,6 +17,7 @@ #define __DMA_IOMMU_H #ifdef __KERNEL__ +#include #include #ifdef CONFIG_IOMMU_DMA
[tip:irq/core] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
Commit-ID: 8a22a3e1e768c309b718f99bd86f9f25a453e0dc Gitweb: https://git.kernel.org/tip/8a22a3e1e768c309b718f99bd86f9f25a453e0dc Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:33 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA Inclusion of include/dma-iommu.h when CONFIG_IOMMU_DMA is not selected results in the following splat: In file included from drivers/irqchip/irq-gic-v3-mbi.c:20:0: ./include/linux/dma-iommu.h:95:69: error: unknown type name ‘dma_addr_t’ static inline int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base) ^~ ./include/linux/dma-iommu.h:108:74: warning: ‘struct list_head’ declared inside parameter list will not be visible outside of this definition or declaration static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list) ^ scripts/Makefile.build:312: recipe for target 'drivers/irqchip/irq-gic-v3-mbi.o' failed Fix it by including linux/types.h. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-5-marc.zyng...@arm.com --- include/linux/dma-iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 92f20832fd28..e8ca5e654277 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -17,6 +17,7 @@ #define __DMA_IOMMU_H #ifdef __KERNEL__ +#include #include #ifdef CONFIG_IOMMU_DMA
[tip:irq/core] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
Commit-ID: 25eaaabb51c9925dc65f5b54fd9a362bf118e70a Gitweb: https://git.kernel.org/tip/25eaaabb51c9925dc65f5b54fd9a362bf118e70a Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:32 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP The ICU and GICP drivers are using an ugly side-band mechanism to find out about the "clear" doorbell when using level interrupts. Let's convert it to level-triggered MSIs, which result in a nice cleanup. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Miquel Raynal Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Link: https://lkml.kernel.org/r/20180508121438.11301-4-marc.zyng...@arm.com --- drivers/irqchip/irq-mvebu-gicp.c | 38 +++--- drivers/irqchip/irq-mvebu-gicp.h | 12 drivers/irqchip/irq-mvebu-icu.c | 33 + 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c index 17a4a7b6cdbb..4e17f7081efc 100644 --- a/drivers/irqchip/irq-mvebu-gicp.c +++ b/drivers/irqchip/irq-mvebu-gicp.c @@ -19,8 +19,6 @@ #include -#include "irq-mvebu-gicp.h" - #define GICP_SETSPI_NSR_OFFSET 0x0 #define GICP_CLRSPI_NSR_OFFSET 0x8 @@ -55,34 +53,18 @@ static int gicp_idx_to_spi(struct mvebu_gicp *gicp, int idx) return -EINVAL; } -int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, -phys_addr_t *clrspi) -{ - struct platform_device *pdev; - struct mvebu_gicp *gicp; - - pdev = of_find_device_by_node(dn); - if (!pdev) - return -ENODEV; - - gicp = platform_get_drvdata(pdev); - if (!gicp) - return -ENODEV; - - *setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; - *clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; - - return 0; -} - static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { struct mvebu_gicp *gicp = data->chip_data; phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; - - msg->data = data->hwirq; - msg->address_lo = lower_32_bits(setspi); - msg->address_hi = upper_32_bits(setspi); + phys_addr_t clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; + + msg[0].data = data->hwirq; + msg[0].address_lo = lower_32_bits(setspi); + msg[0].address_hi = upper_32_bits(setspi); + msg[1].data = data->hwirq; + msg[1].address_lo = lower_32_bits(clrspi); + msg[1].address_hi = upper_32_bits(clrspi); } static struct irq_chip gicp_irq_chip = { @@ -170,13 +152,15 @@ static const struct irq_domain_ops gicp_domain_ops = { static struct irq_chip gicp_msi_irq_chip = { .name = "GICP", .irq_set_type = irq_chip_set_type_parent, + .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, }; static struct msi_domain_ops gicp_msi_ops = { }; static struct msi_domain_info gicp_msi_domain_info = { - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_LEVEL_CAPABLE), .ops= _msi_ops, .chip = _msi_irq_chip, }; diff --git a/drivers/irqchip/irq-mvebu-gicp.h b/drivers/irqchip/irq-mvebu-gicp.h deleted file mode 100644 index eaa12fb72102.. --- a/drivers/irqchip/irq-mvebu-gicp.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __MVEBU_GICP_H__ -#define __MVEBU_GICP_H__ - -#include - -struct device_node; - -int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, -phys_addr_t *clrspi); - -#endif /* __MVEBU_GICP_H__ */ diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c index e18c48d3a92e..13063339b416 100644 --- a/drivers/irqchip/irq-mvebu-icu.c +++ b/drivers/irqchip/irq-mvebu-icu.c @@ -21,8 +21,6 @@ #include -#include "irq-mvebu-gicp.h" - /* ICU registers */ #define ICU_SETSPI_NSR_AL 0x10 #define ICU_SETSPI_NSR_AH 0x14 @@ -43,6 +41,7 @@ struct mvebu_icu { void __iomem *base; struct irq_domain *domain; struct device *dev; + atomic_t initialized; }; struct mvebu_icu_irq_data { @@ -51,6 +50,18 @@ struct mvebu_icu_irq_data { unsigned int type; }; +static void mvebu_icu_init(struct mvebu_icu *icu, struct msi_msg *msg) +{ + if (atomic_cmpxchg(>initialized, false, true)) + return; + + /* Set Clear/Set ICU SPI message address
[tip:irq/core] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
Commit-ID: 25eaaabb51c9925dc65f5b54fd9a362bf118e70a Gitweb: https://git.kernel.org/tip/25eaaabb51c9925dc65f5b54fd9a362bf118e70a Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:32 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:59:00 +0200 irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP The ICU and GICP drivers are using an ugly side-band mechanism to find out about the "clear" doorbell when using level interrupts. Let's convert it to level-triggered MSIs, which result in a nice cleanup. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Miquel Raynal Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Link: https://lkml.kernel.org/r/20180508121438.11301-4-marc.zyng...@arm.com --- drivers/irqchip/irq-mvebu-gicp.c | 38 +++--- drivers/irqchip/irq-mvebu-gicp.h | 12 drivers/irqchip/irq-mvebu-icu.c | 33 + 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c index 17a4a7b6cdbb..4e17f7081efc 100644 --- a/drivers/irqchip/irq-mvebu-gicp.c +++ b/drivers/irqchip/irq-mvebu-gicp.c @@ -19,8 +19,6 @@ #include -#include "irq-mvebu-gicp.h" - #define GICP_SETSPI_NSR_OFFSET 0x0 #define GICP_CLRSPI_NSR_OFFSET 0x8 @@ -55,34 +53,18 @@ static int gicp_idx_to_spi(struct mvebu_gicp *gicp, int idx) return -EINVAL; } -int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, -phys_addr_t *clrspi) -{ - struct platform_device *pdev; - struct mvebu_gicp *gicp; - - pdev = of_find_device_by_node(dn); - if (!pdev) - return -ENODEV; - - gicp = platform_get_drvdata(pdev); - if (!gicp) - return -ENODEV; - - *setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; - *clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; - - return 0; -} - static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { struct mvebu_gicp *gicp = data->chip_data; phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; - - msg->data = data->hwirq; - msg->address_lo = lower_32_bits(setspi); - msg->address_hi = upper_32_bits(setspi); + phys_addr_t clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; + + msg[0].data = data->hwirq; + msg[0].address_lo = lower_32_bits(setspi); + msg[0].address_hi = upper_32_bits(setspi); + msg[1].data = data->hwirq; + msg[1].address_lo = lower_32_bits(clrspi); + msg[1].address_hi = upper_32_bits(clrspi); } static struct irq_chip gicp_irq_chip = { @@ -170,13 +152,15 @@ static const struct irq_domain_ops gicp_domain_ops = { static struct irq_chip gicp_msi_irq_chip = { .name = "GICP", .irq_set_type = irq_chip_set_type_parent, + .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, }; static struct msi_domain_ops gicp_msi_ops = { }; static struct msi_domain_info gicp_msi_domain_info = { - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_LEVEL_CAPABLE), .ops= _msi_ops, .chip = _msi_irq_chip, }; diff --git a/drivers/irqchip/irq-mvebu-gicp.h b/drivers/irqchip/irq-mvebu-gicp.h deleted file mode 100644 index eaa12fb72102.. --- a/drivers/irqchip/irq-mvebu-gicp.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __MVEBU_GICP_H__ -#define __MVEBU_GICP_H__ - -#include - -struct device_node; - -int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi, -phys_addr_t *clrspi); - -#endif /* __MVEBU_GICP_H__ */ diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c index e18c48d3a92e..13063339b416 100644 --- a/drivers/irqchip/irq-mvebu-icu.c +++ b/drivers/irqchip/irq-mvebu-icu.c @@ -21,8 +21,6 @@ #include -#include "irq-mvebu-gicp.h" - /* ICU registers */ #define ICU_SETSPI_NSR_AL 0x10 #define ICU_SETSPI_NSR_AH 0x14 @@ -43,6 +41,7 @@ struct mvebu_icu { void __iomem *base; struct irq_domain *domain; struct device *dev; + atomic_t initialized; }; struct mvebu_icu_irq_data { @@ -51,6 +50,18 @@ struct mvebu_icu_irq_data { unsigned int type; }; +static void mvebu_icu_init(struct mvebu_icu *icu, struct msi_msg *msg) +{ + if (atomic_cmpxchg(>initialized, false, true)) + return; + + /* Set Clear/Set ICU SPI message address in AP */ + writel_relaxed(msg[0].address_hi, icu->base + ICU_SETSPI_NSR_AH); + writel_relaxed(msg[0].address_lo, icu->base + ICU_SETSPI_NSR_AL); + writel_relaxed(msg[1].address_hi, icu->base + ICU_CLRSPI_NSR_AH); +
[tip:irq/core] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
Commit-ID: 0be8153cbc2af9a96e9ab8631fc3ba23bb52dbe3 Gitweb: https://git.kernel.org/tip/0be8153cbc2af9a96e9ab8631fc3ba23bb52dbe3 Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:30 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:58:59 +0200 genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers So far, MSIs have been used to signal edge-triggered interrupts, as a write is a good model for an edge (you can't "unwrite" something). On the other hand, routing zillions of wires in an SoC because you need level interrupts is a bit extreme. People have come up with a variety of schemes to support this, which involves sending two messages: one to signal the interrupt, and one to clear it. Since the kernel cannot represent this, we've ended up with side-band mechanisms that are pretty awful. Instead, let's acknoledge the requirement, and ensure that, under the right circumstances, the irq_compose_msg and irq_write_msg can take as a parameter an array of two messages instead of a pointer to a single one. We also add some checking that the compose method only clobbers the second message if the MSI domain has been created with the MSI_FLAG_LEVEL_CAPABLE flags. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-2-marc.zyng...@arm.com --- include/linux/msi.h | 2 ++ kernel/irq/msi.c| 33 - 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/include/linux/msi.h b/include/linux/msi.h index 1f1bbb5b4679..5839d8062dfc 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -289,6 +289,8 @@ enum { * MSI_FLAG_ACTIVATE_EARLY has been set. */ MSI_FLAG_MUST_REACTIVATE= (1 << 5), + /* Is level-triggered capable, using two messages */ + MSI_FLAG_LEVEL_CAPABLE = (1 << 6), }; int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2a8571f72b17..4ca2fd46645d 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -76,6 +76,19 @@ static inline void irq_chip_write_msi_msg(struct irq_data *data, data->chip->irq_write_msi_msg(data, msg); } +static void msi_check_level(struct irq_domain *domain, struct msi_msg *msg) +{ + struct msi_domain_info *info = domain->host_data; + + /* +* If the MSI provider has messed with the second message and +* not advertized that it is level-capable, signal the breakage. +*/ + WARN_ON(!((info->flags & MSI_FLAG_LEVEL_CAPABLE) && + (info->chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)) && + (msg[1].address_lo || msg[1].address_hi || msg[1].data)); +} + /** * msi_domain_set_affinity - Generic affinity setter function for MSI domains * @irq_data: The irq data associated to the interrupt @@ -89,13 +102,14 @@ int msi_domain_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) { struct irq_data *parent = irq_data->parent_data; - struct msi_msg msg; + struct msi_msg msg[2] = { [1] = { }, }; int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) { - BUG_ON(irq_chip_compose_msi_msg(irq_data, )); - irq_chip_write_msi_msg(irq_data, ); + BUG_ON(irq_chip_compose_msi_msg(irq_data, msg)); + msi_check_level(irq_data->domain, msg); + irq_chip_write_msi_msg(irq_data, msg); } return ret; @@ -104,20 +118,21 @@ int msi_domain_set_affinity(struct irq_data *irq_data, static int msi_domain_activate(struct irq_domain *domain, struct irq_data *irq_data, bool early) { - struct msi_msg msg; + struct msi_msg msg[2] = { [1] = { }, }; - BUG_ON(irq_chip_compose_msi_msg(irq_data, )); - irq_chip_write_msi_msg(irq_data, ); + BUG_ON(irq_chip_compose_msi_msg(irq_data, msg)); + msi_check_level(irq_data->domain, msg); + irq_chip_write_msi_msg(irq_data, msg); return 0; } static void msi_domain_deactivate(struct irq_domain *domain, struct irq_data *irq_data) { - struct msi_msg msg; + struct msi_msg msg[2]; - memset(, 0, sizeof(msg)); - irq_chip_write_msi_msg(irq_data, ); + memset(msg, 0, sizeof(msg)); + irq_chip_write_msi_msg(irq_data, msg); } static int msi_domain_alloc(struct irq_domain *domain,
[tip:irq/core] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
Commit-ID: 0be8153cbc2af9a96e9ab8631fc3ba23bb52dbe3 Gitweb: https://git.kernel.org/tip/0be8153cbc2af9a96e9ab8631fc3ba23bb52dbe3 Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:30 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:58:59 +0200 genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers So far, MSIs have been used to signal edge-triggered interrupts, as a write is a good model for an edge (you can't "unwrite" something). On the other hand, routing zillions of wires in an SoC because you need level interrupts is a bit extreme. People have come up with a variety of schemes to support this, which involves sending two messages: one to signal the interrupt, and one to clear it. Since the kernel cannot represent this, we've ended up with side-band mechanisms that are pretty awful. Instead, let's acknoledge the requirement, and ensure that, under the right circumstances, the irq_compose_msg and irq_write_msg can take as a parameter an array of two messages instead of a pointer to a single one. We also add some checking that the compose method only clobbers the second message if the MSI domain has been created with the MSI_FLAG_LEVEL_CAPABLE flags. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-2-marc.zyng...@arm.com --- include/linux/msi.h | 2 ++ kernel/irq/msi.c| 33 - 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/include/linux/msi.h b/include/linux/msi.h index 1f1bbb5b4679..5839d8062dfc 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -289,6 +289,8 @@ enum { * MSI_FLAG_ACTIVATE_EARLY has been set. */ MSI_FLAG_MUST_REACTIVATE= (1 << 5), + /* Is level-triggered capable, using two messages */ + MSI_FLAG_LEVEL_CAPABLE = (1 << 6), }; int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2a8571f72b17..4ca2fd46645d 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -76,6 +76,19 @@ static inline void irq_chip_write_msi_msg(struct irq_data *data, data->chip->irq_write_msi_msg(data, msg); } +static void msi_check_level(struct irq_domain *domain, struct msi_msg *msg) +{ + struct msi_domain_info *info = domain->host_data; + + /* +* If the MSI provider has messed with the second message and +* not advertized that it is level-capable, signal the breakage. +*/ + WARN_ON(!((info->flags & MSI_FLAG_LEVEL_CAPABLE) && + (info->chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)) && + (msg[1].address_lo || msg[1].address_hi || msg[1].data)); +} + /** * msi_domain_set_affinity - Generic affinity setter function for MSI domains * @irq_data: The irq data associated to the interrupt @@ -89,13 +102,14 @@ int msi_domain_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) { struct irq_data *parent = irq_data->parent_data; - struct msi_msg msg; + struct msi_msg msg[2] = { [1] = { }, }; int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) { - BUG_ON(irq_chip_compose_msi_msg(irq_data, )); - irq_chip_write_msi_msg(irq_data, ); + BUG_ON(irq_chip_compose_msi_msg(irq_data, msg)); + msi_check_level(irq_data->domain, msg); + irq_chip_write_msi_msg(irq_data, msg); } return ret; @@ -104,20 +118,21 @@ int msi_domain_set_affinity(struct irq_data *irq_data, static int msi_domain_activate(struct irq_domain *domain, struct irq_data *irq_data, bool early) { - struct msi_msg msg; + struct msi_msg msg[2] = { [1] = { }, }; - BUG_ON(irq_chip_compose_msi_msg(irq_data, )); - irq_chip_write_msi_msg(irq_data, ); + BUG_ON(irq_chip_compose_msi_msg(irq_data, msg)); + msi_check_level(irq_data->domain, msg); + irq_chip_write_msi_msg(irq_data, msg); return 0; } static void msi_domain_deactivate(struct irq_domain *domain, struct irq_data *irq_data) { - struct msi_msg msg; + struct msi_msg msg[2]; - memset(, 0, sizeof(msg)); - irq_chip_write_msi_msg(irq_data, ); + memset(msg, 0, sizeof(msg)); + irq_chip_write_msi_msg(irq_data, msg); } static int msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
[tip:irq/core] genirq/msi: Limit level-triggered MSI to platform devices
Commit-ID: 6988e0e0d28328467e218f59589b2770675a9ebd Gitweb: https://git.kernel.org/tip/6988e0e0d28328467e218f59589b2770675a9ebd Author: Marc ZyngierAuthorDate: Tue, 8 May 2018 13:14:31 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:58:59 +0200 genirq/msi: Limit level-triggered MSI to platform devices Nobody would be insane enough to try and use level triggered MSIs on PCI, but let's make sure it doesn't happen. Also, let's mandate that the irqchip backing the platform MSI domain is providing the IRQCHIP_SUPPORTS_LEVEL_MSI flag. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-3-marc.zyng...@arm.com --- drivers/base/platform-msi.c | 3 +++ drivers/bus/fsl-mc/fsl-mc-msi.c | 2 ++ drivers/pci/msi.c | 3 +++ include/linux/irq.h | 1 + 4 files changed, 9 insertions(+) diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 8e22073aeeed..60d6cc618f1c 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -101,6 +101,9 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info) chip->irq_set_affinity = msi_domain_set_affinity; if (!chip->irq_write_msi_msg) chip->irq_write_msi_msg = platform_msi_write_msg; + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) && + !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI))) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; } static void platform_msi_free_descs(struct device *dev, int base, int nvec) diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c index ec35e255b496..8b9c66d7c4ff 100644 --- a/drivers/bus/fsl-mc/fsl-mc-msi.c +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c @@ -163,6 +163,8 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, { struct irq_domain *domain; + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE))) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) fsl_mc_msi_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 30250631efe7..f45b74fcc059 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1434,6 +1434,9 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, { struct irq_domain *domain; + if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) pci_msi_domain_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) diff --git a/include/linux/irq.h b/include/linux/irq.h index 65916a305f3d..b2067083aa94 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -512,6 +512,7 @@ enum { IRQCHIP_SKIP_SET_WAKE = (1 << 4), IRQCHIP_ONESHOT_SAFE= (1 << 5), IRQCHIP_EOI_THREADED= (1 << 6), + IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7), }; #include
[tip:irq/core] genirq/msi: Limit level-triggered MSI to platform devices
Commit-ID: 6988e0e0d28328467e218f59589b2770675a9ebd Gitweb: https://git.kernel.org/tip/6988e0e0d28328467e218f59589b2770675a9ebd Author: Marc Zyngier AuthorDate: Tue, 8 May 2018 13:14:31 +0100 Committer: Thomas Gleixner CommitDate: Sun, 13 May 2018 15:58:59 +0200 genirq/msi: Limit level-triggered MSI to platform devices Nobody would be insane enough to try and use level triggered MSIs on PCI, but let's make sure it doesn't happen. Also, let's mandate that the irqchip backing the platform MSI domain is providing the IRQCHIP_SUPPORTS_LEVEL_MSI flag. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Rob Herring Cc: Jason Cooper Cc: Ard Biesheuvel Cc: Srinivas Kandagatla Cc: Thomas Petazzoni Cc: Miquel Raynal Link: https://lkml.kernel.org/r/20180508121438.11301-3-marc.zyng...@arm.com --- drivers/base/platform-msi.c | 3 +++ drivers/bus/fsl-mc/fsl-mc-msi.c | 2 ++ drivers/pci/msi.c | 3 +++ include/linux/irq.h | 1 + 4 files changed, 9 insertions(+) diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 8e22073aeeed..60d6cc618f1c 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -101,6 +101,9 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info) chip->irq_set_affinity = msi_domain_set_affinity; if (!chip->irq_write_msi_msg) chip->irq_write_msi_msg = platform_msi_write_msg; + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) && + !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI))) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; } static void platform_msi_free_descs(struct device *dev, int base, int nvec) diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c index ec35e255b496..8b9c66d7c4ff 100644 --- a/drivers/bus/fsl-mc/fsl-mc-msi.c +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c @@ -163,6 +163,8 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, { struct irq_domain *domain; + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE))) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) fsl_mc_msi_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 30250631efe7..f45b74fcc059 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1434,6 +1434,9 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, { struct irq_domain *domain; + if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) + info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) pci_msi_domain_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) diff --git a/include/linux/irq.h b/include/linux/irq.h index 65916a305f3d..b2067083aa94 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -512,6 +512,7 @@ enum { IRQCHIP_SKIP_SET_WAKE = (1 << 4), IRQCHIP_ONESHOT_SAFE= (1 << 5), IRQCHIP_EOI_THREADED= (1 << 6), + IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7), }; #include
[tip:irq/core] irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG
Commit-ID: c5baa1be8f559d5f33c412d00cc1c86762a8bbbf Gitweb: https://git.kernel.org/tip/c5baa1be8f559d5f33c412d00cc1c86762a8bbbf Author: Marc ZyngierAuthorDate: Wed, 17 Jan 2018 14:26:47 + Committer: Thomas Gleixner CommitDate: Wed, 24 Jan 2018 12:32:58 +0100 irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG CONFIG_IRQ_DOMAIN_DEBUG is similar to CONFIG_GENERIC_IRQ_DEBUGFS, just with less information. Spring cleanup time. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Yang Shunyong Link: https://lkml.kernel.org/r/20180117142647.23622-1-marc.zyng...@arm.com --- Documentation/IRQ-domain.txt| 36 + arch/arm/configs/aspeed_g4_defconfig| 1 - arch/arm/configs/aspeed_g5_defconfig| 1 - arch/arm/configs/hisi_defconfig | 1 - arch/arm/configs/multi_v7_defconfig | 1 - arch/arm/configs/mvebu_v7_defconfig | 1 - arch/arm/configs/pxa_defconfig | 1 - arch/arm/configs/sama5_defconfig| 1 - arch/arm/configs/tegra_defconfig| 1 - arch/arm/configs/vt8500_v6_v7_defconfig | 1 - arch/powerpc/configs/fsl-emb-nonhw.config | 1 - arch/powerpc/configs/powernv_defconfig | 1 - arch/powerpc/configs/ppc64_defconfig| 1 - arch/powerpc/configs/pseries_defconfig | 1 - arch/xtensa/configs/audio_kc705_defconfig | 1 - arch/xtensa/configs/cadence_csp_defconfig | 1 - arch/xtensa/configs/generic_kc705_defconfig | 1 - arch/xtensa/configs/nommu_kc705_defconfig | 1 - arch/xtensa/configs/smp_lx200_defconfig | 1 - kernel/irq/Kconfig | 10 --- kernel/irq/irqdomain.c | 118 21 files changed, 2 insertions(+), 180 deletions(-) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 4a1cd76..507775c 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -265,37 +265,5 @@ support other architectures, such as ARM, ARM64 etc. === Debugging === -If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on -CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in -your debugfs mount point, called irq_domain_mapping. This file -contains a live snapshot of all the IRQ domains in the system: - - name mapped linear-max direct-max devtree-node - pl061 8 8 0 /smb/gpio@e008 - pl061 8 8 0 /smb/gpio@e105 - pMSI 0 0 0 /interrupt-controller@e1101000/v2m@e008 - MSI 37 0 0 /interrupt-controller@e1101000/v2m@e008 - GICv2m37 0 0 /interrupt-controller@e1101000/v2m@e008 - GICv2448 448 0 /interrupt-controller@e1101000 - -it also iterates over the interrupts to display their mapping in the -domains, and makes the domain stacking visible: - - -irqhwirqchip namechip data active type domain -1 0x00019 GICv20x0916bfd8 *LINEAR GICv2 -2 0x0001d GICv20x0916bfd8 LINEAR GICv2 -3 0x0001e GICv20x0916bfd8 *LINEAR GICv2 -4 0x0001b GICv20x0916bfd8 *LINEAR GICv2 -5 0x0001a GICv20x0916bfd8 LINEAR GICv2 -[...] - 96 0x81808 MSI 0x (null) RADIX MSI - 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m - 96+ 0x00063 GICv20x0916bfd8 LINEAR GICv2 - 97 0x08800 MSI 0x (null) * RADIX MSI - 97+ 0x00064 GICv2m 0x8003ee116980 * RADIX GICv2m - 97+ 0x00064 GICv20x0916bfd8 *LINEAR GICv2 - -Here, interrupts 1-5 are only using a single domain, while 96 and 97 -are build out of a stack of three domain, each level performing a -particular function. +Most of the internals of the IRQ subsystem are exposed in debugfs by +turning CONFIG_GENERIC_IRQ_DEBUGFS on. diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index d23b9d5..95946de 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -1,7 +1,6 @@ CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index c0ad7b8..8c7ea03 100644 --- a/arch/arm/configs/aspeed_g5_defconfig
[tip:irq/core] irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG
Commit-ID: c5baa1be8f559d5f33c412d00cc1c86762a8bbbf Gitweb: https://git.kernel.org/tip/c5baa1be8f559d5f33c412d00cc1c86762a8bbbf Author: Marc Zyngier AuthorDate: Wed, 17 Jan 2018 14:26:47 + Committer: Thomas Gleixner CommitDate: Wed, 24 Jan 2018 12:32:58 +0100 irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG CONFIG_IRQ_DOMAIN_DEBUG is similar to CONFIG_GENERIC_IRQ_DEBUGFS, just with less information. Spring cleanup time. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Yang Shunyong Link: https://lkml.kernel.org/r/20180117142647.23622-1-marc.zyng...@arm.com --- Documentation/IRQ-domain.txt| 36 + arch/arm/configs/aspeed_g4_defconfig| 1 - arch/arm/configs/aspeed_g5_defconfig| 1 - arch/arm/configs/hisi_defconfig | 1 - arch/arm/configs/multi_v7_defconfig | 1 - arch/arm/configs/mvebu_v7_defconfig | 1 - arch/arm/configs/pxa_defconfig | 1 - arch/arm/configs/sama5_defconfig| 1 - arch/arm/configs/tegra_defconfig| 1 - arch/arm/configs/vt8500_v6_v7_defconfig | 1 - arch/powerpc/configs/fsl-emb-nonhw.config | 1 - arch/powerpc/configs/powernv_defconfig | 1 - arch/powerpc/configs/ppc64_defconfig| 1 - arch/powerpc/configs/pseries_defconfig | 1 - arch/xtensa/configs/audio_kc705_defconfig | 1 - arch/xtensa/configs/cadence_csp_defconfig | 1 - arch/xtensa/configs/generic_kc705_defconfig | 1 - arch/xtensa/configs/nommu_kc705_defconfig | 1 - arch/xtensa/configs/smp_lx200_defconfig | 1 - kernel/irq/Kconfig | 10 --- kernel/irq/irqdomain.c | 118 21 files changed, 2 insertions(+), 180 deletions(-) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 4a1cd76..507775c 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -265,37 +265,5 @@ support other architectures, such as ARM, ARM64 etc. === Debugging === -If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on -CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in -your debugfs mount point, called irq_domain_mapping. This file -contains a live snapshot of all the IRQ domains in the system: - - name mapped linear-max direct-max devtree-node - pl061 8 8 0 /smb/gpio@e008 - pl061 8 8 0 /smb/gpio@e105 - pMSI 0 0 0 /interrupt-controller@e1101000/v2m@e008 - MSI 37 0 0 /interrupt-controller@e1101000/v2m@e008 - GICv2m37 0 0 /interrupt-controller@e1101000/v2m@e008 - GICv2448 448 0 /interrupt-controller@e1101000 - -it also iterates over the interrupts to display their mapping in the -domains, and makes the domain stacking visible: - - -irqhwirqchip namechip data active type domain -1 0x00019 GICv20x0916bfd8 *LINEAR GICv2 -2 0x0001d GICv20x0916bfd8 LINEAR GICv2 -3 0x0001e GICv20x0916bfd8 *LINEAR GICv2 -4 0x0001b GICv20x0916bfd8 *LINEAR GICv2 -5 0x0001a GICv20x0916bfd8 LINEAR GICv2 -[...] - 96 0x81808 MSI 0x (null) RADIX MSI - 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m - 96+ 0x00063 GICv20x0916bfd8 LINEAR GICv2 - 97 0x08800 MSI 0x (null) * RADIX MSI - 97+ 0x00064 GICv2m 0x8003ee116980 * RADIX GICv2m - 97+ 0x00064 GICv20x0916bfd8 *LINEAR GICv2 - -Here, interrupts 1-5 are only using a single domain, while 96 and 97 -are build out of a stack of three domain, each level performing a -particular function. +Most of the internals of the IRQ subsystem are exposed in debugfs by +turning CONFIG_GENERIC_IRQ_DEBUGFS on. diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index d23b9d5..95946de 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -1,7 +1,6 @@ CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index c0ad7b8..8c7ea03 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -1,7 +1,6 @@ CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set
[tip:irq/urgent] genirq: Restore trigger settings in irq_modify_status()
Commit-ID: e8f241893dfbbebe2813c01eac54f263e6a5e59c Gitweb: http://git.kernel.org/tip/e8f241893dfbbebe2813c01eac54f263e6a5e59c Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 10:53:45 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 12:04:14 +0200 genirq: Restore trigger settings in irq_modify_status() irq_modify_status starts by clearing the trigger settings from irq_data before applying the new settings, but doesn't restore them, leaving them to IRQ_TYPE_NONE. That's pretty confusing to the potential request_irq() that could follow. Instead, snapshot the settings before clearing them, and restore them if the irq_modify_status() invocation was not changing the trigger. Fixes: 1e2a7d78499e ("irqdomain: Don't set type when mapping an IRQ") Reported-and-tested-by: jeffy Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jon Hunter Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/20170818095345.12378-1-marc.zyng...@arm.com --- kernel/irq/chip.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index a3cc37c..3675c60 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -1000,7 +1000,7 @@ EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) { - unsigned long flags; + unsigned long flags, trigger, tmp; struct irq_desc *desc = irq_get_desc_lock(irq, , 0); if (!desc) @@ -1014,6 +1014,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) irq_settings_clr_and_set(desc, clr, set); + trigger = irqd_get_trigger_type(>irq_data); + irqd_clear(>irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU | IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT); if (irq_settings_has_no_balance_set(desc)) @@ -1025,7 +1027,11 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) if (irq_settings_is_level(desc)) irqd_set(>irq_data, IRQD_LEVEL); - irqd_set(>irq_data, irq_settings_get_trigger_mask(desc)); + tmp = irq_settings_get_trigger_mask(desc); + if (tmp != IRQ_TYPE_NONE) + trigger = tmp; + + irqd_set(>irq_data, trigger); irq_put_desc_unlock(desc, flags); }
[tip:irq/urgent] genirq: Restore trigger settings in irq_modify_status()
Commit-ID: e8f241893dfbbebe2813c01eac54f263e6a5e59c Gitweb: http://git.kernel.org/tip/e8f241893dfbbebe2813c01eac54f263e6a5e59c Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 10:53:45 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 12:04:14 +0200 genirq: Restore trigger settings in irq_modify_status() irq_modify_status starts by clearing the trigger settings from irq_data before applying the new settings, but doesn't restore them, leaving them to IRQ_TYPE_NONE. That's pretty confusing to the potential request_irq() that could follow. Instead, snapshot the settings before clearing them, and restore them if the irq_modify_status() invocation was not changing the trigger. Fixes: 1e2a7d78499e ("irqdomain: Don't set type when mapping an IRQ") Reported-and-tested-by: jeffy Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jon Hunter Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/20170818095345.12378-1-marc.zyng...@arm.com --- kernel/irq/chip.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index a3cc37c..3675c60 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -1000,7 +1000,7 @@ EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) { - unsigned long flags; + unsigned long flags, trigger, tmp; struct irq_desc *desc = irq_get_desc_lock(irq, , 0); if (!desc) @@ -1014,6 +1014,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) irq_settings_clr_and_set(desc, clr, set); + trigger = irqd_get_trigger_type(>irq_data); + irqd_clear(>irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU | IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT); if (irq_settings_has_no_balance_set(desc)) @@ -1025,7 +1027,11 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) if (irq_settings_is_level(desc)) irqd_set(>irq_data, IRQD_LEVEL); - irqd_set(>irq_data, irq_settings_get_trigger_mask(desc)); + tmp = irq_settings_get_trigger_mask(desc); + if (tmp != IRQ_TYPE_NONE) + trigger = tmp; + + irqd_set(>irq_data, trigger); irq_put_desc_unlock(desc, flags); }
[tip:irq/core] irqchip/xtensa-mx: Report that effective affinity is a single target
Commit-ID: 500912121411e0175d44b69a7810ac6068e78326 Gitweb: http://git.kernel.org/tip/500912121411e0175d44b69a7810ac6068e78326 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:25 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:43 +0200 irqchip/xtensa-mx: Report that effective affinity is a single target The xtensa-mx driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-13-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-xtensa-mx.c | 6 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index bca9a88..1139de9 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -223,6 +223,7 @@ config VERSATILE_FPGA_IRQ_NR config XTENSA_MX bool select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config XILINX_INTC bool diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index 72a391e..a15a951 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c @@ -32,6 +32,7 @@ static int xtensa_mx_irq_map(struct irq_domain *d, unsigned int irq, irq_set_status_flags(irq, IRQ_LEVEL); return 0; } + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return xtensa_irq_map(d, irq, hw); } @@ -121,9 +122,12 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d) static int xtensa_mx_irq_set_affinity(struct irq_data *d, const struct cpumask *dest, bool force) { - unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask); + int cpu = cpumask_any_and(dest, cpu_online_mask); + unsigned mask = 1u << cpu; set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return 0; }
[tip:irq/core] irqchip/xtensa-mx: Report that effective affinity is a single target
Commit-ID: 500912121411e0175d44b69a7810ac6068e78326 Gitweb: http://git.kernel.org/tip/500912121411e0175d44b69a7810ac6068e78326 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:25 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:43 +0200 irqchip/xtensa-mx: Report that effective affinity is a single target The xtensa-mx driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-13-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-xtensa-mx.c | 6 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index bca9a88..1139de9 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -223,6 +223,7 @@ config VERSATILE_FPGA_IRQ_NR config XTENSA_MX bool select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config XILINX_INTC bool diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index 72a391e..a15a951 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c @@ -32,6 +32,7 @@ static int xtensa_mx_irq_map(struct irq_domain *d, unsigned int irq, irq_set_status_flags(irq, IRQ_LEVEL); return 0; } + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return xtensa_irq_map(d, irq, hw); } @@ -121,9 +122,12 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d) static int xtensa_mx_irq_set_affinity(struct irq_data *d, const struct cpumask *dest, bool force) { - unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask); + int cpu = cpumask_any_and(dest, cpu_online_mask); + unsigned mask = 1u << cpu; set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return 0; }
[tip:irq/core] irqchip/mips-gic: Report that effective affinity is a single target
Commit-ID: 18416e45b76189daf37ba53b2bd0b9ac3749e92e Gitweb: http://git.kernel.org/tip/18416e45b76189daf37ba53b2bd0b9ac3749e92e Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:24 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:43 +0200 irqchip/mips-gic: Report that effective affinity is a single target The MIPS GIC driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-12-marc.zyng...@arm.com --- drivers/irqchip/Kconfig| 1 + drivers/irqchip/irq-mips-gic.c | 10 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 39bfa5b..bca9a88 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -141,6 +141,7 @@ config IRQ_MIPS_CPU select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config CLPS711X_IRQCHIP bool diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 6ab1d3a..6461380 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -445,24 +445,27 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq); cpumask_t tmp = CPU_MASK_NONE; unsigned long flags; - int i; + int i, cpu; cpumask_and(, cpumask, cpu_online_mask); if (cpumask_empty()) return -EINVAL; + cpu = cpumask_first(); + /* Assumption : cpumask refers to a single CPU */ spin_lock_irqsave(_lock, flags); /* Re-route this IRQ */ - gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first())); + gic_map_to_vpe(irq, mips_cm_vp_id(cpu)); /* Update the pcpu_masks */ for (i = 0; i < min(gic_vpes, NR_CPUS); i++) clear_bit(irq, pcpu_masks[i].pcpu_mask); - set_bit(irq, pcpu_masks[cpumask_first()].pcpu_mask); + set_bit(irq, pcpu_masks[cpu].pcpu_mask); cpumask_copy(irq_data_get_affinity_mask(d), cpumask); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); spin_unlock_irqrestore(_lock, flags); return IRQ_SET_MASK_OK_NOCOPY; @@ -716,6 +719,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, if (err) return err; + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return gic_shared_irq_domain_map(d, virq, hwirq, 0); }
[tip:irq/core] irqchip/mips-gic: Report that effective affinity is a single target
Commit-ID: 18416e45b76189daf37ba53b2bd0b9ac3749e92e Gitweb: http://git.kernel.org/tip/18416e45b76189daf37ba53b2bd0b9ac3749e92e Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:24 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:43 +0200 irqchip/mips-gic: Report that effective affinity is a single target The MIPS GIC driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-12-marc.zyng...@arm.com --- drivers/irqchip/Kconfig| 1 + drivers/irqchip/irq-mips-gic.c | 10 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 39bfa5b..bca9a88 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -141,6 +141,7 @@ config IRQ_MIPS_CPU select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config CLPS711X_IRQCHIP bool diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 6ab1d3a..6461380 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -445,24 +445,27 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq); cpumask_t tmp = CPU_MASK_NONE; unsigned long flags; - int i; + int i, cpu; cpumask_and(, cpumask, cpu_online_mask); if (cpumask_empty()) return -EINVAL; + cpu = cpumask_first(); + /* Assumption : cpumask refers to a single CPU */ spin_lock_irqsave(_lock, flags); /* Re-route this IRQ */ - gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first())); + gic_map_to_vpe(irq, mips_cm_vp_id(cpu)); /* Update the pcpu_masks */ for (i = 0; i < min(gic_vpes, NR_CPUS); i++) clear_bit(irq, pcpu_masks[i].pcpu_mask); - set_bit(irq, pcpu_masks[cpumask_first()].pcpu_mask); + set_bit(irq, pcpu_masks[cpu].pcpu_mask); cpumask_copy(irq_data_get_affinity_mask(d), cpumask); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); spin_unlock_irqrestore(_lock, flags); return IRQ_SET_MASK_OK_NOCOPY; @@ -716,6 +719,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, if (err) return err; + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return gic_shared_irq_domain_map(d, virq, hwirq, 0); }
[tip:irq/core] irqchip/hip04: Report that effective affinity is a single target
Commit-ID: 79a0d4d8f1ae9568a952c8e5928ee81b30c8df11 Gitweb: http://git.kernel.org/tip/79a0d4d8f1ae9568a952c8e5928ee81b30c8df11 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:23 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/hip04: Report that effective affinity is a single target The HIP04 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-11-marc.zyng...@arm.com --- arch/arm/mach-hisi/Kconfig | 1 + drivers/irqchip/irq-hip04.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index a3b091a..65a048f 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -39,6 +39,7 @@ config ARCH_HIP04 select HAVE_ARM_ARCH_TIMER select MCPM if SMP select MCPM_QUAD_CLUSTER if SMP + select GENERIC_IRQ_EFFECTIVE_AFF_MASK help Support for Hisilicon HiP04 SoC family diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index c1b4ee9..5b4fd2f 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c @@ -165,6 +165,8 @@ static int hip04_irq_set_affinity(struct irq_data *d, writel_relaxed(val | bit, reg); raw_spin_unlock(_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -312,6 +314,7 @@ static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_set_chip_and_handler(irq, _irq_chip, handle_fasteoi_irq); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } irq_set_chip_data(irq, d->host_data); return 0;
[tip:irq/core] irqchip/hip04: Report that effective affinity is a single target
Commit-ID: 79a0d4d8f1ae9568a952c8e5928ee81b30c8df11 Gitweb: http://git.kernel.org/tip/79a0d4d8f1ae9568a952c8e5928ee81b30c8df11 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:23 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/hip04: Report that effective affinity is a single target The HIP04 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-11-marc.zyng...@arm.com --- arch/arm/mach-hisi/Kconfig | 1 + drivers/irqchip/irq-hip04.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index a3b091a..65a048f 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -39,6 +39,7 @@ config ARCH_HIP04 select HAVE_ARM_ARCH_TIMER select MCPM if SMP select MCPM_QUAD_CLUSTER if SMP + select GENERIC_IRQ_EFFECTIVE_AFF_MASK help Support for Hisilicon HiP04 SoC family diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index c1b4ee9..5b4fd2f 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c @@ -165,6 +165,8 @@ static int hip04_irq_set_affinity(struct irq_data *d, writel_relaxed(val | bit, reg); raw_spin_unlock(_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -312,6 +314,7 @@ static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_set_chip_and_handler(irq, _irq_chip, handle_fasteoi_irq); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } irq_set_chip_data(irq, d->host_data); return 0;
[tip:irq/core] irqchip/metag-ext: Report that effective affinity is a single target
Commit-ID: 64b5aaad3c743be4f866cfe1ef2c903582e389a3 Gitweb: http://git.kernel.org/tip/64b5aaad3c743be4f866cfe1ef2c903582e389a3 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:22 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/metag-ext: Report that effective affinity is a single target The metag-ext driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-10-marc.zyng...@arm.com --- arch/metag/Kconfig | 1 + drivers/irqchip/irq-metag-ext.c | 4 2 files changed, 5 insertions(+) diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig index 5b7a45d..7d8b322 100644 --- a/arch/metag/Kconfig +++ b/arch/metag/Kconfig @@ -26,6 +26,7 @@ config METAG select HAVE_SYSCALL_TRACEPOINTS select HAVE_UNDERSCORE_SYMBOL_PREFIX select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c index 0cdd923..be7216b 100644 --- a/drivers/irqchip/irq-metag-ext.c +++ b/drivers/irqchip/irq-metag-ext.c @@ -518,6 +518,8 @@ static int meta_intc_set_affinity(struct irq_data *data, metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); + irq_data_update_effective_affinity(data, cpumask_of(cpu)); + return 0; } #else @@ -578,6 +580,8 @@ static int meta_intc_map(struct irq_domain *d, unsigned int irq, else irq_set_chip_and_handler(irq, _intc_edge_chip, handle_edge_irq); + + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return 0; }
[tip:irq/core] irqchip/metag-ext: Report that effective affinity is a single target
Commit-ID: 64b5aaad3c743be4f866cfe1ef2c903582e389a3 Gitweb: http://git.kernel.org/tip/64b5aaad3c743be4f866cfe1ef2c903582e389a3 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:22 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/metag-ext: Report that effective affinity is a single target The metag-ext driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-10-marc.zyng...@arm.com --- arch/metag/Kconfig | 1 + drivers/irqchip/irq-metag-ext.c | 4 2 files changed, 5 insertions(+) diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig index 5b7a45d..7d8b322 100644 --- a/arch/metag/Kconfig +++ b/arch/metag/Kconfig @@ -26,6 +26,7 @@ config METAG select HAVE_SYSCALL_TRACEPOINTS select HAVE_UNDERSCORE_SYMBOL_PREFIX select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c index 0cdd923..be7216b 100644 --- a/drivers/irqchip/irq-metag-ext.c +++ b/drivers/irqchip/irq-metag-ext.c @@ -518,6 +518,8 @@ static int meta_intc_set_affinity(struct irq_data *data, metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); + irq_data_update_effective_affinity(data, cpumask_of(cpu)); + return 0; } #else @@ -578,6 +580,8 @@ static int meta_intc_map(struct irq_domain *d, unsigned int irq, else irq_set_chip_and_handler(irq, _intc_edge_chip, handle_edge_irq); + + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return 0; }
[tip:irq/core] irqchip/bcm-7038-l1: Report that effective affinity is a single target
Commit-ID: b8d9884ac6c2c5222ea4a2d23bf9bec613e8eacc Gitweb: http://git.kernel.org/tip/b8d9884ac6c2c5222ea4a2d23bf9bec613e8eacc Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:21 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/bcm-7038-l1: Report that effective affinity is a single target The BCM 7038-L1 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-9-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-bcm7038-l1.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b36a55d..39bfa5b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -102,6 +102,7 @@ config BCM7038_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7120_L2_IRQ bool diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index c2662a1..55cfb98 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -212,6 +212,8 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, __bcm7038_l1_unmask(d, first_cpu); raw_spin_unlock_irqrestore(>lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(first_cpu)); + return 0; } @@ -299,6 +301,7 @@ static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, { irq_set_chip_and_handler(virq, _l1_irq_chip, handle_level_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; }
[tip:irq/core] irqchip/bcm-7038-l1: Report that effective affinity is a single target
Commit-ID: b8d9884ac6c2c5222ea4a2d23bf9bec613e8eacc Gitweb: http://git.kernel.org/tip/b8d9884ac6c2c5222ea4a2d23bf9bec613e8eacc Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:21 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:42 +0200 irqchip/bcm-7038-l1: Report that effective affinity is a single target The BCM 7038-L1 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-9-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-bcm7038-l1.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b36a55d..39bfa5b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -102,6 +102,7 @@ config BCM7038_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7120_L2_IRQ bool diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index c2662a1..55cfb98 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -212,6 +212,8 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, __bcm7038_l1_unmask(d, first_cpu); raw_spin_unlock_irqrestore(>lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(first_cpu)); + return 0; } @@ -299,6 +301,7 @@ static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, { irq_set_chip_and_handler(virq, _l1_irq_chip, handle_level_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; }
[tip:irq/core] irqchip/bcm-6345-l1: Report that effective affinity is a single target
Commit-ID: d0ed5e8e14e95fb3b70885be5ae35d0736866f72 Gitweb: http://git.kernel.org/tip/d0ed5e8e14e95fb3b70885be5ae35d0736866f72 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:20 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:41 +0200 irqchip/bcm-6345-l1: Report that effective affinity is a single target The BCM 6345-L1 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-8-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-bcm6345-l1.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cd68877..b36a55d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -96,6 +96,7 @@ config BCM6345_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7038_L1_IRQ bool diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index daa4ae8..43f8abe 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -231,6 +231,8 @@ static int bcm6345_l1_set_affinity(struct irq_data *d, } raw_spin_unlock_irqrestore(>lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(new_cpu)); + return IRQ_SET_MASK_OK_NOCOPY; } @@ -291,6 +293,7 @@ static int bcm6345_l1_map(struct irq_domain *d, unsigned int virq, irq_set_chip_and_handler(virq, _l1_irq_chip, handle_percpu_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; }
[tip:irq/core] irqchip/bcm-6345-l1: Report that effective affinity is a single target
Commit-ID: d0ed5e8e14e95fb3b70885be5ae35d0736866f72 Gitweb: http://git.kernel.org/tip/d0ed5e8e14e95fb3b70885be5ae35d0736866f72 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:20 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:41 +0200 irqchip/bcm-6345-l1: Report that effective affinity is a single target The BCM 6345-L1 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-8-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-bcm6345-l1.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cd68877..b36a55d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -96,6 +96,7 @@ config BCM6345_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7038_L1_IRQ bool diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index daa4ae8..43f8abe 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -231,6 +231,8 @@ static int bcm6345_l1_set_affinity(struct irq_data *d, } raw_spin_unlock_irqrestore(>lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(new_cpu)); + return IRQ_SET_MASK_OK_NOCOPY; } @@ -291,6 +293,7 @@ static int bcm6345_l1_map(struct irq_domain *d, unsigned int virq, irq_set_chip_and_handler(virq, _l1_irq_chip, handle_percpu_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; }
[tip:irq/core] irqchip/armada-370-xp: Report that effective affinity is a single target
Commit-ID: e31793a3e51137a910b827b18e532d6c1fa54514 Gitweb: http://git.kernel.org/tip/e31793a3e51137a910b827b18e532d6c1fa54514 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:19 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:41 +0200 irqchip/armada-370-xp: Report that effective affinity is a single target The Armada 370 XP driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-7-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-armada-370-xp.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index ce99c1e..cd68877 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -66,6 +66,7 @@ config ARMADA_370_XP_IRQ bool select GENERIC_IRQ_CHIP select PCI_MSI if PCI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ALPINE_MSI bool diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b207b2c..eb81567 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -330,6 +330,8 @@ static int armada_xp_set_affinity(struct irq_data *d, writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); raw_spin_unlock(_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -363,6 +365,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } else { irq_set_chip_and_handler(virq, _370_xp_irq_chip, handle_level_irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); } irq_set_probe(virq);
[tip:irq/core] irqchip/armada-370-xp: Report that effective affinity is a single target
Commit-ID: e31793a3e51137a910b827b18e532d6c1fa54514 Gitweb: http://git.kernel.org/tip/e31793a3e51137a910b827b18e532d6c1fa54514 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:19 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:41 +0200 irqchip/armada-370-xp: Report that effective affinity is a single target The Armada 370 XP driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-7-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-armada-370-xp.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index ce99c1e..cd68877 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -66,6 +66,7 @@ config ARMADA_370_XP_IRQ bool select GENERIC_IRQ_CHIP select PCI_MSI if PCI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ALPINE_MSI bool diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b207b2c..eb81567 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -330,6 +330,8 @@ static int armada_xp_set_affinity(struct irq_data *d, writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); raw_spin_unlock(_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -363,6 +365,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } else { irq_set_chip_and_handler(virq, _370_xp_irq_chip, handle_level_irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); } irq_set_probe(virq);
[tip:irq/core] irqchip/gic-v3-its: Report that effective affinity is a single target
Commit-ID: 0d224d3508f5ba67438b921fc37cf179c9652f20 Gitweb: http://git.kernel.org/tip/0d224d3508f5ba67438b921fc37cf179c9652f20 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:18 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic-v3-its: Report that effective affinity is a single target The GICv3 ITS driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-6-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6893287..22e2285 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -649,6 +649,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, target_col = _dev->its->collections[cpu]; its_send_movi(its_dev, target_col, id); its_dev->event_map.col_map[id] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); } return IRQ_SET_MASK_OK_DONE; @@ -1481,6 +1482,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq, _irq_chip, its_dev); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i))); pr_debug("ID:%d pID:%d vID:%d\n", (int)(hwirq - its_dev->event_map.lpi_base), (int) hwirq, virq + i); @@ -1495,13 +1497,16 @@ static void its_irq_domain_activate(struct irq_domain *domain, struct its_device *its_dev = irq_data_get_irq_chip_data(d); u32 event = its_get_event_id(d); const struct cpumask *cpu_mask = cpu_online_mask; + int cpu; /* get the cpu_mask of local node */ if (its_dev->its->numa_node >= 0) cpu_mask = cpumask_of_node(its_dev->its->numa_node); /* Bind the LPI to the first possible CPU */ - its_dev->event_map.col_map[event] = cpumask_first(cpu_mask); + cpu = cpumask_first(cpu_mask); + its_dev->event_map.col_map[event] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); /* Map the GIC IRQ and event to the device */ its_send_mapti(its_dev, d->hwirq, event);
[tip:irq/core] irqchip/gic-v3-its: Report that effective affinity is a single target
Commit-ID: 0d224d3508f5ba67438b921fc37cf179c9652f20 Gitweb: http://git.kernel.org/tip/0d224d3508f5ba67438b921fc37cf179c9652f20 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:18 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic-v3-its: Report that effective affinity is a single target The GICv3 ITS driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-6-marc.zyng...@arm.com --- drivers/irqchip/irq-gic-v3-its.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6893287..22e2285 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -649,6 +649,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, target_col = _dev->its->collections[cpu]; its_send_movi(its_dev, target_col, id); its_dev->event_map.col_map[id] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); } return IRQ_SET_MASK_OK_DONE; @@ -1481,6 +1482,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq, _irq_chip, its_dev); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i))); pr_debug("ID:%d pID:%d vID:%d\n", (int)(hwirq - its_dev->event_map.lpi_base), (int) hwirq, virq + i); @@ -1495,13 +1497,16 @@ static void its_irq_domain_activate(struct irq_domain *domain, struct its_device *its_dev = irq_data_get_irq_chip_data(d); u32 event = its_get_event_id(d); const struct cpumask *cpu_mask = cpu_online_mask; + int cpu; /* get the cpu_mask of local node */ if (its_dev->its->numa_node >= 0) cpu_mask = cpumask_of_node(its_dev->its->numa_node); /* Bind the LPI to the first possible CPU */ - its_dev->event_map.col_map[event] = cpumask_first(cpu_mask); + cpu = cpumask_first(cpu_mask); + its_dev->event_map.col_map[event] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); /* Map the GIC IRQ and event to the device */ its_send_mapti(its_dev, d->hwirq, event);
[tip:irq/core] irqchip/gic-v3: Report that effective affinity is a single target
Commit-ID: 956ae91ae8761f2cd8cd7b8d6cb90fd4d0b8a596 Gitweb: http://git.kernel.org/tip/956ae91ae8761f2cd8cd7b8d6cb90fd4d0b8a596 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:17 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic-v3: Report that effective affinity is a single target The GICv3 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-5-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic-v3.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 586929d..ce99c1e 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -35,6 +35,7 @@ config ARM_GIC_V3 select MULTI_IRQ_HANDLER select IRQ_DOMAIN_HIERARCHY select PARTITION_PERCPU + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_V3_ITS bool diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index dbffb7a..511c290 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -670,6 +670,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, else gic_dist_wait_for_rwp(); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #else @@ -768,6 +770,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } /* LPIs */ if (hw >= 8192 && hw < GIC_ID_NR) {
[tip:irq/core] irqchip/gic-v3: Report that effective affinity is a single target
Commit-ID: 956ae91ae8761f2cd8cd7b8d6cb90fd4d0b8a596 Gitweb: http://git.kernel.org/tip/956ae91ae8761f2cd8cd7b8d6cb90fd4d0b8a596 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:17 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic-v3: Report that effective affinity is a single target The GICv3 driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-5-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic-v3.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 586929d..ce99c1e 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -35,6 +35,7 @@ config ARM_GIC_V3 select MULTI_IRQ_HANDLER select IRQ_DOMAIN_HIERARCHY select PARTITION_PERCPU + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_V3_ITS bool diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index dbffb7a..511c290 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -670,6 +670,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, else gic_dist_wait_for_rwp(); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #else @@ -768,6 +770,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } /* LPIs */ if (hw >= 8192 && hw < GIC_ID_NR) {
[tip:irq/core] irqchip/gic: Report that effective affinity is a single target
Commit-ID: 0c9e498286ef9762e0ae62fc8a02b4739796970f Gitweb: http://git.kernel.org/tip/0c9e498286ef9762e0ae62fc8a02b4739796970f Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:16 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic: Report that effective affinity is a single target The GIC driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-4-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f1fd5f4..586929d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -7,6 +7,7 @@ config ARM_GIC select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select MULTI_IRQ_HANDLER + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_PM bool diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 1b1df4f..20dd2ba 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -344,6 +344,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, writel_relaxed(val | bit, reg); gic_unlock_irqrestore(flags); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #endif @@ -966,6 +968,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, >chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } return 0; }
[tip:irq/core] irqchip/gic: Report that effective affinity is a single target
Commit-ID: 0c9e498286ef9762e0ae62fc8a02b4739796970f Gitweb: http://git.kernel.org/tip/0c9e498286ef9762e0ae62fc8a02b4739796970f Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:16 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:40 +0200 irqchip/gic: Report that effective affinity is a single target The GIC driver only targets a single CPU at a time, even if the notional affinity is wider. Let's inform the core code about this. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-4-marc.zyng...@arm.com --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f1fd5f4..586929d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -7,6 +7,7 @@ config ARM_GIC select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select MULTI_IRQ_HANDLER + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_PM bool diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 1b1df4f..20dd2ba 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -344,6 +344,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, writel_relaxed(val | bit, reg); gic_unlock_irqrestore(flags); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #endif @@ -966,6 +968,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, >chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } return 0; }
[tip:irq/core] genirq/proc: Use the the accessor to report the effective affinity
Commit-ID: 6bc6d4abd22e890cf69a05554fa8f8f83f351515 Gitweb: http://git.kernel.org/tip/6bc6d4abd22e890cf69a05554fa8f8f83f351515 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:15 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:39 +0200 genirq/proc: Use the the accessor to report the effective affinity If CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is defined, but that the interrupt is not single target, the effective affinity reported in /proc/irq/x/effective_affinity will be empty, which is not the truth. Instead, use the accessor to report the affinity, which will pick the right mask. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-3-marc.zyng...@arm.com --- kernel/irq/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 7f9642a..0534781 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -61,7 +61,7 @@ static int show_irq_affinity(int type, struct seq_file *m) case EFFECTIVE: case EFFECTIVE_LIST: #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK - mask = desc->irq_common_data.effective_affinity; + mask = irq_data_get_effective_affinity_mask(>irq_data); break; #else return -EINVAL;
[tip:irq/core] genirq/proc: Use the the accessor to report the effective affinity
Commit-ID: 6bc6d4abd22e890cf69a05554fa8f8f83f351515 Gitweb: http://git.kernel.org/tip/6bc6d4abd22e890cf69a05554fa8f8f83f351515 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:15 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:39 +0200 genirq/proc: Use the the accessor to report the effective affinity If CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is defined, but that the interrupt is not single target, the effective affinity reported in /proc/irq/x/effective_affinity will be empty, which is not the truth. Instead, use the accessor to report the affinity, which will pick the right mask. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-3-marc.zyng...@arm.com --- kernel/irq/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 7f9642a..0534781 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -61,7 +61,7 @@ static int show_irq_affinity(int type, struct seq_file *m) case EFFECTIVE: case EFFECTIVE_LIST: #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK - mask = desc->irq_common_data.effective_affinity; + mask = irq_data_get_effective_affinity_mask(>irq_data); break; #else return -EINVAL;
[tip:irq/core] genirq: Restrict effective affinity to interrupts actually using it
Commit-ID: 74def747bcd09692bdbf8c6a15350795b0f11ca8 Gitweb: http://git.kernel.org/tip/74def747bcd09692bdbf8c6a15350795b0f11ca8 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:39:14 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:39 +0200 genirq: Restrict effective affinity to interrupts actually using it Just because CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected doesn't mean that all the interrupts are using the effective affinity mask. For a number of them, this mask is likely to be empty. In order to deal with this, let's restrict the use of the effective affinity mask to these interrupts that have a non empty effective affinity. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-2-marc.zyng...@arm.com --- include/linux/irq.h | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index d2d54379..dcfac6c 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -781,7 +781,10 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d) static inline struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) { - return d->common->effective_affinity; + if (!cpumask_empty(d->common->effective_affinity)) + return d->common->effective_affinity; + + return d->common->affinity; } static inline void irq_data_update_effective_affinity(struct irq_data *d, const struct cpumask *m)
[tip:irq/core] genirq: Restrict effective affinity to interrupts actually using it
Commit-ID: 74def747bcd09692bdbf8c6a15350795b0f11ca8 Gitweb: http://git.kernel.org/tip/74def747bcd09692bdbf8c6a15350795b0f11ca8 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:39:14 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:54:39 +0200 genirq: Restrict effective affinity to interrupts actually using it Just because CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected doesn't mean that all the interrupts are using the effective affinity mask. For a number of them, this mask is likely to be empty. In order to deal with this, let's restrict the use of the effective affinity mask to these interrupts that have a non empty effective affinity. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Andrew Lunn Cc: James Hogan Cc: Jason Cooper Cc: Paul Burton Cc: Chris Zankel Cc: Kevin Cernekee Cc: Wei Xu Cc: Max Filippov Cc: Florian Fainelli Cc: Gregory Clement Cc: Matt Redfearn Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20170818083925.10108-2-marc.zyng...@arm.com --- include/linux/irq.h | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index d2d54379..dcfac6c 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -781,7 +781,10 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d) static inline struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) { - return d->common->effective_affinity; + if (!cpumask_empty(d->common->effective_affinity)) + return d->common->effective_affinity; + + return d->common->affinity; } static inline void irq_data_update_effective_affinity(struct irq_data *d, const struct cpumask *m)
[tip:irq/core] genirq/debugfs: Triggering of interrupts from userspace
Commit-ID: 536e2e34bd002267384b06683f023003a830 Gitweb: http://git.kernel.org/tip/536e2e34bd002267384b06683f023003a830 Author: Marc ZyngierAuthorDate: Fri, 18 Aug 2017 09:11:56 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:36:24 +0200 genirq/debugfs: Triggering of interrupts from userspace When developing new (and therefore buggy) interrupt related code, it can sometimes be useful to inject interrupts without having to rely on a device to actually generate them. This functionnality relies either on the irqchip driver to expose a irq_set_irqchip_state(IRQCHIP_STATE_PENDING) callback, or on the core code to be able to retrigger a (edge-only) interrupt. To use this feature: echo -n trigger > /sys/kernel/debug/irq/irqs/IRQNUM WARNING: This is DANGEROUS, and strictly a debug feature. Do not use it on a production system. Your HW is likely to catch fire, your data to be corrupted, and reporting this will make you look an even bigger fool than the idiot who wrote this patch. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: http://lkml.kernel.org/r/20170818081156.9264-1-marc.zyng...@arm.com --- kernel/irq/debugfs.c | 50 +- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4d384ed..c3fdb36 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -5,6 +5,7 @@ */ #include #include +#include #include "internals.h" @@ -171,8 +172,55 @@ static int irq_debug_open(struct inode *inode, struct file *file) return single_open(file, irq_debug_show, inode->i_private); } +static ssize_t irq_debug_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct irq_desc *desc = file_inode(file)->i_private; + char buf[8] = { 0, }; + size_t size; + + size = min(sizeof(buf) - 1, count); + if (copy_from_user(buf, user_buf, size)) + return -EFAULT; + + if (!strncmp(buf, "trigger", size)) { + unsigned long flags; + int err; + + /* Try the HW interface first */ + err = irq_set_irqchip_state(irq_desc_get_irq(desc), + IRQCHIP_STATE_PENDING, true); + if (!err) + return count; + + /* +* Otherwise, try to inject via the resend interface, +* which may or may not succeed. +*/ + chip_bus_lock(desc); + raw_spin_lock_irqsave(>lock, flags); + + if (irq_settings_is_level(desc)) { + /* Can't do level, sorry */ + err = -EINVAL; + } else { + desc->istate |= IRQS_PENDING; + check_irq_resend(desc); + err = 0; + } + + raw_spin_unlock_irqrestore(>lock, flags); + chip_bus_sync_unlock(desc); + + return err ? err : count; + } + + return count; +} + static const struct file_operations dfs_irq_ops = { .open = irq_debug_open, + .write = irq_debug_write, .read = seq_read, .llseek = seq_lseek, .release= single_release, @@ -186,7 +234,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) return; sprintf(name, "%d", irq); - desc->debugfs_file = debugfs_create_file(name, 0444, irq_dir, desc, + desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc, _irq_ops); }
[tip:irq/core] genirq/debugfs: Triggering of interrupts from userspace
Commit-ID: 536e2e34bd002267384b06683f023003a830 Gitweb: http://git.kernel.org/tip/536e2e34bd002267384b06683f023003a830 Author: Marc Zyngier AuthorDate: Fri, 18 Aug 2017 09:11:56 +0100 Committer: Thomas Gleixner CommitDate: Fri, 18 Aug 2017 10:36:24 +0200 genirq/debugfs: Triggering of interrupts from userspace When developing new (and therefore buggy) interrupt related code, it can sometimes be useful to inject interrupts without having to rely on a device to actually generate them. This functionnality relies either on the irqchip driver to expose a irq_set_irqchip_state(IRQCHIP_STATE_PENDING) callback, or on the core code to be able to retrigger a (edge-only) interrupt. To use this feature: echo -n trigger > /sys/kernel/debug/irq/irqs/IRQNUM WARNING: This is DANGEROUS, and strictly a debug feature. Do not use it on a production system. Your HW is likely to catch fire, your data to be corrupted, and reporting this will make you look an even bigger fool than the idiot who wrote this patch. Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Link: http://lkml.kernel.org/r/20170818081156.9264-1-marc.zyng...@arm.com --- kernel/irq/debugfs.c | 50 +- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4d384ed..c3fdb36 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -5,6 +5,7 @@ */ #include #include +#include #include "internals.h" @@ -171,8 +172,55 @@ static int irq_debug_open(struct inode *inode, struct file *file) return single_open(file, irq_debug_show, inode->i_private); } +static ssize_t irq_debug_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct irq_desc *desc = file_inode(file)->i_private; + char buf[8] = { 0, }; + size_t size; + + size = min(sizeof(buf) - 1, count); + if (copy_from_user(buf, user_buf, size)) + return -EFAULT; + + if (!strncmp(buf, "trigger", size)) { + unsigned long flags; + int err; + + /* Try the HW interface first */ + err = irq_set_irqchip_state(irq_desc_get_irq(desc), + IRQCHIP_STATE_PENDING, true); + if (!err) + return count; + + /* +* Otherwise, try to inject via the resend interface, +* which may or may not succeed. +*/ + chip_bus_lock(desc); + raw_spin_lock_irqsave(>lock, flags); + + if (irq_settings_is_level(desc)) { + /* Can't do level, sorry */ + err = -EINVAL; + } else { + desc->istate |= IRQS_PENDING; + check_irq_resend(desc); + err = 0; + } + + raw_spin_unlock_irqrestore(>lock, flags); + chip_bus_sync_unlock(desc); + + return err ? err : count; + } + + return count; +} + static const struct file_operations dfs_irq_ops = { .open = irq_debug_open, + .write = irq_debug_write, .read = seq_read, .llseek = seq_lseek, .release= single_release, @@ -186,7 +234,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) return; sprintf(name, "%d", irq); - desc->debugfs_file = debugfs_create_file(name, 0444, irq_dir, desc, + desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc, _irq_ops); }
[tip:locking/core] clocksource/arm_arch_timer: Use static_branch_enable_cpuslocked()
Commit-ID: 450f9689f294c331c56ec37d68302ccc19c7caa2 Gitweb: http://git.kernel.org/tip/450f9689f294c331c56ec37d68302ccc19c7caa2 Author: Marc ZyngierAuthorDate: Tue, 1 Aug 2017 09:02:57 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:29:00 +0200 clocksource/arm_arch_timer: Use static_branch_enable_cpuslocked() Use the new static_branch_enable_cpuslocked() function to switch the workaround static key on the CPU hotplug path. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-5-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- drivers/clocksource/arm_arch_timer.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index aae87c4..c62e716 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -455,7 +455,11 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa per_cpu(timer_unstable_counter_workaround, i) = wa; } - static_branch_enable(_timer_read_ool_enabled); + /* +* Use the locked version, as we're called from the CPU +* hotplug framework. Otherwise, we end-up in deadlock-land. +*/ + static_branch_enable_cpuslocked(_timer_read_ool_enabled); /* * Don't use the vdso fastpath if errata require using the
[tip:locking/core] clocksource/arm_arch_timer: Use static_branch_enable_cpuslocked()
Commit-ID: 450f9689f294c331c56ec37d68302ccc19c7caa2 Gitweb: http://git.kernel.org/tip/450f9689f294c331c56ec37d68302ccc19c7caa2 Author: Marc Zyngier AuthorDate: Tue, 1 Aug 2017 09:02:57 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:29:00 +0200 clocksource/arm_arch_timer: Use static_branch_enable_cpuslocked() Use the new static_branch_enable_cpuslocked() function to switch the workaround static key on the CPU hotplug path. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-5-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- drivers/clocksource/arm_arch_timer.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index aae87c4..c62e716 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -455,7 +455,11 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa per_cpu(timer_unstable_counter_workaround, i) = wa; } - static_branch_enable(_timer_read_ool_enabled); + /* +* Use the locked version, as we're called from the CPU +* hotplug framework. Otherwise, we end-up in deadlock-land. +*/ + static_branch_enable_cpuslocked(_timer_read_ool_enabled); /* * Don't use the vdso fastpath if errata require using the
[tip:locking/core] jump_label: Provide hotplug context variants
Commit-ID: 5a40527f8f0798553764fc8db4111d7d9c33ea51 Gitweb: http://git.kernel.org/tip/5a40527f8f0798553764fc8db4111d7d9c33ea51 Author: Marc ZyngierAuthorDate: Tue, 1 Aug 2017 09:02:56 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:59 +0200 jump_label: Provide hotplug context variants As using the normal static key API under the hotplug lock is pretty much impossible, let's provide a variant of some of them that require the hotplug lock to have already been taken. These function are only meant to be used in CPU hotplug callbacks. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-4-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- Documentation/static-keys.txt | 15 +++ include/linux/jump_label.h| 11 +-- kernel/jump_label.c | 22 ++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Documentation/static-keys.txt b/Documentation/static-keys.txt index 870b4be..ab16efe 100644 --- a/Documentation/static-keys.txt +++ b/Documentation/static-keys.txt @@ -154,6 +154,21 @@ and 'static_key_count()'. In general, if you use these functions, they should be protected with the same mutex used around the enable/disable or increment/decrement function. +Note that switching branches results in some locks being taken, +particularly the CPU hotplug lock (in order to avoid races against +CPUs being brought in the kernel whilst the kernel is getting +patched). Calling the static key API from within a hotplug notifier is +thus a sure deadlock recipe. In order to still allow use of the +functionnality, the following functions are provided: + + static_key_enable_cpuslocked() + static_key_disable_cpuslocked() + static_branch_enable_cpuslocked() + static_branch_disable_cpuslocked() + +These functions are *not* general purpose, and must only be used when +you really know that you're in the above context, and no other. + Where an array of keys is required, it can be defined as:: DEFINE_STATIC_KEY_ARRAY_TRUE(keys, count); diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 740a42e..cd58616 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -163,6 +163,8 @@ extern void jump_label_apply_nops(struct module *mod); extern int static_key_count(struct static_key *key); extern void static_key_enable(struct static_key *key); extern void static_key_disable(struct static_key *key); +extern void static_key_enable_cpuslocked(struct static_key *key); +extern void static_key_disable_cpuslocked(struct static_key *key); /* * We should be using ATOMIC_INIT() for initializing .enabled, but @@ -254,6 +256,9 @@ static inline void static_key_disable(struct static_key *key) atomic_set(>enabled, 0); } +#define static_key_enable_cpuslocked(k)static_key_enable((k)) +#define static_key_disable_cpuslocked(k) static_key_disable((k)) + #define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) } #define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) } @@ -415,8 +420,10 @@ extern bool wrong_branch_error(void); * Normal usage; boolean enable/disable. */ -#define static_branch_enable(x)static_key_enable(&(x)->key) -#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable(x) static_key_enable(&(x)->key) +#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable_cpuslocked(x) static_key_enable_cpuslocked(&(x)->key) +#define static_branch_disable_cpuslocked(x) static_key_disable_cpuslocked(&(x)->key) #endif /* __ASSEMBLY__ */ diff --git a/kernel/jump_label.c b/kernel/jump_label.c index cc6d815..0bf2e8f5 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -126,15 +126,15 @@ void static_key_slow_inc(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_slow_inc); -void static_key_enable(struct static_key *key) +void static_key_enable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(); + if (atomic_read(>enabled) > 0) { WARN_ON_ONCE(atomic_read(>enabled) != 1); return; } - cpus_read_lock(); jump_label_lock(); if (atomic_read(>enabled) == 0) { atomic_set(>enabled, -1); @@ -145,23 +145,37 @@ void static_key_enable(struct static_key *key) atomic_set_release(>enabled, 1); } jump_label_unlock(); +} +EXPORT_SYMBOL_GPL(static_key_enable_cpuslocked); + +void
[tip:locking/core] jump_label: Provide hotplug context variants
Commit-ID: 5a40527f8f0798553764fc8db4111d7d9c33ea51 Gitweb: http://git.kernel.org/tip/5a40527f8f0798553764fc8db4111d7d9c33ea51 Author: Marc Zyngier AuthorDate: Tue, 1 Aug 2017 09:02:56 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:59 +0200 jump_label: Provide hotplug context variants As using the normal static key API under the hotplug lock is pretty much impossible, let's provide a variant of some of them that require the hotplug lock to have already been taken. These function are only meant to be used in CPU hotplug callbacks. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-4-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- Documentation/static-keys.txt | 15 +++ include/linux/jump_label.h| 11 +-- kernel/jump_label.c | 22 ++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Documentation/static-keys.txt b/Documentation/static-keys.txt index 870b4be..ab16efe 100644 --- a/Documentation/static-keys.txt +++ b/Documentation/static-keys.txt @@ -154,6 +154,21 @@ and 'static_key_count()'. In general, if you use these functions, they should be protected with the same mutex used around the enable/disable or increment/decrement function. +Note that switching branches results in some locks being taken, +particularly the CPU hotplug lock (in order to avoid races against +CPUs being brought in the kernel whilst the kernel is getting +patched). Calling the static key API from within a hotplug notifier is +thus a sure deadlock recipe. In order to still allow use of the +functionnality, the following functions are provided: + + static_key_enable_cpuslocked() + static_key_disable_cpuslocked() + static_branch_enable_cpuslocked() + static_branch_disable_cpuslocked() + +These functions are *not* general purpose, and must only be used when +you really know that you're in the above context, and no other. + Where an array of keys is required, it can be defined as:: DEFINE_STATIC_KEY_ARRAY_TRUE(keys, count); diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 740a42e..cd58616 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -163,6 +163,8 @@ extern void jump_label_apply_nops(struct module *mod); extern int static_key_count(struct static_key *key); extern void static_key_enable(struct static_key *key); extern void static_key_disable(struct static_key *key); +extern void static_key_enable_cpuslocked(struct static_key *key); +extern void static_key_disable_cpuslocked(struct static_key *key); /* * We should be using ATOMIC_INIT() for initializing .enabled, but @@ -254,6 +256,9 @@ static inline void static_key_disable(struct static_key *key) atomic_set(>enabled, 0); } +#define static_key_enable_cpuslocked(k)static_key_enable((k)) +#define static_key_disable_cpuslocked(k) static_key_disable((k)) + #define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) } #define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) } @@ -415,8 +420,10 @@ extern bool wrong_branch_error(void); * Normal usage; boolean enable/disable. */ -#define static_branch_enable(x)static_key_enable(&(x)->key) -#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable(x) static_key_enable(&(x)->key) +#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable_cpuslocked(x) static_key_enable_cpuslocked(&(x)->key) +#define static_branch_disable_cpuslocked(x) static_key_disable_cpuslocked(&(x)->key) #endif /* __ASSEMBLY__ */ diff --git a/kernel/jump_label.c b/kernel/jump_label.c index cc6d815..0bf2e8f5 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -126,15 +126,15 @@ void static_key_slow_inc(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_slow_inc); -void static_key_enable(struct static_key *key) +void static_key_enable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(); + if (atomic_read(>enabled) > 0) { WARN_ON_ONCE(atomic_read(>enabled) != 1); return; } - cpus_read_lock(); jump_label_lock(); if (atomic_read(>enabled) == 0) { atomic_set(>enabled, -1); @@ -145,23 +145,37 @@ void static_key_enable(struct static_key *key) atomic_set_release(>enabled, 1); } jump_label_unlock(); +} +EXPORT_SYMBOL_GPL(static_key_enable_cpuslocked); + +void static_key_enable(struct static_key *key) +{ + cpus_read_lock(); + static_key_enable_cpuslocked(key); cpus_read_unlock(); } EXPORT_SYMBOL_GPL(static_key_enable); -void
[tip:locking/core] jump_label: Split out code under the hotplug lock
Commit-ID: 8b7b412807053ab5f059ffae426a280e769a5bda Gitweb: http://git.kernel.org/tip/8b7b412807053ab5f059ffae426a280e769a5bda Author: Marc ZyngierAuthorDate: Tue, 1 Aug 2017 09:02:55 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:58 +0200 jump_label: Split out code under the hotplug lock In order to later introduce an "already locked" version of some of the static key funcions, let's split the code into the core stuff (the *_cpuslocked functions) and the usual helpers, which now take/release the hotplug lock and call into the _cpuslocked versions. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-3-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- kernel/jump_label.c | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 161301f..cc6d815 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -79,11 +79,10 @@ int static_key_count(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_count); -void static_key_slow_inc(struct static_key *key) +static void static_key_slow_inc_cpuslocked(struct static_key *key) { int v, v1; - cpus_read_lock(); STATIC_KEY_CHECK_USE(); /* @@ -100,10 +99,8 @@ void static_key_slow_inc(struct static_key *key) */ for (v = atomic_read(>enabled); v > 0; v = v1) { v1 = atomic_cmpxchg(>enabled, v, v + 1); - if (likely(v1 == v)) { - cpus_read_unlock(); + if (likely(v1 == v)) return; - } } jump_label_lock(); @@ -119,6 +116,12 @@ void static_key_slow_inc(struct static_key *key) atomic_inc(>enabled); } jump_label_unlock(); +} + +void static_key_slow_inc(struct static_key *key) +{ + cpus_read_lock(); + static_key_slow_inc_cpuslocked(key); cpus_read_unlock(); } EXPORT_SYMBOL_GPL(static_key_slow_inc); @@ -163,10 +166,10 @@ void static_key_disable(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_disable); -static void __static_key_slow_dec(struct static_key *key, - unsigned long rate_limit, struct delayed_work *work) +static void static_key_slow_dec_cpuslocked(struct static_key *key, + unsigned long rate_limit, + struct delayed_work *work) { - cpus_read_lock(); /* * The negative count check is valid even when a negative * key->enabled is in use by static_key_slow_inc(); a @@ -177,7 +180,6 @@ static void __static_key_slow_dec(struct static_key *key, if (!atomic_dec_and_mutex_lock(>enabled, _label_mutex)) { WARN(atomic_read(>enabled) < 0, "jump label: negative count!\n"); - cpus_read_unlock(); return; } @@ -188,6 +190,14 @@ static void __static_key_slow_dec(struct static_key *key, jump_label_update(key); } jump_label_unlock(); +} + +static void __static_key_slow_dec(struct static_key *key, + unsigned long rate_limit, + struct delayed_work *work) +{ + cpus_read_lock(); + static_key_slow_dec_cpuslocked(key, rate_limit, work); cpus_read_unlock(); }
[tip:locking/core] jump_label: Split out code under the hotplug lock
Commit-ID: 8b7b412807053ab5f059ffae426a280e769a5bda Gitweb: http://git.kernel.org/tip/8b7b412807053ab5f059ffae426a280e769a5bda Author: Marc Zyngier AuthorDate: Tue, 1 Aug 2017 09:02:55 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:58 +0200 jump_label: Split out code under the hotplug lock In order to later introduce an "already locked" version of some of the static key funcions, let's split the code into the core stuff (the *_cpuslocked functions) and the usual helpers, which now take/release the hotplug lock and call into the _cpuslocked versions. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-3-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- kernel/jump_label.c | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 161301f..cc6d815 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -79,11 +79,10 @@ int static_key_count(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_count); -void static_key_slow_inc(struct static_key *key) +static void static_key_slow_inc_cpuslocked(struct static_key *key) { int v, v1; - cpus_read_lock(); STATIC_KEY_CHECK_USE(); /* @@ -100,10 +99,8 @@ void static_key_slow_inc(struct static_key *key) */ for (v = atomic_read(>enabled); v > 0; v = v1) { v1 = atomic_cmpxchg(>enabled, v, v + 1); - if (likely(v1 == v)) { - cpus_read_unlock(); + if (likely(v1 == v)) return; - } } jump_label_lock(); @@ -119,6 +116,12 @@ void static_key_slow_inc(struct static_key *key) atomic_inc(>enabled); } jump_label_unlock(); +} + +void static_key_slow_inc(struct static_key *key) +{ + cpus_read_lock(); + static_key_slow_inc_cpuslocked(key); cpus_read_unlock(); } EXPORT_SYMBOL_GPL(static_key_slow_inc); @@ -163,10 +166,10 @@ void static_key_disable(struct static_key *key) } EXPORT_SYMBOL_GPL(static_key_disable); -static void __static_key_slow_dec(struct static_key *key, - unsigned long rate_limit, struct delayed_work *work) +static void static_key_slow_dec_cpuslocked(struct static_key *key, + unsigned long rate_limit, + struct delayed_work *work) { - cpus_read_lock(); /* * The negative count check is valid even when a negative * key->enabled is in use by static_key_slow_inc(); a @@ -177,7 +180,6 @@ static void __static_key_slow_dec(struct static_key *key, if (!atomic_dec_and_mutex_lock(>enabled, _label_mutex)) { WARN(atomic_read(>enabled) < 0, "jump label: negative count!\n"); - cpus_read_unlock(); return; } @@ -188,6 +190,14 @@ static void __static_key_slow_dec(struct static_key *key, jump_label_update(key); } jump_label_unlock(); +} + +static void __static_key_slow_dec(struct static_key *key, + unsigned long rate_limit, + struct delayed_work *work) +{ + cpus_read_lock(); + static_key_slow_dec_cpuslocked(key, rate_limit, work); cpus_read_unlock(); }
[tip:locking/core] jump_label: Move CPU hotplug locking
Commit-ID: b70cecf4b6b72a9977576ab32cca0e24f286f517 Gitweb: http://git.kernel.org/tip/b70cecf4b6b72a9977576ab32cca0e24f286f517 Author: Marc ZyngierAuthorDate: Tue, 1 Aug 2017 09:02:54 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:58 +0200 jump_label: Move CPU hotplug locking As we're about to rework the locking, let's move the taking and release of the CPU hotplug lock to locations that will make its reworking completely obvious. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-2-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- kernel/jump_label.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index f2ea678..161301f 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -83,6 +83,7 @@ void static_key_slow_inc(struct static_key *key) { int v, v1; + cpus_read_lock(); STATIC_KEY_CHECK_USE(); /* @@ -99,11 +100,12 @@ void static_key_slow_inc(struct static_key *key) */ for (v = atomic_read(>enabled); v > 0; v = v1) { v1 = atomic_cmpxchg(>enabled, v, v + 1); - if (likely(v1 == v)) + if (likely(v1 == v)) { + cpus_read_unlock(); return; + } } - cpus_read_lock(); jump_label_lock(); if (atomic_read(>enabled) == 0) { atomic_set(>enabled, -1);
[tip:locking/core] jump_label: Move CPU hotplug locking
Commit-ID: b70cecf4b6b72a9977576ab32cca0e24f286f517 Gitweb: http://git.kernel.org/tip/b70cecf4b6b72a9977576ab32cca0e24f286f517 Author: Marc Zyngier AuthorDate: Tue, 1 Aug 2017 09:02:54 +0100 Committer: Ingo Molnar CommitDate: Thu, 10 Aug 2017 12:28:58 +0200 jump_label: Move CPU hotplug locking As we're about to rework the locking, let's move the taking and release of the CPU hotplug lock to locations that will make its reworking completely obvious. Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Cc: Leo Yan Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Link: http://lkml.kernel.org/r/20170801080257.5056-2-marc.zyng...@arm.com Signed-off-by: Ingo Molnar --- kernel/jump_label.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index f2ea678..161301f 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -83,6 +83,7 @@ void static_key_slow_inc(struct static_key *key) { int v, v1; + cpus_read_lock(); STATIC_KEY_CHECK_USE(); /* @@ -99,11 +100,12 @@ void static_key_slow_inc(struct static_key *key) */ for (v = atomic_read(>enabled); v > 0; v = v1) { v1 = atomic_cmpxchg(>enabled, v, v + 1); - if (likely(v1 == v)) + if (likely(v1 == v)) { + cpus_read_unlock(); return; + } } - cpus_read_lock(); jump_label_lock(); if (atomic_read(>enabled) == 0) { atomic_set(>enabled, -1);
[tip:irq/urgent] irqdomain: Allow ACPI device nodes to be used as irqdomain identifiers
Commit-ID: c5c601c4295f89368f4a304cb3ae4aebdf80db22 Gitweb: http://git.kernel.org/tip/c5c601c4295f89368f4a304cb3ae4aebdf80db22 Author: Marc ZyngierAuthorDate: Fri, 7 Jul 2017 09:39:59 +0100 Committer: Thomas Gleixner CommitDate: Fri, 7 Jul 2017 12:13:29 +0200 irqdomain: Allow ACPI device nodes to be used as irqdomain identifiers A number of irqchip implementations are (ab)using the irqdomain allocator by passing a fwnode that is neither a FWNODE_OF or a FWNODE_IRQCHIP. This is pretty bad, but it also feels pretty crap to force these drivers to allocate their own irqchip_fwid when they already have a proper fwnode. Instead, let's teach the irqdomain allocator about ACPI device nodes, and add some lovely name generation code... Tested on an arm64 D05 system. Reported-and-tested-by: John Garry Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Agustin Vega-Frias Cc: Ma Jun Cc: Hanjun Guo Link: http://lkml.kernel.org/r/20170707083959.10349-1-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 16 1 file changed, 16 insertions(+) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index ed47688..f1f2514 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1,5 +1,6 @@ #define pr_fmt(fmt) "irq: " fmt +#include #include #include #include @@ -155,6 +156,21 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, domain->name = fwid->name; break; } +#ifdef CONFIG_ACPI + } else if (is_acpi_device_node(fwnode)) { + struct acpi_buffer buf = { + .length = ACPI_ALLOCATE_BUFFER, + }; + acpi_handle handle; + + handle = acpi_device_handle(to_acpi_device_node(fwnode)); + if (acpi_get_name(handle, ACPI_FULL_PATHNAME, ) == AE_OK) { + domain->name = buf.pointer; + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + } + + domain->fwnode = fwnode; +#endif } else if (of_node) { char *name;
[tip:irq/urgent] irqdomain: Allow ACPI device nodes to be used as irqdomain identifiers
Commit-ID: c5c601c4295f89368f4a304cb3ae4aebdf80db22 Gitweb: http://git.kernel.org/tip/c5c601c4295f89368f4a304cb3ae4aebdf80db22 Author: Marc Zyngier AuthorDate: Fri, 7 Jul 2017 09:39:59 +0100 Committer: Thomas Gleixner CommitDate: Fri, 7 Jul 2017 12:13:29 +0200 irqdomain: Allow ACPI device nodes to be used as irqdomain identifiers A number of irqchip implementations are (ab)using the irqdomain allocator by passing a fwnode that is neither a FWNODE_OF or a FWNODE_IRQCHIP. This is pretty bad, but it also feels pretty crap to force these drivers to allocate their own irqchip_fwid when they already have a proper fwnode. Instead, let's teach the irqdomain allocator about ACPI device nodes, and add some lovely name generation code... Tested on an arm64 D05 system. Reported-and-tested-by: John Garry Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Agustin Vega-Frias Cc: Ma Jun Cc: Hanjun Guo Link: http://lkml.kernel.org/r/20170707083959.10349-1-marc.zyng...@arm.com --- kernel/irq/irqdomain.c | 16 1 file changed, 16 insertions(+) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index ed47688..f1f2514 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1,5 +1,6 @@ #define pr_fmt(fmt) "irq: " fmt +#include #include #include #include @@ -155,6 +156,21 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, domain->name = fwid->name; break; } +#ifdef CONFIG_ACPI + } else if (is_acpi_device_node(fwnode)) { + struct acpi_buffer buf = { + .length = ACPI_ALLOCATE_BUFFER, + }; + acpi_handle handle; + + handle = acpi_device_handle(to_acpi_device_node(fwnode)); + if (acpi_get_name(handle, ACPI_FULL_PATHNAME, ) == AE_OK) { + domain->name = buf.pointer; + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + } + + domain->fwnode = fwnode; +#endif } else if (of_node) { char *name;
[tip:irq/core] Documentation: Update IRQ-domain.txt to document irq_domain_mapping
Commit-ID: 53286669392b2d888f4b78b0e7894e022e668d11 Gitweb: http://git.kernel.org/tip/53286669392b2d888f4b78b0e7894e022e668d11 Author: Marc ZyngierAuthorDate: Fri, 12 May 2017 12:55:38 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:45 +0200 Documentation: Update IRQ-domain.txt to document irq_domain_mapping irq_domain_mapping is a rather useful tool to understand how IRqs are mapped in irqdomains, and yet it is not documented anywhere. Let's address this. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-5-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- Documentation/IRQ-domain.txt | 41 +++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 82001a2..1f246eb 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -231,5 +231,42 @@ needs to: 4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap, they are unused with hierarchy irq_domain. -Hierarchy irq_domain may also be used to support other architectures, -such as ARM, ARM64 etc. +Hierarchy irq_domain is in no way x86 specific, and is heavily used to +support other architectures, such as ARM, ARM64 etc. + +=== Debugging === + +If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on +CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in +your debugfs mount point, called irq_domain_mapping. This file +contains a live snapshot of all the IRQ domains in the system: + + name mapped linear-max direct-max devtree-node + pl061 8 8 0 /smb/gpio@e008 + pl061 8 8 0 /smb/gpio@e105 + pMSI 0 0 0 /interrupt-controller@e1101000/v2m@e008 + MSI 37 0 0 /interrupt-controller@e1101000/v2m@e008 + GICv2m37 0 0 /interrupt-controller@e1101000/v2m@e008 + GICv2448 448 0 /interrupt-controller@e1101000 + +it also iterates over the interrupts to display their mapping in the +domains, and makes the domain stacking visible: + + +irqhwirqchip namechip data active type domain +1 0x00019 GICv20x0916bfd8 *LINEAR GICv2 +2 0x0001d GICv20x0916bfd8 LINEAR GICv2 +3 0x0001e GICv20x0916bfd8 *LINEAR GICv2 +4 0x0001b GICv20x0916bfd8 *LINEAR GICv2 +5 0x0001a GICv20x0916bfd8 LINEAR GICv2 +[...] + 96 0x81808 MSI 0x (null) RADIX MSI + 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m + 96+ 0x00063 GICv20x0916bfd8 LINEAR GICv2 + 97 0x08800 MSI 0x (null) * RADIX MSI + 97+ 0x00064 GICv2m 0x8003ee116980 * RADIX GICv2m + 97+ 0x00064 GICv20x0916bfd8 *LINEAR GICv2 + +Here, interrupts 1-5 are only using a single domain, while 96 and 97 +are build out of a stack of three domain, each level performing a +particular function.
[tip:irq/core] Documentation: Update IRQ-domain.txt to document irq_domain_mapping
Commit-ID: 53286669392b2d888f4b78b0e7894e022e668d11 Gitweb: http://git.kernel.org/tip/53286669392b2d888f4b78b0e7894e022e668d11 Author: Marc Zyngier AuthorDate: Fri, 12 May 2017 12:55:38 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:45 +0200 Documentation: Update IRQ-domain.txt to document irq_domain_mapping irq_domain_mapping is a rather useful tool to understand how IRqs are mapped in irqdomains, and yet it is not documented anywhere. Let's address this. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-5-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- Documentation/IRQ-domain.txt | 41 +++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 82001a2..1f246eb 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -231,5 +231,42 @@ needs to: 4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap, they are unused with hierarchy irq_domain. -Hierarchy irq_domain may also be used to support other architectures, -such as ARM, ARM64 etc. +Hierarchy irq_domain is in no way x86 specific, and is heavily used to +support other architectures, such as ARM, ARM64 etc. + +=== Debugging === + +If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on +CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in +your debugfs mount point, called irq_domain_mapping. This file +contains a live snapshot of all the IRQ domains in the system: + + name mapped linear-max direct-max devtree-node + pl061 8 8 0 /smb/gpio@e008 + pl061 8 8 0 /smb/gpio@e105 + pMSI 0 0 0 /interrupt-controller@e1101000/v2m@e008 + MSI 37 0 0 /interrupt-controller@e1101000/v2m@e008 + GICv2m37 0 0 /interrupt-controller@e1101000/v2m@e008 + GICv2448 448 0 /interrupt-controller@e1101000 + +it also iterates over the interrupts to display their mapping in the +domains, and makes the domain stacking visible: + + +irqhwirqchip namechip data active type domain +1 0x00019 GICv20x0916bfd8 *LINEAR GICv2 +2 0x0001d GICv20x0916bfd8 LINEAR GICv2 +3 0x0001e GICv20x0916bfd8 *LINEAR GICv2 +4 0x0001b GICv20x0916bfd8 *LINEAR GICv2 +5 0x0001a GICv20x0916bfd8 LINEAR GICv2 +[...] + 96 0x81808 MSI 0x (null) RADIX MSI + 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m + 96+ 0x00063 GICv20x0916bfd8 LINEAR GICv2 + 97 0x08800 MSI 0x (null) * RADIX MSI + 97+ 0x00064 GICv2m 0x8003ee116980 * RADIX GICv2m + 97+ 0x00064 GICv20x0916bfd8 *LINEAR GICv2 + +Here, interrupts 1-5 are only using a single domain, while 96 and 97 +are build out of a stack of three domain, each level performing a +particular function.
[tip:irq/core] genirq/msi: Populate the domain name if provided by the irqchip
Commit-ID: a97b852b4d4c2f8c50cab13c71566639f9a1a990 Gitweb: http://git.kernel.org/tip/a97b852b4d4c2f8c50cab13c71566639f9a1a990 Author: Marc ZyngierAuthorDate: Fri, 12 May 2017 12:55:37 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:45 +0200 genirq/msi: Populate the domain name if provided by the irqchip In order to ease debug, let's populate the domain name upfront, before any MSI gets requested. This allows the domain to appear in the irq_domain_mapping, and the user to easily find the expected data. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-4-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/msi.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index ddc2f54..fe4d48e 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -265,13 +265,19 @@ struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent) { + struct irq_domain *domain; + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) msi_domain_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) msi_domain_update_chip_ops(info); - return irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0, - fwnode, _domain_ops, info); + domain = irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0, +fwnode, _domain_ops, info); + if (domain && info->chip && info->chip->name) + domain->name = info->chip->name; + + return domain; } int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
[tip:irq/core] genirq/msi: Populate the domain name if provided by the irqchip
Commit-ID: a97b852b4d4c2f8c50cab13c71566639f9a1a990 Gitweb: http://git.kernel.org/tip/a97b852b4d4c2f8c50cab13c71566639f9a1a990 Author: Marc Zyngier AuthorDate: Fri, 12 May 2017 12:55:37 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:45 +0200 genirq/msi: Populate the domain name if provided by the irqchip In order to ease debug, let's populate the domain name upfront, before any MSI gets requested. This allows the domain to appear in the irq_domain_mapping, and the user to easily find the expected data. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-4-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/msi.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index ddc2f54..fe4d48e 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -265,13 +265,19 @@ struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent) { + struct irq_domain *domain; + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) msi_domain_update_dom_ops(info); if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) msi_domain_update_chip_ops(info); - return irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0, - fwnode, _domain_ops, info); + domain = irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0, +fwnode, _domain_ops, info); + if (domain && info->chip && info->chip->name) + domain->name = info->chip->name; + + return domain; } int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
[tip:irq/core] irqdomain: Let irq_domain_mapping display ACPI fwnode attributes
Commit-ID: 2370c00dc7232d0c4af224e7730b4de031f3b1a0 Gitweb: http://git.kernel.org/tip/2370c00dc7232d0c4af224e7730b4de031f3b1a0 Author: Marc ZyngierAuthorDate: Fri, 12 May 2017 12:55:36 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:44 +0200 irqdomain: Let irq_domain_mapping display ACPI fwnode attributes If the system is using ACPI, there is no of_node to display. But ACPI can use a struct irqchip_fwid as a domain identifier, and it can be used to display the name contained in that structure. The output on such a system will look like this: pMSI 0 0 0 irqchip@e118 MSI 37 0 0 irqchip@e118 GICv2m 37 0 0 irqchip@e118 GICv2 448 448 0 irqchip@08003000 Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-3-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/irqdomain.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 1f6cd2c..70b9da7 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -801,15 +801,26 @@ static int virq_debug_show(struct seq_file *m, void *private) mutex_lock(_domain_mutex); list_for_each_entry(domain, _domain_list, link) { struct device_node *of_node; + const char *name; + int count = 0; + of_node = irq_domain_get_of_node(domain); + if (of_node) + name = of_node_full_name(of_node); + else if (is_fwnode_irqchip(domain->fwnode)) + name = container_of(domain->fwnode, struct irqchip_fwid, + fwnode)->name; + else + name = ""; + radix_tree_for_each_slot(slot, >revmap_tree, , 0) count++; seq_printf(m, "%c%-16s %6u %10u %10u %s\n", domain == irq_default_domain ? '*' : ' ', domain->name, domain->revmap_size + count, domain->revmap_size, domain->revmap_direct_max_irq, - of_node ? of_node_full_name(of_node) : ""); + name); } mutex_unlock(_domain_mutex);
[tip:irq/core] irqdomain: Let irq_domain_mapping display ACPI fwnode attributes
Commit-ID: 2370c00dc7232d0c4af224e7730b4de031f3b1a0 Gitweb: http://git.kernel.org/tip/2370c00dc7232d0c4af224e7730b4de031f3b1a0 Author: Marc Zyngier AuthorDate: Fri, 12 May 2017 12:55:36 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:44 +0200 irqdomain: Let irq_domain_mapping display ACPI fwnode attributes If the system is using ACPI, there is no of_node to display. But ACPI can use a struct irqchip_fwid as a domain identifier, and it can be used to display the name contained in that structure. The output on such a system will look like this: pMSI 0 0 0 irqchip@e118 MSI 37 0 0 irqchip@e118 GICv2m 37 0 0 irqchip@e118 GICv2 448 448 0 irqchip@08003000 Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-3-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/irqdomain.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 1f6cd2c..70b9da7 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -801,15 +801,26 @@ static int virq_debug_show(struct seq_file *m, void *private) mutex_lock(_domain_mutex); list_for_each_entry(domain, _domain_list, link) { struct device_node *of_node; + const char *name; + int count = 0; + of_node = irq_domain_get_of_node(domain); + if (of_node) + name = of_node_full_name(of_node); + else if (is_fwnode_irqchip(domain->fwnode)) + name = container_of(domain->fwnode, struct irqchip_fwid, + fwnode)->name; + else + name = ""; + radix_tree_for_each_slot(slot, >revmap_tree, , 0) count++; seq_printf(m, "%c%-16s %6u %10u %10u %s\n", domain == irq_default_domain ? '*' : ' ', domain->name, domain->revmap_size + count, domain->revmap_size, domain->revmap_direct_max_irq, - of_node ? of_node_full_name(of_node) : ""); + name); } mutex_unlock(_domain_mutex);
[tip:irq/core] irqdomain: Let irq_domain_mapping display hierarchical domains
Commit-ID: fe17a42e704a64477b15bb2cf8366fe3e5119aff Gitweb: http://git.kernel.org/tip/fe17a42e704a64477b15bb2cf8366fe3e5119aff Author: Marc ZyngierAuthorDate: Fri, 12 May 2017 12:55:35 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:44 +0200 irqdomain: Let irq_domain_mapping display hierarchical domains Hierarchical domains seem to be hard to grasp, and a number of aspiring kernel hackers find them utterly discombobulating. In order to ease their pain, let's make them appear in /sys/kernel/debug/irq_domain_mapping, such as the following: 96 0x81808 MSI0x (null) RADIX MSI 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m 96+ 0x00063 GICv2 0x0916bfd8 LINEAR GICv2 [output compressed to fit in a commit log] This shows that IRQ96 is implemented by a stack of three domains, the + sign indicating the stacking. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-2-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/irqdomain.c | 68 +++--- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 31805f2..1f6cd2c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -746,13 +746,54 @@ unsigned int irq_find_mapping(struct irq_domain *domain, EXPORT_SYMBOL_GPL(irq_find_mapping); #ifdef CONFIG_IRQ_DOMAIN_DEBUG +static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc) +{ + struct irq_domain *domain; + struct irq_data *data; + + domain = desc->irq_data.domain; + data = >irq_data; + + while (domain) { + unsigned int irq = data->irq; + unsigned long hwirq = data->hwirq; + struct irq_chip *chip; + bool direct; + + if (data == >irq_data) + seq_printf(m, "%5d ", irq); + else + seq_printf(m, "%5d+ ", irq); + seq_printf(m, "0x%05lx ", hwirq); + + chip = irq_data_get_irq_chip(data); + seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); + + seq_printf(m, data ? "0x%p " : " %p ", + irq_data_get_irq_chip_data(data)); + + seq_printf(m, " %c", (desc->action && desc->action->handler) ? '*' : ' '); + direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq); + seq_printf(m, "%6s%-8s ", + (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", + direct ? "(DIRECT)" : ""); + seq_printf(m, "%s\n", domain->name); +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + domain = domain->parent; + data = data->parent_data; +#else + domain = NULL; +#endif + } +} + static int virq_debug_show(struct seq_file *m, void *private) { unsigned long flags; struct irq_desc *desc; struct irq_domain *domain; struct radix_tree_iter iter; - void *data, **slot; + void **slot; int i; seq_printf(m, " %-16s %-6s %-10s %-10s %s\n", @@ -782,30 +823,7 @@ static int virq_debug_show(struct seq_file *m, void *private) continue; raw_spin_lock_irqsave(>lock, flags); - domain = desc->irq_data.domain; - - if (domain) { - struct irq_chip *chip; - int hwirq = desc->irq_data.hwirq; - bool direct; - - seq_printf(m, "%5d ", i); - seq_printf(m, "0x%05x ", hwirq); - - chip = irq_desc_get_chip(desc); - seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); - - data = irq_desc_get_chip_data(desc); - seq_printf(m, data ? "0x%p " : " %p ", data); - - seq_printf(m, " %c", (desc->action && desc->action->handler) ? '*' : ' '); - direct = (i == hwirq) && (i < domain->revmap_direct_max_irq); - seq_printf(m, "%6s%-8s ", - (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", - direct ? "(DIRECT)" : ""); - seq_printf(m, "%s\n", desc->irq_data.domain->name); - } - + virq_debug_show_one(m, desc); raw_spin_unlock_irqrestore(>lock, flags); }
[tip:irq/core] irqdomain: Let irq_domain_mapping display hierarchical domains
Commit-ID: fe17a42e704a64477b15bb2cf8366fe3e5119aff Gitweb: http://git.kernel.org/tip/fe17a42e704a64477b15bb2cf8366fe3e5119aff Author: Marc Zyngier AuthorDate: Fri, 12 May 2017 12:55:35 +0100 Committer: Thomas Gleixner CommitDate: Mon, 22 May 2017 22:29:44 +0200 irqdomain: Let irq_domain_mapping display hierarchical domains Hierarchical domains seem to be hard to grasp, and a number of aspiring kernel hackers find them utterly discombobulating. In order to ease their pain, let's make them appear in /sys/kernel/debug/irq_domain_mapping, such as the following: 96 0x81808 MSI0x (null) RADIX MSI 96+ 0x00063 GICv2m 0x8003ee116980 RADIX GICv2m 96+ 0x00063 GICv2 0x0916bfd8 LINEAR GICv2 [output compressed to fit in a commit log] This shows that IRQ96 is implemented by a stack of three domains, the + sign indicating the stacking. Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/20170512115538.10767-2-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/irqdomain.c | 68 +++--- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 31805f2..1f6cd2c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -746,13 +746,54 @@ unsigned int irq_find_mapping(struct irq_domain *domain, EXPORT_SYMBOL_GPL(irq_find_mapping); #ifdef CONFIG_IRQ_DOMAIN_DEBUG +static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc) +{ + struct irq_domain *domain; + struct irq_data *data; + + domain = desc->irq_data.domain; + data = >irq_data; + + while (domain) { + unsigned int irq = data->irq; + unsigned long hwirq = data->hwirq; + struct irq_chip *chip; + bool direct; + + if (data == >irq_data) + seq_printf(m, "%5d ", irq); + else + seq_printf(m, "%5d+ ", irq); + seq_printf(m, "0x%05lx ", hwirq); + + chip = irq_data_get_irq_chip(data); + seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); + + seq_printf(m, data ? "0x%p " : " %p ", + irq_data_get_irq_chip_data(data)); + + seq_printf(m, " %c", (desc->action && desc->action->handler) ? '*' : ' '); + direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq); + seq_printf(m, "%6s%-8s ", + (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", + direct ? "(DIRECT)" : ""); + seq_printf(m, "%s\n", domain->name); +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + domain = domain->parent; + data = data->parent_data; +#else + domain = NULL; +#endif + } +} + static int virq_debug_show(struct seq_file *m, void *private) { unsigned long flags; struct irq_desc *desc; struct irq_domain *domain; struct radix_tree_iter iter; - void *data, **slot; + void **slot; int i; seq_printf(m, " %-16s %-6s %-10s %-10s %s\n", @@ -782,30 +823,7 @@ static int virq_debug_show(struct seq_file *m, void *private) continue; raw_spin_lock_irqsave(>lock, flags); - domain = desc->irq_data.domain; - - if (domain) { - struct irq_chip *chip; - int hwirq = desc->irq_data.hwirq; - bool direct; - - seq_printf(m, "%5d ", i); - seq_printf(m, "0x%05x ", hwirq); - - chip = irq_desc_get_chip(desc); - seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); - - data = irq_desc_get_chip_data(desc); - seq_printf(m, data ? "0x%p " : " %p ", data); - - seq_printf(m, " %c", (desc->action && desc->action->handler) ? '*' : ' '); - direct = (i == hwirq) && (i < domain->revmap_direct_max_irq); - seq_printf(m, "%6s%-8s ", - (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", - direct ? "(DIRECT)" : ""); - seq_printf(m, "%s\n", desc->irq_data.domain->name); - } - + virq_debug_show_one(m, desc); raw_spin_unlock_irqrestore(>lock, flags); }
[tip:timers/core] hrtimer: Catch invalid clockids again
Commit-ID: 336a9cde10d641e70bac67d90ae91b3190c3edca Gitweb: http://git.kernel.org/tip/336a9cde10d641e70bac67d90ae91b3190c3edca Author: Marc ZyngierAuthorDate: Fri, 15 Jan 2016 17:41:09 + Committer: Thomas Gleixner CommitDate: Sat, 18 Feb 2017 10:58:39 +0100 hrtimer: Catch invalid clockids again commit 82e88ff1ea94 ("hrtimer: Revert CLOCK_MONOTONIC_RAW support") removed unfortunately a sanity check in the hrtimer code which was part of that MONOTONIC_RAW patch series. It would have caught the bogus usage of CLOCK_MONOTONIC_RAW in the wireless code. So bring it back. It is way too easy to take any random clockid and feed it to the hrtimer subsystem. At best, it gets mapped to a monotonic base, but it would be better to just catch illegal values as early as possible. Detect invalid clockids, map them to CLOCK_MONOTONIC and emit a warning. [ tglx: Replaced the BUG by a WARN and gracefully map to CLOCK_MONOTONIC ] Signed-off-by: Marc Zyngier Cc: Tomasz Nowicki Cc: Christoffer Dall Link: http://lkml.kernel.org/r/1452879670-16133-3-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/time/hrtimer.c | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index edabde6..8e11d8d 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -94,17 +94,15 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = }; static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { + /* Make sure we catch unsupported clockids */ + [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, + [CLOCK_REALTIME]= HRTIMER_BASE_REALTIME, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, [CLOCK_BOOTTIME]= HRTIMER_BASE_BOOTTIME, [CLOCK_TAI] = HRTIMER_BASE_TAI, }; -static inline int hrtimer_clockid_to_base(clockid_t clock_id) -{ - return hrtimer_clock_to_base_table[clock_id]; -} - /* * Functions and macros which are different for UP/SMP systems are kept in a * single place @@ -1081,6 +1079,18 @@ u64 hrtimer_get_next_event(void) } #endif +static inline int hrtimer_clockid_to_base(clockid_t clock_id) +{ + if (likely(clock_id < MAX_CLOCKS)) { + int base = hrtimer_clock_to_base_table[clock_id]; + + if (likely(base != HRTIMER_MAX_CLOCK_BASES)) + return base; + } + WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); + return HRTIMER_BASE_MONOTONIC; +} + static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode) {
[tip:timers/core] hrtimer: Catch invalid clockids again
Commit-ID: 336a9cde10d641e70bac67d90ae91b3190c3edca Gitweb: http://git.kernel.org/tip/336a9cde10d641e70bac67d90ae91b3190c3edca Author: Marc Zyngier AuthorDate: Fri, 15 Jan 2016 17:41:09 + Committer: Thomas Gleixner CommitDate: Sat, 18 Feb 2017 10:58:39 +0100 hrtimer: Catch invalid clockids again commit 82e88ff1ea94 ("hrtimer: Revert CLOCK_MONOTONIC_RAW support") removed unfortunately a sanity check in the hrtimer code which was part of that MONOTONIC_RAW patch series. It would have caught the bogus usage of CLOCK_MONOTONIC_RAW in the wireless code. So bring it back. It is way too easy to take any random clockid and feed it to the hrtimer subsystem. At best, it gets mapped to a monotonic base, but it would be better to just catch illegal values as early as possible. Detect invalid clockids, map them to CLOCK_MONOTONIC and emit a warning. [ tglx: Replaced the BUG by a WARN and gracefully map to CLOCK_MONOTONIC ] Signed-off-by: Marc Zyngier Cc: Tomasz Nowicki Cc: Christoffer Dall Link: http://lkml.kernel.org/r/1452879670-16133-3-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/time/hrtimer.c | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index edabde6..8e11d8d 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -94,17 +94,15 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = }; static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { + /* Make sure we catch unsupported clockids */ + [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, + [CLOCK_REALTIME]= HRTIMER_BASE_REALTIME, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, [CLOCK_BOOTTIME]= HRTIMER_BASE_BOOTTIME, [CLOCK_TAI] = HRTIMER_BASE_TAI, }; -static inline int hrtimer_clockid_to_base(clockid_t clock_id) -{ - return hrtimer_clock_to_base_table[clock_id]; -} - /* * Functions and macros which are different for UP/SMP systems are kept in a * single place @@ -1081,6 +1079,18 @@ u64 hrtimer_get_next_event(void) } #endif +static inline int hrtimer_clockid_to_base(clockid_t clock_id) +{ + if (likely(clock_id < MAX_CLOCKS)) { + int base = hrtimer_clock_to_base_table[clock_id]; + + if (likely(base != HRTIMER_MAX_CLOCK_BASES)) + return base; + } + WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); + return HRTIMER_BASE_MONOTONIC; +} + static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode) {
[tip:irq/urgent] irqdomain: Avoid activating interrupts more than once
Commit-ID: 08d85f3ea99f1eeafc4e8507936190e86a16ee8c Gitweb: http://git.kernel.org/tip/08d85f3ea99f1eeafc4e8507936190e86a16ee8c Author: Marc ZyngierAuthorDate: Tue, 17 Jan 2017 16:00:48 + Committer: Thomas Gleixner CommitDate: Mon, 30 Jan 2017 15:18:56 +0100 irqdomain: Avoid activating interrupts more than once Since commit f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early"), we can end-up activating a PCI/MSI twice (once at allocation time, and once at startup time). This is normally of no consequences, except that there is some HW out there that may misbehave if activate is used more than once (the GICv3 ITS, for example, uses the activate callback to issue the MAPVI command, and the architecture spec says that "If there is an existing mapping for the EventID-DeviceID combination, behavior is UNPREDICTABLE"). While this could be worked around in each individual driver, it may make more sense to tackle the issue at the core level. In order to avoid getting in that situation, let's have a per-interrupt flag to remember if we have already activated that interrupt or not. Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early") Reported-and-tested-by: Andre Przywara Signed-off-by: Marc Zyngier Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/1484668848-24361-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h| 17 + kernel/irq/irqdomain.c | 44 ++-- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index e798755..39e3254 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -184,6 +184,7 @@ struct irq_data { * * IRQD_TRIGGER_MASK - Mask for the trigger type bits * IRQD_SETAFFINITY_PENDING- Affinity setting is pending + * IRQD_ACTIVATED - Interrupt has already been activated * IRQD_NO_BALANCING - Balancing disabled for this IRQ * IRQD_PER_CPU- Interrupt is per cpu * IRQD_AFFINITY_SET - Interrupt affinity was set @@ -202,6 +203,7 @@ struct irq_data { enum { IRQD_TRIGGER_MASK = 0xf, IRQD_SETAFFINITY_PENDING= (1 << 8), + IRQD_ACTIVATED = (1 << 9), IRQD_NO_BALANCING = (1 << 10), IRQD_PER_CPU= (1 << 11), IRQD_AFFINITY_SET = (1 << 12), @@ -312,6 +314,21 @@ static inline bool irqd_affinity_is_managed(struct irq_data *d) return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED; } +static inline bool irqd_is_activated(struct irq_data *d) +{ + return __irqd_to_state(d) & IRQD_ACTIVATED; +} + +static inline void irqd_set_activated(struct irq_data *d) +{ + __irqd_to_state(d) |= IRQD_ACTIVATED; +} + +static inline void irqd_clr_activated(struct irq_data *d) +{ + __irqd_to_state(d) &= ~IRQD_ACTIVATED; +} + #undef __irqd_to_state static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 8c0a0ae..b59e676 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1346,6 +1346,30 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); +static void __irq_domain_activate_irq(struct irq_data *irq_data) +{ + if (irq_data && irq_data->domain) { + struct irq_domain *domain = irq_data->domain; + + if (irq_data->parent_data) + __irq_domain_activate_irq(irq_data->parent_data); + if (domain->ops->activate) + domain->ops->activate(domain, irq_data); + } +} + +static void __irq_domain_deactivate_irq(struct irq_data *irq_data) +{ + if (irq_data && irq_data->domain) { + struct irq_domain *domain = irq_data->domain; + + if (domain->ops->deactivate) + domain->ops->deactivate(domain, irq_data); + if (irq_data->parent_data) + __irq_domain_deactivate_irq(irq_data->parent_data); + } +} + /** * irq_domain_activate_irq - Call domain_ops->activate recursively to activate * interrupt @@ -1356,13 +1380,9 @@ EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); */ void irq_domain_activate_irq(struct irq_data *irq_data) { - if (irq_data && irq_data->domain) { - struct irq_domain *domain = irq_data->domain; - - if (irq_data->parent_data) - irq_domain_activate_irq(irq_data->parent_data); - if (domain->ops->activate) - domain->ops->activate(domain, irq_data); + if (!irqd_is_activated(irq_data)) { +
[tip:irq/urgent] irqdomain: Avoid activating interrupts more than once
Commit-ID: 08d85f3ea99f1eeafc4e8507936190e86a16ee8c Gitweb: http://git.kernel.org/tip/08d85f3ea99f1eeafc4e8507936190e86a16ee8c Author: Marc Zyngier AuthorDate: Tue, 17 Jan 2017 16:00:48 + Committer: Thomas Gleixner CommitDate: Mon, 30 Jan 2017 15:18:56 +0100 irqdomain: Avoid activating interrupts more than once Since commit f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early"), we can end-up activating a PCI/MSI twice (once at allocation time, and once at startup time). This is normally of no consequences, except that there is some HW out there that may misbehave if activate is used more than once (the GICv3 ITS, for example, uses the activate callback to issue the MAPVI command, and the architecture spec says that "If there is an existing mapping for the EventID-DeviceID combination, behavior is UNPREDICTABLE"). While this could be worked around in each individual driver, it may make more sense to tackle the issue at the core level. In order to avoid getting in that situation, let's have a per-interrupt flag to remember if we have already activated that interrupt or not. Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early") Reported-and-tested-by: Andre Przywara Signed-off-by: Marc Zyngier Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/1484668848-24361-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- include/linux/irq.h| 17 + kernel/irq/irqdomain.c | 44 ++-- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index e798755..39e3254 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -184,6 +184,7 @@ struct irq_data { * * IRQD_TRIGGER_MASK - Mask for the trigger type bits * IRQD_SETAFFINITY_PENDING- Affinity setting is pending + * IRQD_ACTIVATED - Interrupt has already been activated * IRQD_NO_BALANCING - Balancing disabled for this IRQ * IRQD_PER_CPU- Interrupt is per cpu * IRQD_AFFINITY_SET - Interrupt affinity was set @@ -202,6 +203,7 @@ struct irq_data { enum { IRQD_TRIGGER_MASK = 0xf, IRQD_SETAFFINITY_PENDING= (1 << 8), + IRQD_ACTIVATED = (1 << 9), IRQD_NO_BALANCING = (1 << 10), IRQD_PER_CPU= (1 << 11), IRQD_AFFINITY_SET = (1 << 12), @@ -312,6 +314,21 @@ static inline bool irqd_affinity_is_managed(struct irq_data *d) return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED; } +static inline bool irqd_is_activated(struct irq_data *d) +{ + return __irqd_to_state(d) & IRQD_ACTIVATED; +} + +static inline void irqd_set_activated(struct irq_data *d) +{ + __irqd_to_state(d) |= IRQD_ACTIVATED; +} + +static inline void irqd_clr_activated(struct irq_data *d) +{ + __irqd_to_state(d) &= ~IRQD_ACTIVATED; +} + #undef __irqd_to_state static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 8c0a0ae..b59e676 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1346,6 +1346,30 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain, } EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); +static void __irq_domain_activate_irq(struct irq_data *irq_data) +{ + if (irq_data && irq_data->domain) { + struct irq_domain *domain = irq_data->domain; + + if (irq_data->parent_data) + __irq_domain_activate_irq(irq_data->parent_data); + if (domain->ops->activate) + domain->ops->activate(domain, irq_data); + } +} + +static void __irq_domain_deactivate_irq(struct irq_data *irq_data) +{ + if (irq_data && irq_data->domain) { + struct irq_domain *domain = irq_data->domain; + + if (domain->ops->deactivate) + domain->ops->deactivate(domain, irq_data); + if (irq_data->parent_data) + __irq_domain_deactivate_irq(irq_data->parent_data); + } +} + /** * irq_domain_activate_irq - Call domain_ops->activate recursively to activate * interrupt @@ -1356,13 +1380,9 @@ EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); */ void irq_domain_activate_irq(struct irq_data *irq_data) { - if (irq_data && irq_data->domain) { - struct irq_domain *domain = irq_data->domain; - - if (irq_data->parent_data) - irq_domain_activate_irq(irq_data->parent_data); - if (domain->ops->activate) - domain->ops->activate(domain, irq_data); + if (!irqd_is_activated(irq_data)) { + __irq_domain_activate_irq(irq_data); + irqd_set_activated(irq_data); } } @@ -1376,13
[tip:irq/core] genirq/msi: Drop artificial PCI dependency
Commit-ID: 4e201566402c878a225d4425df8a4a664c6f251e Gitweb: http://git.kernel.org/tip/4e201566402c878a225d4425df8a4a664c6f251e Author: Marc ZyngierAuthorDate: Tue, 22 Nov 2016 09:21:16 + Committer: Thomas Gleixner CommitDate: Tue, 22 Nov 2016 11:00:19 +0100 genirq/msi: Drop artificial PCI dependency The generic MSI layer doesn't have any PCI ties anymore, and the build hack should have been removed some time ago. Fixes: d9109698be6e ("genirq: Introduce msi_domain_alloc/free_irqs()") Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/1479806476-20801-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/msi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 8a3e8727..ee23006 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -14,9 +14,7 @@ #include #include #include - -/* Temparory solution for building, will be removed later */ -#include +#include /** * alloc_msi_entry - Allocate an initialize msi_entry
[tip:irq/core] genirq/msi: Drop artificial PCI dependency
Commit-ID: 4e201566402c878a225d4425df8a4a664c6f251e Gitweb: http://git.kernel.org/tip/4e201566402c878a225d4425df8a4a664c6f251e Author: Marc Zyngier AuthorDate: Tue, 22 Nov 2016 09:21:16 + Committer: Thomas Gleixner CommitDate: Tue, 22 Nov 2016 11:00:19 +0100 genirq/msi: Drop artificial PCI dependency The generic MSI layer doesn't have any PCI ties anymore, and the build hack should have been removed some time ago. Fixes: d9109698be6e ("genirq: Introduce msi_domain_alloc/free_irqs()") Signed-off-by: Marc Zyngier Link: http://lkml.kernel.org/r/1479806476-20801-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/msi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 8a3e8727..ee23006 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -14,9 +14,7 @@ #include #include #include - -/* Temparory solution for building, will be removed later */ -#include +#include /** * alloc_msi_entry - Allocate an initialize msi_entry
[tip:irq/urgent] genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE
Commit-ID: e2a5069355e5e3c0644a831d3e690049c4d0624b Gitweb: http://git.kernel.org/tip/e2a5069355e5e3c0644a831d3e690049c4d0624b Author: Marc ZyngierAuthorDate: Mon, 19 Sep 2016 09:49:27 +0100 Committer: Thomas Gleixner CommitDate: Tue, 20 Sep 2016 01:04:49 +0200 genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE There is no point in trying to configure the trigger of a chained interrupt if no trigger information has been configured. At best this is ignored, and at the worse this confuses the underlying irqchip (which is likely not to handle such a thing), and unnecessarily alarms the user. Only apply the configuration if type is not IRQ_TYPE_NONE. Fixes: 1e12c4a9393b ("genirq: Correctly configure the trigger on chained interrupts") Reported-and-tested-by: Geert Uytterhoeven Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/CAMuHMdVW1eTn20=etycj8hkvwohasuh_yqxry2mgbevz8fp...@mail.gmail.com Link: http://lkml.kernel.org/r/1474274967-15984-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v3.c | 7 --- kernel/irq/chip.c| 8 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index ede5672..da6c0ba 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -548,7 +548,7 @@ static int gic_starting_cpu(unsigned int cpu) static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, unsigned long cluster_id) { - int cpu = *base_cpu; + int next_cpu, cpu = *base_cpu; unsigned long mpidr = cpu_logical_map(cpu); u16 tlist = 0; @@ -562,9 +562,10 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, tlist |= 1 << (mpidr & 0xf); - cpu = cpumask_next(cpu, mask); - if (cpu >= nr_cpu_ids) + next_cpu = cpumask_next(cpu, mask); + if (next_cpu >= nr_cpu_ids) goto out; + cpu = next_cpu; mpidr = cpu_logical_map(cpu); diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6373890..26ba565 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -820,6 +820,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, desc->name = name; if (handle != handle_bad_irq && is_chained) { + unsigned int type = irqd_get_trigger_type(>irq_data); + /* * We're about to start this interrupt immediately, * hence the need to set the trigger configuration. @@ -828,8 +830,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, * chained interrupt. Reset it immediately because we * do know better. */ - __irq_set_trigger(desc, irqd_get_trigger_type(>irq_data)); - desc->handle_irq = handle; + if (type != IRQ_TYPE_NONE) { + __irq_set_trigger(desc, type); + desc->handle_irq = handle; + } irq_settings_set_noprobe(desc); irq_settings_set_norequest(desc);
[tip:irq/urgent] genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE
Commit-ID: e2a5069355e5e3c0644a831d3e690049c4d0624b Gitweb: http://git.kernel.org/tip/e2a5069355e5e3c0644a831d3e690049c4d0624b Author: Marc Zyngier AuthorDate: Mon, 19 Sep 2016 09:49:27 +0100 Committer: Thomas Gleixner CommitDate: Tue, 20 Sep 2016 01:04:49 +0200 genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE There is no point in trying to configure the trigger of a chained interrupt if no trigger information has been configured. At best this is ignored, and at the worse this confuses the underlying irqchip (which is likely not to handle such a thing), and unnecessarily alarms the user. Only apply the configuration if type is not IRQ_TYPE_NONE. Fixes: 1e12c4a9393b ("genirq: Correctly configure the trigger on chained interrupts") Reported-and-tested-by: Geert Uytterhoeven Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/CAMuHMdVW1eTn20=etycj8hkvwohasuh_yqxry2mgbevz8fp...@mail.gmail.com Link: http://lkml.kernel.org/r/1474274967-15984-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v3.c | 7 --- kernel/irq/chip.c| 8 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index ede5672..da6c0ba 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -548,7 +548,7 @@ static int gic_starting_cpu(unsigned int cpu) static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, unsigned long cluster_id) { - int cpu = *base_cpu; + int next_cpu, cpu = *base_cpu; unsigned long mpidr = cpu_logical_map(cpu); u16 tlist = 0; @@ -562,9 +562,10 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, tlist |= 1 << (mpidr & 0xf); - cpu = cpumask_next(cpu, mask); - if (cpu >= nr_cpu_ids) + next_cpu = cpumask_next(cpu, mask); + if (next_cpu >= nr_cpu_ids) goto out; + cpu = next_cpu; mpidr = cpu_logical_map(cpu); diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6373890..26ba565 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -820,6 +820,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, desc->name = name; if (handle != handle_bad_irq && is_chained) { + unsigned int type = irqd_get_trigger_type(>irq_data); + /* * We're about to start this interrupt immediately, * hence the need to set the trigger configuration. @@ -828,8 +830,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, * chained interrupt. Reset it immediately because we * do know better. */ - __irq_set_trigger(desc, irqd_get_trigger_type(>irq_data)); - desc->handle_irq = handle; + if (type != IRQ_TYPE_NONE) { + __irq_set_trigger(desc, type); + desc->handle_irq = handle; + } irq_settings_set_noprobe(desc); irq_settings_set_norequest(desc);
[tip:irq/urgent] genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE
Commit-ID: 1984e075915cbae65336a99b1879865080d8e55e Gitweb: http://git.kernel.org/tip/1984e075915cbae65336a99b1879865080d8e55e Author: Marc ZyngierAuthorDate: Mon, 19 Sep 2016 09:49:27 +0100 Committer: Thomas Gleixner CommitDate: Mon, 19 Sep 2016 11:31:36 +0200 genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE There is no point in trying to configure the trigger of a chained interrupt if no trigger information has been configured. At best this is ignored, and at the worse this confuses the underlying irqchip (which is likely not to handle such a thing), and unnecessarily alarms the user. Only apply the configuration if type is not IRQ_TYPE_NONE. Fixes: 1e12c4a9393b ("genirq: Correctly configure the trigger on chained interrupts") Reported-and-tested-by: Geert Uytterhoeven Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/CAMuHMdVW1eTn20=etycj8hkvwohasuh_yqxry2mgbevz8fp...@mail.gmail.com Link: http://lkml.kernel.org/r/1474274967-15984-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/chip.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6373890..26ba565 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -820,6 +820,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, desc->name = name; if (handle != handle_bad_irq && is_chained) { + unsigned int type = irqd_get_trigger_type(>irq_data); + /* * We're about to start this interrupt immediately, * hence the need to set the trigger configuration. @@ -828,8 +830,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, * chained interrupt. Reset it immediately because we * do know better. */ - __irq_set_trigger(desc, irqd_get_trigger_type(>irq_data)); - desc->handle_irq = handle; + if (type != IRQ_TYPE_NONE) { + __irq_set_trigger(desc, type); + desc->handle_irq = handle; + } irq_settings_set_noprobe(desc); irq_settings_set_norequest(desc);
[tip:irq/urgent] genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE
Commit-ID: 1984e075915cbae65336a99b1879865080d8e55e Gitweb: http://git.kernel.org/tip/1984e075915cbae65336a99b1879865080d8e55e Author: Marc Zyngier AuthorDate: Mon, 19 Sep 2016 09:49:27 +0100 Committer: Thomas Gleixner CommitDate: Mon, 19 Sep 2016 11:31:36 +0200 genirq: Skip chained interrupt trigger setup if type is IRQ_TYPE_NONE There is no point in trying to configure the trigger of a chained interrupt if no trigger information has been configured. At best this is ignored, and at the worse this confuses the underlying irqchip (which is likely not to handle such a thing), and unnecessarily alarms the user. Only apply the configuration if type is not IRQ_TYPE_NONE. Fixes: 1e12c4a9393b ("genirq: Correctly configure the trigger on chained interrupts") Reported-and-tested-by: Geert Uytterhoeven Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/CAMuHMdVW1eTn20=etycj8hkvwohasuh_yqxry2mgbevz8fp...@mail.gmail.com Link: http://lkml.kernel.org/r/1474274967-15984-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/chip.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6373890..26ba565 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -820,6 +820,8 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, desc->name = name; if (handle != handle_bad_irq && is_chained) { + unsigned int type = irqd_get_trigger_type(>irq_data); + /* * We're about to start this interrupt immediately, * hence the need to set the trigger configuration. @@ -828,8 +830,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, * chained interrupt. Reset it immediately because we * do know better. */ - __irq_set_trigger(desc, irqd_get_trigger_type(>irq_data)); - desc->handle_irq = handle; + if (type != IRQ_TYPE_NONE) { + __irq_set_trigger(desc, type); + desc->handle_irq = handle; + } irq_settings_set_noprobe(desc); irq_settings_set_norequest(desc);
[tip:irq/urgent] genirq/msi: Make sure PCI MSIs are activated early
Commit-ID: f3b0946d629c8bfbd3e5f038e30cb9c711a35f10 Gitweb: http://git.kernel.org/tip/f3b0946d629c8bfbd3e5f038e30cb9c711a35f10 Author: Marc ZyngierAuthorDate: Wed, 13 Jul 2016 17:18:33 +0100 Committer: Thomas Gleixner CommitDate: Tue, 9 Aug 2016 09:19:32 +0200 genirq/msi: Make sure PCI MSIs are activated early Bharat Kumar Gogada reported issues with the generic MSI code, where the end-point ended up with garbage in its MSI configuration (both for the vector and the message). It turns out that the two MSI paths in the kernel are doing slightly different things: generic MSI: disable MSI -> allocate MSI -> enable MSI -> setup EP PCI MSI: disable MSI -> allocate MSI -> setup EP -> enable MSI And it turns out that end-points are allowed to latch the content of the MSI configuration registers as soon as MSIs are enabled. In Bharat's case, the end-point ends up using whatever was there already, which is not what you want. In order to make things converge, we introduce a new MSI domain flag (MSI_FLAG_ACTIVATE_EARLY) that is unconditionally set for PCI/MSI. When set, this flag forces the programming of the end-point as soon as the MSIs are allocated. A consequence of this is that we have an extra activate in irq_startup, but that should be without much consequence. tglx: - Several people reported a VMWare regression with PCI/MSI-X passthrough. It turns out that the patch also cures that issue. - We need to have a look at the MSI disable interrupt path, where we write the msg to all zeros without disabling MSI in the PCI device. Is that correct? Fixes: 52f518a3a7c2 "x86/MSI: Use hierarchical irqdomains to manage MSI interrupts" Reported-and-tested-by: Bharat Kumar Gogada Reported-and-tested-by: Foster Snowhill Reported-by: Matthias Prager Reported-by: Jason Taylor Signed-off-by: Marc Zyngier Acked-by: Bjorn Helgaas Cc: linux-...@vger.kernel.org Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/1468426713-31431-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/pci/msi.c | 2 ++ include/linux/msi.h | 2 ++ kernel/irq/msi.c| 11 +++ 3 files changed, 15 insertions(+) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a02981e..eafa613 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1411,6 +1411,8 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) pci_msi_domain_update_chip_ops(info); + info->flags |= MSI_FLAG_ACTIVATE_EARLY; + domain = msi_create_irq_domain(fwnode, info, parent); if (!domain) return NULL; diff --git a/include/linux/msi.h b/include/linux/msi.h index 4f0bfe5..e8c81fb 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -270,6 +270,8 @@ enum { MSI_FLAG_MULTI_PCI_MSI = (1 << 2), /* Support PCI MSIX interrupts */ MSI_FLAG_PCI_MSIX = (1 << 3), + /* Needs early activate, required for PCI */ + MSI_FLAG_ACTIVATE_EARLY = (1 << 4), }; int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 5499935..19e9dfb 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -359,6 +359,17 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, else dev_dbg(dev, "irq [%d-%d] for MSI\n", virq, virq + desc->nvec_used - 1); + /* +* This flag is set by the PCI layer as we need to activate +* the MSI entries before the PCI layer enables MSI in the +* card. Otherwise the card latches a random msi message. +*/ + if (info->flags & MSI_FLAG_ACTIVATE_EARLY) { + struct irq_data *irq_data; + + irq_data = irq_domain_get_irq_data(domain, desc->irq); + irq_domain_activate_irq(irq_data); + } } return 0;
[tip:irq/urgent] genirq/msi: Make sure PCI MSIs are activated early
Commit-ID: f3b0946d629c8bfbd3e5f038e30cb9c711a35f10 Gitweb: http://git.kernel.org/tip/f3b0946d629c8bfbd3e5f038e30cb9c711a35f10 Author: Marc Zyngier AuthorDate: Wed, 13 Jul 2016 17:18:33 +0100 Committer: Thomas Gleixner CommitDate: Tue, 9 Aug 2016 09:19:32 +0200 genirq/msi: Make sure PCI MSIs are activated early Bharat Kumar Gogada reported issues with the generic MSI code, where the end-point ended up with garbage in its MSI configuration (both for the vector and the message). It turns out that the two MSI paths in the kernel are doing slightly different things: generic MSI: disable MSI -> allocate MSI -> enable MSI -> setup EP PCI MSI: disable MSI -> allocate MSI -> setup EP -> enable MSI And it turns out that end-points are allowed to latch the content of the MSI configuration registers as soon as MSIs are enabled. In Bharat's case, the end-point ends up using whatever was there already, which is not what you want. In order to make things converge, we introduce a new MSI domain flag (MSI_FLAG_ACTIVATE_EARLY) that is unconditionally set for PCI/MSI. When set, this flag forces the programming of the end-point as soon as the MSIs are allocated. A consequence of this is that we have an extra activate in irq_startup, but that should be without much consequence. tglx: - Several people reported a VMWare regression with PCI/MSI-X passthrough. It turns out that the patch also cures that issue. - We need to have a look at the MSI disable interrupt path, where we write the msg to all zeros without disabling MSI in the PCI device. Is that correct? Fixes: 52f518a3a7c2 "x86/MSI: Use hierarchical irqdomains to manage MSI interrupts" Reported-and-tested-by: Bharat Kumar Gogada Reported-and-tested-by: Foster Snowhill Reported-by: Matthias Prager Reported-by: Jason Taylor Signed-off-by: Marc Zyngier Acked-by: Bjorn Helgaas Cc: linux-...@vger.kernel.org Cc: sta...@vger.kernel.org Link: http://lkml.kernel.org/r/1468426713-31431-1-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/pci/msi.c | 2 ++ include/linux/msi.h | 2 ++ kernel/irq/msi.c| 11 +++ 3 files changed, 15 insertions(+) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a02981e..eafa613 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -1411,6 +1411,8 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) pci_msi_domain_update_chip_ops(info); + info->flags |= MSI_FLAG_ACTIVATE_EARLY; + domain = msi_create_irq_domain(fwnode, info, parent); if (!domain) return NULL; diff --git a/include/linux/msi.h b/include/linux/msi.h index 4f0bfe5..e8c81fb 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -270,6 +270,8 @@ enum { MSI_FLAG_MULTI_PCI_MSI = (1 << 2), /* Support PCI MSIX interrupts */ MSI_FLAG_PCI_MSIX = (1 << 3), + /* Needs early activate, required for PCI */ + MSI_FLAG_ACTIVATE_EARLY = (1 << 4), }; int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 5499935..19e9dfb 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -359,6 +359,17 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, else dev_dbg(dev, "irq [%d-%d] for MSI\n", virq, virq + desc->nvec_used - 1); + /* +* This flag is set by the PCI layer as we need to activate +* the MSI entries before the PCI layer enables MSI in the +* card. Otherwise the card latches a random msi message. +*/ + if (info->flags & MSI_FLAG_ACTIVATE_EARLY) { + struct irq_data *irq_data; + + irq_data = irq_domain_get_irq_data(domain, desc->irq); + irq_domain_activate_irq(irq_data); + } } return 0;
[tip:timers/urgent] clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered
Commit-ID: f005bd7e3b84a353475a2895e2c7686a66297d87 Gitweb: http://git.kernel.org/tip/f005bd7e3b84a353475a2895e2c7686a66297d87 Author: Marc ZyngierAuthorDate: Mon, 1 Aug 2016 10:54:15 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Aug 2016 16:15:53 +0200 clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered The ARM architected timer produces level-triggered interrupts (this is mandated by the architecture). Unfortunately, a number of device-trees get this wrong, and expose an edge-triggered interrupt. Until now, this wasn't too much an issue, as the programming of the trigger would fail (the corresponding PPI cannot be reconfigured), and the kernel would be happy with this. But we're about to change this, and trust DT a lot if the driver doesn't provide its own trigger information. In that context, the timer breaks badly. While we do need to fix the DTs, there is also some userspace out there (kvmtool) that generates the same kind of broken DT on the fly, and that will completely break with newer kernels. As a safety measure, and to keep buggy software alive as well as buying us some time to fix DTs all over the place, let's check what trigger configuration has been given us by the firmware. If this is not a level configuration, then we know that the DT/ACPI configuration is bust, and we pick some defaults which won't be worse than the existing setup. Signed-off-by: Marc Zyngier Cc: Andrew Lunn Cc: Liu Gang Cc: Mark Rutland Cc: Masahiro Yamada Cc: Wenbin Song Cc: Mingkai Hu Cc: Florian Fainelli Cc: Kevin Hilman Cc: Daniel Lezcano Cc: Michal Simek Cc: Jon Hunter Cc: a...@kernel.org Cc: bcm-kernel-feedback-l...@broadcom.com Cc: linux-arm-ker...@lists.infradead.org Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Ray Jui Cc: "Hou Zhiqiang" Cc: Tirumalesh Chalamarla Cc: linux-samsung-...@vger.kernel.org Cc: Yuan Yao Cc: Jan Glauber Cc: Gregory Clement Cc: linux-amlo...@lists.infradead.org Cc: soren.brinkm...@xilinx.com Cc: Rajesh Bhagat Cc: Scott Branden Cc: Duc Dang Cc: Kukjin Kim Cc: Carlo Caione Cc: Dinh Nguyen Link: http://lkml.kernel.org/r/1470045256-9032-2-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/arm_arch_timer.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 28bce3f..5770054 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -8,6 +8,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt)"arm_arch_timer: " fmt + #include #include #include @@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void) arch_timer_ppi[PHYS_NONSECURE_PPI]); } +static u32 check_ppi_trigger(int irq) +{ + u32 flags = irq_get_trigger_type(irq); + + if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { + pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); + pr_warn("WARNING: Please fix your firmware\n"); + flags = IRQF_TRIGGER_LOW; + } + + return flags; +} + static int arch_timer_starting_cpu(unsigned int cpu) { struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + u32 flags; __arch_timer_setup(ARCH_CP15_TIMER, clk); - enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); + flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); + enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); - if (arch_timer_has_nonsecure_ppi()) - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + if (arch_timer_has_nonsecure_ppi()) { + flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + } arch_counter_set_user_access(); if (evtstrm_enable)
[tip:timers/urgent] clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered
Commit-ID: f005bd7e3b84a353475a2895e2c7686a66297d87 Gitweb: http://git.kernel.org/tip/f005bd7e3b84a353475a2895e2c7686a66297d87 Author: Marc Zyngier AuthorDate: Mon, 1 Aug 2016 10:54:15 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Aug 2016 16:15:53 +0200 clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered The ARM architected timer produces level-triggered interrupts (this is mandated by the architecture). Unfortunately, a number of device-trees get this wrong, and expose an edge-triggered interrupt. Until now, this wasn't too much an issue, as the programming of the trigger would fail (the corresponding PPI cannot be reconfigured), and the kernel would be happy with this. But we're about to change this, and trust DT a lot if the driver doesn't provide its own trigger information. In that context, the timer breaks badly. While we do need to fix the DTs, there is also some userspace out there (kvmtool) that generates the same kind of broken DT on the fly, and that will completely break with newer kernels. As a safety measure, and to keep buggy software alive as well as buying us some time to fix DTs all over the place, let's check what trigger configuration has been given us by the firmware. If this is not a level configuration, then we know that the DT/ACPI configuration is bust, and we pick some defaults which won't be worse than the existing setup. Signed-off-by: Marc Zyngier Cc: Andrew Lunn Cc: Liu Gang Cc: Mark Rutland Cc: Masahiro Yamada Cc: Wenbin Song Cc: Mingkai Hu Cc: Florian Fainelli Cc: Kevin Hilman Cc: Daniel Lezcano Cc: Michal Simek Cc: Jon Hunter Cc: a...@kernel.org Cc: bcm-kernel-feedback-l...@broadcom.com Cc: linux-arm-ker...@lists.infradead.org Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Ray Jui Cc: "Hou Zhiqiang" Cc: Tirumalesh Chalamarla Cc: linux-samsung-...@vger.kernel.org Cc: Yuan Yao Cc: Jan Glauber Cc: Gregory Clement Cc: linux-amlo...@lists.infradead.org Cc: soren.brinkm...@xilinx.com Cc: Rajesh Bhagat Cc: Scott Branden Cc: Duc Dang Cc: Kukjin Kim Cc: Carlo Caione Cc: Dinh Nguyen Link: http://lkml.kernel.org/r/1470045256-9032-2-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/arm_arch_timer.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 28bce3f..5770054 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -8,6 +8,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt)"arm_arch_timer: " fmt + #include #include #include @@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void) arch_timer_ppi[PHYS_NONSECURE_PPI]); } +static u32 check_ppi_trigger(int irq) +{ + u32 flags = irq_get_trigger_type(irq); + + if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { + pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); + pr_warn("WARNING: Please fix your firmware\n"); + flags = IRQF_TRIGGER_LOW; + } + + return flags; +} + static int arch_timer_starting_cpu(unsigned int cpu) { struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + u32 flags; __arch_timer_setup(ARCH_CP15_TIMER, clk); - enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); + flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); + enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); - if (arch_timer_has_nonsecure_ppi()) - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + if (arch_timer_has_nonsecure_ppi()) { + flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + } arch_counter_set_user_access(); if (evtstrm_enable)
[tip:timers/urgent] clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered
Commit-ID: 1604dd8aa5827c71b1fdc302c53b678dfa20c6fc Gitweb: http://git.kernel.org/tip/1604dd8aa5827c71b1fdc302c53b678dfa20c6fc Author: Marc ZyngierAuthorDate: Mon, 1 Aug 2016 10:54:15 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Aug 2016 15:17:45 +0200 clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered The ARM architected timer produces level-triggered interrupts (this is mandated by the architecture). Unfortunately, a number of device-trees get this wrong, and expose an edge-triggered interrupt. Until now, this wasn't too much an issue, as the programming of the trigger would fail (the corresponding PPI cannot be reconfigured), and the kernel would be happy with this. But we're about to change this, and trust DT a lot if the driver doesn't provide its own trigger information. In that context, the timer breaks badly. While we do need to fix the DTs, there is also some userspace out there (kvmtool) that generates the same kind of broken DT on the fly, and that will completely break with newer kernels. As a safety measure, and to keep buggy software alive as well as buying us some time to fix DTs all over the place, let's check what trigger configuration has been given us by the firmware. If this is not a level configuration, then we know that the DT/ACPI configuration is bust, and we pick some defaults which won't be worse than the existing setup. Signed-off-by: Marc Zyngier Cc: Andrew Lunn Cc: Liu Gang Cc: Mark Rutland Cc: Masahiro Yamada Cc: Wenbin Song Cc: Mingkai Hu Cc: Florian Fainelli Cc: Kevin Hilman Cc: Daniel Lezcano Cc: Michal Simek Cc: Jon Hunter Cc: a...@kernel.org Cc: bcm-kernel-feedback-l...@broadcom.com Cc: linux-arm-ker...@lists.infradead.org Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Ray Jui Cc: "Hou Zhiqiang" Cc: Tirumalesh Chalamarla Cc: linux-samsung-...@vger.kernel.org Cc: Yuan Yao Cc: Jan Glauber Cc: Gregory Clement Cc: linux-amlo...@lists.infradead.org Cc: soren.brinkm...@xilinx.com Cc: Rajesh Bhagat Cc: Scott Branden Cc: Duc Dang Cc: Kukjin Kim Cc: Carlo Caione Cc: Dinh Nguyen Link: http://lkml.kernel.org/r/1470045256-9032-2-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/arm_arch_timer.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 28bce3f..5770054 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -8,6 +8,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt)"arm_arch_timer: " fmt + #include #include #include @@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void) arch_timer_ppi[PHYS_NONSECURE_PPI]); } +static u32 check_ppi_trigger(int irq) +{ + u32 flags = irq_get_trigger_type(irq); + + if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { + pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); + pr_warn("WARNING: Please fix your firmware\n"); + flags = IRQF_TRIGGER_LOW; + } + + return flags; +} + static int arch_timer_starting_cpu(unsigned int cpu) { struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + u32 flags; __arch_timer_setup(ARCH_CP15_TIMER, clk); - enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); + flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); + enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); - if (arch_timer_has_nonsecure_ppi()) - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + if (arch_timer_has_nonsecure_ppi()) { + flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + } arch_counter_set_user_access(); if (evtstrm_enable)
[tip:timers/urgent] clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered
Commit-ID: 1604dd8aa5827c71b1fdc302c53b678dfa20c6fc Gitweb: http://git.kernel.org/tip/1604dd8aa5827c71b1fdc302c53b678dfa20c6fc Author: Marc Zyngier AuthorDate: Mon, 1 Aug 2016 10:54:15 +0100 Committer: Thomas Gleixner CommitDate: Mon, 1 Aug 2016 15:17:45 +0200 clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered The ARM architected timer produces level-triggered interrupts (this is mandated by the architecture). Unfortunately, a number of device-trees get this wrong, and expose an edge-triggered interrupt. Until now, this wasn't too much an issue, as the programming of the trigger would fail (the corresponding PPI cannot be reconfigured), and the kernel would be happy with this. But we're about to change this, and trust DT a lot if the driver doesn't provide its own trigger information. In that context, the timer breaks badly. While we do need to fix the DTs, there is also some userspace out there (kvmtool) that generates the same kind of broken DT on the fly, and that will completely break with newer kernels. As a safety measure, and to keep buggy software alive as well as buying us some time to fix DTs all over the place, let's check what trigger configuration has been given us by the firmware. If this is not a level configuration, then we know that the DT/ACPI configuration is bust, and we pick some defaults which won't be worse than the existing setup. Signed-off-by: Marc Zyngier Cc: Andrew Lunn Cc: Liu Gang Cc: Mark Rutland Cc: Masahiro Yamada Cc: Wenbin Song Cc: Mingkai Hu Cc: Florian Fainelli Cc: Kevin Hilman Cc: Daniel Lezcano Cc: Michal Simek Cc: Jon Hunter Cc: a...@kernel.org Cc: bcm-kernel-feedback-l...@broadcom.com Cc: linux-arm-ker...@lists.infradead.org Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Ray Jui Cc: "Hou Zhiqiang" Cc: Tirumalesh Chalamarla Cc: linux-samsung-...@vger.kernel.org Cc: Yuan Yao Cc: Jan Glauber Cc: Gregory Clement Cc: linux-amlo...@lists.infradead.org Cc: soren.brinkm...@xilinx.com Cc: Rajesh Bhagat Cc: Scott Branden Cc: Duc Dang Cc: Kukjin Kim Cc: Carlo Caione Cc: Dinh Nguyen Link: http://lkml.kernel.org/r/1470045256-9032-2-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/arm_arch_timer.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 28bce3f..5770054 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -8,6 +8,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt)"arm_arch_timer: " fmt + #include #include #include @@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void) arch_timer_ppi[PHYS_NONSECURE_PPI]); } +static u32 check_ppi_trigger(int irq) +{ + u32 flags = irq_get_trigger_type(irq); + + if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { + pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); + pr_warn("WARNING: Please fix your firmware\n"); + flags = IRQF_TRIGGER_LOW; + } + + return flags; +} + static int arch_timer_starting_cpu(unsigned int cpu) { struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + u32 flags; __arch_timer_setup(ARCH_CP15_TIMER, clk); - enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); + flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); + enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); - if (arch_timer_has_nonsecure_ppi()) - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + if (arch_timer_has_nonsecure_ppi()) { + flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + } arch_counter_set_user_access(); if (evtstrm_enable)
[tip:irq/core] irqchip/gic-v3: Add support for partitioned PPIs
Commit-ID: e3825ba1af3a27d7522c9f5f929f5a13b8b138ae Gitweb: http://git.kernel.org/tip/e3825ba1af3a27d7522c9f5f929f5a13b8b138ae Author: Marc ZyngierAuthorDate: Mon, 11 Apr 2016 09:57:54 +0100 Committer: Thomas Gleixner CommitDate: Mon, 2 May 2016 13:42:51 +0200 irqchip/gic-v3: Add support for partitioned PPIs Plug the partitioning layer into the GICv3 PPI code, parsing the DT and building the partition affinities and providing the generic code with partition data and callbacks. Signed-off-by: Marc Zyngier Cc: Mark Rutland Cc: devicet...@vger.kernel.org Cc: Jason Cooper Cc: Will Deacon Cc: Rob Herring Link: http://lkml.kernel.org/r/1460365075-7316-5-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic-v3.c | 176 ++- 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index ea1836b..6c17de7 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -27,6 +27,7 @@ config ARM_GIC_V3 select IRQ_DOMAIN select MULTI_IRQ_HANDLER select IRQ_DOMAIN_HIERARCHY + select PARTITION_PERCPU config ARM_GIC_V3_ITS bool diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5b7d3c2..f83e5f4 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -44,6 +45,7 @@ struct redist_region { }; struct gic_chip_data { + struct fwnode_handle*fwnode; void __iomem*dist_base; struct redist_region*redist_regions; struct rdists rdists; @@ -51,6 +53,7 @@ struct gic_chip_data { u64 redist_stride; u32 nr_redist_regions; unsigned intirq_nr; + struct partition_desc *ppi_descs[16]; }; static struct gic_chip_data gic_data __read_mostly; @@ -812,10 +815,62 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq, } } +static int gic_irq_domain_select(struct irq_domain *d, +struct irq_fwspec *fwspec, +enum irq_domain_bus_token bus_token) +{ + /* Not for us */ +if (fwspec->fwnode != d->fwnode) + return 0; + + /* If this is not DT, then we have a single domain */ + if (!is_of_node(fwspec->fwnode)) + return 1; + + /* +* If this is a PPI and we have a 4th (non-null) parameter, +* then we need to match the partition domain. +*/ + if (fwspec->param_count >= 4 && + fwspec->param[0] == 1 && fwspec->param[3] != 0) + return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]); + + return d == gic_data.domain; +} + static const struct irq_domain_ops gic_irq_domain_ops = { .translate = gic_irq_domain_translate, .alloc = gic_irq_domain_alloc, .free = gic_irq_domain_free, + .select = gic_irq_domain_select, +}; + +static int partition_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + struct device_node *np; + int ret; + + np = of_find_node_by_phandle(fwspec->param[3]); + if (WARN_ON(!np)) + return -EINVAL; + + ret = partition_translate_id(gic_data.ppi_descs[fwspec->param[1]], +of_node_to_fwnode(np)); + if (ret < 0) + return ret; + + *hwirq = ret; + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static const struct irq_domain_ops partition_domain_ops = { + .translate = partition_domain_translate, + .select = gic_irq_domain_select, }; static void gicv3_enable_quirks(void) @@ -843,6 +898,7 @@ static int __init gic_init_bases(void __iomem *dist_base, if (static_key_true(_deactivate)) pr_info("GIC: Using split EOI/Deactivate mode\n"); + gic_data.fwnode = handle; gic_data.dist_base = dist_base; gic_data.redist_regions = rdist_regs; gic_data.nr_redist_regions = nr_redist_regions; @@ -901,6 +957,119 @@ static int __init gic_validate_dist_version(void __iomem *dist_base) return 0; } +static int get_cpu_number(struct device_node *dn) +{ + const __be32 *cell; + u64 hwid; + int i; + + cell = of_get_property(dn, "reg", NULL); + if (!cell) + return -1; + + hwid = of_read_number(cell,
[tip:irq/core] irqchip/gic-v3: Add support for partitioned PPIs
Commit-ID: e3825ba1af3a27d7522c9f5f929f5a13b8b138ae Gitweb: http://git.kernel.org/tip/e3825ba1af3a27d7522c9f5f929f5a13b8b138ae Author: Marc Zyngier AuthorDate: Mon, 11 Apr 2016 09:57:54 +0100 Committer: Thomas Gleixner CommitDate: Mon, 2 May 2016 13:42:51 +0200 irqchip/gic-v3: Add support for partitioned PPIs Plug the partitioning layer into the GICv3 PPI code, parsing the DT and building the partition affinities and providing the generic code with partition data and callbacks. Signed-off-by: Marc Zyngier Cc: Mark Rutland Cc: devicet...@vger.kernel.org Cc: Jason Cooper Cc: Will Deacon Cc: Rob Herring Link: http://lkml.kernel.org/r/1460365075-7316-5-git-send-email-marc.zyng...@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-gic-v3.c | 176 ++- 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index ea1836b..6c17de7 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -27,6 +27,7 @@ config ARM_GIC_V3 select IRQ_DOMAIN select MULTI_IRQ_HANDLER select IRQ_DOMAIN_HIERARCHY + select PARTITION_PERCPU config ARM_GIC_V3_ITS bool diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5b7d3c2..f83e5f4 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -44,6 +45,7 @@ struct redist_region { }; struct gic_chip_data { + struct fwnode_handle*fwnode; void __iomem*dist_base; struct redist_region*redist_regions; struct rdists rdists; @@ -51,6 +53,7 @@ struct gic_chip_data { u64 redist_stride; u32 nr_redist_regions; unsigned intirq_nr; + struct partition_desc *ppi_descs[16]; }; static struct gic_chip_data gic_data __read_mostly; @@ -812,10 +815,62 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq, } } +static int gic_irq_domain_select(struct irq_domain *d, +struct irq_fwspec *fwspec, +enum irq_domain_bus_token bus_token) +{ + /* Not for us */ +if (fwspec->fwnode != d->fwnode) + return 0; + + /* If this is not DT, then we have a single domain */ + if (!is_of_node(fwspec->fwnode)) + return 1; + + /* +* If this is a PPI and we have a 4th (non-null) parameter, +* then we need to match the partition domain. +*/ + if (fwspec->param_count >= 4 && + fwspec->param[0] == 1 && fwspec->param[3] != 0) + return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]); + + return d == gic_data.domain; +} + static const struct irq_domain_ops gic_irq_domain_ops = { .translate = gic_irq_domain_translate, .alloc = gic_irq_domain_alloc, .free = gic_irq_domain_free, + .select = gic_irq_domain_select, +}; + +static int partition_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + struct device_node *np; + int ret; + + np = of_find_node_by_phandle(fwspec->param[3]); + if (WARN_ON(!np)) + return -EINVAL; + + ret = partition_translate_id(gic_data.ppi_descs[fwspec->param[1]], +of_node_to_fwnode(np)); + if (ret < 0) + return ret; + + *hwirq = ret; + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static const struct irq_domain_ops partition_domain_ops = { + .translate = partition_domain_translate, + .select = gic_irq_domain_select, }; static void gicv3_enable_quirks(void) @@ -843,6 +898,7 @@ static int __init gic_init_bases(void __iomem *dist_base, if (static_key_true(_deactivate)) pr_info("GIC: Using split EOI/Deactivate mode\n"); + gic_data.fwnode = handle; gic_data.dist_base = dist_base; gic_data.redist_regions = rdist_regs; gic_data.nr_redist_regions = nr_redist_regions; @@ -901,6 +957,119 @@ static int __init gic_validate_dist_version(void __iomem *dist_base) return 0; } +static int get_cpu_number(struct device_node *dn) +{ + const __be32 *cell; + u64 hwid; + int i; + + cell = of_get_property(dn, "reg", NULL); + if (!cell) + return -1; + + hwid = of_read_number(cell, of_n_addr_cells(dn)); + + /* +* Non affinity bits must be set to 0 in the DT +*/ + if (hwid & ~MPIDR_HWID_BITMASK) + return -1; +