Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+71 -17
+30
arch/mips/include/asm/mips-gic.h
··· 311 311 } 312 312 313 313 /** 314 + * mips_gic_vx_map_reg() - Return GIC_Vx_<intr>_MAP register offset 315 + * @intr: A GIC local interrupt 316 + * 317 + * Determine the index of the GIC_VL_<intr>_MAP or GIC_VO_<intr>_MAP register 318 + * within the block of GIC map registers. This is almost the same as the order 319 + * of interrupts in the pending & mask registers, as used by enum 320 + * mips_gic_local_interrupt, but moves the FDC interrupt & thus offsets the 321 + * interrupts after it... 322 + * 323 + * Return: The map register index corresponding to @intr. 324 + * 325 + * The return value is suitable for use with the (read|write)_gic_v[lo]_map 326 + * accessor functions. 327 + */ 328 + static inline unsigned int 329 + mips_gic_vx_map_reg(enum mips_gic_local_interrupt intr) 330 + { 331 + /* WD, Compare & Timer are 1:1 */ 332 + if (intr <= GIC_LOCAL_INT_TIMER) 333 + return intr; 334 + 335 + /* FDC moves to after Timer... */ 336 + if (intr == GIC_LOCAL_INT_FDC) 337 + return GIC_LOCAL_INT_TIMER + 1; 338 + 339 + /* As a result everything else is offset by 1 */ 340 + return intr + 1; 341 + } 342 + 343 + /** 314 344 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq 315 345 * 316 346 * Determine the virq number to use for the coprocessor 0 count/compare
+13 -2
drivers/irqchip/irq-csky-mpintc.c
··· 89 89 if (cpu >= nr_cpu_ids) 90 90 return -EINVAL; 91 91 92 - /* Enable interrupt destination */ 93 - cpu |= BIT(31); 92 + /* 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 106 writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + offset); 96 107
+24 -11
drivers/irqchip/irq-gic-v3-its.c
··· 733 733 } 734 734 735 735 static int its_wait_for_range_completion(struct its_node *its, 736 - struct its_cmd_block *from, 736 + u64 prev_idx, 737 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 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 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 749 while (1) { 750 + s64 delta; 751 + 746 752 rd_idx = readl_relaxed(its->base + GITS_CREADR); 747 753 748 - /* Direct case */ 749 - if (from_idx < to_idx && rd_idx >= to_idx) 750 - break; 754 + /* 755 + * Compute the read pointer progress, taking the 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 */ 753 - if (from_idx >= to_idx && rd_idx >= to_idx && rd_idx < from_idx) 762 + linear_idx += delta; 763 + if (linear_idx >= to_idx) 754 764 break; 755 765 756 766 count--; 757 767 if (!count) { 758 - pr_err_ratelimited("ITS queue timeout (%llu %llu %llu)\n", 759 - from_idx, to_idx, rd_idx); 768 + pr_err_ratelimited("ITS queue timeout (%llu %llu)\n", 769 + to_idx, linear_idx); 760 770 return -1; 761 771 } 772 + prev_idx = rd_idx; 762 773 cpu_relax(); 763 774 udelay(1); 764 775 } ··· 786 775 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \ 787 776 synctype *sync_obj; \ 788 777 unsigned long flags; \ 778 + u64 rd_idx; \ 789 779 \ 790 780 raw_spin_lock_irqsave(&its->lock, flags); \ 791 781 \ ··· 808 796 } \ 809 797 \ 810 798 post: \ 799 + rd_idx = readl_relaxed(its->base + GITS_CREADR); \ 811 800 next_cmd = its_post_commands(its); \ 812 801 raw_spin_unlock_irqrestore(&its->lock, flags); \ 813 802 \ 814 - if (its_wait_for_range_completion(its, cmd, next_cmd)) \ 803 + if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \ 815 804 pr_err_ratelimited("ITS cmd %ps failed\n", builder); \ 816 805 } 817 806
+2 -2
drivers/irqchip/irq-mips-gic.c
··· 388 388 intr = GIC_HWIRQ_TO_LOCAL(d->hwirq); 389 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 392 if (cd->mask) 393 393 write_gic_vl_smask(BIT(intr)); 394 394 } ··· 517 517 spin_lock_irqsave(&gic_lock, flags); 518 518 for_each_online_cpu(cpu) { 519 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 522 spin_unlock_irqrestore(&gic_lock, flags); 523 523
+2 -2
drivers/irqchip/irq-ti-sci-inta.c
··· 159 159 parent_fwspec.param[1] = vint_desc->vint_id; 160 160 161 161 parent_virq = irq_create_fwspec_mapping(&parent_fwspec); 162 - if (parent_virq <= 0) { 162 + if (parent_virq == 0) { 163 163 kfree(vint_desc); 164 - return ERR_PTR(parent_virq); 164 + return ERR_PTR(-EINVAL); 165 165 } 166 166 vint_desc->parent_virq = parent_virq; 167 167