aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-06-16 18:40:01 -0400
committerThomas Gleixner <tglx@linutronix.de>2019-06-16 18:40:01 -0400
commita52548dd0491a544558e971cd5963501e1a2024d (patch)
treecdac94b5ac88a2896ecffe1fe48f2452edd1cc22
parentfb4e0592654adb31bc6f3a738d6499b816a655d6 (diff)
parenta050fa5476d418fc16b25abe168b3d38ba11e13c (diff)
Merge tag 'irqchip-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent
Pull irqchip fixes for 5.2 from Marc Zyngier: - CSky mpintc: allow interrupts to be broadcast - TI sci-inta: fix error handling - MIPS GIC: Fix local interrupt mapping - ITS: Fix command queue wrapping
-rw-r--r--arch/mips/include/asm/mips-gic.h30
-rw-r--r--drivers/irqchip/irq-csky-mpintc.c15
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c35
-rw-r--r--drivers/irqchip/irq-mips-gic.c4
-rw-r--r--drivers/irqchip/irq-ti-sci-inta.c4
5 files changed, 71 insertions, 17 deletions
diff --git a/arch/mips/include/asm/mips-gic.h b/arch/mips/include/asm/mips-gic.h
index 558059a8f218..0277b56157af 100644
--- a/arch/mips/include/asm/mips-gic.h
+++ b/arch/mips/include/asm/mips-gic.h
@@ -315,6 +315,36 @@ static inline bool mips_gic_present(void)
315} 315}
316 316
317/** 317/**
318 * mips_gic_vx_map_reg() - Return GIC_Vx_<intr>_MAP register offset
319 * @intr: A GIC local interrupt
320 *
321 * Determine the index of the GIC_VL_<intr>_MAP or GIC_VO_<intr>_MAP register
322 * within the block of GIC map registers. This is almost the same as the order
323 * of interrupts in the pending & mask registers, as used by enum
324 * mips_gic_local_interrupt, but moves the FDC interrupt & thus offsets the
325 * interrupts after it...
326 *
327 * Return: The map register index corresponding to @intr.
328 *
329 * The return value is suitable for use with the (read|write)_gic_v[lo]_map
330 * accessor functions.
331 */
332static inline unsigned int
333mips_gic_vx_map_reg(enum mips_gic_local_interrupt intr)
334{
335 /* WD, Compare & Timer are 1:1 */
336 if (intr <= GIC_LOCAL_INT_TIMER)
337 return intr;
338
339 /* FDC moves to after Timer... */
340 if (intr == GIC_LOCAL_INT_FDC)
341 return GIC_LOCAL_INT_TIMER + 1;
342
343 /* As a result everything else is offset by 1 */
344 return intr + 1;
345}
346
347/**
318 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq 348 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq
319 * 349 *
320 * Determine the virq number to use for the coprocessor 0 count/compare 350 * Determine the virq number to use for the coprocessor 0 count/compare
diff --git a/drivers/irqchip/irq-csky-mpintc.c b/drivers/irqchip/irq-csky-mpintc.c
index c67c961ab6cc..a4c1aacba1ff 100644
--- a/drivers/irqchip/irq-csky-mpintc.c
+++ b/drivers/irqchip/irq-csky-mpintc.c
@@ -89,8 +89,19 @@ static int csky_irq_set_affinity(struct irq_data *d,
89 if (cpu >= nr_cpu_ids) 89 if (cpu >= nr_cpu_ids)
90 return -EINVAL; 90 return -EINVAL;
91 91
92 /* Enable interrupt destination */ 92 /*
93 cpu |= BIT(31); 93 * The csky,mpintc could support auto irq deliver, but it only
94 * could deliver external irq to one cpu or all cpus. So it
95 * doesn't support deliver external irq to a group of cpus
96 * with cpu_mask.
97 * SO we only use auto deliver mode when affinity mask_val is
98 * equal to cpu_present_mask.
99 *
100 */
101 if (cpumask_equal(mask_val, cpu_present_mask))
102 cpu = 0;
103 else
104 cpu |= BIT(31);
94 105
95 writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + offset); 106 writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + offset);
96 107
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 1e364d3ad9c5..f0523916232d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -744,32 +744,43 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
744} 744}
745 745
746static int its_wait_for_range_completion(struct its_node *its, 746static int its_wait_for_range_completion(struct its_node *its,
747 struct its_cmd_block *from, 747 u64 prev_idx,
748 struct its_cmd_block *to) 748 struct its_cmd_block *to)
749{ 749{
750 u64 rd_idx, from_idx, to_idx; 750 u64 rd_idx, to_idx, linear_idx;
751 u32 count = 1000000; /* 1s! */ 751 u32 count = 1000000; /* 1s! */
752 752
753 from_idx = its_cmd_ptr_to_offset(its, from); 753 /* Linearize to_idx if the command set has wrapped around */
754 to_idx = its_cmd_ptr_to_offset(its, to); 754 to_idx = its_cmd_ptr_to_offset(its, to);
755 if (to_idx < prev_idx)
756 to_idx += ITS_CMD_QUEUE_SZ;
757
758 linear_idx = prev_idx;
755 759
756 while (1) { 760 while (1) {
761 s64 delta;
762
757 rd_idx = readl_relaxed(its->base + GITS_CREADR); 763 rd_idx = readl_relaxed(its->base + GITS_CREADR);
758 764
759 /* Direct case */ 765 /*
760 if (from_idx < to_idx && rd_idx >= to_idx) 766 * Compute the read pointer progress, taking the
761 break; 767 * potential wrap-around into account.
768 */
769 delta = rd_idx - prev_idx;
770 if (rd_idx < prev_idx)
771 delta += ITS_CMD_QUEUE_SZ;
762 772
763 /* Wrapped case */ 773 linear_idx += delta;
764 if (from_idx >= to_idx && rd_idx >= to_idx && rd_idx < from_idx) 774 if (linear_idx >= to_idx)
765 break; 775 break;
766 776
767 count--; 777 count--;
768 if (!count) { 778 if (!count) {
769 pr_err_ratelimited("ITS queue timeout (%llu %llu %llu)\n", 779 pr_err_ratelimited("ITS queue timeout (%llu %llu)\n",
770 from_idx, to_idx, rd_idx); 780 to_idx, linear_idx);
771 return -1; 781 return -1;
772 } 782 }
783 prev_idx = rd_idx;
773 cpu_relax(); 784 cpu_relax();
774 udelay(1); 785 udelay(1);
775 } 786 }
@@ -786,6 +797,7 @@ void name(struct its_node *its, \
786 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \ 797 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \
787 synctype *sync_obj; \ 798 synctype *sync_obj; \
788 unsigned long flags; \ 799 unsigned long flags; \
800 u64 rd_idx; \
789 \ 801 \
790 raw_spin_lock_irqsave(&its->lock, flags); \ 802 raw_spin_lock_irqsave(&its->lock, flags); \
791 \ 803 \
@@ -807,10 +819,11 @@ void name(struct its_node *its, \
807 } \ 819 } \
808 \ 820 \
809post: \ 821post: \
822 rd_idx = readl_relaxed(its->base + GITS_CREADR); \
810 next_cmd = its_post_commands(its); \ 823 next_cmd = its_post_commands(its); \
811 raw_spin_unlock_irqrestore(&its->lock, flags); \ 824 raw_spin_unlock_irqrestore(&its->lock, flags); \
812 \ 825 \
813 if (its_wait_for_range_completion(its, cmd, next_cmd)) \ 826 if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \
814 pr_err_ratelimited("ITS cmd %ps failed\n", builder); \ 827 pr_err_ratelimited("ITS cmd %ps failed\n", builder); \
815} 828}
816 829
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index d32268cc1174..f3985469c221 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -388,7 +388,7 @@ static void gic_all_vpes_irq_cpu_online(struct irq_data *d)
388 intr = GIC_HWIRQ_TO_LOCAL(d->hwirq); 388 intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
389 cd = irq_data_get_irq_chip_data(d); 389 cd = irq_data_get_irq_chip_data(d);
390 390
391 write_gic_vl_map(intr, cd->map); 391 write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
392 if (cd->mask) 392 if (cd->mask)
393 write_gic_vl_smask(BIT(intr)); 393 write_gic_vl_smask(BIT(intr));
394} 394}
@@ -517,7 +517,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
517 spin_lock_irqsave(&gic_lock, flags); 517 spin_lock_irqsave(&gic_lock, flags);
518 for_each_online_cpu(cpu) { 518 for_each_online_cpu(cpu) {
519 write_gic_vl_other(mips_cm_vp_id(cpu)); 519 write_gic_vl_other(mips_cm_vp_id(cpu));
520 write_gic_vo_map(intr, map); 520 write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
521 } 521 }
522 spin_unlock_irqrestore(&gic_lock, flags); 522 spin_unlock_irqrestore(&gic_lock, flags);
523 523
diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c
index 011b60a49e3f..ef4d625d2d80 100644
--- a/drivers/irqchip/irq-ti-sci-inta.c
+++ b/drivers/irqchip/irq-ti-sci-inta.c
@@ -159,9 +159,9 @@ static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_dom
159 parent_fwspec.param[1] = vint_desc->vint_id; 159 parent_fwspec.param[1] = vint_desc->vint_id;
160 160
161 parent_virq = irq_create_fwspec_mapping(&parent_fwspec); 161 parent_virq = irq_create_fwspec_mapping(&parent_fwspec);
162 if (parent_virq <= 0) { 162 if (parent_virq == 0) {
163 kfree(vint_desc); 163 kfree(vint_desc);
164 return ERR_PTR(parent_virq); 164 return ERR_PTR(-EINVAL);
165 } 165 }
166 vint_desc->parent_virq = parent_virq; 166 vint_desc->parent_virq = parent_virq;
167 167