Skip to content

Commit 9d4f24b

Browse files
author
Marc Zyngier
committed
irqchip/qcom-pdc: Trim unused levels of the interrupt hierarchy
The QCOM PDC driver creates a bunch of unnecessary levels in the interrupt hierarchy when dealing with non-wakeup-capable interrupts. By definition, these lines are terminated at the PDC level, and everything below this is completely fake. This also results in additional complexity as most of the callbacks have to check for the validity of the parent level. Needless to say, this doesn't look very good. Solve this by disconnecting the interrupt hierarchy below the last valid level, and considerably simplify the handling of all the other interrupts by avoiding now unnecessary cheks. In most cases, the standard irq_*_parent() handlers are directly used. This also cures an issue reporting by Maulik where gpio_to_irq() returns an error after having observed a set of invalid levels. Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Maulik Shah <[email protected]> Tested-by: Maulik Shah <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 131d326 commit 9d4f24b

File tree

1 file changed

+11
-57
lines changed

1 file changed

+11
-57
lines changed

drivers/irqchip/qcom-pdc.c

Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
5353
return readl_relaxed(pdc_base + reg + i * sizeof(u32));
5454
}
5555

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-
7656
static void pdc_enable_intr(struct irq_data *d, bool on)
7757
{
7858
int pin_out = d->hwirq;
@@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
9171

9272
static void qcom_pdc_gic_disable(struct irq_data *d)
9373
{
94-
if (d->hwirq == GPIO_NO_WAKE_IRQ)
95-
return;
96-
9774
pdc_enable_intr(d, false);
9875
irq_chip_disable_parent(d);
9976
}
10077

10178
static void qcom_pdc_gic_enable(struct irq_data *d)
10279
{
103-
if (d->hwirq == GPIO_NO_WAKE_IRQ)
104-
return;
105-
10680
pdc_enable_intr(d, true);
10781
irq_chip_enable_parent(d);
10882
}
10983

110-
static void qcom_pdc_gic_mask(struct irq_data *d)
111-
{
112-
if (d->hwirq == GPIO_NO_WAKE_IRQ)
113-
return;
114-
115-
irq_chip_mask_parent(d);
116-
}
117-
118-
static void qcom_pdc_gic_unmask(struct irq_data *d)
119-
{
120-
if (d->hwirq == GPIO_NO_WAKE_IRQ)
121-
return;
122-
123-
irq_chip_unmask_parent(d);
124-
}
125-
12684
/*
12785
* GIC does not handle falling edge or active low. To allow falling edge and
12886
* active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
159117
*/
160118
static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
161119
{
162-
int pin_out = d->hwirq;
163120
enum pdc_irq_config_bits pdc_type;
164121
enum pdc_irq_config_bits old_pdc_type;
165122
int ret;
166123

167-
if (pin_out == GPIO_NO_WAKE_IRQ)
168-
return 0;
169-
170124
switch (type) {
171125
case IRQ_TYPE_EDGE_RISING:
172126
pdc_type = PDC_EDGE_RISING;
@@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
191145
return -EINVAL;
192146
}
193147

194-
old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
195-
pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
148+
old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
149+
pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
196150

197151
ret = irq_chip_set_type_parent(d, type);
198152
if (ret)
@@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
216170
static struct irq_chip qcom_pdc_gic_chip = {
217171
.name = "PDC",
218172
.irq_eoi = irq_chip_eoi_parent,
219-
.irq_mask = qcom_pdc_gic_mask,
220-
.irq_unmask = qcom_pdc_gic_unmask,
173+
.irq_mask = irq_chip_mask_parent,
174+
.irq_unmask = irq_chip_unmask_parent,
221175
.irq_disable = qcom_pdc_gic_disable,
222176
.irq_enable = qcom_pdc_gic_enable,
223-
.irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state,
224-
.irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state,
177+
.irq_get_irqchip_state = irq_chip_get_parent_state,
178+
.irq_set_irqchip_state = irq_chip_set_parent_state,
225179
.irq_retrigger = irq_chip_retrigger_hierarchy,
226180
.irq_set_type = qcom_pdc_gic_set_type,
227181
.flags = IRQCHIP_MASK_ON_SUSPEND |
@@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
282236

283237
parent_hwirq = get_parent_hwirq(hwirq);
284238
if (parent_hwirq == PDC_NO_PARENT_IRQ)
285-
return 0;
239+
return irq_domain_disconnect_hierarchy(domain->parent, virq);
286240

287241
if (type & IRQ_TYPE_EDGE_BOTH)
288242
type = IRQ_TYPE_EDGE_RISING;
@@ -319,17 +273,17 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
319273
if (ret)
320274
return ret;
321275

276+
if (hwirq == GPIO_NO_WAKE_IRQ)
277+
return irq_domain_disconnect_hierarchy(domain, virq);
278+
322279
ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
323280
&qcom_pdc_gic_chip, NULL);
324281
if (ret)
325282
return ret;
326283

327-
if (hwirq == GPIO_NO_WAKE_IRQ)
328-
return 0;
329-
330284
parent_hwirq = get_parent_hwirq(hwirq);
331285
if (parent_hwirq == PDC_NO_PARENT_IRQ)
332-
return 0;
286+
return irq_domain_disconnect_hierarchy(domain->parent, virq);
333287

334288
if (type & IRQ_TYPE_EDGE_BOTH)
335289
type = IRQ_TYPE_EDGE_RISING;

0 commit comments

Comments
 (0)