diff options
| -rw-r--r-- | arch/arm/mach-ns9xxx/irq.c | 58 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/Kconfig | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/interrupt.c | 50 | ||||
| -rw-r--r-- | drivers/vlynq/vlynq.c | 64 | ||||
| -rw-r--r-- | include/linux/irq.h | 59 | ||||
| -rw-r--r-- | kernel/irq/Kconfig | 4 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 154 | ||||
| -rw-r--r-- | kernel/irq/debug.h | 10 | ||||
| -rw-r--r-- | kernel/irq/handle.c | 16 | ||||
| -rw-r--r-- | kernel/irq/internals.h | 6 | ||||
| -rw-r--r-- | kernel/irq/irqdesc.c | 3 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 92 | ||||
| -rw-r--r-- | kernel/irq/migration.c | 5 | ||||
| -rw-r--r-- | kernel/irq/spurious.c | 10 |
14 files changed, 297 insertions, 235 deletions
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 389fa5c669de..bf0fd48cbd80 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c | |||
| @@ -31,17 +31,11 @@ static void ns9xxx_mask_irq(struct irq_data *d) | |||
| 31 | __raw_writel(ic, SYS_IC(prio / 4)); | 31 | __raw_writel(ic, SYS_IC(prio / 4)); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static void ns9xxx_ack_irq(struct irq_data *d) | 34 | static void ns9xxx_eoi_irq(struct irq_data *d) |
| 35 | { | 35 | { |
| 36 | __raw_writel(0, SYS_ISRADDR); | 36 | __raw_writel(0, SYS_ISRADDR); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static void ns9xxx_maskack_irq(struct irq_data *d) | ||
| 40 | { | ||
| 41 | ns9xxx_mask_irq(d); | ||
| 42 | ns9xxx_ack_irq(d); | ||
| 43 | } | ||
| 44 | |||
| 45 | static void ns9xxx_unmask_irq(struct irq_data *d) | 39 | static void ns9xxx_unmask_irq(struct irq_data *d) |
| 46 | { | 40 | { |
| 47 | /* XXX: better use cpp symbols */ | 41 | /* XXX: better use cpp symbols */ |
| @@ -52,56 +46,11 @@ static void ns9xxx_unmask_irq(struct irq_data *d) | |||
| 52 | } | 46 | } |
| 53 | 47 | ||
| 54 | static struct irq_chip ns9xxx_chip = { | 48 | static struct irq_chip ns9xxx_chip = { |
| 55 | .irq_ack = ns9xxx_ack_irq, | 49 | .irq_eoi = ns9xxx_eoi_irq, |
| 56 | .irq_mask = ns9xxx_mask_irq, | 50 | .irq_mask = ns9xxx_mask_irq, |
| 57 | .irq_mask_ack = ns9xxx_maskack_irq, | ||
| 58 | .irq_unmask = ns9xxx_unmask_irq, | 51 | .irq_unmask = ns9xxx_unmask_irq, |
| 59 | }; | 52 | }; |
| 60 | 53 | ||
| 61 | #if 0 | ||
| 62 | #define handle_irq handle_level_irq | ||
| 63 | #else | ||
| 64 | static void handle_prio_irq(unsigned int irq, struct irq_desc *desc) | ||
| 65 | { | ||
| 66 | struct irqaction *action; | ||
| 67 | irqreturn_t action_ret; | ||
| 68 | |||
| 69 | raw_spin_lock(&desc->lock); | ||
| 70 | |||
| 71 | BUG_ON(desc->status & IRQ_INPROGRESS); | ||
| 72 | |||
| 73 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | ||
| 74 | kstat_incr_irqs_this_cpu(irq, desc); | ||
| 75 | |||
| 76 | action = desc->action; | ||
| 77 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
| 78 | goto out_mask; | ||
| 79 | |||
| 80 | desc->status |= IRQ_INPROGRESS; | ||
| 81 | raw_spin_unlock(&desc->lock); | ||
| 82 | |||
| 83 | action_ret = handle_IRQ_event(irq, action); | ||
| 84 | |||
| 85 | /* XXX: There is no direct way to access noirqdebug, so check | ||
| 86 | * unconditionally for spurious irqs... | ||
| 87 | * Maybe this function should go to kernel/irq/chip.c? */ | ||
| 88 | note_interrupt(irq, desc, action_ret); | ||
| 89 | |||
| 90 | raw_spin_lock(&desc->lock); | ||
| 91 | desc->status &= ~IRQ_INPROGRESS; | ||
| 92 | |||
| 93 | if (desc->status & IRQ_DISABLED) | ||
| 94 | out_mask: | ||
| 95 | desc->irq_data.chip->irq_mask(&desc->irq_data); | ||
| 96 | |||
| 97 | /* ack unconditionally to unmask lower prio irqs */ | ||
| 98 | desc->irq_data.chip->irq_ack(&desc->irq_data); | ||
| 99 | |||
| 100 | raw_spin_unlock(&desc->lock); | ||
| 101 | } | ||
| 102 | #define handle_irq handle_prio_irq | ||
| 103 | #endif | ||
| 104 | |||
| 105 | void __init ns9xxx_init_irq(void) | 54 | void __init ns9xxx_init_irq(void) |
| 106 | { | 55 | { |
| 107 | int i; | 56 | int i; |
| @@ -119,7 +68,8 @@ void __init ns9xxx_init_irq(void) | |||
| 119 | 68 | ||
| 120 | for (i = 0; i <= 31; ++i) { | 69 | for (i = 0; i <= 31; ++i) { |
| 121 | set_irq_chip(i, &ns9xxx_chip); | 70 | set_irq_chip(i, &ns9xxx_chip); |
| 122 | set_irq_handler(i, handle_irq); | 71 | set_irq_handler(i, handle_fasteoi_irq); |
| 123 | set_irq_flags(i, IRQF_VALID); | 72 | set_irq_flags(i, IRQF_VALID); |
| 73 | irq_set_status_flags(i, IRQ_LEVEL); | ||
| 124 | } | 74 | } |
| 125 | } | 75 | } |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 48cd7d2e1b75..81239ebed83f 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
| @@ -9,6 +9,7 @@ config PPC_CELL_COMMON | |||
| 9 | select PPC_INDIRECT_IO | 9 | select PPC_INDIRECT_IO |
| 10 | select PPC_NATIVE | 10 | select PPC_NATIVE |
| 11 | select PPC_RTAS | 11 | select PPC_RTAS |
| 12 | select IRQ_EDGE_EOI_HANDLER | ||
| 12 | 13 | ||
| 13 | config PPC_CELL_NATIVE | 14 | config PPC_CELL_NATIVE |
| 14 | bool | 15 | bool |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 624d26e72f1d..ec9fc7d82068 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
| @@ -235,54 +235,6 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) | |||
| 235 | "IBM,CBEA-Internal-Interrupt-Controller"); | 235 | "IBM,CBEA-Internal-Interrupt-Controller"); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | extern int noirqdebug; | ||
| 239 | |||
| 240 | static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) | ||
| 241 | { | ||
| 242 | struct irq_chip *chip = get_irq_desc_chip(desc); | ||
| 243 | |||
| 244 | raw_spin_lock(&desc->lock); | ||
| 245 | |||
| 246 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | ||
| 247 | |||
| 248 | /* | ||
| 249 | * If we're currently running this IRQ, or its disabled, | ||
| 250 | * we shouldn't process the IRQ. Mark it pending, handle | ||
| 251 | * the necessary masking and go out | ||
| 252 | */ | ||
| 253 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | ||
| 254 | !desc->action)) { | ||
| 255 | desc->status |= IRQ_PENDING; | ||
| 256 | goto out_eoi; | ||
| 257 | } | ||
| 258 | |||
| 259 | kstat_incr_irqs_this_cpu(irq, desc); | ||
| 260 | |||
| 261 | /* Mark the IRQ currently in progress.*/ | ||
| 262 | desc->status |= IRQ_INPROGRESS; | ||
| 263 | |||
| 264 | do { | ||
| 265 | struct irqaction *action = desc->action; | ||
| 266 | irqreturn_t action_ret; | ||
| 267 | |||
| 268 | if (unlikely(!action)) | ||
| 269 | goto out_eoi; | ||
| 270 | |||
| 271 | desc->status &= ~IRQ_PENDING; | ||
| 272 | raw_spin_unlock(&desc->lock); | ||
| 273 | action_ret = handle_IRQ_event(irq, action); | ||
| 274 | if (!noirqdebug) | ||
| 275 | note_interrupt(irq, desc, action_ret); | ||
| 276 | raw_spin_lock(&desc->lock); | ||
| 277 | |||
| 278 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | ||
| 279 | |||
| 280 | desc->status &= ~IRQ_INPROGRESS; | ||
| 281 | out_eoi: | ||
| 282 | chip->irq_eoi(&desc->irq_data); | ||
| 283 | raw_spin_unlock(&desc->lock); | ||
| 284 | } | ||
| 285 | |||
| 286 | static int iic_host_map(struct irq_host *h, unsigned int virq, | 238 | static int iic_host_map(struct irq_host *h, unsigned int virq, |
| 287 | irq_hw_number_t hw) | 239 | irq_hw_number_t hw) |
| 288 | { | 240 | { |
| @@ -295,7 +247,7 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, | |||
| 295 | handle_iic_irq); | 247 | handle_iic_irq); |
| 296 | break; | 248 | break; |
| 297 | default: | 249 | default: |
| 298 | set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); | 250 | set_irq_chip_and_handler(virq, &iic_chip, handle_edge_eoi_irq); |
| 299 | } | 251 | } |
| 300 | return 0; | 252 | return 0; |
| 301 | } | 253 | } |
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index f885c868a04d..aa250cebecd2 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c | |||
| @@ -135,40 +135,40 @@ static void vlynq_reset(struct vlynq_device *dev) | |||
| 135 | msleep(5); | 135 | msleep(5); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static void vlynq_irq_unmask(unsigned int irq) | 138 | static void vlynq_irq_unmask(struct irq_data *d) |
| 139 | { | 139 | { |
| 140 | u32 val; | 140 | struct vlynq_device *dev = irq_data_get_irq_chip_data(d); |
| 141 | struct vlynq_device *dev = get_irq_chip_data(irq); | ||
| 142 | int virq; | 141 | int virq; |
| 142 | u32 val; | ||
| 143 | 143 | ||
| 144 | BUG_ON(!dev); | 144 | BUG_ON(!dev); |
| 145 | virq = irq - dev->irq_start; | 145 | virq = d->irq - dev->irq_start; |
| 146 | val = readl(&dev->remote->int_device[virq >> 2]); | 146 | val = readl(&dev->remote->int_device[virq >> 2]); |
| 147 | val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); | 147 | val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); |
| 148 | writel(val, &dev->remote->int_device[virq >> 2]); | 148 | writel(val, &dev->remote->int_device[virq >> 2]); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static void vlynq_irq_mask(unsigned int irq) | 151 | static void vlynq_irq_mask(struct irq_data *d) |
| 152 | { | 152 | { |
| 153 | u32 val; | 153 | struct vlynq_device *dev = irq_data_get_irq_chip_data(d); |
| 154 | struct vlynq_device *dev = get_irq_chip_data(irq); | ||
| 155 | int virq; | 154 | int virq; |
| 155 | u32 val; | ||
| 156 | 156 | ||
| 157 | BUG_ON(!dev); | 157 | BUG_ON(!dev); |
| 158 | virq = irq - dev->irq_start; | 158 | virq = d->irq - dev->irq_start; |
| 159 | val = readl(&dev->remote->int_device[virq >> 2]); | 159 | val = readl(&dev->remote->int_device[virq >> 2]); |
| 160 | val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); | 160 | val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); |
| 161 | writel(val, &dev->remote->int_device[virq >> 2]); | 161 | writel(val, &dev->remote->int_device[virq >> 2]); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) | 164 | static int vlynq_irq_type(struct irq_data *d, unsigned int flow_type) |
| 165 | { | 165 | { |
| 166 | u32 val; | 166 | struct vlynq_device *dev = irq_data_get_irq_chip_data(d); |
| 167 | struct vlynq_device *dev = get_irq_chip_data(irq); | ||
| 168 | int virq; | 167 | int virq; |
| 168 | u32 val; | ||
| 169 | 169 | ||
| 170 | BUG_ON(!dev); | 170 | BUG_ON(!dev); |
| 171 | virq = irq - dev->irq_start; | 171 | virq = d->irq - dev->irq_start; |
| 172 | val = readl(&dev->remote->int_device[virq >> 2]); | 172 | val = readl(&dev->remote->int_device[virq >> 2]); |
| 173 | switch (flow_type & IRQ_TYPE_SENSE_MASK) { | 173 | switch (flow_type & IRQ_TYPE_SENSE_MASK) { |
| 174 | case IRQ_TYPE_EDGE_RISING: | 174 | case IRQ_TYPE_EDGE_RISING: |
| @@ -192,10 +192,9 @@ static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) | |||
| 192 | return 0; | 192 | return 0; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static void vlynq_local_ack(unsigned int irq) | 195 | static void vlynq_local_ack(struct irq_data *d) |
| 196 | { | 196 | { |
| 197 | struct vlynq_device *dev = get_irq_chip_data(irq); | 197 | struct vlynq_device *dev = irq_data_get_irq_chip_data(d); |
| 198 | |||
| 199 | u32 status = readl(&dev->local->status); | 198 | u32 status = readl(&dev->local->status); |
| 200 | 199 | ||
| 201 | pr_debug("%s: local status: 0x%08x\n", | 200 | pr_debug("%s: local status: 0x%08x\n", |
| @@ -203,10 +202,9 @@ static void vlynq_local_ack(unsigned int irq) | |||
| 203 | writel(status, &dev->local->status); | 202 | writel(status, &dev->local->status); |
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | static void vlynq_remote_ack(unsigned int irq) | 205 | static void vlynq_remote_ack(struct irq_data *d) |
| 207 | { | 206 | { |
| 208 | struct vlynq_device *dev = get_irq_chip_data(irq); | 207 | struct vlynq_device *dev = irq_data_get_irq_chip_data(d); |
| 209 | |||
| 210 | u32 status = readl(&dev->remote->status); | 208 | u32 status = readl(&dev->remote->status); |
| 211 | 209 | ||
| 212 | pr_debug("%s: remote status: 0x%08x\n", | 210 | pr_debug("%s: remote status: 0x%08x\n", |
| @@ -238,23 +236,23 @@ static irqreturn_t vlynq_irq(int irq, void *dev_id) | |||
| 238 | 236 | ||
| 239 | static struct irq_chip vlynq_irq_chip = { | 237 | static struct irq_chip vlynq_irq_chip = { |
| 240 | .name = "vlynq", | 238 | .name = "vlynq", |
| 241 | .unmask = vlynq_irq_unmask, | 239 | .irq_unmask = vlynq_irq_unmask, |
| 242 | .mask = vlynq_irq_mask, | 240 | .irq_mask = vlynq_irq_mask, |
| 243 | .set_type = vlynq_irq_type, | 241 | .irq_set_type = vlynq_irq_type, |
| 244 | }; | 242 | }; |
| 245 | 243 | ||
| 246 | static struct irq_chip vlynq_local_chip = { | 244 | static struct irq_chip vlynq_local_chip = { |
| 247 | .name = "vlynq local error", | 245 | .name = "vlynq local error", |
| 248 | .unmask = vlynq_irq_unmask, | 246 | .irq_unmask = vlynq_irq_unmask, |
| 249 | .mask = vlynq_irq_mask, | 247 | .irq_mask = vlynq_irq_mask, |
| 250 | .ack = vlynq_local_ack, | 248 | .irq_ack = vlynq_local_ack, |
| 251 | }; | 249 | }; |
| 252 | 250 | ||
| 253 | static struct irq_chip vlynq_remote_chip = { | 251 | static struct irq_chip vlynq_remote_chip = { |
| 254 | .name = "vlynq local error", | 252 | .name = "vlynq local error", |
| 255 | .unmask = vlynq_irq_unmask, | 253 | .irq_unmask = vlynq_irq_unmask, |
| 256 | .mask = vlynq_irq_mask, | 254 | .irq_mask = vlynq_irq_mask, |
| 257 | .ack = vlynq_remote_ack, | 255 | .irq_ack = vlynq_remote_ack, |
| 258 | }; | 256 | }; |
| 259 | 257 | ||
| 260 | static int vlynq_setup_irq(struct vlynq_device *dev) | 258 | static int vlynq_setup_irq(struct vlynq_device *dev) |
| @@ -291,17 +289,17 @@ static int vlynq_setup_irq(struct vlynq_device *dev) | |||
| 291 | for (i = dev->irq_start; i <= dev->irq_end; i++) { | 289 | for (i = dev->irq_start; i <= dev->irq_end; i++) { |
| 292 | virq = i - dev->irq_start; | 290 | virq = i - dev->irq_start; |
| 293 | if (virq == dev->local_irq) { | 291 | if (virq == dev->local_irq) { |
| 294 | set_irq_chip_and_handler(i, &vlynq_local_chip, | 292 | irq_set_chip_and_handler(i, &vlynq_local_chip, |
| 295 | handle_level_irq); | 293 | handle_level_irq); |
| 296 | set_irq_chip_data(i, dev); | 294 | irq_set_chip_data(i, dev); |
| 297 | } else if (virq == dev->remote_irq) { | 295 | } else if (virq == dev->remote_irq) { |
| 298 | set_irq_chip_and_handler(i, &vlynq_remote_chip, | 296 | irq_set_chip_and_handler(i, &vlynq_remote_chip, |
| 299 | handle_level_irq); | 297 | handle_level_irq); |
| 300 | set_irq_chip_data(i, dev); | 298 | irq_set_chip_data(i, dev); |
| 301 | } else { | 299 | } else { |
| 302 | set_irq_chip_and_handler(i, &vlynq_irq_chip, | 300 | irq_set_chip_and_handler(i, &vlynq_irq_chip, |
| 303 | handle_simple_irq); | 301 | handle_simple_irq); |
| 304 | set_irq_chip_data(i, dev); | 302 | irq_set_chip_data(i, dev); |
| 305 | writel(0, &dev->remote->int_device[virq >> 2]); | 303 | writel(0, &dev->remote->int_device[virq >> 2]); |
| 306 | } | 304 | } |
| 307 | } | 305 | } |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 5d876c9b3a3d..b3741c83774c 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -135,7 +135,7 @@ struct msi_desc; | |||
| 135 | * struct irq_data - per irq and irq chip data passed down to chip functions | 135 | * struct irq_data - per irq and irq chip data passed down to chip functions |
| 136 | * @irq: interrupt number | 136 | * @irq: interrupt number |
| 137 | * @node: node index useful for balancing | 137 | * @node: node index useful for balancing |
| 138 | * @state_use_accessor: status information for irq chip functions. | 138 | * @state_use_accessors: status information for irq chip functions. |
| 139 | * Use accessor functions to deal with it | 139 | * Use accessor functions to deal with it |
| 140 | * @chip: low level interrupt hardware access | 140 | * @chip: low level interrupt hardware access |
| 141 | * @handler_data: per-IRQ data for the irq_chip methods | 141 | * @handler_data: per-IRQ data for the irq_chip methods |
| @@ -174,6 +174,9 @@ struct irq_data { | |||
| 174 | * from suspend | 174 | * from suspend |
| 175 | * IRDQ_MOVE_PCNTXT - Interrupt can be moved in process | 175 | * IRDQ_MOVE_PCNTXT - Interrupt can be moved in process |
| 176 | * context | 176 | * context |
| 177 | * IRQD_IRQ_DISABLED - Disabled state of the interrupt | ||
| 178 | * IRQD_IRQ_MASKED - Masked state of the interrupt | ||
| 179 | * IRQD_IRQ_INPROGRESS - In progress state of the interrupt | ||
| 177 | */ | 180 | */ |
| 178 | enum { | 181 | enum { |
| 179 | IRQD_TRIGGER_MASK = 0xf, | 182 | IRQD_TRIGGER_MASK = 0xf, |
| @@ -184,6 +187,9 @@ enum { | |||
| 184 | IRQD_LEVEL = (1 << 13), | 187 | IRQD_LEVEL = (1 << 13), |
| 185 | IRQD_WAKEUP_STATE = (1 << 14), | 188 | IRQD_WAKEUP_STATE = (1 << 14), |
| 186 | IRQD_MOVE_PCNTXT = (1 << 15), | 189 | IRQD_MOVE_PCNTXT = (1 << 15), |
| 190 | IRQD_IRQ_DISABLED = (1 << 16), | ||
| 191 | IRQD_IRQ_MASKED = (1 << 17), | ||
| 192 | IRQD_IRQ_INPROGRESS = (1 << 18), | ||
| 187 | }; | 193 | }; |
| 188 | 194 | ||
| 189 | static inline bool irqd_is_setaffinity_pending(struct irq_data *d) | 195 | static inline bool irqd_is_setaffinity_pending(struct irq_data *d) |
| @@ -206,6 +212,11 @@ static inline bool irqd_affinity_was_set(struct irq_data *d) | |||
| 206 | return d->state_use_accessors & IRQD_AFFINITY_SET; | 212 | return d->state_use_accessors & IRQD_AFFINITY_SET; |
| 207 | } | 213 | } |
| 208 | 214 | ||
| 215 | static inline void irqd_mark_affinity_was_set(struct irq_data *d) | ||
| 216 | { | ||
| 217 | d->state_use_accessors |= IRQD_AFFINITY_SET; | ||
| 218 | } | ||
| 219 | |||
| 209 | static inline u32 irqd_get_trigger_type(struct irq_data *d) | 220 | static inline u32 irqd_get_trigger_type(struct irq_data *d) |
| 210 | { | 221 | { |
| 211 | return d->state_use_accessors & IRQD_TRIGGER_MASK; | 222 | return d->state_use_accessors & IRQD_TRIGGER_MASK; |
| @@ -235,6 +246,36 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d) | |||
| 235 | return d->state_use_accessors & IRQD_MOVE_PCNTXT; | 246 | return d->state_use_accessors & IRQD_MOVE_PCNTXT; |
| 236 | } | 247 | } |
| 237 | 248 | ||
| 249 | static inline bool irqd_irq_disabled(struct irq_data *d) | ||
| 250 | { | ||
| 251 | return d->state_use_accessors & IRQD_IRQ_DISABLED; | ||
| 252 | } | ||
| 253 | |||
| 254 | static inline bool irqd_irq_masked(struct irq_data *d) | ||
| 255 | { | ||
| 256 | return d->state_use_accessors & IRQD_IRQ_MASKED; | ||
| 257 | } | ||
| 258 | |||
| 259 | static inline bool irqd_irq_inprogress(struct irq_data *d) | ||
| 260 | { | ||
| 261 | return d->state_use_accessors & IRQD_IRQ_INPROGRESS; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* | ||
| 265 | * Functions for chained handlers which can be enabled/disabled by the | ||
| 266 | * standard disable_irq/enable_irq calls. Must be called with | ||
| 267 | * irq_desc->lock held. | ||
| 268 | */ | ||
| 269 | static inline void irqd_set_chained_irq_inprogress(struct irq_data *d) | ||
| 270 | { | ||
| 271 | d->state_use_accessors |= IRQD_IRQ_INPROGRESS; | ||
| 272 | } | ||
| 273 | |||
| 274 | static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d) | ||
| 275 | { | ||
| 276 | d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS; | ||
| 277 | } | ||
| 278 | |||
| 238 | /** | 279 | /** |
| 239 | * struct irq_chip - hardware interrupt chip descriptor | 280 | * struct irq_chip - hardware interrupt chip descriptor |
| 240 | * | 281 | * |
| @@ -271,6 +312,8 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d) | |||
| 271 | * @irq_set_wake: enable/disable power-management wake-on of an IRQ | 312 | * @irq_set_wake: enable/disable power-management wake-on of an IRQ |
| 272 | * @irq_bus_lock: function to lock access to slow bus (i2c) chips | 313 | * @irq_bus_lock: function to lock access to slow bus (i2c) chips |
| 273 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips | 314 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips |
| 315 | * @irq_cpu_online: configure an interrupt source for a secondary CPU | ||
| 316 | * @irq_cpu_offline: un-configure an interrupt source for a secondary CPU | ||
| 274 | * @irq_print_chip: optional to print special chip info in show_interrupts | 317 | * @irq_print_chip: optional to print special chip info in show_interrupts |
| 275 | * @flags: chip specific flags | 318 | * @flags: chip specific flags |
| 276 | * | 319 | * |
| @@ -319,6 +362,9 @@ struct irq_chip { | |||
| 319 | void (*irq_bus_lock)(struct irq_data *data); | 362 | void (*irq_bus_lock)(struct irq_data *data); |
| 320 | void (*irq_bus_sync_unlock)(struct irq_data *data); | 363 | void (*irq_bus_sync_unlock)(struct irq_data *data); |
| 321 | 364 | ||
| 365 | void (*irq_cpu_online)(struct irq_data *data); | ||
| 366 | void (*irq_cpu_offline)(struct irq_data *data); | ||
| 367 | |||
| 322 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); | 368 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); |
| 323 | 369 | ||
| 324 | unsigned long flags; | 370 | unsigned long flags; |
| @@ -335,11 +381,14 @@ struct irq_chip { | |||
| 335 | * IRQCHIP_SET_TYPE_MASKED: Mask before calling chip.irq_set_type() | 381 | * IRQCHIP_SET_TYPE_MASKED: Mask before calling chip.irq_set_type() |
| 336 | * IRQCHIP_EOI_IF_HANDLED: Only issue irq_eoi() when irq was handled | 382 | * IRQCHIP_EOI_IF_HANDLED: Only issue irq_eoi() when irq was handled |
| 337 | * IRQCHIP_MASK_ON_SUSPEND: Mask non wake irqs in the suspend path | 383 | * IRQCHIP_MASK_ON_SUSPEND: Mask non wake irqs in the suspend path |
| 384 | * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks | ||
| 385 | * when irq enabled | ||
| 338 | */ | 386 | */ |
| 339 | enum { | 387 | enum { |
| 340 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), | 388 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), |
| 341 | IRQCHIP_EOI_IF_HANDLED = (1 << 1), | 389 | IRQCHIP_EOI_IF_HANDLED = (1 << 1), |
| 342 | IRQCHIP_MASK_ON_SUSPEND = (1 << 2), | 390 | IRQCHIP_MASK_ON_SUSPEND = (1 << 2), |
| 391 | IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), | ||
| 343 | }; | 392 | }; |
| 344 | 393 | ||
| 345 | /* This include will go away once we isolated irq_desc usage to core code */ | 394 | /* This include will go away once we isolated irq_desc usage to core code */ |
| @@ -364,6 +413,10 @@ struct irqaction; | |||
| 364 | extern int setup_irq(unsigned int irq, struct irqaction *new); | 413 | extern int setup_irq(unsigned int irq, struct irqaction *new); |
| 365 | extern void remove_irq(unsigned int irq, struct irqaction *act); | 414 | extern void remove_irq(unsigned int irq, struct irqaction *act); |
| 366 | 415 | ||
| 416 | extern void irq_cpu_online(void); | ||
| 417 | extern void irq_cpu_offline(void); | ||
| 418 | extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask); | ||
| 419 | |||
| 367 | #ifdef CONFIG_GENERIC_HARDIRQS | 420 | #ifdef CONFIG_GENERIC_HARDIRQS |
| 368 | 421 | ||
| 369 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) | 422 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) |
| @@ -380,9 +433,6 @@ static inline void irq_move_masked_irq(struct irq_data *data) { } | |||
| 380 | 433 | ||
| 381 | extern int no_irq_affinity; | 434 | extern int no_irq_affinity; |
| 382 | 435 | ||
| 383 | /* Handle irq action chains: */ | ||
| 384 | extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action); | ||
| 385 | |||
| 386 | /* | 436 | /* |
| 387 | * Built-in IRQ handlers for various IRQ types, | 437 | * Built-in IRQ handlers for various IRQ types, |
| 388 | * callable via desc->handle_irq() | 438 | * callable via desc->handle_irq() |
| @@ -390,6 +440,7 @@ extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action); | |||
| 390 | extern void handle_level_irq(unsigned int irq, struct irq_desc *desc); | 440 | extern void handle_level_irq(unsigned int irq, struct irq_desc *desc); |
| 391 | extern void handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc); | 441 | extern void handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc); |
| 392 | extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc); | 442 | extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc); |
| 443 | extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc); | ||
| 393 | extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc); | 444 | extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc); |
| 394 | extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc); | 445 | extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc); |
| 395 | extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc); | 446 | extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc); |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 00f2c037267a..72606ba10b14 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
| @@ -51,6 +51,10 @@ config HARDIRQS_SW_RESEND | |||
| 51 | config IRQ_PREFLOW_FASTEOI | 51 | config IRQ_PREFLOW_FASTEOI |
| 52 | bool | 52 | bool |
| 53 | 53 | ||
| 54 | # Edge style eoi based handler (cell) | ||
| 55 | config IRQ_EDGE_EOI_HANDLER | ||
| 56 | bool | ||
| 57 | |||
| 54 | # Support forced irq threading | 58 | # Support forced irq threading |
| 55 | config IRQ_FORCED_THREADING | 59 | config IRQ_FORCED_THREADING |
| 56 | bool | 60 | bool |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index c9c0601f0615..03099d521f5e 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -37,6 +37,12 @@ int irq_set_chip(unsigned int irq, struct irq_chip *chip) | |||
| 37 | irq_chip_set_defaults(chip); | 37 | irq_chip_set_defaults(chip); |
| 38 | desc->irq_data.chip = chip; | 38 | desc->irq_data.chip = chip; |
| 39 | irq_put_desc_unlock(desc, flags); | 39 | irq_put_desc_unlock(desc, flags); |
| 40 | /* | ||
| 41 | * For !CONFIG_SPARSE_IRQ make the irq show up in | ||
| 42 | * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is | ||
| 43 | * already marked, and this call is harmless. | ||
| 44 | */ | ||
| 45 | irq_reserve_irq(irq); | ||
| 40 | return 0; | 46 | return 0; |
| 41 | } | 47 | } |
| 42 | EXPORT_SYMBOL(irq_set_chip); | 48 | EXPORT_SYMBOL(irq_set_chip); |
| @@ -134,25 +140,25 @@ EXPORT_SYMBOL_GPL(irq_get_irq_data); | |||
| 134 | 140 | ||
| 135 | static void irq_state_clr_disabled(struct irq_desc *desc) | 141 | static void irq_state_clr_disabled(struct irq_desc *desc) |
| 136 | { | 142 | { |
| 137 | desc->istate &= ~IRQS_DISABLED; | 143 | irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED); |
| 138 | irq_compat_clr_disabled(desc); | 144 | irq_compat_clr_disabled(desc); |
| 139 | } | 145 | } |
| 140 | 146 | ||
| 141 | static void irq_state_set_disabled(struct irq_desc *desc) | 147 | static void irq_state_set_disabled(struct irq_desc *desc) |
| 142 | { | 148 | { |
| 143 | desc->istate |= IRQS_DISABLED; | 149 | irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); |
| 144 | irq_compat_set_disabled(desc); | 150 | irq_compat_set_disabled(desc); |
| 145 | } | 151 | } |
| 146 | 152 | ||
| 147 | static void irq_state_clr_masked(struct irq_desc *desc) | 153 | static void irq_state_clr_masked(struct irq_desc *desc) |
| 148 | { | 154 | { |
| 149 | desc->istate &= ~IRQS_MASKED; | 155 | irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED); |
| 150 | irq_compat_clr_masked(desc); | 156 | irq_compat_clr_masked(desc); |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | static void irq_state_set_masked(struct irq_desc *desc) | 159 | static void irq_state_set_masked(struct irq_desc *desc) |
| 154 | { | 160 | { |
| 155 | desc->istate |= IRQS_MASKED; | 161 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); |
| 156 | irq_compat_set_masked(desc); | 162 | irq_compat_set_masked(desc); |
| 157 | } | 163 | } |
| 158 | 164 | ||
| @@ -372,11 +378,11 @@ void handle_nested_irq(unsigned int irq) | |||
| 372 | kstat_incr_irqs_this_cpu(irq, desc); | 378 | kstat_incr_irqs_this_cpu(irq, desc); |
| 373 | 379 | ||
| 374 | action = desc->action; | 380 | action = desc->action; |
| 375 | if (unlikely(!action || (desc->istate & IRQS_DISABLED))) | 381 | if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) |
| 376 | goto out_unlock; | 382 | goto out_unlock; |
| 377 | 383 | ||
| 378 | irq_compat_set_progress(desc); | 384 | irq_compat_set_progress(desc); |
| 379 | desc->istate |= IRQS_INPROGRESS; | 385 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 380 | raw_spin_unlock_irq(&desc->lock); | 386 | raw_spin_unlock_irq(&desc->lock); |
| 381 | 387 | ||
| 382 | action_ret = action->thread_fn(action->irq, action->dev_id); | 388 | action_ret = action->thread_fn(action->irq, action->dev_id); |
| @@ -384,7 +390,7 @@ void handle_nested_irq(unsigned int irq) | |||
| 384 | note_interrupt(irq, desc, action_ret); | 390 | note_interrupt(irq, desc, action_ret); |
| 385 | 391 | ||
| 386 | raw_spin_lock_irq(&desc->lock); | 392 | raw_spin_lock_irq(&desc->lock); |
| 387 | desc->istate &= ~IRQS_INPROGRESS; | 393 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 388 | irq_compat_clr_progress(desc); | 394 | irq_compat_clr_progress(desc); |
| 389 | 395 | ||
| 390 | out_unlock: | 396 | out_unlock: |
| @@ -416,14 +422,14 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
| 416 | { | 422 | { |
| 417 | raw_spin_lock(&desc->lock); | 423 | raw_spin_lock(&desc->lock); |
| 418 | 424 | ||
| 419 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 425 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
| 420 | if (!irq_check_poll(desc)) | 426 | if (!irq_check_poll(desc)) |
| 421 | goto out_unlock; | 427 | goto out_unlock; |
| 422 | 428 | ||
| 423 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | 429 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
| 424 | kstat_incr_irqs_this_cpu(irq, desc); | 430 | kstat_incr_irqs_this_cpu(irq, desc); |
| 425 | 431 | ||
| 426 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) | 432 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
| 427 | goto out_unlock; | 433 | goto out_unlock; |
| 428 | 434 | ||
| 429 | handle_irq_event(desc); | 435 | handle_irq_event(desc); |
| @@ -448,7 +454,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 448 | raw_spin_lock(&desc->lock); | 454 | raw_spin_lock(&desc->lock); |
| 449 | mask_ack_irq(desc); | 455 | mask_ack_irq(desc); |
| 450 | 456 | ||
| 451 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 457 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
| 452 | if (!irq_check_poll(desc)) | 458 | if (!irq_check_poll(desc)) |
| 453 | goto out_unlock; | 459 | goto out_unlock; |
| 454 | 460 | ||
| @@ -459,12 +465,12 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 459 | * If its disabled or no action available | 465 | * If its disabled or no action available |
| 460 | * keep it masked and get out of here | 466 | * keep it masked and get out of here |
| 461 | */ | 467 | */ |
| 462 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) | 468 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
| 463 | goto out_unlock; | 469 | goto out_unlock; |
| 464 | 470 | ||
| 465 | handle_irq_event(desc); | 471 | handle_irq_event(desc); |
| 466 | 472 | ||
| 467 | if (!(desc->istate & (IRQS_DISABLED | IRQS_ONESHOT))) | 473 | if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) |
| 468 | unmask_irq(desc); | 474 | unmask_irq(desc); |
| 469 | out_unlock: | 475 | out_unlock: |
| 470 | raw_spin_unlock(&desc->lock); | 476 | raw_spin_unlock(&desc->lock); |
| @@ -496,7 +502,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 496 | { | 502 | { |
| 497 | raw_spin_lock(&desc->lock); | 503 | raw_spin_lock(&desc->lock); |
| 498 | 504 | ||
| 499 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 505 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
| 500 | if (!irq_check_poll(desc)) | 506 | if (!irq_check_poll(desc)) |
| 501 | goto out; | 507 | goto out; |
| 502 | 508 | ||
| @@ -507,7 +513,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 507 | * If its disabled or no action available | 513 | * If its disabled or no action available |
| 508 | * then mask it and get out of here: | 514 | * then mask it and get out of here: |
| 509 | */ | 515 | */ |
| 510 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) { | 516 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { |
| 511 | irq_compat_set_pending(desc); | 517 | irq_compat_set_pending(desc); |
| 512 | desc->istate |= IRQS_PENDING; | 518 | desc->istate |= IRQS_PENDING; |
| 513 | mask_irq(desc); | 519 | mask_irq(desc); |
| @@ -558,8 +564,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 558 | * we shouldn't process the IRQ. Mark it pending, handle | 564 | * we shouldn't process the IRQ. Mark it pending, handle |
| 559 | * the necessary masking and go out | 565 | * the necessary masking and go out |
| 560 | */ | 566 | */ |
| 561 | if (unlikely((desc->istate & (IRQS_DISABLED | IRQS_INPROGRESS) || | 567 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || |
| 562 | !desc->action))) { | 568 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { |
| 563 | if (!irq_check_poll(desc)) { | 569 | if (!irq_check_poll(desc)) { |
| 564 | irq_compat_set_pending(desc); | 570 | irq_compat_set_pending(desc); |
| 565 | desc->istate |= IRQS_PENDING; | 571 | desc->istate |= IRQS_PENDING; |
| @@ -584,20 +590,65 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 584 | * Renable it, if it was not disabled in meantime. | 590 | * Renable it, if it was not disabled in meantime. |
| 585 | */ | 591 | */ |
| 586 | if (unlikely(desc->istate & IRQS_PENDING)) { | 592 | if (unlikely(desc->istate & IRQS_PENDING)) { |
| 587 | if (!(desc->istate & IRQS_DISABLED) && | 593 | if (!irqd_irq_disabled(&desc->irq_data) && |
| 588 | (desc->istate & IRQS_MASKED)) | 594 | irqd_irq_masked(&desc->irq_data)) |
| 589 | unmask_irq(desc); | 595 | unmask_irq(desc); |
| 590 | } | 596 | } |
| 591 | 597 | ||
| 592 | handle_irq_event(desc); | 598 | handle_irq_event(desc); |
| 593 | 599 | ||
| 594 | } while ((desc->istate & IRQS_PENDING) && | 600 | } while ((desc->istate & IRQS_PENDING) && |
| 595 | !(desc->istate & IRQS_DISABLED)); | 601 | !irqd_irq_disabled(&desc->irq_data)); |
| 596 | 602 | ||
| 597 | out_unlock: | 603 | out_unlock: |
| 598 | raw_spin_unlock(&desc->lock); | 604 | raw_spin_unlock(&desc->lock); |
| 599 | } | 605 | } |
| 600 | 606 | ||
| 607 | #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER | ||
| 608 | /** | ||
| 609 | * handle_edge_eoi_irq - edge eoi type IRQ handler | ||
| 610 | * @irq: the interrupt number | ||
| 611 | * @desc: the interrupt description structure for this irq | ||
| 612 | * | ||
| 613 | * Similar as the above handle_edge_irq, but using eoi and w/o the | ||
| 614 | * mask/unmask logic. | ||
| 615 | */ | ||
| 616 | void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc) | ||
| 617 | { | ||
| 618 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
| 619 | |||
| 620 | raw_spin_lock(&desc->lock); | ||
| 621 | |||
| 622 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
| 623 | /* | ||
| 624 | * If we're currently running this IRQ, or its disabled, | ||
| 625 | * we shouldn't process the IRQ. Mark it pending, handle | ||
| 626 | * the necessary masking and go out | ||
| 627 | */ | ||
| 628 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || | ||
| 629 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { | ||
| 630 | if (!irq_check_poll(desc)) { | ||
| 631 | desc->istate |= IRQS_PENDING; | ||
| 632 | goto out_eoi; | ||
| 633 | } | ||
| 634 | } | ||
| 635 | kstat_incr_irqs_this_cpu(irq, desc); | ||
| 636 | |||
| 637 | do { | ||
| 638 | if (unlikely(!desc->action)) | ||
| 639 | goto out_eoi; | ||
| 640 | |||
| 641 | handle_irq_event(desc); | ||
| 642 | |||
| 643 | } while ((desc->istate & IRQS_PENDING) && | ||
| 644 | !irqd_irq_disabled(&desc->irq_data)); | ||
| 645 | |||
| 646 | out_unlock: | ||
| 647 | chip->irq_eoi(&desc->irq_data); | ||
| 648 | raw_spin_unlock(&desc->lock); | ||
| 649 | } | ||
| 650 | #endif | ||
| 651 | |||
| 601 | /** | 652 | /** |
| 602 | * handle_percpu_irq - Per CPU local irq handler | 653 | * handle_percpu_irq - Per CPU local irq handler |
| 603 | * @irq: the interrupt number | 654 | * @irq: the interrupt number |
| @@ -642,8 +693,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 642 | if (handle == handle_bad_irq) { | 693 | if (handle == handle_bad_irq) { |
| 643 | if (desc->irq_data.chip != &no_irq_chip) | 694 | if (desc->irq_data.chip != &no_irq_chip) |
| 644 | mask_ack_irq(desc); | 695 | mask_ack_irq(desc); |
| 645 | irq_compat_set_disabled(desc); | 696 | irq_state_set_disabled(desc); |
| 646 | desc->istate |= IRQS_DISABLED; | ||
| 647 | desc->depth = 1; | 697 | desc->depth = 1; |
| 648 | } | 698 | } |
| 649 | desc->handle_irq = handle; | 699 | desc->handle_irq = handle; |
| @@ -684,8 +734,70 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | |||
| 684 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | 734 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
| 685 | if (irq_settings_can_move_pcntxt(desc)) | 735 | if (irq_settings_can_move_pcntxt(desc)) |
| 686 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); | 736 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); |
| 737 | if (irq_settings_is_level(desc)) | ||
| 738 | irqd_set(&desc->irq_data, IRQD_LEVEL); | ||
| 687 | 739 | ||
| 688 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); | 740 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); |
| 689 | 741 | ||
| 690 | irq_put_desc_unlock(desc, flags); | 742 | irq_put_desc_unlock(desc, flags); |
| 691 | } | 743 | } |
| 744 | |||
| 745 | /** | ||
| 746 | * irq_cpu_online - Invoke all irq_cpu_online functions. | ||
| 747 | * | ||
| 748 | * Iterate through all irqs and invoke the chip.irq_cpu_online() | ||
| 749 | * for each. | ||
| 750 | */ | ||
| 751 | void irq_cpu_online(void) | ||
| 752 | { | ||
| 753 | struct irq_desc *desc; | ||
| 754 | struct irq_chip *chip; | ||
| 755 | unsigned long flags; | ||
| 756 | unsigned int irq; | ||
| 757 | |||
| 758 | for_each_active_irq(irq) { | ||
| 759 | desc = irq_to_desc(irq); | ||
| 760 | if (!desc) | ||
| 761 | continue; | ||
| 762 | |||
| 763 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 764 | |||
| 765 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
| 766 | if (chip && chip->irq_cpu_online && | ||
| 767 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || | ||
| 768 | !irqd_irq_disabled(&desc->irq_data))) | ||
| 769 | chip->irq_cpu_online(&desc->irq_data); | ||
| 770 | |||
| 771 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * irq_cpu_offline - Invoke all irq_cpu_offline functions. | ||
| 777 | * | ||
| 778 | * Iterate through all irqs and invoke the chip.irq_cpu_offline() | ||
| 779 | * for each. | ||
| 780 | */ | ||
| 781 | void irq_cpu_offline(void) | ||
| 782 | { | ||
| 783 | struct irq_desc *desc; | ||
| 784 | struct irq_chip *chip; | ||
| 785 | unsigned long flags; | ||
| 786 | unsigned int irq; | ||
| 787 | |||
| 788 | for_each_active_irq(irq) { | ||
| 789 | desc = irq_to_desc(irq); | ||
| 790 | if (!desc) | ||
| 791 | continue; | ||
| 792 | |||
| 793 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 794 | |||
| 795 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
| 796 | if (chip && chip->irq_cpu_offline && | ||
| 797 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || | ||
| 798 | !irqd_irq_disabled(&desc->irq_data))) | ||
| 799 | chip->irq_cpu_offline(&desc->irq_data); | ||
| 800 | |||
| 801 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 802 | } | ||
| 803 | } | ||
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h index d1a33b7fa61d..a0bd875ba3d5 100644 --- a/kernel/irq/debug.h +++ b/kernel/irq/debug.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #define P(f) if (desc->status & f) printk("%14s set\n", #f) | 7 | #define P(f) if (desc->status & f) printk("%14s set\n", #f) |
| 8 | #define PS(f) if (desc->istate & f) printk("%14s set\n", #f) | 8 | #define PS(f) if (desc->istate & f) printk("%14s set\n", #f) |
| 9 | /* FIXME */ | ||
| 10 | #define PD(f) do { } while (0) | ||
| 9 | 11 | ||
| 10 | static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | 12 | static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) |
| 11 | { | 13 | { |
| @@ -28,13 +30,15 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | |||
| 28 | P(IRQ_NOAUTOEN); | 30 | P(IRQ_NOAUTOEN); |
| 29 | 31 | ||
| 30 | PS(IRQS_AUTODETECT); | 32 | PS(IRQS_AUTODETECT); |
| 31 | PS(IRQS_INPROGRESS); | ||
| 32 | PS(IRQS_REPLAY); | 33 | PS(IRQS_REPLAY); |
| 33 | PS(IRQS_WAITING); | 34 | PS(IRQS_WAITING); |
| 34 | PS(IRQS_DISABLED); | ||
| 35 | PS(IRQS_PENDING); | 35 | PS(IRQS_PENDING); |
| 36 | PS(IRQS_MASKED); | 36 | |
| 37 | PD(IRQS_INPROGRESS); | ||
| 38 | PD(IRQS_DISABLED); | ||
| 39 | PD(IRQS_MASKED); | ||
| 37 | } | 40 | } |
| 38 | 41 | ||
| 39 | #undef P | 42 | #undef P |
| 40 | #undef PS | 43 | #undef PS |
| 44 | #undef PD | ||
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 517561fc7317..1a2fb77f2fd6 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
| @@ -178,25 +178,13 @@ irqreturn_t handle_irq_event(struct irq_desc *desc) | |||
| 178 | irq_compat_clr_pending(desc); | 178 | irq_compat_clr_pending(desc); |
| 179 | desc->istate &= ~IRQS_PENDING; | 179 | desc->istate &= ~IRQS_PENDING; |
| 180 | irq_compat_set_progress(desc); | 180 | irq_compat_set_progress(desc); |
| 181 | desc->istate |= IRQS_INPROGRESS; | 181 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 182 | raw_spin_unlock(&desc->lock); | 182 | raw_spin_unlock(&desc->lock); |
| 183 | 183 | ||
| 184 | ret = handle_irq_event_percpu(desc, action); | 184 | ret = handle_irq_event_percpu(desc, action); |
| 185 | 185 | ||
| 186 | raw_spin_lock(&desc->lock); | 186 | raw_spin_lock(&desc->lock); |
| 187 | desc->istate &= ~IRQS_INPROGRESS; | 187 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 188 | irq_compat_clr_progress(desc); | 188 | irq_compat_clr_progress(desc); |
| 189 | return ret; | 189 | return ret; |
| 190 | } | 190 | } |
| 191 | |||
| 192 | /** | ||
| 193 | * handle_IRQ_event - irq action chain handler | ||
| 194 | * @irq: the interrupt number | ||
| 195 | * @action: the interrupt action chain for this irq | ||
| 196 | * | ||
| 197 | * Handles the action chain of an irq event | ||
| 198 | */ | ||
| 199 | irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | ||
| 200 | { | ||
| 201 | return handle_irq_event_percpu(irq_to_desc(irq), action); | ||
| 202 | } | ||
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 6c6ec9a49027..6b8b9713e28d 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
| @@ -44,26 +44,20 @@ enum { | |||
| 44 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt | 44 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt |
| 45 | * detection | 45 | * detection |
| 46 | * IRQS_POLL_INPROGRESS - polling in progress | 46 | * IRQS_POLL_INPROGRESS - polling in progress |
| 47 | * IRQS_INPROGRESS - Interrupt in progress | ||
| 48 | * IRQS_ONESHOT - irq is not unmasked in primary handler | 47 | * IRQS_ONESHOT - irq is not unmasked in primary handler |
| 49 | * IRQS_REPLAY - irq is replayed | 48 | * IRQS_REPLAY - irq is replayed |
| 50 | * IRQS_WAITING - irq is waiting | 49 | * IRQS_WAITING - irq is waiting |
| 51 | * IRQS_DISABLED - irq is disabled | ||
| 52 | * IRQS_PENDING - irq is pending and replayed later | 50 | * IRQS_PENDING - irq is pending and replayed later |
| 53 | * IRQS_MASKED - irq is masked | ||
| 54 | * IRQS_SUSPENDED - irq is suspended | 51 | * IRQS_SUSPENDED - irq is suspended |
| 55 | */ | 52 | */ |
| 56 | enum { | 53 | enum { |
| 57 | IRQS_AUTODETECT = 0x00000001, | 54 | IRQS_AUTODETECT = 0x00000001, |
| 58 | IRQS_SPURIOUS_DISABLED = 0x00000002, | 55 | IRQS_SPURIOUS_DISABLED = 0x00000002, |
| 59 | IRQS_POLL_INPROGRESS = 0x00000008, | 56 | IRQS_POLL_INPROGRESS = 0x00000008, |
| 60 | IRQS_INPROGRESS = 0x00000010, | ||
| 61 | IRQS_ONESHOT = 0x00000020, | 57 | IRQS_ONESHOT = 0x00000020, |
| 62 | IRQS_REPLAY = 0x00000040, | 58 | IRQS_REPLAY = 0x00000040, |
| 63 | IRQS_WAITING = 0x00000080, | 59 | IRQS_WAITING = 0x00000080, |
| 64 | IRQS_DISABLED = 0x00000100, | ||
| 65 | IRQS_PENDING = 0x00000200, | 60 | IRQS_PENDING = 0x00000200, |
| 66 | IRQS_MASKED = 0x00000400, | ||
| 67 | IRQS_SUSPENDED = 0x00000800, | 61 | IRQS_SUSPENDED = 0x00000800, |
| 68 | }; | 62 | }; |
| 69 | 63 | ||
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 6fb014f172f7..2c039c9b9383 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
| @@ -80,7 +80,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | |||
| 80 | desc->irq_data.handler_data = NULL; | 80 | desc->irq_data.handler_data = NULL; |
| 81 | desc->irq_data.msi_desc = NULL; | 81 | desc->irq_data.msi_desc = NULL; |
| 82 | irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); | 82 | irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); |
| 83 | desc->istate = IRQS_DISABLED; | 83 | irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); |
| 84 | desc->handle_irq = handle_bad_irq; | 84 | desc->handle_irq = handle_bad_irq; |
| 85 | desc->depth = 1; | 85 | desc->depth = 1; |
| 86 | desc->irq_count = 0; | 86 | desc->irq_count = 0; |
| @@ -238,7 +238,6 @@ int __init early_irq_init(void) | |||
| 238 | 238 | ||
| 239 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 239 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
| 240 | [0 ... NR_IRQS-1] = { | 240 | [0 ... NR_IRQS-1] = { |
| 241 | .istate = IRQS_DISABLED, | ||
| 242 | .handle_irq = handle_bad_irq, | 241 | .handle_irq = handle_bad_irq, |
| 243 | .depth = 1, | 242 | .depth = 1, |
| 244 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), | 243 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a2aa73e536c..acf540768b8f 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -41,7 +41,7 @@ early_param("threadirqs", setup_forced_irqthreads); | |||
| 41 | void synchronize_irq(unsigned int irq) | 41 | void synchronize_irq(unsigned int irq) |
| 42 | { | 42 | { |
| 43 | struct irq_desc *desc = irq_to_desc(irq); | 43 | struct irq_desc *desc = irq_to_desc(irq); |
| 44 | unsigned int state; | 44 | bool inprogress; |
| 45 | 45 | ||
| 46 | if (!desc) | 46 | if (!desc) |
| 47 | return; | 47 | return; |
| @@ -53,16 +53,16 @@ void synchronize_irq(unsigned int irq) | |||
| 53 | * Wait until we're out of the critical section. This might | 53 | * Wait until we're out of the critical section. This might |
| 54 | * give the wrong answer due to the lack of memory barriers. | 54 | * give the wrong answer due to the lack of memory barriers. |
| 55 | */ | 55 | */ |
| 56 | while (desc->istate & IRQS_INPROGRESS) | 56 | while (irqd_irq_inprogress(&desc->irq_data)) |
| 57 | cpu_relax(); | 57 | cpu_relax(); |
| 58 | 58 | ||
| 59 | /* Ok, that indicated we're done: double-check carefully. */ | 59 | /* Ok, that indicated we're done: double-check carefully. */ |
| 60 | raw_spin_lock_irqsave(&desc->lock, flags); | 60 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 61 | state = desc->istate; | 61 | inprogress = irqd_irq_inprogress(&desc->irq_data); |
| 62 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 62 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 63 | 63 | ||
| 64 | /* Oops, that failed? */ | 64 | /* Oops, that failed? */ |
| 65 | } while (state & IRQS_INPROGRESS); | 65 | } while (inprogress); |
| 66 | 66 | ||
| 67 | /* | 67 | /* |
| 68 | * We made sure that no hardirq handler is running. Now verify | 68 | * We made sure that no hardirq handler is running. Now verify |
| @@ -112,13 +112,13 @@ void irq_set_thread_affinity(struct irq_desc *desc) | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 114 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
| 115 | static inline bool irq_can_move_pcntxt(struct irq_desc *desc) | 115 | static inline bool irq_can_move_pcntxt(struct irq_data *data) |
| 116 | { | 116 | { |
| 117 | return irq_settings_can_move_pcntxt(desc); | 117 | return irqd_can_move_in_process_context(data); |
| 118 | } | 118 | } |
| 119 | static inline bool irq_move_pending(struct irq_desc *desc) | 119 | static inline bool irq_move_pending(struct irq_data *data) |
| 120 | { | 120 | { |
| 121 | return irqd_is_setaffinity_pending(&desc->irq_data); | 121 | return irqd_is_setaffinity_pending(data); |
| 122 | } | 122 | } |
| 123 | static inline void | 123 | static inline void |
| 124 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) | 124 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) |
| @@ -131,43 +131,34 @@ irq_get_pending(struct cpumask *mask, struct irq_desc *desc) | |||
| 131 | cpumask_copy(mask, desc->pending_mask); | 131 | cpumask_copy(mask, desc->pending_mask); |
| 132 | } | 132 | } |
| 133 | #else | 133 | #else |
| 134 | static inline bool irq_can_move_pcntxt(struct irq_desc *desc) { return true; } | 134 | static inline bool irq_can_move_pcntxt(struct irq_data *data) { return true; } |
| 135 | static inline bool irq_move_pending(struct irq_desc *desc) { return false; } | 135 | static inline bool irq_move_pending(struct irq_desc *data) { return false; } |
| 136 | static inline void | 136 | static inline void |
| 137 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { } | 137 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { } |
| 138 | static inline void | 138 | static inline void |
| 139 | irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { } | 139 | irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { } |
| 140 | #endif | 140 | #endif |
| 141 | 141 | ||
| 142 | /** | 142 | int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) |
| 143 | * irq_set_affinity - Set the irq affinity of a given irq | ||
| 144 | * @irq: Interrupt to set affinity | ||
| 145 | * @cpumask: cpumask | ||
| 146 | * | ||
| 147 | */ | ||
| 148 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
| 149 | { | 143 | { |
| 150 | struct irq_desc *desc = irq_to_desc(irq); | 144 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
| 151 | struct irq_chip *chip = desc->irq_data.chip; | 145 | struct irq_desc *desc = irq_data_to_desc(data); |
| 152 | unsigned long flags; | ||
| 153 | int ret = 0; | 146 | int ret = 0; |
| 154 | 147 | ||
| 155 | if (!chip->irq_set_affinity) | 148 | if (!chip || !chip->irq_set_affinity) |
| 156 | return -EINVAL; | 149 | return -EINVAL; |
| 157 | 150 | ||
| 158 | raw_spin_lock_irqsave(&desc->lock, flags); | 151 | if (irq_can_move_pcntxt(data)) { |
| 159 | 152 | ret = chip->irq_set_affinity(data, mask, false); | |
| 160 | if (irq_can_move_pcntxt(desc)) { | ||
| 161 | ret = chip->irq_set_affinity(&desc->irq_data, mask, false); | ||
| 162 | switch (ret) { | 153 | switch (ret) { |
| 163 | case IRQ_SET_MASK_OK: | 154 | case IRQ_SET_MASK_OK: |
| 164 | cpumask_copy(desc->irq_data.affinity, mask); | 155 | cpumask_copy(data->affinity, mask); |
| 165 | case IRQ_SET_MASK_OK_NOCOPY: | 156 | case IRQ_SET_MASK_OK_NOCOPY: |
| 166 | irq_set_thread_affinity(desc); | 157 | irq_set_thread_affinity(desc); |
| 167 | ret = 0; | 158 | ret = 0; |
| 168 | } | 159 | } |
| 169 | } else { | 160 | } else { |
| 170 | irqd_set_move_pending(&desc->irq_data); | 161 | irqd_set_move_pending(data); |
| 171 | irq_copy_pending(desc, mask); | 162 | irq_copy_pending(desc, mask); |
| 172 | } | 163 | } |
| 173 | 164 | ||
| @@ -176,7 +167,28 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
| 176 | schedule_work(&desc->affinity_notify->work); | 167 | schedule_work(&desc->affinity_notify->work); |
| 177 | } | 168 | } |
| 178 | irq_compat_set_affinity(desc); | 169 | irq_compat_set_affinity(desc); |
| 179 | irqd_set(&desc->irq_data, IRQD_AFFINITY_SET); | 170 | irqd_set(data, IRQD_AFFINITY_SET); |
| 171 | |||
| 172 | return ret; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * irq_set_affinity - Set the irq affinity of a given irq | ||
| 177 | * @irq: Interrupt to set affinity | ||
| 178 | * @mask: cpumask | ||
| 179 | * | ||
| 180 | */ | ||
| 181 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
| 182 | { | ||
| 183 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 184 | unsigned long flags; | ||
| 185 | int ret; | ||
| 186 | |||
| 187 | if (!desc) | ||
| 188 | return -EINVAL; | ||
| 189 | |||
| 190 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 191 | ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); | ||
| 180 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 192 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 181 | return ret; | 193 | return ret; |
| 182 | } | 194 | } |
| @@ -206,7 +218,7 @@ static void irq_affinity_notify(struct work_struct *work) | |||
| 206 | goto out; | 218 | goto out; |
| 207 | 219 | ||
| 208 | raw_spin_lock_irqsave(&desc->lock, flags); | 220 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 209 | if (irq_move_pending(desc)) | 221 | if (irq_move_pending(&desc->irq_data)) |
| 210 | irq_get_pending(cpumask, desc); | 222 | irq_get_pending(cpumask, desc); |
| 211 | else | 223 | else |
| 212 | cpumask_copy(cpumask, desc->irq_data.affinity); | 224 | cpumask_copy(cpumask, desc->irq_data.affinity); |
| @@ -551,9 +563,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 551 | flags &= IRQ_TYPE_SENSE_MASK; | 563 | flags &= IRQ_TYPE_SENSE_MASK; |
| 552 | 564 | ||
| 553 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { | 565 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { |
| 554 | if (!(desc->istate & IRQS_MASKED)) | 566 | if (!irqd_irq_masked(&desc->irq_data)) |
| 555 | mask_irq(desc); | 567 | mask_irq(desc); |
| 556 | if (!(desc->istate & IRQS_DISABLED)) | 568 | if (!irqd_irq_disabled(&desc->irq_data)) |
| 557 | unmask = 1; | 569 | unmask = 1; |
| 558 | } | 570 | } |
| 559 | 571 | ||
| @@ -651,7 +663,7 @@ again: | |||
| 651 | * irq_wake_thread(). See the comment there which explains the | 663 | * irq_wake_thread(). See the comment there which explains the |
| 652 | * serialization. | 664 | * serialization. |
| 653 | */ | 665 | */ |
| 654 | if (unlikely(desc->istate & IRQS_INPROGRESS)) { | 666 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) { |
| 655 | raw_spin_unlock_irq(&desc->lock); | 667 | raw_spin_unlock_irq(&desc->lock); |
| 656 | chip_bus_sync_unlock(desc); | 668 | chip_bus_sync_unlock(desc); |
| 657 | cpu_relax(); | 669 | cpu_relax(); |
| @@ -668,12 +680,10 @@ again: | |||
| 668 | 680 | ||
| 669 | desc->threads_oneshot &= ~action->thread_mask; | 681 | desc->threads_oneshot &= ~action->thread_mask; |
| 670 | 682 | ||
| 671 | if (!desc->threads_oneshot && !(desc->istate & IRQS_DISABLED) && | 683 | if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && |
| 672 | (desc->istate & IRQS_MASKED)) { | 684 | irqd_irq_masked(&desc->irq_data)) |
| 673 | irq_compat_clr_masked(desc); | 685 | unmask_irq(desc); |
| 674 | desc->istate &= ~IRQS_MASKED; | 686 | |
| 675 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
| 676 | } | ||
| 677 | out_unlock: | 687 | out_unlock: |
| 678 | raw_spin_unlock_irq(&desc->lock); | 688 | raw_spin_unlock_irq(&desc->lock); |
| 679 | chip_bus_sync_unlock(desc); | 689 | chip_bus_sync_unlock(desc); |
| @@ -767,7 +777,7 @@ static int irq_thread(void *data) | |||
| 767 | atomic_inc(&desc->threads_active); | 777 | atomic_inc(&desc->threads_active); |
| 768 | 778 | ||
| 769 | raw_spin_lock_irq(&desc->lock); | 779 | raw_spin_lock_irq(&desc->lock); |
| 770 | if (unlikely(desc->istate & IRQS_DISABLED)) { | 780 | if (unlikely(irqd_irq_disabled(&desc->irq_data))) { |
| 771 | /* | 781 | /* |
| 772 | * CHECKME: We might need a dedicated | 782 | * CHECKME: We might need a dedicated |
| 773 | * IRQ_THREAD_PENDING flag here, which | 783 | * IRQ_THREAD_PENDING flag here, which |
| @@ -985,8 +995,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 985 | } | 995 | } |
| 986 | 996 | ||
| 987 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ | 997 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ |
| 988 | IRQS_INPROGRESS | IRQS_ONESHOT | \ | 998 | IRQS_ONESHOT | IRQS_WAITING); |
| 989 | IRQS_WAITING); | 999 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 990 | 1000 | ||
| 991 | if (new->flags & IRQF_PERCPU) { | 1001 | if (new->flags & IRQF_PERCPU) { |
| 992 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | 1002 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index ec4806d4778b..e33d9c8d5089 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
| @@ -60,13 +60,12 @@ void move_masked_irq(int irq) | |||
| 60 | 60 | ||
| 61 | void irq_move_irq(struct irq_data *idata) | 61 | void irq_move_irq(struct irq_data *idata) |
| 62 | { | 62 | { |
| 63 | struct irq_desc *desc = irq_data_to_desc(idata); | ||
| 64 | bool masked; | 63 | bool masked; |
| 65 | 64 | ||
| 66 | if (likely(!irqd_is_setaffinity_pending(idata))) | 65 | if (likely(!irqd_is_setaffinity_pending(idata))) |
| 67 | return; | 66 | return; |
| 68 | 67 | ||
| 69 | if (unlikely(desc->istate & IRQS_DISABLED)) | 68 | if (unlikely(irqd_irq_disabled(idata))) |
| 70 | return; | 69 | return; |
| 71 | 70 | ||
| 72 | /* | 71 | /* |
| @@ -74,7 +73,7 @@ void irq_move_irq(struct irq_data *idata) | |||
| 74 | * threaded interrupt with ONESHOT set, we can end up with an | 73 | * threaded interrupt with ONESHOT set, we can end up with an |
| 75 | * interrupt storm. | 74 | * interrupt storm. |
| 76 | */ | 75 | */ |
| 77 | masked = desc->istate & IRQS_MASKED; | 76 | masked = irqd_irq_masked(idata); |
| 78 | if (!masked) | 77 | if (!masked) |
| 79 | idata->chip->irq_mask(idata); | 78 | idata->chip->irq_mask(idata); |
| 80 | irq_move_masked_irq(idata); | 79 | irq_move_masked_irq(idata); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dd586ebf9c8c..83f4799f46be 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
| @@ -45,12 +45,12 @@ bool irq_wait_for_poll(struct irq_desc *desc) | |||
| 45 | #ifdef CONFIG_SMP | 45 | #ifdef CONFIG_SMP |
| 46 | do { | 46 | do { |
| 47 | raw_spin_unlock(&desc->lock); | 47 | raw_spin_unlock(&desc->lock); |
| 48 | while (desc->istate & IRQS_INPROGRESS) | 48 | while (irqd_irq_inprogress(&desc->irq_data)) |
| 49 | cpu_relax(); | 49 | cpu_relax(); |
| 50 | raw_spin_lock(&desc->lock); | 50 | raw_spin_lock(&desc->lock); |
| 51 | } while (desc->istate & IRQS_INPROGRESS); | 51 | } while (irqd_irq_inprogress(&desc->irq_data)); |
| 52 | /* Might have been disabled in meantime */ | 52 | /* Might have been disabled in meantime */ |
| 53 | return !(desc->istate & IRQS_DISABLED) && desc->action; | 53 | return !irqd_irq_disabled(&desc->irq_data) && desc->action; |
| 54 | #else | 54 | #else |
| 55 | return false; | 55 | return false; |
| 56 | #endif | 56 | #endif |
| @@ -75,7 +75,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
| 75 | * Do not poll disabled interrupts unless the spurious | 75 | * Do not poll disabled interrupts unless the spurious |
| 76 | * disabled poller asks explicitely. | 76 | * disabled poller asks explicitely. |
| 77 | */ | 77 | */ |
| 78 | if ((desc->istate & IRQS_DISABLED) && !force) | 78 | if (irqd_irq_disabled(&desc->irq_data) && !force) |
| 79 | goto out; | 79 | goto out; |
| 80 | 80 | ||
| 81 | /* | 81 | /* |
| @@ -88,7 +88,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
| 88 | goto out; | 88 | goto out; |
| 89 | 89 | ||
| 90 | /* Already running on another processor */ | 90 | /* Already running on another processor */ |
| 91 | if (desc->istate & IRQS_INPROGRESS) { | 91 | if (irqd_irq_inprogress(&desc->irq_data)) { |
| 92 | /* | 92 | /* |
| 93 | * Already running: If it is shared get the other | 93 | * Already running: If it is shared get the other |
| 94 | * CPU to go looking for our mystery interrupt too | 94 | * CPU to go looking for our mystery interrupt too |
