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 <[email protected]>
> Reviewed-by: Mahesh Salgaonkar <[email protected]>
> Reviewed-by: Tyrel Datwyler <[email protected]>
> Tested-by: Shashank MS <[email protected]>
> ---
>  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




>  /*
>   * 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_HVPIPE_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 */


Reply via email to