Skip to content

Commit 89ed0b7

Browse files
hmynenimpe
authored andcommitted
powerpc/pseries/vas: Add VAS IRQ primary handler
irq_default_primary_handler() can be used only with IRQF_ONESHOT flag, but the flag disables IRQ before executing the thread handler and enables it after the interrupt is handled. But this IRQ disable sets the VAS IRQ OFF state in the hypervisor. In case if NX faults during this window, the hypervisor will not deliver the fault interrupt to the partition and the user space may wait continuously for the CSB update. So use VAS specific IRQ handler instead of calling the default primary handler. Increment pending_faults counter in IRQ handler and the bottom thread handler will process all faults based on this counter. In case if the another interrupt is received while the thread is running, it will be processed using this counter. The synchronization of top and bottom handlers will be done with IRQTF_RUNTHREAD flag and will re-enter to bottom half if this flag is set. Signed-off-by: Haren Myneni <[email protected]> Reviewed-by: Frederic Barrat <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 9abf231 commit 89ed0b7

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

arch/powerpc/platforms/pseries/vas.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,41 @@ static irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
200200
struct vas_user_win_ref *tsk_ref;
201201
int rc;
202202

203-
rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb));
204-
if (!rc) {
205-
tsk_ref = &txwin->vas_win.task_ref;
206-
vas_dump_crb(&crb);
207-
vas_update_csb(&crb, tsk_ref);
203+
while (atomic_read(&txwin->pending_faults)) {
204+
rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb));
205+
if (!rc) {
206+
tsk_ref = &txwin->vas_win.task_ref;
207+
vas_dump_crb(&crb);
208+
vas_update_csb(&crb, tsk_ref);
209+
}
210+
atomic_dec(&txwin->pending_faults);
208211
}
209212

210213
return IRQ_HANDLED;
211214
}
212215

216+
/*
217+
* irq_default_primary_handler() can be used only with IRQF_ONESHOT
218+
* which disables IRQ before executing the thread handler and enables
219+
* it after. But this disabling interrupt sets the VAS IRQ OFF
220+
* state in the hypervisor. If the NX generates fault interrupt
221+
* during this window, the hypervisor will not deliver this
222+
* interrupt to the LPAR. So use VAS specific IRQ handler instead
223+
* of calling the default primary handler.
224+
*/
225+
static irqreturn_t pseries_vas_irq_handler(int irq, void *data)
226+
{
227+
struct pseries_vas_window *txwin = data;
228+
229+
/*
230+
* The thread hanlder will process this interrupt if it is
231+
* already running.
232+
*/
233+
atomic_inc(&txwin->pending_faults);
234+
235+
return IRQ_WAKE_THREAD;
236+
}
237+
213238
/*
214239
* Allocate window and setup IRQ mapping.
215240
*/
@@ -240,8 +265,9 @@ static int allocate_setup_window(struct pseries_vas_window *txwin,
240265
goto out_irq;
241266
}
242267

243-
rc = request_threaded_irq(txwin->fault_virq, NULL,
244-
pseries_vas_fault_thread_fn, IRQF_ONESHOT,
268+
rc = request_threaded_irq(txwin->fault_virq,
269+
pseries_vas_irq_handler,
270+
pseries_vas_fault_thread_fn, 0,
245271
txwin->name, txwin);
246272
if (rc) {
247273
pr_err("VAS-Window[%d]: Request IRQ(%u) failed with %d\n",

arch/powerpc/platforms/pseries/vas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct pseries_vas_window {
132132
u64 flags;
133133
char *name;
134134
int fault_virq;
135+
atomic_t pending_faults; /* Number of pending faults */
135136
};
136137

137138
int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);

0 commit comments

Comments
 (0)