hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/kernel/irq/pm.c
....@@ -69,12 +69,26 @@
6969
7070 static bool suspend_device_irq(struct irq_desc *desc)
7171 {
72
+ unsigned long chipflags = irq_desc_get_chip(desc)->flags;
73
+ struct irq_data *irqd = &desc->irq_data;
74
+
7275 if (!desc->action || irq_desc_is_chained(desc) ||
7376 desc->no_suspend_depth)
7477 return false;
7578
76
- if (irqd_is_wakeup_set(&desc->irq_data)) {
77
- irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
79
+ if (irqd_is_wakeup_set(irqd)) {
80
+ irqd_set(irqd, IRQD_WAKEUP_ARMED);
81
+
82
+ if ((chipflags & IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND) &&
83
+ irqd_irq_disabled(irqd)) {
84
+ /*
85
+ * Interrupt marked for wakeup is in disabled state.
86
+ * Enable interrupt here to unmask/enable in irqchip
87
+ * to be able to resume with such interrupts.
88
+ */
89
+ __enable_irq(desc);
90
+ irqd_set(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
91
+ }
7892 /*
7993 * We return true here to force the caller to issue
8094 * synchronize_irq(). We need to make sure that the
....@@ -93,7 +107,7 @@
93107 * chip level. The chip implementation indicates that with
94108 * IRQCHIP_MASK_ON_SUSPEND.
95109 */
96
- if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
110
+ if (chipflags & IRQCHIP_MASK_ON_SUSPEND)
97111 mask_irq(desc);
98112 return true;
99113 }
....@@ -137,7 +151,19 @@
137151
138152 static void resume_irq(struct irq_desc *desc)
139153 {
140
- irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
154
+ struct irq_data *irqd = &desc->irq_data;
155
+
156
+ irqd_clear(irqd, IRQD_WAKEUP_ARMED);
157
+
158
+ if (irqd_is_enabled_on_suspend(irqd)) {
159
+ /*
160
+ * Interrupt marked for wakeup was enabled during suspend
161
+ * entry. Disable such interrupts to restore them back to
162
+ * original state.
163
+ */
164
+ __disable_irq(desc);
165
+ irqd_clear(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
166
+ }
141167
142168 if (desc->istate & IRQS_SUSPENDED)
143169 goto resume;
....@@ -177,6 +203,30 @@
177203 }
178204
179205 /**
206
+ * rearm_wake_irq - rearm a wakeup interrupt line after signaling wakeup
207
+ * @irq: Interrupt to rearm
208
+ */
209
+void rearm_wake_irq(unsigned int irq)
210
+{
211
+ unsigned long flags;
212
+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
213
+
214
+ if (!desc)
215
+ return;
216
+
217
+ if (!(desc->istate & IRQS_SUSPENDED) ||
218
+ !irqd_is_wakeup_set(&desc->irq_data))
219
+ goto unlock;
220
+
221
+ desc->istate &= ~IRQS_SUSPENDED;
222
+ irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
223
+ __enable_irq(desc);
224
+
225
+unlock:
226
+ irq_put_desc_busunlock(desc, flags);
227
+}
228
+
229
+/**
180230 * irq_pm_syscore_ops - enable interrupt lines early
181231 *
182232 * Enable all interrupt lines with %IRQF_EARLY_RESUME set.