Message ID | aaad8813b4762a6753cfcd0b605a7574a5192ec7.camel@linux.ibm.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | [v3] powerpc/pseries/vas: Add VAS IRQ primary handler | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/github-powerpc_selftests | success | Successfully ran 10 jobs. |
snowpatch_ozlabs/github-powerpc_ppctests | success | Successfully ran 10 jobs. |
snowpatch_ozlabs/github-powerpc_kernel_qemu | success | Successfully ran 23 jobs. |
snowpatch_ozlabs/github-powerpc_clang | success | Successfully ran 6 jobs. |
snowpatch_ozlabs/github-powerpc_sparse | success | Successfully ran 4 jobs. |
On 10/10/2022 05:41, Haren Myneni wrote: > > 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 <haren@linux.ibm.com> > --- That version looks good to me. Reviewed-by: Frederic Barrat <fbarrat@linux.ibm.com> Fred > v3: Update pending_faults usage in changelog > v2: Use the pending_faults counter for the second interrupt and > process it with the previous interrupt handling if its thread > handler is executing. > > arch/powerpc/platforms/pseries/vas.c | 40 +++++++++++++++++++++++----- > arch/powerpc/platforms/pseries/vas.h | 1 + > 2 files changed, 34 insertions(+), 7 deletions(-) > > diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c > index 1a2cbc156e8f..70f26efcc35a 100644 > --- a/arch/powerpc/platforms/pseries/vas.c > +++ b/arch/powerpc/platforms/pseries/vas.c > @@ -200,16 +200,41 @@ static irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data) > struct vas_user_win_ref *tsk_ref; > int rc; > > - rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb)); > - if (!rc) { > - tsk_ref = &txwin->vas_win.task_ref; > - vas_dump_crb(&crb); > - vas_update_csb(&crb, tsk_ref); > + while (atomic_read(&txwin->pending_faults)) { > + rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb)); > + if (!rc) { > + tsk_ref = &txwin->vas_win.task_ref; > + vas_dump_crb(&crb); > + vas_update_csb(&crb, tsk_ref); > + } > + atomic_dec(&txwin->pending_faults); > } > > return IRQ_HANDLED; > } > > +/* > + * irq_default_primary_handler() can be used only with IRQF_ONESHOT > + * which disables IRQ before executing the thread handler and enables > + * it after. But this disabling interrupt sets the VAS IRQ OFF > + * state in the hypervisor. If the NX generates fault interrupt > + * during this window, the hypervisor will not deliver this > + * interrupt to the LPAR. So use VAS specific IRQ handler instead > + * of calling the default primary handler. > + */ > +static irqreturn_t pseries_vas_irq_handler(int irq, void *data) > +{ > + struct pseries_vas_window *txwin = data; > + > + /* > + * The thread hanlder will process this interrupt if it is > + * already running. > + */ > + atomic_inc(&txwin->pending_faults); > + > + return IRQ_WAKE_THREAD; > +} > + > /* > * Allocate window and setup IRQ mapping. > */ > @@ -240,8 +265,9 @@ static int allocate_setup_window(struct pseries_vas_window *txwin, > goto out_irq; > } > > - rc = request_threaded_irq(txwin->fault_virq, NULL, > - pseries_vas_fault_thread_fn, IRQF_ONESHOT, > + rc = request_threaded_irq(txwin->fault_virq, > + pseries_vas_irq_handler, > + pseries_vas_fault_thread_fn, 0, > txwin->name, txwin); > if (rc) { > pr_err("VAS-Window[%d]: Request IRQ(%u) failed with %d\n", > diff --git a/arch/powerpc/platforms/pseries/vas.h b/arch/powerpc/platforms/pseries/vas.h > index 333ffa2f9f42..a2cb12a31c17 100644 > --- a/arch/powerpc/platforms/pseries/vas.h > +++ b/arch/powerpc/platforms/pseries/vas.h > @@ -132,6 +132,7 @@ struct pseries_vas_window { > u64 flags; > char *name; > int fault_virq; > + atomic_t pending_faults; /* Number of pending faults */ > }; > > int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);
On Sun, 09 Oct 2022 20:41:25 -0700, Haren Myneni wrote: > 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. > > [...] Applied to powerpc/fixes. [1/1] powerpc/pseries/vas: Add VAS IRQ primary handler https://git.kernel.org/powerpc/c/89ed0b769d6adf30364f60e6b1566961821a9893 cheers
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index 1a2cbc156e8f..70f26efcc35a 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -200,16 +200,41 @@ static irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data) struct vas_user_win_ref *tsk_ref; int rc; - rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb)); - if (!rc) { - tsk_ref = &txwin->vas_win.task_ref; - vas_dump_crb(&crb); - vas_update_csb(&crb, tsk_ref); + while (atomic_read(&txwin->pending_faults)) { + rc = h_get_nx_fault(txwin->vas_win.winid, (u64)virt_to_phys(&crb)); + if (!rc) { + tsk_ref = &txwin->vas_win.task_ref; + vas_dump_crb(&crb); + vas_update_csb(&crb, tsk_ref); + } + atomic_dec(&txwin->pending_faults); } return IRQ_HANDLED; } +/* + * irq_default_primary_handler() can be used only with IRQF_ONESHOT + * which disables IRQ before executing the thread handler and enables + * it after. But this disabling interrupt sets the VAS IRQ OFF + * state in the hypervisor. If the NX generates fault interrupt + * during this window, the hypervisor will not deliver this + * interrupt to the LPAR. So use VAS specific IRQ handler instead + * of calling the default primary handler. + */ +static irqreturn_t pseries_vas_irq_handler(int irq, void *data) +{ + struct pseries_vas_window *txwin = data; + + /* + * The thread hanlder will process this interrupt if it is + * already running. + */ + atomic_inc(&txwin->pending_faults); + + return IRQ_WAKE_THREAD; +} + /* * Allocate window and setup IRQ mapping. */ @@ -240,8 +265,9 @@ static int allocate_setup_window(struct pseries_vas_window *txwin, goto out_irq; } - rc = request_threaded_irq(txwin->fault_virq, NULL, - pseries_vas_fault_thread_fn, IRQF_ONESHOT, + rc = request_threaded_irq(txwin->fault_virq, + pseries_vas_irq_handler, + pseries_vas_fault_thread_fn, 0, txwin->name, txwin); if (rc) { pr_err("VAS-Window[%d]: Request IRQ(%u) failed with %d\n", diff --git a/arch/powerpc/platforms/pseries/vas.h b/arch/powerpc/platforms/pseries/vas.h index 333ffa2f9f42..a2cb12a31c17 100644 --- a/arch/powerpc/platforms/pseries/vas.h +++ b/arch/powerpc/platforms/pseries/vas.h @@ -132,6 +132,7 @@ struct pseries_vas_window { u64 flags; char *name; int fault_virq; + atomic_t pending_faults; /* Number of pending faults */ }; int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);
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 <haren@linux.ibm.com> --- v3: Update pending_faults usage in changelog v2: Use the pending_faults counter for the second interrupt and process it with the previous interrupt handling if its thread handler is executing. arch/powerpc/platforms/pseries/vas.c | 40 +++++++++++++++++++++++----- arch/powerpc/platforms/pseries/vas.h | 1 + 2 files changed, 34 insertions(+), 7 deletions(-)