[PATCH v3] powerpc/pseries/vas: Add VAS IRQ primary handler
Frederic Barrat
fbarrat at linux.ibm.com
Wed Oct 12 01:30:10 AEDT 2022
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 at linux.ibm.com>
> ---
That version looks good to me.
Reviewed-by: Frederic Barrat <fbarrat at 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);
More information about the Linuxppc-dev
mailing list