summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-06-29 07:36:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-06-29 07:36:53 -0400
commiteed7d30e126dc5b883b77f3e26bbca6c5b0f4222 (patch)
treedc0cd7d7d3d2070f17833ad2e9b133d42ea747d6 /drivers/irqchip
parenta7211bc9f3d50d77efe77c332b269458a94fcfd2 (diff)
parenta52548dd0491a544558e971cd5963501e1a2024d (diff)
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Ingo Molnar: "Diverse irqchip driver fixes" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/gic-v3-its: Fix command queue pointer comparison bug irqchip/mips-gic: Use the correct local interrupt map registers irqchip/ti-sci-inta: Fix kernel crash if irq_create_fwspec_mapping fail irqchip/irq-csky-mpintc: Support auto irq deliver to all cpus
Diffstat (limited to 'drivers/irqchip')
-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
4 files changed, 41 insertions, 17 deletions
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 d29b44b677e4..35500801dc2b 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -733,32 +733,43 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
733} 733}
734 734
735static int its_wait_for_range_completion(struct its_node *its, 735static int its_wait_for_range_completion(struct its_node *its,
736 struct its_cmd_block *from, 736 u64 prev_idx,
737 struct its_cmd_block *to) 737 struct its_cmd_block *to)
738{ 738{
739 u64 rd_idx, from_idx, to_idx; 739 u64 rd_idx, to_idx, linear_idx;
740 u32 count = 1000000; /* 1s! */ 740 u32 count = 1000000; /* 1s! */
741 741
742 from_idx = its_cmd_ptr_to_offset(its, from); 742 /* Linearize to_idx if the command set has wrapped around */
743 to_idx = its_cmd_ptr_to_offset(its, to); 743 to_idx = its_cmd_ptr_to_offset(its, to);
744 if (to_idx < prev_idx)
745 to_idx += ITS_CMD_QUEUE_SZ;
746
747 linear_idx = prev_idx;
744 748
745 while (1) { 749 while (1) {
750 s64 delta;
751
746 rd_idx = readl_relaxed(its->base + GITS_CREADR); 752 rd_idx = readl_relaxed(its->base + GITS_CREADR);
747 753
748 /* Direct case */ 754 /*
749 if (from_idx < to_idx && rd_idx >= to_idx) 755 * Compute the read pointer progress, taking the
750 break; 756 * potential wrap-around into account.
757 */
758 delta = rd_idx - prev_idx;
759 if (rd_idx < prev_idx)
760 delta += ITS_CMD_QUEUE_SZ;
751 761
752 /* Wrapped case */ 762 linear_idx += delta;
753 if (from_idx >= to_idx && rd_idx >= to_idx && rd_idx < from_idx) 763 if (linear_idx >= to_idx)
754 break; 764 break;
755 765
756 count--; 766 count--;
757 if (!count) { 767 if (!count) {
758 pr_err_ratelimited("ITS queue timeout (%llu %llu %llu)\n", 768 pr_err_ratelimited("ITS queue timeout (%llu %llu)\n",
759 from_idx, to_idx, rd_idx); 769 to_idx, linear_idx);
760 return -1; 770 return -1;
761 } 771 }
772 prev_idx = rd_idx;
762 cpu_relax(); 773 cpu_relax();
763 udelay(1); 774 udelay(1);
764 } 775 }
@@ -775,6 +786,7 @@ void name(struct its_node *its, \
775 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \ 786 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \
776 synctype *sync_obj; \ 787 synctype *sync_obj; \
777 unsigned long flags; \ 788 unsigned long flags; \
789 u64 rd_idx; \
778 \ 790 \
779 raw_spin_lock_irqsave(&its->lock, flags); \ 791 raw_spin_lock_irqsave(&its->lock, flags); \
780 \ 792 \
@@ -796,10 +808,11 @@ void name(struct its_node *its, \
796 } \ 808 } \
797 \ 809 \
798post: \ 810post: \
811 rd_idx = readl_relaxed(its->base + GITS_CREADR); \
799 next_cmd = its_post_commands(its); \ 812 next_cmd = its_post_commands(its); \
800 raw_spin_unlock_irqrestore(&its->lock, flags); \ 813 raw_spin_unlock_irqrestore(&its->lock, flags); \
801 \ 814 \
802 if (its_wait_for_range_completion(its, cmd, next_cmd)) \ 815 if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \
803 pr_err_ratelimited("ITS cmd %ps failed\n", builder); \ 816 pr_err_ratelimited("ITS cmd %ps failed\n", builder); \
804} 817}
805 818
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