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 tag 'irq-core-2020-12-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
"Generic interrupt and irqchips subsystem updates. Unusually, there is
not a single completely new irq chip driver, just new DT bindings and
extensions of existing drivers to accomodate new variants!

Core:

- Consolidation and robustness changes for irq time accounting

- Cleanup and consolidation of irq stats

- Remove the fasteoi IPI flow which has been proved useless

- Provide an interface for converting legacy interrupt mechanism into
irqdomains

Drivers:

- Preliminary support for managed interrupts on platform devices

- Correctly identify allocation of MSIs proxyied by another device

- Generalise the Ocelot support to new SoCs

- Improve GICv4.1 vcpu entry, matching the corresponding KVM
optimisation

- Work around spurious interrupts on Qualcomm PDC

- Random fixes and cleanups"

* tag 'irq-core-2020-12-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (54 commits)
irqchip/qcom-pdc: Fix phantom irq when changing between rising/falling
driver core: platform: Add devm_platform_get_irqs_affinity()
ACPI: Drop acpi_dev_irqresource_disabled()
resource: Add irqresource_disabled()
genirq/affinity: Add irq_update_affinity_desc()
irqchip/gic-v3-its: Flag device allocation as proxied if behind a PCI bridge
irqchip/gic-v3-its: Tag ITS device as shared if allocating for a proxy device
platform-msi: Track shared domain allocation
irqchip/ti-sci-intr: Fix freeing of irqs
irqchip/ti-sci-inta: Fix printing of inta id on probe success
drivers/irqchip: Remove EZChip NPS interrupt controller
Revert "genirq: Add fasteoi IPI flow"
irqchip/hip04: Make IPIs use handle_percpu_devid_irq()
irqchip/bcm2836: Make IPIs use handle_percpu_devid_irq()
irqchip/armada-370-xp: Make IPIs use handle_percpu_devid_irq()
irqchip/gic, gic-v3: Make SGIs use handle_percpu_devid_irq()
irqchip/ocelot: Add support for Jaguar2 platforms
irqchip/ocelot: Add support for Serval platforms
irqchip/ocelot: Add support for Luton platforms
irqchip/ocelot: prepare to support more SoC
...

