[PATCH v4 7/9] powerpc/pseries: Enable HVPIPE event message interrupt

Haren Myneni haren at linux.ibm.com
Sun Sep 7 01:24:25 AEST 2025


On Sat, 2025-09-06 at 15:46 +0530, Madhavan Srinivasan wrote:
> 
> 
> On 8/30/25 11:33 AM, Haren Myneni wrote:
> > The hypervisor signals the OS via a Hypervisor Pipe Event external
> > interrupt when data is available to be received from the pipe.
> > Then the OS  should call RTAS check-exception and provide the input
> > Event Mask as defined for the ‘ibm,hvpipe-msg-events’. In response,
> > check-exception will return an event log containing an Pipe Events
> > message. This message contains the source ID for which this
> > message is intended to and the pipe status such as whether the
> > payload is pending in the hypervisor or pipe to source is closed.
> > 
> > If there is any user space process waiting in the wait_queue for
> > the payload from this source ID, wake up that process which can
> > issue read() to obtain payload with ibm,receive-hvpipe-msg RTAS
> > or close FD if the pipe to source is closed.
> > 
> > The hypervisor has one pipe per partition for all sources and it
> > will not deliver another hvpipe event message until the partition
> > reads the payload for the previous hvpipe event. So if the source
> > ID is not found in the source list, issue the dummy
> > ibm,receive-hvpipe-msg RTAS so that pipe will not blocked.
> > 
> > Register hvpipe event source interrupt based on entries from
> > /proc/device-tree//event-sources/ibm,hvpipe-msg-events property.
> > 
> > Signed-off-by: Haren Myneni <haren at linux.ibm.com>
> > Reviewed-by: Mahesh Salgaonkar <mahesh at linux.ibm.com>
> > Reviewed-by: Tyrel Datwyler <tyreld at linux.ibm.com>
> > Tested-by: Shashank MS <shashank.gowda at in.ibm.com>
> > ---
> >  arch/powerpc/platforms/pseries/papr-hvpipe.c | 146
> > ++++++++++++++++++-
> >  arch/powerpc/platforms/pseries/papr-hvpipe.h |  14 ++
> >  2 files changed, 155 insertions(+), 5 deletions(-)
> > 
> > diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c
> > b/arch/powerpc/platforms/pseries/papr-hvpipe.c
> > index 1e7636c0b275..0969efb39d95 100644
> > --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
> > +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
> > @@ -22,6 +22,11 @@
> >  static DEFINE_SPINLOCK(hvpipe_src_list_lock);
> >  static LIST_HEAD(hvpipe_src_list);
> >  
> > +static unsigned char hvpipe_ras_buf[RTAS_ERROR_LOG_MAX];
> > +static struct workqueue_struct *papr_hvpipe_wq;
> > +static struct work_struct *papr_hvpipe_work = NULL;
> > +static int hvpipe_check_exception_token;
> > +
> 
> checkpatch.pl is not happy, reporting these errors 
> 
> 
> ERROR: do not initialise statics to NULL
> #53: FILE: arch/powerpc/platforms/pseries/papr-hvpipe.c:27:
> +static struct work_struct *papr_hvpipe_work = NULL;
> 
> WARNING: else is not generally useful after a break or return
> #205: FILE: arch/powerpc/platforms/pseries/papr-hvpipe.c:716:
> +		return 0;
> +	} else
> 
> total: 1 errors, 1 warnings, 183 lines checked

Sorry, my mistake. Checked with checkpatch.pl initially, but later
changed. Will post V5 series.

Thanks
Haren
  
