[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