From da343fc776e0bcb238b65d9d24610819b95d0ef4 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 14:19:47 +0200 Subject: irqchip: armada-370-xp: fix invalid cast of signed value into unsigned variable The armada_370_xp_alloc_msi() function returns a signed int, which is negative on error. However, we store the return value into an irq_hw_number_t, which is unsigned. Therefore, we actually never test if armada_370_xp_alloc_msi() returns an error or not, which may lead us to use hwirq numbers of as 0xffffffe4 (when armada_370_xp_alloc_msi() returns -ENOSPC). This commit fixes that by storing the return value of armada_370_xp_alloc_msi() in a signed variable. Fixes: 31f614edb726fcc4d5aa0f2895fbdec9b04a3ca4 ('irqchip: armada-370-xp: implement MSI support') Cc: # v3.13+ Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-2-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Neil Greatorex Signed-off-by: Jason Cooper --- drivers/irqchip/irq-armada-370-xp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 41be897..3c8d89b 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -132,8 +132,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, struct msi_desc *desc) { struct msi_msg msg; - irq_hw_number_t hwirq; - int virq; + int virq, hwirq; hwirq = armada_370_xp_alloc_msi(); if (hwirq < 0) -- cgit v1.1 From 830cbe4b7a918613276aa3d3b28d24410623f92c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 14:19:48 +0200 Subject: irqchip: armada-370-xp: implement the ->check_device() msi_chip operation Until now, we were leaving the ->check_device() msi_chip operation empty, which leads the PCI core to believe that we support both MSI and MSI-X. In fact, we do not support MSI-X, so we have to tell this to the PCI core by providing an implementation of this operation. Fixes: 31f614edb726fcc4d5aa0f2895fbdec9b04a3ca4 ('irqchip: armada-370-xp: implement MSI support') Cc: # v3.13+ Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-3-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Neil Greatorex Signed-off-by: Jason Cooper --- drivers/irqchip/irq-armada-370-xp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 3c8d89b..78b0ac9 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -162,6 +162,15 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, armada_370_xp_free_msi(d->hwirq); } +static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, + int nvec, int type) +{ + /* We support MSI, but not MSI-X */ + if (type == PCI_CAP_ID_MSI) + return 0; + return -EINVAL; +} + static struct irq_chip armada_370_xp_msi_irq_chip = { .name = "armada_370_xp_msi_irq", .irq_enable = unmask_msi_irq, @@ -200,6 +209,7 @@ static int armada_370_xp_msi_init(struct device_node *node, msi_chip->setup_irq = armada_370_xp_setup_msi_irq; msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; + msi_chip->check_device = armada_370_xp_check_msi_device; msi_chip->of_node = node; armada_370_xp_msi_domain = -- cgit v1.1 From ff3c664505bf8a8334bca5045e87b85cfe4d2277 Mon Sep 17 00:00:00 2001 From: Neil Greatorex Date: Fri, 18 Apr 2014 14:19:49 +0200 Subject: irqchip: armada-370-xp: Fix releasing of MSIs Store the value of d->hwirq in a local variable as the real value is wiped out by calling irq_dispose_mapping. Without this patch, the armada_370_xp_free_msi function would always free MSI#0, no matter what was passed to it. Fixes: 31f614edb726fcc4d5aa0f2895fbdec9b04a3ca4 ('irqchip: armada-370-xp: implement MSI support') Cc: # v3.13+ Signed-off-by: Neil Greatorex Link: https://lkml.kernel.org/r/1397823593-1932-4-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-4-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- drivers/irqchip/irq-armada-370-xp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 78b0ac9..868d11b 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -158,8 +158,10 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, unsigned int irq) { struct irq_data *d = irq_get_irq_data(irq); + unsigned long hwirq = d->hwirq; + irq_dispose_mapping(irq); - armada_370_xp_free_msi(d->hwirq); + armada_370_xp_free_msi(hwirq); } static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, -- cgit v1.1 From 8cc3cfc5ccf1680b7c88f874912b6bec2797b76b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 4 Mar 2014 20:43:41 +0000 Subject: irqchip: armanda: Sanitize set_irq_affinity() The set_irq_affinity() function has two issues: 1) It has no protection against selecting an offline cpu from the given mask. 2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm. irq affinity is set to core 3 core 3 goes offline migration code sets mask to cpu_online_mask and calls the irq_set_affinity() callback of the irq_chip which fails due to bit 0,1,2 set. So instead of doing silly for_each_cpu() loops just pick any bit of the mask which intersects with the online mask. Get rid of fiddling with the default_irq_affinity as well. [ Gregory: Fixed the access to the routing register ] Signed-off-by: Thomas Gleixner Acked-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Cc: Jason Cooper Cc: Peter Zijlstra Cc: Ingo Molnar Link: http://lkml.kernel.org/r/20140304203101.088889302@linutronix.de Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-armada-370-xp.c | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 41be897..304a20d 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -41,6 +41,7 @@ #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) +#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) #define ARMADA_375_PPI_CAUSE (0x10) @@ -244,35 +245,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock); static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { - unsigned long reg; - unsigned long new_mask = 0; - unsigned long online_mask = 0; - unsigned long count = 0; irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long reg, mask; int cpu; - for_each_cpu(cpu, mask_val) { - new_mask |= 1 << cpu_logical_map(cpu); - count++; - } - - /* - * Forbid mutlicore interrupt affinity - * This is required since the MPIC HW doesn't limit - * several CPUs from acknowledging the same interrupt. - */ - if (count > 1) - return -EINVAL; - - for_each_cpu(cpu, cpu_online_mask) - online_mask |= 1 << cpu_logical_map(cpu); + /* Select a single core from the affinity mask which is online */ + cpu = cpumask_any_and(mask_val, cpu_online_mask); + mask = 1UL << cpu_logical_map(cpu); raw_spin_lock(&irq_controller_lock); - reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - reg = (reg & (~online_mask)) | new_mask; + reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask; writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - raw_spin_unlock(&irq_controller_lock); return 0; @@ -494,15 +478,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, #ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init(); - - /* - * Set the default affinity from all CPUs to the boot cpu. - * This is required since the MPIC doesn't limit several CPUs - * from acknowledging the same interrupt. - */ - cpumask_clear(irq_default_affinity); - cpumask_set_cpu(smp_processor_id(), irq_default_affinity); - #endif armada_370_xp_msi_init(node, main_int_res.start); -- cgit v1.1 From 3894e9e82dfdc87fa35dc7976e0472d220228826 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 3 Apr 2014 10:21:34 +0300 Subject: irqchip: irq-crossbar: Not allocating enough memory We are allocating the size of a pointer and not the size of the data. This will lead to memory corruption. There isn't actually a "cb_device" struct, btw. The code is only able to compile because GCC knows that all pointers are the same size. Fixes: 96ca848ef7ea ('DRIVERS: IRQCHIP: CROSSBAR: Add support for Crossbar IP') Signed-off-by: Dan Carpenter Acked-by: Sricharan R Cc: Grant Likely Cc: Rob Herring Link: http://lkml.kernel.org/r/20140403072134.GA14286@mwanda Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-crossbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index fc817d2..3d15d16 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c @@ -107,7 +107,7 @@ static int __init crossbar_of_init(struct device_node *node) int i, size, max, reserved = 0, entry; const __be32 *irqsr; - cb = kzalloc(sizeof(struct cb_device *), GFP_KERNEL); + cb = kzalloc(sizeof(*cb), GFP_KERNEL); if (!cb) return -ENOMEM; -- cgit v1.1