+762 -630
+6
Documentation/core-api/irq/irq-domain.rst
··· 147 147 irq_domain_add_simple() 148 148 irq_domain_add_legacy() 149 149 irq_domain_add_legacy_isa() 150 + irq_domain_create_legacy() 150 151 151 152 The Legacy mapping is a special case for drivers that already have a 152 153 range of irq_descs allocated for the hwirqs. It is used when the ··· 185 184 that the driver using the simple domain call irq_create_mapping() 186 185 before any irq_find_mapping() since the latter will actually work 187 186 for the static IRQ assignment case. 187 + 188 + irq_domain_add_legacy() and irq_domain_create_legacy() are functionally 189 + equivalent, except for the first argument is different - the former 190 + accepts an Open Firmware specific 'struct device_node', while the latter 191 + accepts a more general abstraction 'struct fwnode_handle'. 188 192 189 193 Hierarchy IRQ domain 190 194 --------------------
+6 -2
Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.txt
··· 1 1 * Freescale Layerscape external IRQs 2 2 3 - Some Layerscape SOCs (LS1021A, LS1043A, LS1046A) support inverting 3 + Some Layerscape SOCs (LS1021A, LS1043A, LS1046A 4 + LS1088A, LS208xA, LX216xA) support inverting 4 5 the polarity of certain external interrupt lines. 5 6 6 7 The device node must be a child of the node representing the ··· 9 8 10 9 Required properties: 11 10 - compatible: should be "fsl,<soc-name>-extirq", e.g. "fsl,ls1021a-extirq". 11 + "fsl,ls1043a-extirq": for LS1043A, LS1046A. 12 + "fsl,ls1088a-extirq": for LS1088A, LS208xA, LX216xA. 12 13 - #interrupt-cells: Must be 2. The first element is the index of the 13 14 external interrupt line. The second element is the trigger type. 14 15 - #address-cells: Must be 0. 15 16 - interrupt-controller: Identifies the node as an interrupt controller 16 17 - reg: Specifies the Interrupt Polarity Control Register (INTPCR) in 17 - the SCFG. 18 + the SCFG or the External Interrupt Control Register (IRQCR) in 19 + the ISC. 18 20 - interrupt-map: Specifies the mapping from external interrupts to GIC 19 21 interrupts. 20 22 - interrupt-map-mask: Must be <0xffffffff 0>.
-21
Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt
··· 1 - Microsemi Ocelot SoC ICPU Interrupt Controller 2 - 3 - Required properties: 4 - 5 - - compatible : should be "mscc,ocelot-icpu-intr" 6 - - reg : Specifies base physical address and size of the registers. 7 - - interrupt-controller : Identifies the node as an interrupt controller 8 - - #interrupt-cells : Specifies the number of cells needed to encode an 9 - interrupt source. The value shall be 1. 10 - - interrupts : Specifies the CPU interrupt the controller is connected to. 11 - 12 - Example: 13 - 14 - intc: interrupt-controller@70000070 { 15 - compatible = "mscc,ocelot-icpu-intr"; 16 - reg = <0x70000070 0x70>; 17 - #interrupt-cells = <1>; 18 - interrupt-controller; 19 - interrupt-parent = <&cpuintc>; 20 - interrupts = <2>; 21 - };
+64
Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: "http://devicetree.org/schemas/interrupt-controller/mscc,ocelot-icpu-intr.yaml#" 5 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 6 + 7 + title: Microsemi Ocelot SoC ICPU Interrupt Controller 8 + 9 + maintainers: 10 + - Alexandre Belloni <alexandre.belloni@bootlin.com> 11 + 12 + allOf: 13 + - $ref: /schemas/interrupt-controller.yaml# 14 + 15 + description: | 16 + the Microsemi Ocelot interrupt controller that is part of the 17 + ICPU. It is connected directly to the MIPS core interrupt 18 + controller. 19 + 20 + properties: 21 + compatible: 22 + items: 23 + - enum: 24 + - mscc,jaguar2-icpu-intr 25 + - mscc,luton-icpu-intr 26 + - mscc,ocelot-icpu-intr 27 + - mscc,serval-icpu-intr 28 + 29 + 30 + '#interrupt-cells': 31 + const: 1 32 + 33 + '#address-cells': 34 + const: 0 35 + 36 + interrupt-controller: true 37 + 38 + reg: 39 + maxItems: 1 40 + 41 + interrupts: 42 + maxItems: 1 43 + 44 + required: 45 + - compatible 46 + - '#interrupt-cells' 47 + - '#address-cells' 48 + - interrupt-controller 49 + - reg 50 + 51 + additionalProperties: false 52 + 53 + examples: 54 + - | 55 + intc: interrupt-controller@70000070 { 56 + compatible = "mscc,ocelot-icpu-intr"; 57 + reg = <0x70000070 0x70>; 58 + #interrupt-cells = <1>; 59 + #address-cells = <0>; 60 + interrupt-controller; 61 + interrupt-parent = <&cpuintc>; 62 + interrupts = <2>; 63 + }; 64 + ...
+6 -1
arch/Kconfig
··· 644 644 config HAVE_VIRT_CPU_ACCOUNTING 645 645 bool 646 646 647 + config HAVE_VIRT_CPU_ACCOUNTING_IDLE 648 + bool 649 + help 650 + Architecture has its own way to account idle CPU time and therefore 651 + doesn't implement vtime_account_idle(). 652 + 647 653 config ARCH_HAS_SCALED_CPUTIME 648 654 bool 649 655 ··· 663 657 cputime_t. For example, reading/writing 64-bit cputime_t on 664 658 some 32-bit arches may require multiple accesses, so proper 665 659 locking is needed to protect against concurrent accesses. 666 - 667 660 668 661 config HAVE_IRQ_TIME_ACCOUNTING 669 662 bool
+3 -8
arch/arm/include/asm/hardirq.h
··· 2 2 #ifndef __ASM_HARDIRQ_H 3 3 #define __ASM_HARDIRQ_H 4 4 5 - #include <linux/cache.h> 6 - #include <linux/threads.h> 7 5 #include <asm/irq.h> 8 6 9 - typedef struct { 10 - unsigned int __softirq_pending; 11 - } ____cacheline_aligned irq_cpustat_t; 12 - 13 - #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 14 - 15 7 #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 8 + #define ack_bad_irq ack_bad_irq 9 + 10 + #include <asm-generic/hardirq.h> 16 11 17 12 #endif /* __ASM_HARDIRQ_H */
+2
arch/arm/include/asm/irq.h
··· 31 31 void init_IRQ(void); 32 32 33 33 #ifdef CONFIG_SMP 34 + #include <linux/cpumask.h> 35 + 34 36 extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, 35 37 bool exclude_self); 36 38 #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
+2 -5
arch/arm64/include/asm/hardirq.h
··· 13 13 #include <asm/kvm_arm.h> 14 14 #include <asm/sysreg.h> 15 15 16 - typedef struct { 17 - unsigned int __softirq_pending; 18 - } ____cacheline_aligned irq_cpustat_t; 19 - 20 - #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 16 + #define ack_bad_irq ack_bad_irq 17 + #include <asm-generic/hardirq.h> 21 18 22 19 #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 23 20
+15 -5
arch/ia64/kernel/time.c
··· 138 138 struct thread_info *ti = task_thread_info(tsk); 139 139 __u64 stime = vtime_delta(tsk); 140 140 141 - if ((tsk->flags & PF_VCPU) && !irq_count()) 141 + if (tsk->flags & PF_VCPU) 142 142 ti->gtime += stime; 143 - else if (hardirq_count()) 144 - ti->hardirq_time += stime; 145 - else if (in_serving_softirq()) 146 - ti->softirq_time += stime; 147 143 else 148 144 ti->stime += stime; 149 145 } ··· 150 154 struct thread_info *ti = task_thread_info(tsk); 151 155 152 156 ti->idle_time += vtime_delta(tsk); 157 + } 158 + 159 + void vtime_account_softirq(struct task_struct *tsk) 160 + { 161 + struct thread_info *ti = task_thread_info(tsk); 162 + 163 + ti->softirq_time += vtime_delta(tsk); 164 + } 165 + 166 + void vtime_account_hardirq(struct task_struct *tsk) 167 + { 168 + struct thread_info *ti = task_thread_info(tsk); 169 + 170 + ti->hardirq_time += vtime_delta(tsk); 153 171 } 154 172 155 173 #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
-1
arch/parisc/include/asm/hardirq.h
··· 32 32 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); 33 33 34 34 #define __ARCH_IRQ_STAT 35 - #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) 36 35 #define inc_irq_stat(member) this_cpu_inc(irq_stat.member) 37 36 #define __inc_irq_stat(member) __this_cpu_inc(irq_stat.member) 38 37 #define ack_bad_irq(irq) WARN(1, "unexpected IRQ trap at vector %02x\n", irq)
+40 -16
arch/powerpc/kernel/time.c
··· 311 311 return stime_scaled; 312 312 } 313 313 314 - static unsigned long vtime_delta(struct task_struct *tsk, 314 + static unsigned long vtime_delta(struct cpu_accounting_data *acct, 315 315 unsigned long *stime_scaled, 316 316 unsigned long *steal_time) 317 317 { 318 318 unsigned long now, stime; 319 - struct cpu_accounting_data *acct = get_accounting(tsk); 320 319 321 320 WARN_ON_ONCE(!irqs_disabled()); 322 321 ··· 330 331 return stime; 331 332 } 332 333 334 + static void vtime_delta_kernel(struct cpu_accounting_data *acct, 335 + unsigned long *stime, unsigned long *stime_scaled) 336 + { 337 + unsigned long steal_time; 338 + 339 + *stime = vtime_delta(acct, stime_scaled, &steal_time); 340 + *stime -= min(*stime, steal_time); 341 + acct->steal_time += steal_time; 342 + } 343 + 333 344 void vtime_account_kernel(struct task_struct *tsk) 334 345 { 335 - unsigned long stime, stime_scaled, steal_time; 336 346 struct cpu_accounting_data *acct = get_accounting(tsk); 347 + unsigned long stime, stime_scaled; 337 348 338 - stime = vtime_delta(tsk, &stime_scaled, &steal_time); 349 + vtime_delta_kernel(acct, &stime, &stime_scaled); 339 350 340 - stime -= min(stime, steal_time); 341 - acct->steal_time += steal_time; 342 - 343 - if ((tsk->flags & PF_VCPU) && !irq_count()) { 351 + if (tsk->flags & PF_VCPU) { 344 352 acct->gtime += stime; 345 353 #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 346 354 acct->utime_scaled += stime_scaled; 347 355 #endif 348 356 } else { 349 - if (hardirq_count()) 350 - acct->hardirq_time += stime; 351 - else if (in_serving_softirq()) 352 - acct->softirq_time += stime; 353 - else 354 - acct->stime += stime; 355 - 357 + acct->stime += stime; 356 358 #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 357 359 acct->stime_scaled += stime_scaled; 358 360 #endif ··· 366 366 unsigned long stime, stime_scaled, steal_time; 367 367 struct cpu_accounting_data *acct = get_accounting(tsk); 368 368 369 - stime = vtime_delta(tsk, &stime_scaled, &steal_time); 369 + stime = vtime_delta(acct, &stime_scaled, &steal_time); 370 370 acct->idle_time += stime + steal_time; 371 + } 372 + 373 + static void vtime_account_irq_field(struct cpu_accounting_data *acct, 374 + unsigned long *field) 375 + { 376 + unsigned long stime, stime_scaled; 377 + 378 + vtime_delta_kernel(acct, &stime, &stime_scaled); 379 + *field += stime; 380 + #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 381 + acct->stime_scaled += stime_scaled; 382 + #endif 383 + } 384 + 385 + void vtime_account_softirq(struct task_struct *tsk) 386 + { 387 + struct cpu_accounting_data *acct = get_accounting(tsk); 388 + vtime_account_irq_field(acct, &acct->softirq_time); 389 + } 390 + 391 + void vtime_account_hardirq(struct task_struct *tsk) 392 + { 393 + struct cpu_accounting_data *acct = get_accounting(tsk); 394 + vtime_account_irq_field(acct, &acct->hardirq_time); 371 395 } 372 396 373 397 static void vtime_flush_scaled(struct task_struct *tsk,
+1
arch/s390/Kconfig
··· 178 178 select HAVE_RSEQ 179 179 select HAVE_SYSCALL_TRACEPOINTS 180 180 select HAVE_VIRT_CPU_ACCOUNTING 181 + select HAVE_VIRT_CPU_ACCOUNTING_IDLE 181 182 select IOMMU_HELPER if PCI 182 183 select IOMMU_SUPPORT if PCI 183 184 select MODULES_USE_ELF_RELA
-1
arch/s390/include/asm/vtime.h
··· 2 2 #ifndef _S390_VTIME_H 3 3 #define _S390_VTIME_H 4 4 5 - #define __ARCH_HAS_VTIME_ACCOUNT 6 5 #define __ARCH_HAS_VTIME_TASK_SWITCH 7 6 8 7 #endif /* _S390_VTIME_H */
+37 -22
arch/s390/kernel/vtime.c
··· 222 222 S390_lowcore.avg_steal_timer = avg_steal; 223 223 } 224 224 225 + static u64 vtime_delta(void) 226 + { 227 + u64 timer = S390_lowcore.last_update_timer; 228 + 229 + S390_lowcore.last_update_timer = get_vtimer(); 230 + 231 + return timer - S390_lowcore.last_update_timer; 232 + } 233 + 225 234 /* 226 235 * Update process times based on virtual cpu times stored by entry.S 227 236 * to the lowcore fields user_timer, system_timer & steal_clock. 228 237 */ 229 - void vtime_account_irq_enter(struct task_struct *tsk) 230 - { 231 - u64 timer; 232 - 233 - timer = S390_lowcore.last_update_timer; 234 - S390_lowcore.last_update_timer = get_vtimer(); 235 - timer -= S390_lowcore.last_update_timer; 236 - 237 - if ((tsk->flags & PF_VCPU) && (irq_count() == 0)) 238 - S390_lowcore.guest_timer += timer; 239 - else if (hardirq_count()) 240 - S390_lowcore.hardirq_timer += timer; 241 - else if (in_serving_softirq()) 242 - S390_lowcore.softirq_timer += timer; 243 - else 244 - S390_lowcore.system_timer += timer; 245 - 246 - virt_timer_forward(timer); 247 - } 248 - EXPORT_SYMBOL_GPL(vtime_account_irq_enter); 249 - 250 238 void vtime_account_kernel(struct task_struct *tsk) 251 - __attribute__((alias("vtime_account_irq_enter"))); 239 + { 240 + u64 delta = vtime_delta(); 241 + 242 + if (tsk->flags & PF_VCPU) 243 + S390_lowcore.guest_timer += delta; 244 + else 245 + S390_lowcore.system_timer += delta; 246 + 247 + virt_timer_forward(delta); 248 + } 252 249 EXPORT_SYMBOL_GPL(vtime_account_kernel); 250 + 251 + void vtime_account_softirq(struct task_struct *tsk) 252 + { 253 + u64 delta = vtime_delta(); 254 + 255 + S390_lowcore.softirq_timer += delta; 256 + 257 + virt_timer_forward(delta); 258 + } 259 + 260 + void vtime_account_hardirq(struct task_struct *tsk) 261 + { 262 + u64 delta = vtime_delta(); 263 + 264 + S390_lowcore.hardirq_timer += delta; 265 + 266 + virt_timer_forward(delta); 267 + } 253 268 254 269 /* 255 270 * Sorted add to a list. List is linear searched until first bigger
+4 -10
arch/sh/include/asm/hardirq.h
··· 2 2 #ifndef __ASM_SH_HARDIRQ_H 3 3 #define __ASM_SH_HARDIRQ_H 4 4 5 - #include <linux/threads.h> 6 - #include <linux/irq.h> 7 - 8 - typedef struct { 9 - unsigned int __softirq_pending; 10 - unsigned int __nmi_count; /* arch dependent */ 11 - } ____cacheline_aligned irq_cpustat_t; 12 - 13 - #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 14 - 15 5 extern void ack_bad_irq(unsigned int irq); 6 + #define ack_bad_irq ack_bad_irq 7 + #define ARCH_WANTS_NMI_IRQSTAT 8 + 9 + #include <asm-generic/hardirq.h> 16 10 17 11 #endif /* __ASM_SH_HARDIRQ_H */
+1 -1
arch/sh/kernel/irq.c
··· 44 44 45 45 seq_printf(p, "%*s: ", prec, "NMI"); 46 46 for_each_online_cpu(j) 47 - seq_printf(p, "%10u ", nmi_count(j)); 47 + seq_printf(p, "%10u ", per_cpu(irq_stat.__nmi_count, j)); 48 48 seq_printf(p, " Non-maskable interrupts\n"); 49 49 50 50 seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+1 -1
arch/sh/kernel/traps.c
··· 186 186 arch_ftrace_nmi_enter(); 187 187 188 188 nmi_enter(); 189 - nmi_count(cpu)++; 189 + this_cpu_inc(irq_stat.__nmi_count); 190 190 191 191 switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) { 192 192 case NOTIFY_OK:
+1 -16
arch/um/include/asm/hardirq.h
··· 2 2 #ifndef __ASM_UM_HARDIRQ_H 3 3 #define __ASM_UM_HARDIRQ_H 4 4 5 - #include <linux/cache.h> 6 - #include <linux/threads.h> 7 - 8 - typedef struct { 9 - unsigned int __softirq_pending; 10 - } ____cacheline_aligned irq_cpustat_t; 11 - 12 - #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 13 - #include <linux/irq.h> 14 - 15 - #ifndef ack_bad_irq 16 - static inline void ack_bad_irq(unsigned int irq) 17 - { 18 - printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq); 19 - } 20 - #endif 5 + #include <asm-generic/hardirq.h> 21 6 22 7 #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 23 8
+5 -12
drivers/acpi/resource.c
··· 380 380 } 381 381 EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); 382 382 383 - static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) 384 - { 385 - res->start = gsi; 386 - res->end = gsi; 387 - res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; 388 - } 389 - 390 383 static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, 391 384 u8 triggering, u8 polarity, u8 shareable, 392 385 bool legacy) ··· 387 394 int irq, p, t; 388 395 389 396 if (!valid_IRQ(gsi)) { 390 - acpi_dev_irqresource_disabled(res, gsi); 397 + irqresource_disabled(res, gsi); 391 398 return; 392 399 } 393 400 ··· 419 426 res->start = irq; 420 427 res->end = irq; 421 428 } else { 422 - acpi_dev_irqresource_disabled(res, gsi); 429 + irqresource_disabled(res, gsi); 423 430 } 424 431 } 425 432 ··· 456 463 */ 457 464 irq = &ares->data.irq; 458 465 if (index >= irq->interrupt_count) { 459 - acpi_dev_irqresource_disabled(res, 0); 466 + irqresource_disabled(res, 0); 460 467 return false; 461 468 } 462 469 acpi_dev_get_irqresource(res, irq->interrupts[index], ··· 466 473 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 467 474 ext_irq = &ares->data.extended_irq; 468 475 if (index >= ext_irq->interrupt_count) { 469 - acpi_dev_irqresource_disabled(res, 0); 476 + irqresource_disabled(res, 0); 470 477 return false; 471 478 } 472 479 if (is_gsi(ext_irq)) ··· 474 481 ext_irq->triggering, ext_irq->polarity, 475 482 ext_irq->shareable, false); 476 483 else 477 - acpi_dev_irqresource_disabled(res, 0); 484 + irqresource_disabled(res, 0); 478 485 break; 479 486 default: 480 487 res->flags = 0;
+7
drivers/base/platform-msi.c
··· 59 59 return irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 60 60 info->chip, info->chip_data); 61 61 } 62 + 63 + static void platform_msi_set_proxy_dev(msi_alloc_info_t *arg) 64 + { 65 + arg->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE; 66 + } 62 67 #else 63 68 #define platform_msi_set_desc NULL 64 69 #define platform_msi_init NULL 70 + #define platform_msi_set_proxy_dev(x) do {} while(0) 65 71 #endif 66 72 67 73 static void platform_msi_update_dom_ops(struct msi_domain_info *info) ··· 349 343 if (!domain) 350 344 goto free_priv; 351 345 346 + platform_msi_set_proxy_dev(&data->arg); 352 347 err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg); 353 348 if (err) 354 349 goto free_domain;
+121
drivers/base/platform.c
··· 15 15 #include <linux/of_irq.h> 16 16 #include <linux/module.h> 17 17 #include <linux/init.h> 18 + #include <linux/interrupt.h> 19 + #include <linux/ioport.h> 18 20 #include <linux/dma-mapping.h> 19 21 #include <linux/memblock.h> 20 22 #include <linux/err.h> ··· 305 303 return nr; 306 304 } 307 305 EXPORT_SYMBOL_GPL(platform_irq_count); 306 + 307 + struct irq_affinity_devres { 308 + unsigned int count; 309 + unsigned int irq[]; 310 + }; 311 + 312 + static void platform_disable_acpi_irq(struct platform_device *pdev, int index) 313 + { 314 + struct resource *r; 315 + 316 + r = platform_get_resource(pdev, IORESOURCE_IRQ, index); 317 + if (r) 318 + irqresource_disabled(r, 0); 319 + } 320 + 321 + static void devm_platform_get_irqs_affinity_release(struct device *dev, 322 + void *res) 323 + { 324 + struct irq_affinity_devres *ptr = res; 325 + int i; 326 + 327 + for (i = 0; i < ptr->count; i++) { 328 + irq_dispose_mapping(ptr->irq[i]); 329 + 330 + if (has_acpi_companion(dev)) 331 + platform_disable_acpi_irq(to_platform_device(dev), i); 332 + } 333 + } 334 + 335 + /** 336 + * devm_platform_get_irqs_affinity - devm method to get a set of IRQs for a 337 + * device using an interrupt affinity descriptor 338 + * @dev: platform device pointer 339 + * @affd: affinity descriptor 340 + * @minvec: minimum count of interrupt vectors 341 + * @maxvec: maximum count of interrupt vectors 342 + * @irqs: pointer holder for IRQ numbers 343 + * 344 + * Gets a set of IRQs for a platform device, and updates IRQ afffinty according 345 + * to the passed affinity descriptor 346 + * 347 + * Return: Number of vectors on success, negative error number on failure. 348 + */ 349 + int devm_platform_get_irqs_affinity(struct platform_device *dev, 350 + struct irq_affinity *affd, 351 + unsigned int minvec, 352 + unsigned int maxvec, 353 + int **irqs) 354 + { 355 + struct irq_affinity_devres *ptr; 356 + struct irq_affinity_desc *desc; 357 + size_t size; 358 + int i, ret, nvec; 359 + 360 + if (!affd) 361 + return -EPERM; 362 + 363 + if (maxvec < minvec) 364 + return -ERANGE; 365 + 366 + nvec = platform_irq_count(dev); 367 + 368 + if (nvec < minvec) 369 + return -ENOSPC; 370 + 371 + nvec = irq_calc_affinity_vectors(minvec, nvec, affd); 372 + if (nvec < minvec) 373 + return -ENOSPC; 374 + 375 + if (nvec > maxvec) 376 + nvec = maxvec; 377 + 378 + size = sizeof(*ptr) + sizeof(unsigned int) * nvec; 379 + ptr = devres_alloc(devm_platform_get_irqs_affinity_release, size, 380 + GFP_KERNEL); 381 + if (!ptr) 382 + return -ENOMEM; 383 + 384 + ptr->count = nvec; 385 + 386 + for (i = 0; i < nvec; i++) { 387 + int irq = platform_get_irq(dev, i); 388 + if (irq < 0) { 389 + ret = irq; 390 + goto err_free_devres; 391 + } 392 + ptr->irq[i] = irq; 393 + } 394 + 395 + desc = irq_create_affinity_masks(nvec, affd); 396 + if (!desc) { 397 + ret = -ENOMEM; 398 + goto err_free_devres; 399 + } 400 + 401 + for (i = 0; i < nvec; i++) { 402 + ret = irq_update_affinity_desc(ptr->irq[i], &desc[i]); 403 + if (ret) { 404 + dev_err(&dev->dev, "failed to update irq%d affinity descriptor (%d)\n", 405 + ptr->irq[i], ret); 406 + goto err_free_desc; 407 + } 408 + } 409 + 410 + devres_add(&dev->dev, ptr); 411 + 412 + kfree(desc); 413 + 414 + *irqs = ptr->irq; 415 + 416 + return nvec; 417 + 418 + err_free_desc: 419 + kfree(desc); 420 + err_free_devres: 421 + devres_free(ptr); 422 + return ret; 423 + } 424 + EXPORT_SYMBOL_GPL(devm_platform_get_irqs_affinity); 308 425 309 426 /** 310 427 * platform_get_resource_byname - get a resource for a device by name
+5 -6
drivers/base/regmap/regmap-irq.c
··· 803 803 } 804 804 805 805 if (irq_base) 806 - d->domain = irq_domain_add_legacy(to_of_node(fwnode), 807 - chip->num_irqs, irq_base, 808 - 0, &regmap_domain_ops, d); 806 + d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs, 807 + irq_base, 0, 808 + &regmap_domain_ops, d); 809 809 else 810 - d->domain = irq_domain_add_linear(to_of_node(fwnode), 811 - chip->num_irqs, 812 - &regmap_domain_ops, d); 810 + d->domain = irq_domain_create_linear(fwnode, chip->num_irqs, 811 + &regmap_domain_ops, d); 813 812 if (!d->domain) { 814 813 dev_err(map->dev, "Failed to create IRQ domain\n"); 815 814 ret = -ENOMEM;
-7
drivers/irqchip/Kconfig
··· 387 387 config PARTITION_PERCPU 388 388 bool 389 389 390 - config EZNPS_GIC 391 - bool "NPS400 Global Interrupt Manager (GIM)" 392 - depends on ARC || (COMPILE_TEST && !64BIT) 393 - select IRQ_DOMAIN 394 - help 395 - Support the EZchip NPS400 global interrupt controller 396 - 397 390 config STM32_EXTI 398 391 bool 399 392 select IRQ_DOMAIN
-1
drivers/irqchip/Makefile
··· 86 86 obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o 87 87 obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o 88 88 obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o 89 - obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o 90 89 obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o 91 90 obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o 92 91 obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
+1 -2
drivers/irqchip/irq-alpine-msi.c
··· 165 165 return 0; 166 166 167 167 err_sgi: 168 - while (--i >= 0) 169 - irq_domain_free_irqs_parent(domain, virq, i); 168 + irq_domain_free_irqs_parent(domain, virq, i - 1); 170 169 alpine_msix_free_sgi(priv, sgi, nr_irqs); 171 170 return err; 172 171 }
+1 -1
drivers/irqchip/irq-armada-370-xp.c
··· 382 382 irq_set_percpu_devid(virq + i); 383 383 irq_domain_set_info(d, virq + i, i, &ipi_irqchip, 384 384 d->host_data, 385 - handle_percpu_devid_fasteoi_ipi, 385 + handle_percpu_devid_irq, 386 386 NULL, NULL); 387 387 } 388 388
+1 -1
drivers/irqchip/irq-bcm2836.c
··· 209 209 irq_set_percpu_devid(virq + i); 210 210 irq_domain_set_info(d, virq + i, i, &bcm2836_arm_irqchip_ipi, 211 211 d->host_data, 212 - handle_percpu_devid_fasteoi_ipi, 212 + handle_percpu_devid_irq, 213 213 NULL, NULL); 214 214 } 215 215
-165
drivers/irqchip/irq-eznps.c
··· 1 - /* 2 - * Copyright (c) 2016, Mellanox Technologies. All rights reserved. 3 - * 4 - * This software is available to you under a choice of one of two 5 - * licenses. You may choose to be licensed under the terms of the GNU 6 - * General Public License (GPL) Version 2, available from the file 7 - * COPYING in the main directory of this source tree, or the 8 - * OpenIB.org BSD license below: 9 - * 10 - * Redistribution and use in source and binary forms, with or 11 - * without modification, are permitted provided that the following 12 - * conditions are met: 13 - * 14 - * - Redistributions of source code must retain the above 15 - * copyright notice, this list of conditions and the following 16 - * disclaimer. 17 - * 18 - * - Redistributions in binary form must reproduce the above 19 - * copyright notice, this list of conditions and the following 20 - * disclaimer in the documentation and/or other materials 21 - * provided with the distribution. 22 - * 23 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 - * SOFTWARE. 31 - */ 32 - 33 - #include <linux/interrupt.h> 34 - #include <linux/module.h> 35 - #include <linux/of.h> 36 - #include <linux/irq.h> 37 - #include <linux/irqdomain.h> 38 - #include <linux/irqchip.h> 39 - #include <soc/nps/common.h> 40 - 41 - #define NPS_NR_CPU_IRQS 8 /* number of interrupt lines of NPS400 CPU */ 42 - #define NPS_TIMER0_IRQ 3 43 - 44 - /* 45 - * NPS400 core includes an Interrupt Controller (IC) support. 46 - * All cores can deactivate level irqs at first level control 47 - * at cores mesh layer called MTM. 48 - * For devices out side chip e.g. uart, network there is another 49 - * level called Global Interrupt Manager (GIM). 50 - * This second level can control level and edge interrupt. 51 - * 52 - * NOTE: AUX_IENABLE and CTOP_AUX_IACK are auxiliary registers 53 - * with private HW copy per CPU. 54 - */ 55 - 56 - static void nps400_irq_mask(struct irq_data *irqd) 57 - { 58 - unsigned int ienb; 59 - unsigned int irq = irqd_to_hwirq(irqd); 60 - 61 - ienb = read_aux_reg(AUX_IENABLE); 62 - ienb &= ~(1 << irq); 63 - write_aux_reg(AUX_IENABLE, ienb); 64 - } 65 - 66 - static void nps400_irq_unmask(struct irq_data *irqd) 67 - { 68 - unsigned int ienb; 69 - unsigned int irq = irqd_to_hwirq(irqd); 70 - 71 - ienb = read_aux_reg(AUX_IENABLE); 72 - ienb |= (1 << irq); 73 - write_aux_reg(AUX_IENABLE, ienb); 74 - } 75 - 76 - static void nps400_irq_eoi_global(struct irq_data *irqd) 77 - { 78 - unsigned int __maybe_unused irq = irqd_to_hwirq(irqd); 79 - 80 - write_aux_reg(CTOP_AUX_IACK, 1 << irq); 81 - 82 - /* Don't ack GIC before all device access attempts are done */ 83 - mb(); 84 - 85 - nps_ack_gic(); 86 - } 87 - 88 - static void nps400_irq_ack(struct irq_data *irqd) 89 - { 90 - unsigned int __maybe_unused irq = irqd_to_hwirq(irqd); 91 - 92 - write_aux_reg(CTOP_AUX_IACK, 1 << irq); 93 - } 94 - 95 - static struct irq_chip nps400_irq_chip_fasteoi = { 96 - .name = "NPS400 IC Global", 97 - .irq_mask = nps400_irq_mask, 98 - .irq_unmask = nps400_irq_unmask, 99 - .irq_eoi = nps400_irq_eoi_global, 100 - }; 101 - 102 - static struct irq_chip nps400_irq_chip_percpu = { 103 - .name = "NPS400 IC", 104 - .irq_mask = nps400_irq_mask, 105 - .irq_unmask = nps400_irq_unmask, 106 - .irq_ack = nps400_irq_ack, 107 - }; 108 - 109 - static int nps400_irq_map(struct irq_domain *d, unsigned int virq, 110 - irq_hw_number_t hw) 111 - { 112 - switch (hw) { 113 - case NPS_TIMER0_IRQ: 114 - #ifdef CONFIG_SMP 115 - case NPS_IPI_IRQ: 116 - #endif 117 - irq_set_percpu_devid(virq); 118 - irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu, 119 - handle_percpu_devid_irq); 120 - break; 121 - default: 122 - irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi, 123 - handle_fasteoi_irq); 124 - break; 125 - } 126 - 127 - return 0; 128 - } 129 - 130 - static const struct irq_domain_ops nps400_irq_ops = { 131 - .xlate = irq_domain_xlate_onecell, 132 - .map = nps400_irq_map, 133 - }; 134 - 135 - static int __init nps400_of_init(struct device_node *node, 136 - struct device_node *parent) 137 - { 138 - struct irq_domain *nps400_root_domain; 139 - 140 - if (parent) { 141 - pr_err("DeviceTree incore ic not a root irq controller\n"); 142 - return -EINVAL; 143 - } 144 - 145 - nps400_root_domain = irq_domain_add_linear(node, NPS_NR_CPU_IRQS, 146 - &nps400_irq_ops, NULL); 147 - 148 - if (!nps400_root_domain) { 149 - pr_err("nps400 root irq domain not avail\n"); 150 - return -ENOMEM; 151 - } 152 - 153 - /* 154 - * Needed for primary domain lookup to succeed 155 - * This is a primary irqchip, and can never have a parent 156 - */ 157 - irq_set_default_host(nps400_root_domain); 158 - 159 - #ifdef CONFIG_SMP 160 - irq_create_mapping(nps400_root_domain, NPS_IPI_IRQ); 161 - #endif 162 - 163 - return 0; 164 - } 165 - IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
+8 -3
drivers/irqchip/irq-gic-v3-its-pci-msi.c
··· 67 67 /* 68 68 * If pdev is downstream of any aliasing bridges, take an upper 69 69 * bound of how many other vectors could map to the same DevID. 70 + * Also tell the ITS that the signalling will come from a proxy 71 + * device, and that special allocation rules apply. 70 72 */ 71 73 pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev); 72 - if (alias_dev != pdev && alias_dev->subordinate) 73 - pci_walk_bus(alias_dev->subordinate, its_pci_msi_vec_count, 74 - &alias_count); 74 + if (alias_dev != pdev) { 75 + if (alias_dev->subordinate) 76 + pci_walk_bus(alias_dev->subordinate, 77 + its_pci_msi_vec_count, &alias_count); 78 + info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE; 79 + } 75 80 76 81 /* ITS specific DeviceID, as the core ITS ignores dev. */ 77 82 info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
+4 -1
drivers/irqchip/irq-gic-v3-its.c
··· 3487 3487 goto out; 3488 3488 } 3489 3489 3490 + if (info->flags & MSI_ALLOC_FLAGS_PROXY_DEVICE) 3491 + its_dev->shared = true; 3492 + 3490 3493 pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec)); 3491 3494 out: 3492 3495 mutex_unlock(&its->dev_alloc_lock); ··· 3811 3808 WARN_ON_ONCE(readq_relaxed_poll_timeout_atomic(vlpi_base + GICR_VPENDBASER, 3812 3809 val, 3813 3810 !(val & GICR_VPENDBASER_Dirty), 3814 - 10, 500)); 3811 + 1, 500)); 3815 3812 } 3816 3813 3817 3814 static void its_vpe_schedule(struct its_vpe *vpe)
-6
drivers/irqchip/irq-gic-v3.c
··· 1302 1302 1303 1303 switch (__get_intid_range(hw)) { 1304 1304 case SGI_RANGE: 1305 - irq_set_percpu_devid(irq); 1306 - irq_domain_set_info(d, irq, hw, chip, d->host_data, 1307 - handle_percpu_devid_fasteoi_ipi, 1308 - NULL, NULL); 1309 - break; 1310 - 1311 1305 case PPI_RANGE: 1312 1306 case EPPI_RANGE: 1313 1307 irq_set_percpu_devid(irq);
+2 -8
drivers/irqchip/irq-gic.c
··· 973 973 /* 974 974 * gic_get_sgir_physaddr - get the physical address for the SGI register 975 975 * 976 - * REturn the physical address of the SGI register to be used 976 + * Return the physical address of the SGI register to be used 977 977 * by some early assembly code when the kernel is not yet available. 978 978 */ 979 979 static unsigned long gic_dist_physaddr; ··· 1005 1005 struct irq_data *irqd = irq_desc_get_irq_data(irq_to_desc(irq)); 1006 1006 1007 1007 switch (hw) { 1008 - case 0 ... 15: 1009 - irq_set_percpu_devid(irq); 1010 - irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data, 1011 - handle_percpu_devid_fasteoi_ipi, 1012 - NULL, NULL); 1013 - break; 1014 - case 16 ... 31: 1008 + case 0 ... 31: 1015 1009 irq_set_percpu_devid(irq); 1016 1010 irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data, 1017 1011 handle_percpu_devid_irq, NULL, NULL);
+1 -5
drivers/irqchip/irq-hip04.c
··· 296 296 static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq, 297 297 irq_hw_number_t hw) 298 298 { 299 - if (hw < 16) { 300 - irq_set_percpu_devid(irq); 301 - irq_set_chip_and_handler(irq, &hip04_irq_chip, 302 - handle_percpu_devid_fasteoi_ipi); 303 - } else if (hw < 32) { 299 + if (hw < 32) { 304 300 irq_set_percpu_devid(irq); 305 301 irq_set_chip_and_handler(irq, &hip04_irq_chip, 306 302 handle_percpu_devid_irq);
+3 -4
drivers/irqchip/irq-loongson-htpic.c
··· 59 59 int i; 60 60 61 61 for (i = 0; i < HTINT_NUM_VECTORS; i++) { 62 - uint32_t val; 63 - 64 62 /* Disable all HT Vectors */ 65 63 writel(0x0, htpic->base + HTINT_EN_OFF + i * 0x4); 66 - val = readl(htpic->base + i * 0x4); 64 + /* Read back to force write */ 65 + (void) readl(htpic->base + i * 0x4); 67 66 /* Ack all possible pending IRQs */ 68 67 writel(GENMASK(31, 0), htpic->base + i * 0x4); 69 68 } ··· 80 81 .resume = htpic_resume, 81 82 }; 82 83 83 - int __init htpic_of_init(struct device_node *node, struct device_node *parent) 84 + static int __init htpic_of_init(struct device_node *node, struct device_node *parent) 84 85 { 85 86 unsigned int parent_irq[4]; 86 87 int i, err;
+6 -10
drivers/irqchip/irq-ls-extirq.c
··· 18 18 struct ls_extirq_data { 19 19 struct regmap *syscon; 20 20 u32 intpcr; 21 - bool bit_reverse; 21 + bool is_ls1021a_or_ls1043a; 22 22 u32 nirq; 23 23 struct irq_fwspec map[MAXIRQ]; 24 24 }; ··· 30 30 irq_hw_number_t hwirq = data->hwirq; 31 31 u32 value, mask; 32 32 33 - if (priv->bit_reverse) 33 + if (priv->is_ls1021a_or_ls1043a) 34 34 mask = 1U << (31 - hwirq); 35 35 else 36 36 mask = 1U << hwirq; ··· 174 174 if (ret) 175 175 goto out; 176 176 177 - if (of_device_is_compatible(node, "fsl,ls1021a-extirq")) { 178 - u32 revcr; 179 - 180 - ret = regmap_read(priv->syscon, LS1021A_SCFGREVCR, &revcr); 181 - if (ret) 182 - goto out; 183 - priv->bit_reverse = (revcr != 0); 184 - } 177 + priv->is_ls1021a_or_ls1043a = of_device_is_compatible(node, "fsl,ls1021a-extirq") || 178 + of_device_is_compatible(node, "fsl,ls1043a-extirq"); 185 179 186 180 domain = irq_domain_add_hierarchy(parent_domain, 0, priv->nirq, node, 187 181 &extirq_domain_ops, priv); ··· 189 195 } 190 196 191 197 IRQCHIP_DECLARE(ls1021a_extirq, "fsl,ls1021a-extirq", ls_extirq_of_init); 198 + IRQCHIP_DECLARE(ls1043a_extirq, "fsl,ls1043a-extirq", ls_extirq_of_init); 199 + IRQCHIP_DECLARE(ls1088a_extirq, "fsl,ls1088a-extirq", ls_extirq_of_init);
+122 -22
drivers/irqchip/irq-mscc-ocelot.c
··· 12 12 #include <linux/irqchip/chained_irq.h> 13 13 #include <linux/interrupt.h> 14 14 15 - #define ICPU_CFG_INTR_INTR_STICKY 0x10 16 - #define ICPU_CFG_INTR_INTR_ENA 0x18 17 - #define ICPU_CFG_INTR_INTR_ENA_CLR 0x1c 18 - #define ICPU_CFG_INTR_INTR_ENA_SET 0x20 19 - #define ICPU_CFG_INTR_DST_INTR_IDENT(x) (0x38 + 0x4 * (x)) 20 - #define ICPU_CFG_INTR_INTR_TRIGGER(x) (0x5c + 0x4 * (x)) 15 + #define ICPU_CFG_INTR_DST_INTR_IDENT(_p, x) ((_p)->reg_off_ident + 0x4 * (x)) 16 + #define ICPU_CFG_INTR_INTR_TRIGGER(_p, x) ((_p)->reg_off_trigger + 0x4 * (x)) 21 17 22 - #define OCELOT_NR_IRQ 24 18 + #define FLAGS_HAS_TRIGGER BIT(0) 19 + #define FLAGS_NEED_INIT_ENABLE BIT(1) 20 + 21 + struct chip_props { 22 + u8 flags; 23 + u8 reg_off_sticky; 24 + u8 reg_off_ena; 25 + u8 reg_off_ena_clr; 26 + u8 reg_off_ena_set; 27 + u8 reg_off_ident; 28 + u8 reg_off_trigger; 29 + u8 reg_off_ena_irq0; 30 + u8 n_irq; 31 + }; 32 + 33 + static struct chip_props ocelot_props = { 34 + .flags = FLAGS_HAS_TRIGGER, 35 + .reg_off_sticky = 0x10, 36 + .reg_off_ena = 0x18, 37 + .reg_off_ena_clr = 0x1c, 38 + .reg_off_ena_set = 0x20, 39 + .reg_off_ident = 0x38, 40 + .reg_off_trigger = 0x5c, 41 + .n_irq = 24, 42 + }; 43 + 44 + static struct chip_props serval_props = { 45 + .flags = FLAGS_HAS_TRIGGER, 46 + .reg_off_sticky = 0xc, 47 + .reg_off_ena = 0x14, 48 + .reg_off_ena_clr = 0x18, 49 + .reg_off_ena_set = 0x1c, 50 + .reg_off_ident = 0x20, 51 + .reg_off_trigger = 0x4, 52 + .n_irq = 24, 53 + }; 54 + 55 + static struct chip_props luton_props = { 56 + .flags = FLAGS_NEED_INIT_ENABLE, 57 + .reg_off_sticky = 0, 58 + .reg_off_ena = 0x4, 59 + .reg_off_ena_clr = 0x8, 60 + .reg_off_ena_set = 0xc, 61 + .reg_off_ident = 0x18, 62 + .reg_off_ena_irq0 = 0x14, 63 + .n_irq = 28, 64 + }; 65 + 66 + static struct chip_props jaguar2_props = { 67 + .flags = FLAGS_HAS_TRIGGER, 68 + .reg_off_sticky = 0x10, 69 + .reg_off_ena = 0x18, 70 + .reg_off_ena_clr = 0x1c, 71 + .reg_off_ena_set = 0x20, 72 + .reg_off_ident = 0x38, 73 + .reg_off_trigger = 0x5c, 74 + .n_irq = 29, 75 + }; 23 76 24 77 static void ocelot_irq_unmask(struct irq_data *data) 25 78 { 26 79 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); 80 + struct irq_domain *d = data->domain; 81 + struct chip_props *p = d->host_data; 27 82 struct irq_chip_type *ct = irq_data_get_chip_type(data); 28 83 unsigned int mask = data->mask; 29 84 u32 val; 30 85 31 86 irq_gc_lock(gc); 32 - val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(0)) | 33 - irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(1)); 87 + val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(p, 0)) | 88 + irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(p, 1)); 34 89 if (!(val & mask)) 35 - irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_STICKY); 90 + irq_reg_writel(gc, mask, p->reg_off_sticky); 36 91 37 92 *ct->mask_cache &= ~mask; 38 - irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_ENA_SET); 93 + irq_reg_writel(gc, mask, p->reg_off_ena_set); 39 94 irq_gc_unlock(gc); 40 95 } 41 96 ··· 98 43 { 99 44 struct irq_chip *chip = irq_desc_get_chip(desc); 100 45 struct irq_domain *d = irq_desc_get_handler_data(desc); 46 + struct chip_props *p = d->host_data; 101 47 struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0); 102 - u32 reg = irq_reg_readl(gc, ICPU_CFG_INTR_DST_INTR_IDENT(0)); 48 + u32 reg = irq_reg_readl(gc, ICPU_CFG_INTR_DST_INTR_IDENT(p, 0)); 103 49 104 50 chained_irq_enter(chip, desc); 105 51 ··· 114 58 chained_irq_exit(chip, desc); 115 59 } 116 60 117 - static int __init ocelot_irq_init(struct device_node *node, 118 - struct device_node *parent) 61 + static int __init vcoreiii_irq_init(struct device_node *node, 62 + struct device_node *parent, 63 + struct chip_props *p) 119 64 { 120 65 struct irq_domain *domain; 121 66 struct irq_chip_generic *gc; ··· 126 69 if (!parent_irq) 127 70 return -EINVAL; 128 71 129 - domain = irq_domain_add_linear(node, OCELOT_NR_IRQ, 72 + domain = irq_domain_add_linear(node, p->n_irq, 130 73 &irq_generic_chip_ops, NULL); 131 74 if (!domain) { 132 75 pr_err("%pOFn: unable to add irq domain\n", node); 133 76 return -ENOMEM; 134 77 } 135 78 136 - ret = irq_alloc_domain_generic_chips(domain, OCELOT_NR_IRQ, 1, 79 + ret = irq_alloc_domain_generic_chips(domain, p->n_irq, 1, 137 80 "icpu", handle_level_irq, 138 81 0, 0, 0); 139 82 if (ret) { ··· 149 92 goto err_gc_free; 150 93 } 151 94 152 - gc->chip_types[0].regs.ack = ICPU_CFG_INTR_INTR_STICKY; 153 - gc->chip_types[0].regs.mask = ICPU_CFG_INTR_INTR_ENA_CLR; 154 95 gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; 155 - gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; 156 - gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask; 96 + gc->chip_types[0].regs.ack = p->reg_off_sticky; 97 + if (p->flags & FLAGS_HAS_TRIGGER) { 98 + gc->chip_types[0].regs.mask = p->reg_off_ena_clr; 99 + gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask; 100 + gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; 101 + } else { 102 + gc->chip_types[0].regs.enable = p->reg_off_ena_set; 103 + gc->chip_types[0].regs.disable = p->reg_off_ena_clr; 104 + gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg; 105 + gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg; 106 + } 157 107 158 108 /* Mask and ack all interrupts */ 159 - irq_reg_writel(gc, 0, ICPU_CFG_INTR_INTR_ENA); 160 - irq_reg_writel(gc, 0xffffffff, ICPU_CFG_INTR_INTR_STICKY); 109 + irq_reg_writel(gc, 0, p->reg_off_ena); 110 + irq_reg_writel(gc, 0xffffffff, p->reg_off_sticky); 161 111 112 + /* Overall init */ 113 + if (p->flags & FLAGS_NEED_INIT_ENABLE) 114 + irq_reg_writel(gc, BIT(0), p->reg_off_ena_irq0); 115 + 116 + domain->host_data = p; 162 117 irq_set_chained_handler_and_data(parent_irq, ocelot_irq_handler, 163 118 domain); 164 119 ··· 184 115 185 116 return ret; 186 117 } 118 + 119 + static int __init ocelot_irq_init(struct device_node *node, 120 + struct device_node *parent) 121 + { 122 + return vcoreiii_irq_init(node, parent, &ocelot_props); 123 + } 124 + 187 125 IRQCHIP_DECLARE(ocelot_icpu, "mscc,ocelot-icpu-intr", ocelot_irq_init); 126 + 127 + static int __init serval_irq_init(struct device_node *node, 128 + struct device_node *parent) 129 + { 130 + return vcoreiii_irq_init(node, parent, &serval_props); 131 + } 132 + 133 + IRQCHIP_DECLARE(serval_icpu, "mscc,serval-icpu-intr", serval_irq_init); 134 + 135 + static int __init luton_irq_init(struct device_node *node, 136 + struct device_node *parent) 137 + { 138 + return vcoreiii_irq_init(node, parent, &luton_props); 139 + } 140 + 141 + IRQCHIP_DECLARE(luton_icpu, "mscc,luton-icpu-intr", luton_irq_init); 142 + 143 + static int __init jaguar2_irq_init(struct device_node *node, 144 + struct device_node *parent) 145 + { 146 + return vcoreiii_irq_init(node, parent, &jaguar2_props); 147 + } 148 + 149 + IRQCHIP_DECLARE(jaguar2_icpu, "mscc,jaguar2-icpu-intr", jaguar2_irq_init);
+1 -1
drivers/irqchip/irq-ti-sci-inta.c
··· 726 726 INIT_LIST_HEAD(&inta->vint_list); 727 727 mutex_init(&inta->vint_mutex); 728 728 729 - dev_info(dev, "Interrupt Aggregator domain %d created\n", pdev->id); 729 + dev_info(dev, "Interrupt Aggregator domain %d created\n", inta->ti_sci_id); 730 730 731 731 return 0; 732 732 }
+7 -7
drivers/irqchip/irq-ti-sci-intr.c
··· 129 129 * @virq: Corresponding Linux virtual IRQ number 130 130 * @hwirq: Corresponding hwirq for the IRQ within this IRQ domain 131 131 * 132 - * Returns parent irq if all went well else appropriate error pointer. 132 + * Returns intr output irq if all went well else appropriate error pointer. 133 133 */ 134 134 static int ti_sci_intr_alloc_parent_irq(struct irq_domain *domain, 135 135 unsigned int virq, u32 hwirq) ··· 173 173 if (err) 174 174 goto err_msg; 175 175 176 - return p_hwirq; 176 + return out_irq; 177 177 178 178 err_msg: 179 179 irq_domain_free_irqs_parent(domain, virq, 1); ··· 198 198 struct irq_fwspec *fwspec = data; 199 199 unsigned long hwirq; 200 200 unsigned int flags; 201 - int err, p_hwirq; 201 + int err, out_irq; 202 202 203 203 err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &flags); 204 204 if (err) 205 205 return err; 206 206 207 - p_hwirq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq); 208 - if (p_hwirq < 0) 209 - return p_hwirq; 207 + out_irq = ti_sci_intr_alloc_parent_irq(domain, virq, hwirq); 208 + if (out_irq < 0) 209 + return out_irq; 210 210 211 211 irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 212 212 &ti_sci_intr_irq_chip, 213 - (void *)(uintptr_t)p_hwirq); 213 + (void *)(uintptr_t)out_irq); 214 214 215 215 return 0; 216 216 }
+20 -1
drivers/irqchip/qcom-pdc.c
··· 159 159 { 160 160 int pin_out = d->hwirq; 161 161 enum pdc_irq_config_bits pdc_type; 162 + enum pdc_irq_config_bits old_pdc_type; 163 + int ret; 162 164 163 165 if (pin_out == GPIO_NO_WAKE_IRQ) 164 166 return 0; ··· 189 187 return -EINVAL; 190 188 } 191 189 190 + old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out); 192 191 pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type); 193 192 194 - return irq_chip_set_type_parent(d, type); 193 + ret = irq_chip_set_type_parent(d, type); 194 + if (ret) 195 + return ret; 196 + 197 + /* 198 + * When we change types the PDC can give a phantom interrupt. 199 + * Clear it. Specifically the phantom shows up when reconfiguring 200 + * polarity of interrupt without changing the state of the signal 201 + * but let's be consistent and clear it always. 202 + * 203 + * Doing this works because we have IRQCHIP_SET_TYPE_MASKED so the 204 + * interrupt will be cleared before the rest of the system sees it. 205 + */ 206 + if (old_pdc_type != pdc_type) 207 + irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false); 208 + 209 + return 0; 195 210 } 196 211 197 212 static struct irq_chip qcom_pdc_gic_chip = {
+5 -1
include/asm-generic/hardirq.h
··· 7 7 8 8 typedef struct { 9 9 unsigned int __softirq_pending; 10 + #ifdef ARCH_WANTS_NMI_IRQSTAT 11 + unsigned int __nmi_count; 12 + #endif 10 13 } ____cacheline_aligned irq_cpustat_t; 11 14 12 - #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 15 + DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat); 16 + 13 17 #include <linux/irq.h> 14 18 15 19 #ifndef ack_bad_irq
+4
include/asm-generic/msi.h
··· 24 24 typedef struct msi_alloc_info { 25 25 struct msi_desc *desc; 26 26 irq_hw_number_t hwirq; 27 + unsigned long flags; 27 28 union { 28 29 unsigned long ul; 29 30 void *ptr; 30 31 } scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS]; 31 32 } msi_alloc_info_t; 33 + 34 + /* Device generating MSIs is proxying for another device */ 35 + #define MSI_ALLOC_FLAGS_PROXY_DEVICE (1UL << 0) 32 36 33 37 #define GENERIC_MSI_DOMAIN_OPS 1 34 38
+2 -2
include/linux/hardirq.h
··· 32 32 */ 33 33 #define __irq_enter() \ 34 34 do { \ 35 - account_irq_enter_time(current); \ 36 35 preempt_count_add(HARDIRQ_OFFSET); \ 37 36 lockdep_hardirq_enter(); \ 37 + account_hardirq_enter(current); \ 38 38 } while (0) 39 39 40 40 /* ··· 62 62 */ 63 63 #define __irq_exit() \ 64 64 do { \ 65 + account_hardirq_exit(current); \ 65 66 lockdep_hardirq_exit(); \ 66 - account_irq_exit_time(current); \ 67 67 preempt_count_sub(HARDIRQ_OFFSET); \ 68 68 } while (0) 69 69
+8
include/linux/interrupt.h
··· 352 352 extern int irq_select_affinity(unsigned int irq); 353 353 354 354 extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m); 355 + extern int irq_update_affinity_desc(unsigned int irq, 356 + struct irq_affinity_desc *affinity); 355 357 356 358 extern int 357 359 irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); ··· 385 383 386 384 static inline int irq_set_affinity_hint(unsigned int irq, 387 385 const struct cpumask *m) 386 + { 387 + return -EINVAL; 388 + } 389 + 390 + static inline int irq_update_affinity_desc(unsigned int irq, 391 + struct irq_affinity_desc *affinity) 388 392 { 389 393 return -EINVAL; 390 394 }
+7
include/linux/ioport.h
··· 307 307 struct resource *request_free_mem_region(struct resource *base, 308 308 unsigned long size, const char *name); 309 309 310 + static inline void irqresource_disabled(struct resource *res, u32 irq) 311 + { 312 + res->start = irq; 313 + res->end = irq; 314 + res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; 315 + } 316 + 310 317 #ifdef CONFIG_IO_STRICT_DEVMEM 311 318 void revoke_devmem(struct resource *res); 312 319 #else
-16
include/linux/irq.h
··· 647 647 */ 648 648 extern void handle_level_irq(struct irq_desc *desc); 649 649 extern void handle_fasteoi_irq(struct irq_desc *desc); 650 - extern void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc); 651 650 extern void handle_edge_irq(struct irq_desc *desc); 652 651 extern void handle_edge_eoi_irq(struct irq_desc *desc); 653 652 extern void handle_simple_irq(struct irq_desc *desc); ··· 952 953 { 953 954 irq_free_descs(irq, 1); 954 955 } 955 - 956 - #ifdef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ 957 - unsigned int irq_alloc_hwirqs(int cnt, int node); 958 - static inline unsigned int irq_alloc_hwirq(int node) 959 - { 960 - return irq_alloc_hwirqs(1, node); 961 - } 962 - void irq_free_hwirqs(unsigned int from, int cnt); 963 - static inline void irq_free_hwirq(unsigned int irq) 964 - { 965 - return irq_free_hwirqs(irq, 1); 966 - } 967 - int arch_setup_hwirq(unsigned int irq, int node); 968 - void arch_teardown_hwirq(unsigned int irq); 969 - #endif 970 956 971 957 #ifdef CONFIG_GENERIC_IRQ_LEGACY 972 958 void irq_init_desc(unsigned int irq);
-28
include/linux/irq_cpustat.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef __irq_cpustat_h 3 - #define __irq_cpustat_h 4 - 5 - /* 6 - * Contains default mappings for irq_cpustat_t, used by almost every 7 - * architecture. Some arch (like s390) have per cpu hardware pages and 8 - * they define their own mappings for irq_stat. 9 - * 10 - * Keith Owens <kaos@ocs.com.au> July 2000. 11 - */ 12 - 13 - 14 - /* 15 - * Simple wrappers reducing source bloat. Define all irq_stat fields 16 - * here, even ones that are arch dependent. That way we get common 17 - * definitions instead of differing sets for each arch. 18 - */ 19 - 20 - #ifndef __ARCH_IRQ_STAT 21 - DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat); /* defined in asm/hardirq.h */ 22 - #define __IRQ_STAT(cpu, member) (per_cpu(irq_stat.member, cpu)) 23 - #endif 24 - 25 - /* arch dependent irq_stat fields */ 26 - #define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) /* i386 */ 27 - 28 - #endif /* __irq_cpustat_h */
+7 -3
include/linux/irqdomain.h
··· 37 37 #include <linux/radix-tree.h> 38 38 39 39 struct device_node; 40 + struct fwnode_handle; 40 41 struct irq_domain; 41 - struct of_device_id; 42 42 struct irq_chip; 43 43 struct irq_data; 44 44 struct cpumask; ··· 271 271 irq_hw_number_t first_hwirq, 272 272 const struct irq_domain_ops *ops, 273 273 void *host_data); 274 + struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, 275 + unsigned int size, 276 + unsigned int first_irq, 277 + irq_hw_number_t first_hwirq, 278 + const struct irq_domain_ops *ops, 279 + void *host_data); 274 280 extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, 275 281 enum irq_domain_bus_token bus_token); 276 282 extern bool irq_domain_check_msi_remap(void); ··· 387 381 extern void irq_domain_associate_many(struct irq_domain *domain, 388 382 unsigned int irq_base, 389 383 irq_hw_number_t hwirq_base, int count); 390 - extern void irq_domain_disassociate(struct irq_domain *domain, 391 - unsigned int irq); 392 384 393 385 extern unsigned int irq_create_mapping_affinity(struct irq_domain *host, 394 386 irq_hw_number_t hwirq,
+6
include/linux/platform_device.h
··· 15 15 #define PLATFORM_DEVID_NONE (-1) 16 16 #define PLATFORM_DEVID_AUTO (-2) 17 17 18 + struct irq_affinity; 18 19 struct mfd_cell; 19 20 struct property_entry; 20 21 struct platform_device_id; ··· 74 73 extern int platform_get_irq(struct platform_device *, unsigned int); 75 74 extern int platform_get_irq_optional(struct platform_device *, unsigned int); 76 75 extern int platform_irq_count(struct platform_device *); 76 + extern int devm_platform_get_irqs_affinity(struct platform_device *dev, 77 + struct irq_affinity *affd, 78 + unsigned int minvec, 79 + unsigned int maxvec, 80 + int **irqs); 77 81 extern struct resource *platform_get_resource_byname(struct platform_device *, 78 82 unsigned int, 79 83 const char *);
+16 -14
include/linux/preempt.h
··· 77 77 /* preempt_count() and related functions, depends on PREEMPT_NEED_RESCHED */ 78 78 #include <asm/preempt.h> 79 79 80 + #define nmi_count() (preempt_count() & NMI_MASK) 80 81 #define hardirq_count() (preempt_count() & HARDIRQ_MASK) 81 82 #define softirq_count() (preempt_count() & SOFTIRQ_MASK) 82 - #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \ 83 - | NMI_MASK)) 83 + #define irq_count() (nmi_count() | hardirq_count() | softirq_count()) 84 84 85 85 /* 86 - * Are we doing bottom half or hardware interrupt processing? 86 + * Macros to retrieve the current execution context: 87 87 * 88 - * in_irq() - We're in (hard) IRQ context 88 + * in_nmi() - We're in NMI context 89 + * in_hardirq() - We're in hard IRQ context 90 + * in_serving_softirq() - We're in softirq context 91 + * in_task() - We're in task context 92 + */ 93 + #define in_nmi() (nmi_count()) 94 + #define in_hardirq() (hardirq_count()) 95 + #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) 96 + #define in_task() (!(in_nmi() | in_hardirq() | in_serving_softirq())) 97 + 98 + /* 99 + * The following macros are deprecated and should not be used in new code: 100 + * in_irq() - Obsolete version of in_hardirq() 89 101 * in_softirq() - We have BH disabled, or are processing softirqs 90 102 * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled 91 - * in_serving_softirq() - We're in softirq context 92 - * in_nmi() - We're in NMI context 93 - * in_task() - We're in task context 94 - * 95 - * Note: due to the BH disabled confusion: in_softirq(),in_interrupt() really 96 - * should not be used in new code. 97 103 */ 98 104 #define in_irq() (hardirq_count()) 99 105 #define in_softirq() (softirq_count()) 100 106 #define in_interrupt() (irq_count()) 101 - #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) 102 - #define in_nmi() (preempt_count() & NMI_MASK) 103 - #define in_task() (!(preempt_count() & \ 104 - (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET))) 105 107 106 108 /* 107 109 * The preempt_count offset after preempt_disable();
+26 -16
include/linux/vtime.h
··· 83 83 #endif 84 84 85 85 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 86 - extern void vtime_account_irq_enter(struct task_struct *tsk); 87 - static inline void vtime_account_irq_exit(struct task_struct *tsk) 88 - { 89 - /* On hard|softirq exit we always account to hard|softirq cputime */ 90 - vtime_account_kernel(tsk); 91 - } 86 + extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); 87 + extern void vtime_account_softirq(struct task_struct *tsk); 88 + extern void vtime_account_hardirq(struct task_struct *tsk); 92 89 extern void vtime_flush(struct task_struct *tsk); 93 90 #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 94 - static inline void vtime_account_irq_enter(struct task_struct *tsk) { } 95 - static inline void vtime_account_irq_exit(struct task_struct *tsk) { } 91 + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } 92 + static inline void vtime_account_softirq(struct task_struct *tsk) { } 93 + static inline void vtime_account_hardirq(struct task_struct *tsk) { } 96 94 static inline void vtime_flush(struct task_struct *tsk) { } 97 95 #endif 98 96 99 97 100 98 #ifdef CONFIG_IRQ_TIME_ACCOUNTING 101 - extern void irqtime_account_irq(struct task_struct *tsk); 99 + extern void irqtime_account_irq(struct task_struct *tsk, unsigned int offset); 102 100 #else 103 - static inline void irqtime_account_irq(struct task_struct *tsk) { } 101 + static inline void irqtime_account_irq(struct task_struct *tsk, unsigned int offset) { } 104 102 #endif 105 103 106 - static inline void account_irq_enter_time(struct task_struct *tsk) 104 + static inline void account_softirq_enter(struct task_struct *tsk) 107 105 { 108 - vtime_account_irq_enter(tsk); 109 - irqtime_account_irq(tsk); 106 + vtime_account_irq(tsk, SOFTIRQ_OFFSET); 107 + irqtime_account_irq(tsk, SOFTIRQ_OFFSET); 110 108 } 111 109 112 - static inline void account_irq_exit_time(struct task_struct *tsk) 110 + static inline void account_softirq_exit(struct task_struct *tsk) 113 111 { 114 - vtime_account_irq_exit(tsk); 115 - irqtime_account_irq(tsk); 112 + vtime_account_softirq(tsk); 113 + irqtime_account_irq(tsk, 0); 114 + } 115 + 116 + static inline void account_hardirq_enter(struct task_struct *tsk) 117 + { 118 + vtime_account_irq(tsk, HARDIRQ_OFFSET); 119 + irqtime_account_irq(tsk, HARDIRQ_OFFSET); 120 + } 121 + 122 + static inline void account_hardirq_exit(struct task_struct *tsk) 123 + { 124 + vtime_account_hardirq(tsk); 125 + irqtime_account_irq(tsk, 0); 116 126 } 117 127 118 128 #endif /* _LINUX_KERNEL_VTIME_H */
-5
kernel/irq/Kconfig
··· 26 26 config GENERIC_IRQ_EFFECTIVE_AFF_MASK 27 27 bool 28 28 29 - # Facility to allocate a hardware interrupt. This is legacy support 30 - # and should not be used in new code. Use irq domains instead. 31 - config GENERIC_IRQ_LEGACY_ALLOC_HWIRQ 32 - bool 33 - 34 29 # Support for delayed migration from interrupt context 35 30 config GENERIC_PENDING_IRQ 36 31 bool
+1 -28
kernel/irq/chip.c
··· 61 61 EXPORT_SYMBOL(irq_set_chip); 62 62 63 63 /** 64 - * irq_set_type - set the irq trigger type for an irq 64 + * irq_set_irq_type - set the irq trigger type for an irq 65 65 * @irq: irq number 66 66 * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h 67 67 */ ··· 942 942 943 943 if (chip->irq_eoi) 944 944 chip->irq_eoi(&desc->irq_data); 945 - } 946 - 947 - /** 948 - * handle_percpu_devid_fasteoi_ipi - Per CPU local IPI handler with per cpu 949 - * dev ids 950 - * @desc: the interrupt description structure for this irq 951 - * 952 - * The biggest difference with the IRQ version is that the interrupt is 953 - * EOIed early, as the IPI could result in a context switch, and we need to 954 - * make sure the IPI can fire again. We also assume that the arch code has 955 - * registered an action. If not, we are positively doomed. 956 - */ 957 - void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc) 958 - { 959 - struct irq_chip *chip = irq_desc_get_chip(desc); 960 - struct irqaction *action = desc->action; 961 - unsigned int irq = irq_desc_get_irq(desc); 962 - irqreturn_t res; 963 - 964 - __kstat_incr_irqs_this_cpu(desc); 965 - 966 - if (chip->irq_eoi) 967 - chip->irq_eoi(&desc->irq_data); 968 - 969 - trace_irq_handler_entry(irq, action); 970 - res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); 971 - trace_irq_handler_exit(irq, action, res); 972 945 } 973 946 974 947 /**
+1 -1
kernel/irq/generic-chip.c
··· 269 269 } 270 270 271 271 /** 272 - * __irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain 272 + * __irq_alloc_domain_generic_chips - Allocate generic chips for an irq domain 273 273 * @d: irq domain for which to allocate chips 274 274 * @irqs_per_chip: Number of interrupts each chip handles (max 32) 275 275 * @num_ct: Number of irq_chip_type instances associated with this
-51
kernel/irq/irqdesc.c
··· 810 810 } 811 811 EXPORT_SYMBOL_GPL(__irq_alloc_descs); 812 812 813 - #ifdef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ 814 - /** 815 - * irq_alloc_hwirqs - Allocate an irq descriptor and initialize the hardware 816 - * @cnt: number of interrupts to allocate 817 - * @node: node on which to allocate 818 - * 819 - * Returns an interrupt number > 0 or 0, if the allocation fails. 820 - */ 821 - unsigned int irq_alloc_hwirqs(int cnt, int node) 822 - { 823 - int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL, NULL); 824 - 825 - if (irq < 0) 826 - return 0; 827 - 828 - for (i = irq; cnt > 0; i++, cnt--) { 829 - if (arch_setup_hwirq(i, node)) 830 - goto err; 831 - irq_clear_status_flags(i, _IRQ_NOREQUEST); 832 - } 833 - return irq; 834 - 835 - err: 836 - for (i--; i >= irq; i--) { 837 - irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE); 838 - arch_teardown_hwirq(i); 839 - } 840 - irq_free_descs(irq, cnt); 841 - return 0; 842 - } 843 - EXPORT_SYMBOL_GPL(irq_alloc_hwirqs); 844 - 845 - /** 846 - * irq_free_hwirqs - Free irq descriptor and cleanup the hardware 847 - * @from: Free from irq number 848 - * @cnt: number of interrupts to free 849 - * 850 - */ 851 - void irq_free_hwirqs(unsigned int from, int cnt) 852 - { 853 - int i, j; 854 - 855 - for (i = from, j = cnt; j > 0; i++, j--) { 856 - irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE); 857 - arch_teardown_hwirq(i); 858 - } 859 - irq_free_descs(from, cnt); 860 - } 861 - EXPORT_SYMBOL_GPL(irq_free_hwirqs); 862 - #endif 863 - 864 813 /** 865 814 * irq_get_next_irq - get next allocated irq number 866 815 * @offset: where to start the search
+25 -7
kernel/irq/irqdomain.c
··· 360 360 const struct irq_domain_ops *ops, 361 361 void *host_data) 362 362 { 363 + return irq_domain_create_legacy(of_node_to_fwnode(of_node), size, 364 + first_irq, first_hwirq, ops, host_data); 365 + } 366 + EXPORT_SYMBOL_GPL(irq_domain_add_legacy); 367 + 368 + struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, 369 + unsigned int size, 370 + unsigned int first_irq, 371 + irq_hw_number_t first_hwirq, 372 + const struct irq_domain_ops *ops, 373 + void *host_data) 374 + { 363 375 struct irq_domain *domain; 364 376 365 - domain = __irq_domain_add(of_node_to_fwnode(of_node), first_hwirq + size, 366 - first_hwirq + size, 0, ops, host_data); 377 + domain = __irq_domain_add(fwnode, first_hwirq + size, first_hwirq + size, 0, ops, host_data); 367 378 if (domain) 368 379 irq_domain_associate_many(domain, first_irq, first_hwirq, size); 369 380 370 381 return domain; 371 382 } 372 - EXPORT_SYMBOL_GPL(irq_domain_add_legacy); 383 + EXPORT_SYMBOL_GPL(irq_domain_create_legacy); 373 384 374 385 /** 375 386 * irq_find_matching_fwspec() - Locates a domain for a given fwspec ··· 505 494 } 506 495 } 507 496 508 - void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq) 497 + static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq) 509 498 { 510 499 struct irq_data *irq_data = irq_get_irq_data(irq); 511 500 irq_hw_number_t hwirq; ··· 760 749 { 761 750 int i; 762 751 763 - fwspec->fwnode = np ? &np->fwnode : NULL; 752 + fwspec->fwnode = of_node_to_fwnode(np); 764 753 fwspec->param_count = count; 765 754 766 755 for (i = 0; i < count; i++) ··· 1393 1382 unsigned int irq_base, 1394 1383 unsigned int nr_irqs) 1395 1384 { 1396 - if (domain->ops->free) 1397 - domain->ops->free(domain, irq_base, nr_irqs); 1385 + unsigned int i; 1386 + 1387 + if (!domain->ops->free) 1388 + return; 1389 + 1390 + for (i = 0; i < nr_irqs; i++) { 1391 + if (irq_domain_get_irq_data(domain, irq_base + i)) 1392 + domain->ops->free(domain, irq_base + i, 1); 1393 + } 1398 1394 } 1399 1395 1400 1396 int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
+70
kernel/irq/manage.c
··· 371 371 return ret; 372 372 } 373 373 374 + /** 375 + * irq_update_affinity_desc - Update affinity management for an interrupt 376 + * @irq: The interrupt number to update 377 + * @affinity: Pointer to the affinity descriptor 378 + * 379 + * This interface can be used to configure the affinity management of 380 + * interrupts which have been allocated already. 381 + * 382 + * There are certain limitations on when it may be used - attempts to use it 383 + * for when the kernel is configured for generic IRQ reservation mode (in 384 + * config GENERIC_IRQ_RESERVATION_MODE) will fail, as it may conflict with 385 + * managed/non-managed interrupt accounting. In addition, attempts to use it on 386 + * an interrupt which is already started or which has already been configured 387 + * as managed will also fail, as these mean invalid init state or double init. 388 + */ 389 + int irq_update_affinity_desc(unsigned int irq, 390 + struct irq_affinity_desc *affinity) 391 + { 392 + struct irq_desc *desc; 393 + unsigned long flags; 394 + bool activated; 395 + int ret = 0; 396 + 397 + /* 398 + * Supporting this with the reservation scheme used by x86 needs 399 + * some more thought. Fail it for now. 400 + */ 401 + if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE)) 402 + return -EOPNOTSUPP; 403 + 404 + desc = irq_get_desc_buslock(irq, &flags, 0); 405 + if (!desc) 406 + return -EINVAL; 407 + 408 + /* Requires the interrupt to be shut down */ 409 + if (irqd_is_started(&desc->irq_data)) { 410 + ret = -EBUSY; 411 + goto out_unlock; 412 + } 413 + 414 + /* Interrupts which are already managed cannot be modified */ 415 + if (irqd_affinity_is_managed(&desc->irq_data)) { 416 + ret = -EBUSY; 417 + goto out_unlock; 418 + } 419 + 420 + /* 421 + * Deactivate the interrupt. That's required to undo 422 + * anything an earlier activation has established. 423 + */ 424 + activated = irqd_is_activated(&desc->irq_data); 425 + if (activated) 426 + irq_domain_deactivate_irq(&desc->irq_data); 427 + 428 + if (affinity->is_managed) { 429 + irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED); 430 + irqd_set(&desc->irq_data, IRQD_MANAGED_SHUTDOWN); 431 + } 432 + 433 + cpumask_copy(desc->irq_common_data.affinity, &affinity->mask); 434 + 435 + /* Restore the activation state */ 436 + if (activated) 437 + irq_domain_activate_irq(&desc->irq_data, false); 438 + 439 + out_unlock: 440 + irq_put_desc_busunlock(desc, flags); 441 + return ret; 442 + } 443 + 374 444 int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force) 375 445 { 376 446 struct irq_desc *desc = irq_to_desc(irq);
+17 -19
kernel/sched/cputime.c
··· 44 44 } 45 45 46 46 /* 47 - * Called before incrementing preempt_count on {soft,}irq_enter 47 + * Called after incrementing preempt_count on {soft,}irq_enter 48 48 * and before decrementing preempt_count on {soft,}irq_exit. 49 49 */ 50 - void irqtime_account_irq(struct task_struct *curr) 50 + void irqtime_account_irq(struct task_struct *curr, unsigned int offset) 51 51 { 52 52 struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime); 53 + unsigned int pc; 53 54 s64 delta; 54 55 int cpu; 55 56 ··· 60 59 cpu = smp_processor_id(); 61 60 delta = sched_clock_cpu(cpu) - irqtime->irq_start_time; 62 61 irqtime->irq_start_time += delta; 62 + pc = preempt_count() - offset; 63 63 64 64 /* 65 65 * We do not account for softirq time from ksoftirqd here. ··· 68 66 * in that case, so as not to confuse scheduler with a special task 69 67 * that do not consume any time, but still wants to run. 70 68 */ 71 - if (hardirq_count()) 69 + if (pc & HARDIRQ_MASK) 72 70 irqtime_account_delta(irqtime, delta, CPUTIME_IRQ); 73 - else if (in_serving_softirq() && curr != this_cpu_ksoftirqd()) 71 + else if ((pc & SOFTIRQ_OFFSET) && curr != this_cpu_ksoftirqd()) 74 72 irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ); 75 73 } 76 - EXPORT_SYMBOL_GPL(irqtime_account_irq); 77 74 78 75 static u64 irqtime_tick_accounted(u64 maxtime) 79 76 { ··· 419 418 } 420 419 # endif 421 420 422 - /* 423 - * Archs that account the whole time spent in the idle task 424 - * (outside irq) as idle time can rely on this and just implement 425 - * vtime_account_kernel() and vtime_account_idle(). Archs that 426 - * have other meaning of the idle time (s390 only includes the 427 - * time spent by the CPU when it's in low power mode) must override 428 - * vtime_account(). 429 - */ 430 - #ifndef __ARCH_HAS_VTIME_ACCOUNT 431 - void vtime_account_irq_enter(struct task_struct *tsk) 421 + void vtime_account_irq(struct task_struct *tsk, unsigned int offset) 432 422 { 433 - if (!in_interrupt() && is_idle_task(tsk)) 423 + unsigned int pc = preempt_count() - offset; 424 + 425 + if (pc & HARDIRQ_OFFSET) { 426 + vtime_account_hardirq(tsk); 427 + } else if (pc & SOFTIRQ_OFFSET) { 428 + vtime_account_softirq(tsk); 429 + } else if (!IS_ENABLED(CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE) && 430 + is_idle_task(tsk)) { 434 431 vtime_account_idle(tsk); 435 - else 432 + } else { 436 433 vtime_account_kernel(tsk); 434 + } 437 435 } 438 - EXPORT_SYMBOL_GPL(vtime_account_irq_enter); 439 - #endif /* __ARCH_HAS_VTIME_ACCOUNT */ 440 436 441 437 void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, 442 438 u64 *ut, u64 *st)
+63 -66
kernel/softirq.c
··· 92 92 !__kthread_should_park(tsk); 93 93 } 94 94 95 + #ifdef CONFIG_TRACE_IRQFLAGS 96 + DEFINE_PER_CPU(int, hardirqs_enabled); 97 + DEFINE_PER_CPU(int, hardirq_context); 98 + EXPORT_PER_CPU_SYMBOL_GPL(hardirqs_enabled); 99 + EXPORT_PER_CPU_SYMBOL_GPL(hardirq_context); 100 + #endif 101 + 95 102 /* 96 103 * preempt_count and SOFTIRQ_OFFSET usage: 97 104 * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving ··· 109 102 * softirq and whether we just have bh disabled. 110 103 */ 111 104 112 - /* 113 - * This one is for softirq.c-internal use, 114 - * where hardirqs are disabled legitimately: 115 - */ 116 105 #ifdef CONFIG_TRACE_IRQFLAGS 117 - 118 - DEFINE_PER_CPU(int, hardirqs_enabled); 119 - DEFINE_PER_CPU(int, hardirq_context); 120 - EXPORT_PER_CPU_SYMBOL_GPL(hardirqs_enabled); 121 - EXPORT_PER_CPU_SYMBOL_GPL(hardirq_context); 122 - 106 + /* 107 + * This is for softirq.c-internal use, where hardirqs are disabled 108 + * legitimately: 109 + */ 123 110 void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) 124 111 { 125 112 unsigned long flags; ··· 204 203 } 205 204 EXPORT_SYMBOL(__local_bh_enable_ip); 206 205 206 + static inline void invoke_softirq(void) 207 + { 208 + if (ksoftirqd_running(local_softirq_pending())) 209 + return; 210 + 211 + if (!force_irqthreads) { 212 + #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK 213 + /* 214 + * We can safely execute softirq on the current stack if 215 + * it is the irq stack, because it should be near empty 216 + * at this stage. 217 + */ 218 + __do_softirq(); 219 + #else 220 + /* 221 + * Otherwise, irq_exit() is called on the task stack that can 222 + * be potentially deep already. So call softirq in its own stack 223 + * to prevent from any overrun. 224 + */ 225 + do_softirq_own_stack(); 226 + #endif 227 + } else { 228 + wakeup_softirqd(); 229 + } 230 + } 231 + 232 + asmlinkage __visible void do_softirq(void) 233 + { 234 + __u32 pending; 235 + unsigned long flags; 236 + 237 + if (in_interrupt()) 238 + return; 239 + 240 + local_irq_save(flags); 241 + 242 + pending = local_softirq_pending(); 243 + 244 + if (pending && !ksoftirqd_running(pending)) 245 + do_softirq_own_stack(); 246 + 247 + local_irq_restore(flags); 248 + } 249 + 207 250 /* 208 251 * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, 209 252 * but break the loop if need_resched() is set or after 2 ms. ··· 315 270 current->flags &= ~PF_MEMALLOC; 316 271 317 272 pending = local_softirq_pending(); 318 - account_irq_enter_time(current); 319 273 320 274 __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); 321 275 in_hardirq = lockdep_softirq_start(); 276 + account_softirq_enter(current); 322 277 323 278 restart: 324 279 /* Reset the pending bitmask before enabling irqs */ ··· 365 320 wakeup_softirqd(); 366 321 } 367 322 323 + account_softirq_exit(current); 368 324 lockdep_softirq_end(in_hardirq); 369 - account_irq_exit_time(current); 370 325 __local_bh_enable(SOFTIRQ_OFFSET); 371 326 WARN_ON_ONCE(in_interrupt()); 372 327 current_restore_flags(old_flags, PF_MEMALLOC); 373 - } 374 - 375 - asmlinkage __visible void do_softirq(void) 376 - { 377 - __u32 pending; 378 - unsigned long flags; 379 - 380 - if (in_interrupt()) 381 - return; 382 - 383 - local_irq_save(flags); 384 - 385 - pending = local_softirq_pending(); 386 - 387 - if (pending && !ksoftirqd_running(pending)) 388 - do_softirq_own_stack(); 389 - 390 - local_irq_restore(flags); 391 328 } 392 329 393 330 /** ··· 377 350 */ 378 351 void irq_enter_rcu(void) 379 352 { 380 - if (is_idle_task(current) && !in_interrupt()) { 381 - /* 382 - * Prevent raise_softirq from needlessly waking up ksoftirqd 383 - * here, as softirq will be serviced on return from interrupt. 384 - */ 385 - local_bh_disable(); 353 + __irq_enter_raw(); 354 + 355 + if (is_idle_task(current) && (irq_count() == HARDIRQ_OFFSET)) 386 356 tick_irq_enter(); 387 - _local_bh_enable(); 388 - } 389 - __irq_enter(); 357 + 358 + account_hardirq_enter(current); 390 359 } 391 360 392 361 /** ··· 392 369 { 393 370 rcu_irq_enter(); 394 371 irq_enter_rcu(); 395 - } 396 - 397 - static inline void invoke_softirq(void) 398 - { 399 - if (ksoftirqd_running(local_softirq_pending())) 400 - return; 401 - 402 - if (!force_irqthreads) { 403 - #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK 404 - /* 405 - * We can safely execute softirq on the current stack if 406 - * it is the irq stack, because it should be near empty 407 - * at this stage. 408 - */ 409 - __do_softirq(); 410 - #else 411 - /* 412 - * Otherwise, irq_exit() is called on the task stack that can 413 - * be potentially deep already. So call softirq in its own stack 414 - * to prevent from any overrun. 415 - */ 416 - do_softirq_own_stack(); 417 - #endif 418 - } else { 419 - wakeup_softirqd(); 420 - } 421 372 } 422 373 423 374 static inline void tick_irq_exit(void) ··· 414 417 #else 415 418 lockdep_assert_irqs_disabled(); 416 419 #endif 417 - account_irq_exit_time(current); 420 + account_hardirq_exit(current); 418 421 preempt_count_sub(HARDIRQ_OFFSET); 419 422 if (!in_interrupt() && local_softirq_pending()) 420 423 invoke_softirq();