Skip to content

Commit 748f8de

Browse files
author
Mamatha Inamdar
committed
powerpc/pseries: Enable HVPIPE event message interrupt
JIRA: https://issues.redhat.com/browse/RHEL-101849 Conflicts: - Use rtas_token() instead of rtas_function_token() commit b48b6cc Author: Haren Myneni <haren@linux.ibm.com> Date: Tue Sep 9 01:43:59 2025 -0700 powerpc/pseries: Enable HVPIPE event message interrupt 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@linux.ibm.com> Tested-by: Shashank MS <shashank.gowda@in.ibm.com> Reviewed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com> Reviewed-by: Tyrel Datwyler <tyreld@linux.ibm.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20250909084402.1488456-8-haren@linux.ibm.com Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
1 parent 6768da8 commit 748f8de

File tree

2 files changed

+155
-5
lines changed

2 files changed

+155
-5
lines changed

arch/powerpc/platforms/pseries/papr-hvpipe.c

Lines changed: 141 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
static DEFINE_SPINLOCK(hvpipe_src_list_lock);
2323
static LIST_HEAD(hvpipe_src_list);
2424

25+
static unsigned char hvpipe_ras_buf[RTAS_ERROR_LOG_MAX];
26+
static struct workqueue_struct *papr_hvpipe_wq;
27+
static struct work_struct *papr_hvpipe_work;
28+
static int hvpipe_check_exception_token;
29+
2530
/*
2631
* New PowerPC FW provides support for partitions and various
2732
* sources (Ex: remote hardware management console (HMC)) to
@@ -554,6 +559,117 @@ static long papr_hvpipe_dev_ioctl(struct file *filp, unsigned int ioctl,
554559
return ret;
555560
}
556561

562+
/*
563+
* papr_hvpipe_work_fn - called to issue recv HVPIPE RTAS for
564+
* sources that are not monitored by user space so that pipe
565+
* will not be blocked.
566+
*/
567+
static void papr_hvpipe_work_fn(struct work_struct *work)
568+
{
569+
hvpipe_rtas_recv_msg(NULL, 0);
570+
}
571+
572+
/*
573+
* HVPIPE event message IRQ handler.
574+
* The hypervisor sends event IRQ if the partition has payload
575+
* and generates another event only after payload is read with
576+
* recv HVPIPE RTAS.
577+
*/
578+
static irqreturn_t hvpipe_event_interrupt(int irq, void *dev_id)
579+
{
580+
struct hvpipe_event_buf *hvpipe_event;
581+
struct pseries_errorlog *pseries_log;
582+
struct hvpipe_source_info *src_info;
583+
struct rtas_error_log *elog;
584+
int rc;
585+
586+
rc = rtas_call(hvpipe_check_exception_token, 6, 1, NULL,
587+
RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
588+
RTAS_HVPIPE_MSG_EVENTS, 1, __pa(&hvpipe_ras_buf),
589+
rtas_get_error_log_max());
590+
591+
if (rc != 0) {
592+
pr_err_ratelimited("unexpected hvpipe-event-notification failed %d\n", rc);
593+
return IRQ_HANDLED;
594+
}
595+
596+
elog = (struct rtas_error_log *)hvpipe_ras_buf;
597+
if (unlikely(rtas_error_type(elog) != RTAS_TYPE_HVPIPE)) {
598+
pr_warn_ratelimited("Unexpected event type %d\n",
599+
rtas_error_type(elog));
600+
return IRQ_HANDLED;
601+
}
602+
603+
pseries_log = get_pseries_errorlog(elog,
604+
PSERIES_ELOG_SECT_ID_HVPIPE_EVENT);
605+
hvpipe_event = (struct hvpipe_event_buf *)pseries_log->data;
606+
607+
/*
608+
* The hypervisor notifies partition when the payload is
609+
* available to read with recv HVPIPE RTAS and it will not
610+
* notify another event for any source until the previous
611+
* payload is read. Means the pipe is blocked in the
612+
* hypervisor until the payload is read.
613+
*
614+
* If the source is ready to accept payload and wakeup the
615+
* corresponding FD. Hold lock and update hvpipe_status
616+
* and this lock is needed in case the user space process
617+
* is in release FD instead of poll() so that release()
618+
* reads the payload to unblock pipe before closing FD.
619+
*
620+
* otherwise (means no other user process waiting for the
621+
* payload, issue recv HVPIPE RTAS (papr_hvpipe_work_fn())
622+
* to unblock pipe.
623+
*/
624+
spin_lock(&hvpipe_src_list_lock);
625+
src_info = hvpipe_find_source(be32_to_cpu(hvpipe_event->srcID));
626+
if (src_info) {
627+
u32 flags = 0;
628+
629+
if (hvpipe_event->event_type & HVPIPE_LOST_CONNECTION)
630+
flags = HVPIPE_LOST_CONNECTION;
631+
else if (hvpipe_event->event_type & HVPIPE_MSG_AVAILABLE)
632+
flags = HVPIPE_MSG_AVAILABLE;
633+
634+
src_info->hvpipe_status |= flags;
635+
wake_up(&src_info->recv_wqh);
636+
spin_unlock(&hvpipe_src_list_lock);
637+
} else {
638+
spin_unlock(&hvpipe_src_list_lock);
639+
/*
640+
* user space is not waiting on this source. So
641+
* execute receive pipe RTAS so that pipe will not
642+
* be blocked.
643+
*/
644+
if (hvpipe_event->event_type & HVPIPE_MSG_AVAILABLE)
645+
queue_work(papr_hvpipe_wq, papr_hvpipe_work);
646+
}
647+
648+
return IRQ_HANDLED;
649+
}
650+
651+
static int __init enable_hvpipe_IRQ(void)
652+
{
653+
struct device_node *np;
654+
655+
hvpipe_check_exception_token = rtas_token("check-exception");
656+
if (hvpipe_check_exception_token == RTAS_UNKNOWN_SERVICE)
657+
return -ENODEV;
658+
659+
/* hvpipe events */
660+
np = of_find_node_by_path("/event-sources/ibm,hvpipe-msg-events");
661+
if (np != NULL) {
662+
request_event_sources_irqs(np, hvpipe_event_interrupt,
663+
"HPIPE_EVENT");
664+
of_node_put(np);
665+
} else {
666+
pr_err("Can not enable hvpipe event IRQ\n");
667+
return -ENODEV;
668+
}
669+
670+
return 0;
671+
}
672+
557673
static const struct file_operations papr_hvpipe_ops = {
558674
.unlocked_ioctl = papr_hvpipe_dev_ioctl,
559675
};
@@ -576,12 +692,32 @@ static int __init papr_hvpipe_init(void)
576692
!rtas_service_present("ibm,receive-hvpipe-msg"))
577693
return -ENODEV;
578694

