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 <ha...@linux.ibm.com> > > Reviewed-by: Mahesh Salgaonkar <mah...@linux.ibm.com> > > Reviewed-by: Tyrel Datwyler <tyr...@linux.ibm.com> > > Tested-by: Shashank MS <shashank.go...@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 */