| .. | .. |
|---|
| 16 | 16 | #include <linux/irqhandler.h> |
|---|
| 17 | 17 | #include <linux/irqreturn.h> |
|---|
| 18 | 18 | #include <linux/irqnr.h> |
|---|
| 19 | +#include <linux/irq_work.h> |
|---|
| 19 | 20 | #include <linux/topology.h> |
|---|
| 20 | 21 | #include <linux/io.h> |
|---|
| 21 | 22 | #include <linux/slab.h> |
|---|
| .. | .. |
|---|
| 73 | 74 | * IRQ_DISABLE_UNLAZY - Disable lazy irq disable |
|---|
| 74 | 75 | * IRQ_HIDDEN - Don't show up in /proc/interrupts |
|---|
| 75 | 76 | * IRQ_RAW - Skip tick management and irqtime accounting |
|---|
| 77 | + * IRQ_OOB - Interrupt can be delivered to the out-of-band handler |
|---|
| 78 | + * when pipelining is enabled (CONFIG_IRQ_PIPELINE), |
|---|
| 79 | + * regardless of the (virtualized) interrupt state |
|---|
| 80 | + * maintained by local_irq_save/disable(). |
|---|
| 81 | + * IRQ_CHAINED - Interrupt is chained. |
|---|
| 76 | 82 | */ |
|---|
| 77 | 83 | enum { |
|---|
| 78 | 84 | IRQ_TYPE_NONE = 0x00000000, |
|---|
| .. | .. |
|---|
| 101 | 107 | IRQ_DISABLE_UNLAZY = (1 << 19), |
|---|
| 102 | 108 | IRQ_HIDDEN = (1 << 20), |
|---|
| 103 | 109 | IRQ_RAW = (1 << 21), |
|---|
| 110 | + IRQ_OOB = (1 << 22), |
|---|
| 111 | + IRQ_CHAINED = (1 << 23), |
|---|
| 104 | 112 | }; |
|---|
| 105 | 113 | |
|---|
| 106 | 114 | #define IRQF_MODIFY_MASK \ |
|---|
| 107 | 115 | (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ |
|---|
| 108 | 116 | IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ |
|---|
| 109 | 117 | IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \ |
|---|
| 110 | | - IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN) |
|---|
| 118 | + IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN | IRQ_OOB) |
|---|
| 111 | 119 | |
|---|
| 112 | 120 | #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) |
|---|
| 113 | 121 | |
|---|
| .. | .. |
|---|
| 173 | 181 | * irq_domain |
|---|
| 174 | 182 | * @chip_data: platform-specific per-chip private data for the chip |
|---|
| 175 | 183 | * methods, to allow shared chip implementations |
|---|
| 184 | + * @move_work: irq_work for setaffinity deferral when pipelining irqs |
|---|
| 176 | 185 | */ |
|---|
| 177 | 186 | struct irq_data { |
|---|
| 178 | 187 | u32 mask; |
|---|
| .. | .. |
|---|
| 183 | 192 | struct irq_domain *domain; |
|---|
| 184 | 193 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY |
|---|
| 185 | 194 | struct irq_data *parent_data; |
|---|
| 195 | +#endif |
|---|
| 196 | +#if defined(CONFIG_IRQ_PIPELINE) && defined(CONFIG_GENERIC_PENDING_IRQ) |
|---|
| 197 | + struct irq_work move_work; |
|---|
| 186 | 198 | #endif |
|---|
| 187 | 199 | void *chip_data; |
|---|
| 188 | 200 | }; |
|---|
| .. | .. |
|---|
| 221 | 233 | * irq_chip::irq_set_affinity() when deactivated. |
|---|
| 222 | 234 | * IRQD_IRQ_ENABLED_ON_SUSPEND - Interrupt is enabled on suspend by irq pm if |
|---|
| 223 | 235 | * irqchip have flag IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND set. |
|---|
| 236 | + * IRQD_SETAFFINITY_BLOCKED - Pending affinity setting on hold (IRQ_PIPELINE) |
|---|
| 224 | 237 | */ |
|---|
| 225 | 238 | enum { |
|---|
| 226 | 239 | IRQD_TRIGGER_MASK = 0xf, |
|---|
| .. | .. |
|---|
| 247 | 260 | IRQD_HANDLE_ENFORCE_IRQCTX = (1 << 28), |
|---|
| 248 | 261 | IRQD_AFFINITY_ON_ACTIVATE = (1 << 29), |
|---|
| 249 | 262 | IRQD_IRQ_ENABLED_ON_SUSPEND = (1 << 30), |
|---|
| 263 | + IRQD_SETAFFINITY_BLOCKED = (1 << 31), |
|---|
| 250 | 264 | }; |
|---|
| 251 | 265 | |
|---|
| 252 | 266 | #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors) |
|---|
| .. | .. |
|---|
| 254 | 268 | static inline bool irqd_is_setaffinity_pending(struct irq_data *d) |
|---|
| 255 | 269 | { |
|---|
| 256 | 270 | return __irqd_to_state(d) & IRQD_SETAFFINITY_PENDING; |
|---|
| 271 | +} |
|---|
| 272 | + |
|---|
| 273 | +static inline void irqd_set_move_blocked(struct irq_data *d) |
|---|
| 274 | +{ |
|---|
| 275 | + __irqd_to_state(d) |= IRQD_SETAFFINITY_BLOCKED; |
|---|
| 276 | +} |
|---|
| 277 | + |
|---|
| 278 | +static inline void irqd_clr_move_blocked(struct irq_data *d) |
|---|
| 279 | +{ |
|---|
| 280 | + __irqd_to_state(d) &= ~IRQD_SETAFFINITY_BLOCKED; |
|---|
| 281 | +} |
|---|
| 282 | + |
|---|
| 283 | +static inline bool irqd_is_setaffinity_blocked(struct irq_data *d) |
|---|
| 284 | +{ |
|---|
| 285 | + return irqs_pipelined() && __irqd_to_state(d) & IRQD_SETAFFINITY_BLOCKED; |
|---|
| 257 | 286 | } |
|---|
| 258 | 287 | |
|---|
| 259 | 288 | static inline bool irqd_is_per_cpu(struct irq_data *d) |
|---|
| .. | .. |
|---|
| 570 | 599 | * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs |
|---|
| 571 | 600 | * in the suspend path if they are in disabled state |
|---|
| 572 | 601 | * IRQCHIP_AFFINITY_PRE_STARTUP: Default affinity update before startup |
|---|
| 602 | + * IRQCHIP_PIPELINE_SAFE: Chip can work in pipelined mode |
|---|
| 573 | 603 | */ |
|---|
| 574 | 604 | enum { |
|---|
| 575 | 605 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), |
|---|
| .. | .. |
|---|
| 583 | 613 | IRQCHIP_SUPPORTS_NMI = (1 << 8), |
|---|
| 584 | 614 | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9), |
|---|
| 585 | 615 | IRQCHIP_AFFINITY_PRE_STARTUP = (1 << 10), |
|---|
| 616 | + IRQCHIP_PIPELINE_SAFE = (1 << 11), |
|---|
| 586 | 617 | }; |
|---|
| 587 | 618 | |
|---|
| 588 | 619 | #include <linux/irqdesc.h> |
|---|
| .. | .. |
|---|
| 660 | 691 | extern void handle_percpu_devid_irq(struct irq_desc *desc); |
|---|
| 661 | 692 | extern void handle_bad_irq(struct irq_desc *desc); |
|---|
| 662 | 693 | extern void handle_nested_irq(unsigned int irq); |
|---|
| 694 | +extern void handle_synthetic_irq(struct irq_desc *desc); |
|---|
| 663 | 695 | |
|---|
| 664 | 696 | extern void handle_fasteoi_nmi(struct irq_desc *desc); |
|---|
| 665 | 697 | extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc); |
|---|
| .. | .. |
|---|
| 813 | 845 | extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry); |
|---|
| 814 | 846 | extern int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset, |
|---|
| 815 | 847 | struct msi_desc *entry); |
|---|
| 816 | | -extern struct irq_data *irq_get_irq_data(unsigned int irq); |
|---|
| 848 | + |
|---|
| 849 | +static inline struct irq_data *irq_get_irq_data(unsigned int irq) |
|---|
| 850 | +{ |
|---|
| 851 | + struct irq_desc *desc = irq_to_desc(irq); |
|---|
| 852 | + |
|---|
| 853 | + return desc ? &desc->irq_data : NULL; |
|---|
| 854 | +} |
|---|
| 817 | 855 | |
|---|
| 818 | 856 | static inline struct irq_chip *irq_get_chip(unsigned int irq) |
|---|
| 819 | 857 | { |
|---|
| .. | .. |
|---|
| 1056 | 1094 | * different flow mechanisms (level/edge) for it. |
|---|
| 1057 | 1095 | */ |
|---|
| 1058 | 1096 | struct irq_chip_generic { |
|---|
| 1059 | | - raw_spinlock_t lock; |
|---|
| 1097 | + hard_spinlock_t lock; |
|---|
| 1060 | 1098 | void __iomem *reg_base; |
|---|
| 1061 | 1099 | u32 (*reg_readl)(void __iomem *addr); |
|---|
| 1062 | 1100 | void (*reg_writel)(u32 val, void __iomem *addr); |
|---|
| .. | .. |
|---|
| 1183 | 1221 | |
|---|
| 1184 | 1222 | #define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX) |
|---|
| 1185 | 1223 | |
|---|
| 1224 | +#ifdef CONFIG_IRQ_PIPELINE |
|---|
| 1225 | + |
|---|
| 1226 | +int irq_switch_oob(unsigned int irq, bool on); |
|---|
| 1227 | + |
|---|
| 1228 | +#endif /* !CONFIG_IRQ_PIPELINE */ |
|---|
| 1229 | + |
|---|
| 1186 | 1230 | #ifdef CONFIG_SMP |
|---|
| 1187 | 1231 | static inline void irq_gc_lock(struct irq_chip_generic *gc) |
|---|
| 1188 | 1232 | { |
|---|