579-
ret = misc_register(&papr_hvpipe_dev);
580-
if (ret) {
581-
pr_err("misc-dev registration failed %d\n", ret);
582-
return ret;
695+
papr_hvpipe_work = kzalloc(sizeof(struct work_struct), GFP_ATOMIC);
696+
if (!papr_hvpipe_work)
697+
return -ENOMEM;
698+
699+
INIT_WORK(papr_hvpipe_work, papr_hvpipe_work_fn);
700+
701+
papr_hvpipe_wq = alloc_ordered_workqueue("papr hvpipe workqueue", 0);
702+
if (!papr_hvpipe_wq) {
703+
ret = -ENOMEM;
704+
goto out;
583705
}
584706

585-
return 0;
707+
ret = enable_hvpipe_IRQ();
708+
if (!ret)
709+
ret = misc_register(&papr_hvpipe_dev);
710+
711+
if (!ret) {
712+
pr_info("hvpipe feature is enabled\n");
713+
return 0;
714+
}
715+
716+
pr_err("hvpipe feature is not enabled %d\n", ret);
717+
destroy_workqueue(papr_hvpipe_wq);
718+
out:
719+
kfree(papr_hvpipe_work);
720+
papr_hvpipe_work = NULL;
721+
return ret;
586722
}
587723
machine_device_initcall(pseries, papr_hvpipe_init);

arch/powerpc/platforms/pseries/papr-hvpipe.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,18 @@ struct hvpipe_source_info {
1919
struct task_struct *tsk;
2020
};
2121

22+
/*
23+
* Source ID Format 0xCCRRQQQQ
24+
* CC = indicating value is source type (ex: 0x02 for HMC)
25+
* RR = 0x00 (reserved)
26+
* QQQQ = 0x0000 – 0xFFFF indicating the source index indetifier
27+
*/
28+
struct hvpipe_event_buf {
29+
__be32 srcID; /* Source ID */
30+
u8 event_type; /* 0x01 for hvpipe message available */
31+
/* from specified src ID */
32+
/* 0x02 for loss of pipe connection */
33+
/* with specified src ID */
34+
};
35+
2236
#endif /* _PAPR_HVPIPE_H */

0 commit comments

Comments
 (0)