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

Merge branch irq/qcom-pdc-nowake-cleanup into irq/irqchip-next

* irq/qcom-pdc-nowake-cleanup:
: Fix the QCOM PDC mishandling of the interrupt hierarchy by trimming
: it when necessary.
: Export irq_domain_disconnect_hierarchy as a consequence of it.
irqchip/qcom-pdc: Trim unused levels of the interrupt hierarchy
irqdomain: Export irq_domain_disconnect_hierarchy()

Signed-off-by: Marc Zyngier <maz@kernel.org>

+12 -57
+11 -57
drivers/irqchip/qcom-pdc.c
··· 53 53 return readl_relaxed(pdc_base + reg + i * sizeof(u32)); 54 54 } 55 55 56 - static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d, 57 - enum irqchip_irq_state which, 58 - bool *state) 59 - { 60 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 61 - return 0; 62 - 63 - return irq_chip_get_parent_state(d, which, state); 64 - } 65 - 66 - static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d, 67 - enum irqchip_irq_state which, 68 - bool value) 69 - { 70 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 71 - return 0; 72 - 73 - return irq_chip_set_parent_state(d, which, value); 74 - } 75 - 76 56 static void pdc_enable_intr(struct irq_data *d, bool on) 77 57 { 78 58 int pin_out = d->hwirq; ··· 71 91 72 92 static void qcom_pdc_gic_disable(struct irq_data *d) 73 93 { 74 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 75 - return; 76 - 77 94 pdc_enable_intr(d, false); 78 95 irq_chip_disable_parent(d); 79 96 } 80 97 81 98 static void qcom_pdc_gic_enable(struct irq_data *d) 82 99 { 83 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 84 - return; 85 - 86 100 pdc_enable_intr(d, true); 87 101 irq_chip_enable_parent(d); 88 - } 89 - 90 - static void qcom_pdc_gic_mask(struct irq_data *d) 91 - { 92 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 93 - return; 94 - 95 - irq_chip_mask_parent(d); 96 - } 97 - 98 - static void qcom_pdc_gic_unmask(struct irq_data *d) 99 - { 100 - if (d->hwirq == GPIO_NO_WAKE_IRQ) 101 - return; 102 - 103 - irq_chip_unmask_parent(d); 104 102 } 105 103 106 104 /* ··· 117 159 */ 118 160 static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) 119 161 { 120 - int pin_out = d->hwirq; 121 162 enum pdc_irq_config_bits pdc_type; 122 163 enum pdc_irq_config_bits old_pdc_type; 123 164 int ret; 124 - 125 - if (pin_out == GPIO_NO_WAKE_IRQ) 126 - return 0; 127 165 128 166 switch (type) { 129 167 case IRQ_TYPE_EDGE_RISING: ··· 145 191 return -EINVAL; 146 192 } 147 193 148 - old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out); 149 - pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type); 194 + old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq); 195 + pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type); 150 196 151 197 ret = irq_chip_set_type_parent(d, type); 152 198 if (ret) ··· 170 216 static struct irq_chip qcom_pdc_gic_chip = { 171 217 .name = "PDC", 172 218 .irq_eoi = irq_chip_eoi_parent, 173 - .irq_mask = qcom_pdc_gic_mask, 174 - .irq_unmask = qcom_pdc_gic_unmask, 219 + .irq_mask = irq_chip_mask_parent, 220 + .irq_unmask = irq_chip_unmask_parent, 175 221 .irq_disable = qcom_pdc_gic_disable, 176 222 .irq_enable = qcom_pdc_gic_enable, 177 - .irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state, 178 - .irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state, 223 + .irq_get_irqchip_state = irq_chip_get_parent_state, 224 + .irq_set_irqchip_state = irq_chip_set_parent_state, 179 225 .irq_retrigger = irq_chip_retrigger_hierarchy, 180 226 .irq_set_type = qcom_pdc_gic_set_type, 181 227 .flags = IRQCHIP_MASK_ON_SUSPEND | ··· 236 282 237 283 parent_hwirq = get_parent_hwirq(hwirq); 238 284 if (parent_hwirq == PDC_NO_PARENT_IRQ) 239 - return 0; 285 + return irq_domain_disconnect_hierarchy(domain->parent, virq); 240 286 241 287 if (type & IRQ_TYPE_EDGE_BOTH) 242 288 type = IRQ_TYPE_EDGE_RISING; ··· 273 319 if (ret) 274 320 return ret; 275 321 322 + if (hwirq == GPIO_NO_WAKE_IRQ) 323 + return irq_domain_disconnect_hierarchy(domain, virq); 324 + 276 325 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 277 326 &qcom_pdc_gic_chip, NULL); 278 327 if (ret) 279 328 return ret; 280 329 281 - if (hwirq == GPIO_NO_WAKE_IRQ) 282 - return 0; 283 - 284 330 parent_hwirq = get_parent_hwirq(hwirq); 285 331 if (parent_hwirq == PDC_NO_PARENT_IRQ) 286 - return 0; 332 + return irq_domain_disconnect_hierarchy(domain->parent, virq); 287 333 288 334 if (type & IRQ_TYPE_EDGE_BOTH) 289 335 type = IRQ_TYPE_EDGE_RISING;
+1
kernel/irq/irqdomain.c
··· 1215 1215 irqd->chip = ERR_PTR(-ENOTCONN); 1216 1216 return 0; 1217 1217 } 1218 + EXPORT_SYMBOL_GPL(irq_domain_disconnect_hierarchy); 1218 1219 1219 1220 static int irq_domain_trim_hierarchy(unsigned int virq) 1220 1221 {