> 
> 
> 
> 
> >  /*
> >   * New PowerPC FW provides support for partitions and various
> >   * sources (Ex: remote hardware management console (HMC)) to
> > @@ -556,6 +561,117 @@ static long papr_hvpipe_dev_ioctl(struct file
> > *filp, unsigned int ioctl,
> >  	return ret;
> >  }
> >  
> > +/*
> > + * papr_hvpipe_work_fn - called to issue recv HVPIPE RTAS for
> > + * sources that are not monitored by user space so that pipe
> > + * will not be blocked.
> > + */
> > +static void papr_hvpipe_work_fn(struct work_struct *work)
> > +{
> > +	hvpipe_rtas_recv_msg(NULL, 0);
> > +}
> > +
> > +/*
> > + * HVPIPE event message IRQ handler.
> > + * The hypervisor sends event IRQ if the partition has payload
> > + * and generates another event only after payload is read with
> > + * recv HVPIPE RTAS.
> > + */
> > +static irqreturn_t hvpipe_event_interrupt(int irq, void *dev_id)
> > +{
> > +	struct hvpipe_event_buf *hvpipe_event;
> > +	struct pseries_errorlog *pseries_log;
> > +	struct hvpipe_source_info *src_info;
> > +	struct rtas_error_log *elog;
> > +	int rc;
> > +
> > +	rc = rtas_call(hvpipe_check_exception_token, 6, 1, NULL,
> > +		RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
> > +		RTAS_HVPIPE_MSG_EVENTS, 1, __pa(&hvpipe_ras_buf),
> > +		rtas_get_error_log_max());
> > +
> > +	if (rc != 0) {
> > +		pr_err_ratelimited("unexpected hvpipe-event-
> > notification failed %d\n", rc);
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	elog = (struct rtas_error_log *)hvpipe_ras_buf;
> > +	if (unlikely(rtas_error_type(elog) != RTAS_TYPE_HVPIPE)) {
> > +		pr_warn_ratelimited("Unexpected event type %d\n",
> > +				rtas_error_type(elog));
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	pseries_log = get_pseries_errorlog(elog,
> > +				PSERIES_ELOG_SECT_ID_HVPIPE_EVENT)
> > ;
> > +	hvpipe_event = (struct hvpipe_event_buf *)pseries_log-
> > >data;
> > +
> > +	/*
> > +	 * The hypervisor notifies partition when the payload is
> > +	 * available to read with recv HVPIPE RTAS and it will not
> > +	 * notify another event for any source until the previous
> > +	 * payload is read. Means the pipe is blocked in the
> > +	 * hypervisor until the payload is read.
> > +	 *
> > +	 * If the source is ready to accept payload and wakeup the
> > +	 * corresponding FD. Hold lock and update hvpipe_status
> > +	 * and this lock is needed in case the user space process
> > +	 * is in release FD instead of poll() so that release()
> > +	 * reads the payload to unblock pipe before closing FD.
> > +	 *
> > +	 * otherwise (means no other user process waiting for the
> > +	 * payload, issue recv HVPIPE RTAS (papr_hvpipe_work_fn())
> > +	 * to unblock pipe.
> > +	 */
> > +	spin_lock(&hvpipe_src_list_lock);
> > +	src_info = hvpipe_find_source(be32_to_cpu(hvpipe_event-
> > >srcID));
> > +	if (src_info) {
> > +		u32 flags = 0;
> > +
> > +		if (hvpipe_event->event_type &
> > HVPIPE_LOST_CONNECTION)
> > +			flags = HVPIPE_LOST_CONNECTION;
> > +		else if (hvpipe_event->event_type &
> > HVPIPE_MSG_AVAILABLE)
> > +			flags = HVPIPE_MSG_AVAILABLE;
> > +
> > +		src_info->hvpipe_status |= flags;
> > +		wake_up(&src_info->recv_wqh);
> > +		spin_unlock(&hvpipe_src_list_lock);
> > +	} else {
> > +		spin_unlock(&hvpipe_src_list_lock);
> > +		/*
> > +		 * user space is not waiting on this source. So
> > +		 * execute receive pipe RTAS so that pipe will not
> > +		 * be blocked.
> > +		 */
> > +		if (hvpipe_event->event_type &
> > HVPIPE_MSG_AVAILABLE)
> > +			queue_work(papr_hvpipe_wq,
> > papr_hvpipe_work);
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int __init enable_hvpipe_IRQ(void)
> > +{
> > +	struct device_node *np;
> > +
> > +	hvpipe_check_exception_token =
> > rtas_function_token(RTAS_FN_CHECK_EXCEPTION);
> > +	if (hvpipe_check_exception_token  == RTAS_UNKNOWN_SERVICE)
> > +		return -ENODEV;
> > +
> > +	/* hvpipe events */
> > +	np = of_find_node_by_path("/event-sources/ibm,hvpipe-msg-
> > events");
> > +	if (np != NULL) {
> > +		request_event_sources_irqs(np,
> > hvpipe_event_interrupt,
> > +					"HPIPE_EVENT");
> > +		of_node_put(np);
> > +	} else {
> > +		pr_err("Can not enable hvpipe event IRQ\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static const struct file_operations papr_hvpipe_ops = {
> >  	.unlocked_ioctl	=	papr_hvpipe_dev_ioctl,
> >  };
> > @@ -578,12 +694,32 @@ static int __init papr_hvpipe_init(void)
> >  		!rtas_function_implemented(RTAS_FN_IBM_RECEIVE_HVP
> > IPE_MSG))
> >  		return -ENODEV;
> >  
> > -	ret = misc_register(&papr_hvpipe_dev);
> > -	if (ret) {
> > -		pr_err("misc-dev registration failed %d\n", ret);
> > -		return ret;
> > +	papr_hvpipe_work = kzalloc(sizeof(struct work_struct),
> > GFP_ATOMIC);
> > +	if (!papr_hvpipe_work)
> > +		return -ENOMEM;
> > +
> > +	INIT_WORK(papr_hvpipe_work, papr_hvpipe_work_fn);
> > +
> > +	papr_hvpipe_wq = alloc_ordered_workqueue("papr hvpipe
> > workqueue", 0);
> > +	if (!papr_hvpipe_wq) {
> > +		ret = -ENOMEM;
> > +		goto out;
> >  	}
> >  
> > -	return 0;
> > +	ret = enable_hvpipe_IRQ();
> > +	if (!ret)
> > +		ret = misc_register(&papr_hvpipe_dev);
> > +
> > +	if (!ret) {
> > +		pr_info("hvpipe feature is enabled\n");
> > +		return 0;
> > +	} else
> > +		pr_err("hvpipe feature is not enabled %d\n", ret);
> > +
> > +	destroy_workqueue(papr_hvpipe_wq);
> > +out:
> > +	kfree(papr_hvpipe_work);
> > +	papr_hvpipe_work = NULL;
> > +	return ret;
> >  }
> >  machine_device_initcall(pseries, papr_hvpipe_init);
> > diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.h
> > b/arch/powerpc/platforms/pseries/papr-hvpipe.h
> > index 125658e6b596..aab7f77e087d 100644
> > --- a/arch/powerpc/platforms/pseries/papr-hvpipe.h
> > +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.h
> > @@ -19,4 +19,18 @@ struct hvpipe_source_info {
> >  	struct task_struct *tsk;
> >  };
> >  
> > +/*
> > + * Source ID Format 0xCCRRQQQQ
> > + * CC = indicating value is source type (ex: 0x02 for HMC)
> > + * RR = 0x00 (reserved)
> > + * QQQQ = 0x0000 – 0xFFFF indicating the source index indetifier
> > + */
> > +struct hvpipe_event_buf {
> > +	__be32	srcID;		/* Source ID */
> > +	u8	event_type;	/* 0x01 for hvpipe message
> > available */
> > +				/* from specified src ID */
> > +				/* 0x02 for loss of pipe
> > connection */
> > +				/* with specified src ID */
> > +};
> > +
> >  #endif /* _PAPR_HVPIPE_H */


More information about the Linuxppc-dev mailing list