xref: /linux/arch/powerpc/platforms/pseries/papr-hvpipe.c (revision 417552999d0b6681ac30e117ae890828ca7e46b3)
1814ef095SHaren Myneni // SPDX-License-Identifier: GPL-2.0-only
2814ef095SHaren Myneni 
3814ef095SHaren Myneni #define pr_fmt(fmt) "papr-hvpipe: " fmt
4814ef095SHaren Myneni 
5814ef095SHaren Myneni #include <linux/module.h>
6814ef095SHaren Myneni #include <linux/kernel.h>
7814ef095SHaren Myneni #include <linux/types.h>
8814ef095SHaren Myneni #include <linux/delay.h>
9814ef095SHaren Myneni #include <linux/anon_inodes.h>
10814ef095SHaren Myneni #include <linux/miscdevice.h>
11814ef095SHaren Myneni #include <linux/file.h>
12814ef095SHaren Myneni #include <linux/fs.h>
13814ef095SHaren Myneni #include <linux/poll.h>
14814ef095SHaren Myneni #include <linux/of.h>
15814ef095SHaren Myneni #include <asm/machdep.h>
16814ef095SHaren Myneni #include <asm/rtas.h>
1756dbc667SHaren Myneni #include <asm/rtas-work-area.h>
1839a08a4fSHaren Myneni #include <asm/papr-sysparm.h>
19814ef095SHaren Myneni #include <uapi/asm/papr-hvpipe.h>
20814ef095SHaren Myneni #include "pseries.h"
21814ef095SHaren Myneni #include "papr-hvpipe.h"
22814ef095SHaren Myneni 
23814ef095SHaren Myneni static DEFINE_SPINLOCK(hvpipe_src_list_lock);
24814ef095SHaren Myneni static LIST_HEAD(hvpipe_src_list);
25814ef095SHaren Myneni 
26b48b6cc8SHaren Myneni static unsigned char hvpipe_ras_buf[RTAS_ERROR_LOG_MAX];
27b48b6cc8SHaren Myneni static struct workqueue_struct *papr_hvpipe_wq;
28b48b6cc8SHaren Myneni static struct work_struct *papr_hvpipe_work;
29b48b6cc8SHaren Myneni static int hvpipe_check_exception_token;
30*6d84f851SHaren Myneni static bool hvpipe_feature;
31b48b6cc8SHaren Myneni 
32814ef095SHaren Myneni /*
33814ef095SHaren Myneni  * New PowerPC FW provides support for partitions and various
34814ef095SHaren Myneni  * sources (Ex: remote hardware management console (HMC)) to
35814ef095SHaren Myneni  * exchange information through an inband hypervisor channel
36814ef095SHaren Myneni  * called HVPIPE. Only HMCs are supported right now and
37814ef095SHaren Myneni  * partitions can communicate with multiple HMCs and each
38814ef095SHaren Myneni  * source represented by source ID.
39814ef095SHaren Myneni  *
40814ef095SHaren Myneni  * FW introduces send HVPIPE and recv HVPIPE RTAS calls for
41814ef095SHaren Myneni  * partitions to send and receive payloads respectively.
42814ef095SHaren Myneni  *
43814ef095SHaren Myneni  * These RTAS functions have the following certain requirements
44814ef095SHaren Myneni  * / limitations:
45814ef095SHaren Myneni  * - One hvpipe per partition for all sources.
46814ef095SHaren Myneni  * - Assume the return status of send HVPIPE as delivered to source
47814ef095SHaren Myneni  * - Assume the return status of recv HVPIPE as ACK to source
48814ef095SHaren Myneni  * - Generates HVPIPE event message when the payload is ready
49814ef095SHaren Myneni  *   for the partition. The hypervisor will not deliver another
50814ef095SHaren Myneni  *   event until the partition read the previous payload which
51814ef095SHaren Myneni  *   means the pipe is blocked for any sources.
52814ef095SHaren Myneni  *
53814ef095SHaren Myneni  * Linux implementation:
54814ef095SHaren Myneni  * Follow the similar interfaces that the OS has for other RTAS calls.
55814ef095SHaren Myneni  * ex: /dev/papr-indices, /dev/papr-vpd, etc.
56814ef095SHaren Myneni  * - /dev/papr-hvpipe is available for the user space.
57814ef095SHaren Myneni  * - devfd = open("/dev/papr-hvpipe", ..)
58814ef095SHaren Myneni  * - fd = ioctl(fd,HVPIPE_IOC_CREATE_HANDLE,&srcID)-for each source
59814ef095SHaren Myneni  * - write(fd, buf, size) --> Issue send HVPIPE RTAS call and
60814ef095SHaren Myneni  *   returns size for success or the corresponding error for RTAS
61814ef095SHaren Myneni  *   return code for failure.
62814ef095SHaren Myneni  * - poll(fd,..) -> wakeup FD if the payload is available to read.
63814ef095SHaren Myneni  *   HVPIPE event message handler wakeup FD based on source ID in
64814ef095SHaren Myneni  *   the event message
65814ef095SHaren Myneni  * - read(fd, buf, size) --> Issue recv HVPIPE RTAS call and
66814ef095SHaren Myneni  *   returns size for success or the corresponding error for RTAS
67814ef095SHaren Myneni  *   return code for failure.
68814ef095SHaren Myneni  */
69814ef095SHaren Myneni 
7056dbc667SHaren Myneni /*
71cebdb522SHaren Myneni  * ibm,receive-hvpipe-msg RTAS call.
72cebdb522SHaren Myneni  * @area: Caller-provided work area buffer for results.
73cebdb522SHaren Myneni  * @srcID: Source ID returned by the RTAS call.
74cebdb522SHaren Myneni  * @bytesw: Bytes written by RTAS call to @area.
75cebdb522SHaren Myneni  */
rtas_ibm_receive_hvpipe_msg(struct rtas_work_area * area,u32 * srcID,u32 * bytesw)76cebdb522SHaren Myneni static int rtas_ibm_receive_hvpipe_msg(struct rtas_work_area *area,
77cebdb522SHaren Myneni 					u32 *srcID, u32 *bytesw)
78cebdb522SHaren Myneni {
79cebdb522SHaren Myneni 	const s32 token = rtas_function_token(RTAS_FN_IBM_RECEIVE_HVPIPE_MSG);
80cebdb522SHaren Myneni 	u32 rets[2];
81cebdb522SHaren Myneni 	s32 fwrc;
82cebdb522SHaren Myneni 	int ret;
83cebdb522SHaren Myneni 
84cebdb522SHaren Myneni 	if (token == RTAS_UNKNOWN_SERVICE)
85cebdb522SHaren Myneni 		return -ENOENT;
86cebdb522SHaren Myneni 
87cebdb522SHaren Myneni 	do {
88cebdb522SHaren Myneni 		fwrc = rtas_call(token, 2, 3, rets,
89cebdb522SHaren Myneni 				rtas_work_area_phys(area),
90cebdb522SHaren Myneni 				rtas_work_area_size(area));
91cebdb522SHaren Myneni 
92cebdb522SHaren Myneni 	} while (rtas_busy_delay(fwrc));
93cebdb522SHaren Myneni 
94cebdb522SHaren Myneni 	switch (fwrc) {
95cebdb522SHaren Myneni 	case RTAS_SUCCESS:
96cebdb522SHaren Myneni 		*srcID = rets[0];
97cebdb522SHaren Myneni 		*bytesw = rets[1];
98cebdb522SHaren Myneni 		ret = 0;
99cebdb522SHaren Myneni 		break;
100cebdb522SHaren Myneni 	case RTAS_HARDWARE_ERROR:
101cebdb522SHaren Myneni 		ret = -EIO;
102cebdb522SHaren Myneni 		break;
103cebdb522SHaren Myneni 	case RTAS_INVALID_PARAMETER:
104cebdb522SHaren Myneni 		ret = -EINVAL;
105cebdb522SHaren Myneni 		break;
106cebdb522SHaren Myneni 	case RTAS_FUNC_NOT_SUPPORTED:
107cebdb522SHaren Myneni 		ret = -EOPNOTSUPP;
108cebdb522SHaren Myneni 		break;
109cebdb522SHaren Myneni 	default:
110cebdb522SHaren Myneni 		ret = -EIO;
111cebdb522SHaren Myneni 		pr_err_ratelimited("unexpected ibm,receive-hvpipe-msg status %d\n", fwrc);
112cebdb522SHaren Myneni 		break;
113cebdb522SHaren Myneni 	}
114cebdb522SHaren Myneni 
115cebdb522SHaren Myneni 	return ret;
116cebdb522SHaren Myneni }
117cebdb522SHaren Myneni 
118cebdb522SHaren Myneni /*
11956dbc667SHaren Myneni  * ibm,send-hvpipe-msg RTAS call
12056dbc667SHaren Myneni  * @area: Caller-provided work area buffer to send.
12156dbc667SHaren Myneni  * @srcID: Target source for the send pipe message.
12256dbc667SHaren Myneni  */
rtas_ibm_send_hvpipe_msg(struct rtas_work_area * area,u32 srcID)12356dbc667SHaren Myneni static int rtas_ibm_send_hvpipe_msg(struct rtas_work_area *area, u32 srcID)
12456dbc667SHaren Myneni {
12556dbc667SHaren Myneni 	const s32 token = rtas_function_token(RTAS_FN_IBM_SEND_HVPIPE_MSG);
12656dbc667SHaren Myneni 	s32 fwrc;
12756dbc667SHaren Myneni 	int ret;
12856dbc667SHaren Myneni 
12956dbc667SHaren Myneni 	if (token == RTAS_UNKNOWN_SERVICE)
13056dbc667SHaren Myneni 		return -ENOENT;
13156dbc667SHaren Myneni 
13256dbc667SHaren Myneni 	do {
13356dbc667SHaren Myneni 		fwrc = rtas_call(token, 2, 1, NULL, srcID,
13456dbc667SHaren Myneni 				rtas_work_area_phys(area));
13556dbc667SHaren Myneni 
13656dbc667SHaren Myneni 	} while (rtas_busy_delay(fwrc));
13756dbc667SHaren Myneni 
13856dbc667SHaren Myneni 	switch (fwrc) {
13956dbc667SHaren Myneni 	case RTAS_SUCCESS:
14056dbc667SHaren Myneni 		ret = 0;
14156dbc667SHaren Myneni 		break;
14256dbc667SHaren Myneni 	case RTAS_HARDWARE_ERROR:
14356dbc667SHaren Myneni 		ret = -EIO;
14456dbc667SHaren Myneni 		break;
14556dbc667SHaren Myneni 	case RTAS_INVALID_PARAMETER:
14656dbc667SHaren Myneni 		ret = -EINVAL;
14756dbc667SHaren Myneni 		break;
14856dbc667SHaren Myneni 	case RTAS_HVPIPE_CLOSED:
14956dbc667SHaren Myneni 		ret = -EPIPE;
15056dbc667SHaren Myneni 		break;
15156dbc667SHaren Myneni 	case RTAS_FUNC_NOT_SUPPORTED:
15256dbc667SHaren Myneni 		ret = -EOPNOTSUPP;
15356dbc667SHaren Myneni 		break;
15456dbc667SHaren Myneni 	default:
15556dbc667SHaren Myneni 		ret = -EIO;
15656dbc667SHaren Myneni 		pr_err_ratelimited("unexpected ibm,receive-hvpipe-msg status %d\n", fwrc);
15756dbc667SHaren Myneni 		break;
15856dbc667SHaren Myneni 	}
15956dbc667SHaren Myneni 
16056dbc667SHaren Myneni 	return ret;
16156dbc667SHaren Myneni }
16256dbc667SHaren Myneni 
hvpipe_find_source(u32 srcID)163814ef095SHaren Myneni static struct hvpipe_source_info *hvpipe_find_source(u32 srcID)
164814ef095SHaren Myneni {
165814ef095SHaren Myneni 	struct hvpipe_source_info *src_info;
166814ef095SHaren Myneni 
167814ef095SHaren Myneni 	list_for_each_entry(src_info, &hvpipe_src_list, list)
168814ef095SHaren Myneni 		if (src_info->srcID == srcID)
169814ef095SHaren Myneni 			return src_info;
170814ef095SHaren Myneni 
171814ef095SHaren Myneni 	return NULL;
172814ef095SHaren Myneni }
173814ef095SHaren Myneni 
174814ef095SHaren Myneni /*
175cebdb522SHaren Myneni  * This work function collects receive buffer with recv HVPIPE
176cebdb522SHaren Myneni  * RTAS call. Called from read()
177cebdb522SHaren Myneni  * @buf: User specified buffer to copy the payload that returned
178cebdb522SHaren Myneni  *       from recv HVPIPE RTAS.
179cebdb522SHaren Myneni  * @size: Size of buffer user passed.
180cebdb522SHaren Myneni  */
hvpipe_rtas_recv_msg(char __user * buf,int size)181cebdb522SHaren Myneni static int hvpipe_rtas_recv_msg(char __user *buf, int size)
182cebdb522SHaren Myneni {
183cebdb522SHaren Myneni 	struct rtas_work_area *work_area;
184cebdb522SHaren Myneni 	u32 srcID, bytes_written;
185cebdb522SHaren Myneni 	int ret;
186cebdb522SHaren Myneni 
187cebdb522SHaren Myneni 	work_area = rtas_work_area_alloc(SZ_4K);
188cebdb522SHaren Myneni 	if (!work_area) {
189cebdb522SHaren Myneni 		pr_err("Could not allocate RTAS buffer for recv pipe\n");
190cebdb522SHaren Myneni 		return -ENOMEM;
191cebdb522SHaren Myneni 	}
192cebdb522SHaren Myneni 
193cebdb522SHaren Myneni 	ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID,
194cebdb522SHaren Myneni 					&bytes_written);
195cebdb522SHaren Myneni 	if (!ret) {
196cebdb522SHaren Myneni 		/*
197cebdb522SHaren Myneni 		 * Recv HVPIPE RTAS is successful.
198cebdb522SHaren Myneni 		 * When releasing FD or no one is waiting on the
199cebdb522SHaren Myneni 		 * specific source, issue recv HVPIPE RTAS call
200cebdb522SHaren Myneni 		 * so that pipe is not blocked - this func is called
201cebdb522SHaren Myneni 		 * with NULL buf.
202cebdb522SHaren Myneni 		 */
203cebdb522SHaren Myneni 		if (buf) {
204cebdb522SHaren Myneni 			if (size < bytes_written) {
205cebdb522SHaren Myneni 				pr_err("Received the payload size = %d, but the buffer size = %d\n",
206cebdb522SHaren Myneni 					bytes_written, size);
207cebdb522SHaren Myneni 				bytes_written = size;
208cebdb522SHaren Myneni 			}
209cebdb522SHaren Myneni 			ret = copy_to_user(buf,
210cebdb522SHaren Myneni 					rtas_work_area_raw_buf(work_area),
211cebdb522SHaren Myneni 					bytes_written);
212cebdb522SHaren Myneni 			if (!ret)
213cebdb522SHaren Myneni 				ret = bytes_written;
214cebdb522SHaren Myneni 		}
215cebdb522SHaren Myneni 	} else {
216cebdb522SHaren Myneni 		pr_err("ibm,receive-hvpipe-msg failed with %d\n",
217cebdb522SHaren Myneni 				ret);
218cebdb522SHaren Myneni 	}
219cebdb522SHaren Myneni 
220cebdb522SHaren Myneni 	rtas_work_area_free(work_area);
221cebdb522SHaren Myneni 	return ret;
222cebdb522SHaren Myneni }
223cebdb522SHaren Myneni 
224cebdb522SHaren Myneni /*
225814ef095SHaren Myneni  * papr_hvpipe_handle_write -  Issue send HVPIPE RTAS and return
226cebdb522SHaren Myneni  * the size (payload + HVPIPE_HDR_LEN) for RTAS success.
227cebdb522SHaren Myneni  * Otherwise returns the status of RTAS to the user space
228814ef095SHaren Myneni  */
papr_hvpipe_handle_write(struct file * file,const char __user * buf,size_t size,loff_t * off)229814ef095SHaren Myneni static ssize_t papr_hvpipe_handle_write(struct file *file,
230814ef095SHaren Myneni 	const char __user *buf, size_t size, loff_t *off)
231814ef095SHaren Myneni {
232814ef095SHaren Myneni 	struct hvpipe_source_info *src_info = file->private_data;
23356dbc667SHaren Myneni 	struct rtas_work_area *work_area, *work_buf;
23456dbc667SHaren Myneni 	unsigned long ret, len;
23556dbc667SHaren Myneni 	__be64 *area_be;
236814ef095SHaren Myneni 
237*6d84f851SHaren Myneni 	/*
238*6d84f851SHaren Myneni 	 * Return -ENXIO during migration
239*6d84f851SHaren Myneni 	 */
240*6d84f851SHaren Myneni 	if (!hvpipe_feature)
241*6d84f851SHaren Myneni 		return -ENXIO;
242*6d84f851SHaren Myneni 
243814ef095SHaren Myneni 	if (!src_info)
244814ef095SHaren Myneni 		return -EIO;
245814ef095SHaren Myneni 
24656dbc667SHaren Myneni 	/*
24756dbc667SHaren Myneni 	 * Send HVPIPE RTAS is used to send payload to the specific
24856dbc667SHaren Myneni 	 * source with the input parameters source ID and the payload
24956dbc667SHaren Myneni 	 * as buffer list. Each entry in the buffer list contains
25056dbc667SHaren Myneni 	 * address/length pair of the buffer.
25156dbc667SHaren Myneni 	 *
25256dbc667SHaren Myneni 	 * The buffer list format is as follows:
25356dbc667SHaren Myneni 	 *
25456dbc667SHaren Myneni 	 * Header (length of address/length pairs and the header length)
25556dbc667SHaren Myneni 	 * Address of 4K buffer 1
25656dbc667SHaren Myneni 	 * Length of 4K buffer 1 used
25756dbc667SHaren Myneni 	 * ...
25856dbc667SHaren Myneni 	 * Address of 4K buffer n
25956dbc667SHaren Myneni 	 * Length of 4K buffer n used
26056dbc667SHaren Myneni 	 *
26156dbc667SHaren Myneni 	 * See PAPR 7.3.32.2 ibm,send-hvpipe-msg
26256dbc667SHaren Myneni 	 *
26356dbc667SHaren Myneni 	 * Even though can support max 1MB payload, the hypervisor
26456dbc667SHaren Myneni 	 * supports only 4048 bytes payload at present and also
26556dbc667SHaren Myneni 	 * just one address/length entry.
26656dbc667SHaren Myneni 	 *
26756dbc667SHaren Myneni 	 * writev() interface can be added in future when the
26856dbc667SHaren Myneni 	 * hypervisor supports multiple buffer list entries.
26956dbc667SHaren Myneni 	 */
27056dbc667SHaren Myneni 	/* HVPIPE_MAX_WRITE_BUFFER_SIZE = 4048 bytes */
27156dbc667SHaren Myneni 	if ((size > (HVPIPE_HDR_LEN + HVPIPE_MAX_WRITE_BUFFER_SIZE)) ||
27256dbc667SHaren Myneni 		(size <= HVPIPE_HDR_LEN))
27356dbc667SHaren Myneni 		return -EINVAL;
27456dbc667SHaren Myneni 
27556dbc667SHaren Myneni 	/*
27656dbc667SHaren Myneni 	 * The length of (address + length) pair + the length of header
27756dbc667SHaren Myneni 	 */
27856dbc667SHaren Myneni 	len = (2 * sizeof(u64)) + sizeof(u64);
27956dbc667SHaren Myneni 	size -= HVPIPE_HDR_LEN;
28056dbc667SHaren Myneni 	buf += HVPIPE_HDR_LEN;
28156dbc667SHaren Myneni 	mutex_lock(&rtas_ibm_send_hvpipe_msg_lock);
28256dbc667SHaren Myneni 	work_area = rtas_work_area_alloc(SZ_4K);
28356dbc667SHaren Myneni 	if (!work_area) {
28456dbc667SHaren Myneni 		ret = -ENOMEM;
28556dbc667SHaren Myneni 		goto out;
28656dbc667SHaren Myneni 	}
28756dbc667SHaren Myneni 	area_be = (__be64 *)rtas_work_area_raw_buf(work_area);
28856dbc667SHaren Myneni 	/* header */
28956dbc667SHaren Myneni 	area_be[0] = cpu_to_be64(len);
29056dbc667SHaren Myneni 
29156dbc667SHaren Myneni 	work_buf = rtas_work_area_alloc(SZ_4K);
29256dbc667SHaren Myneni 	if (!work_buf) {
29356dbc667SHaren Myneni 		ret = -ENOMEM;
29456dbc667SHaren Myneni 		goto out_work;
29556dbc667SHaren Myneni 	}
29656dbc667SHaren Myneni 	/* First buffer address */
29756dbc667SHaren Myneni 	area_be[1] = cpu_to_be64(rtas_work_area_phys(work_buf));
29856dbc667SHaren Myneni 	/* First buffer address length */
29956dbc667SHaren Myneni 	area_be[2] = cpu_to_be64(size);
30056dbc667SHaren Myneni 
30156dbc667SHaren Myneni 	if (!copy_from_user(rtas_work_area_raw_buf(work_buf), buf, size)) {
30256dbc667SHaren Myneni 		ret = rtas_ibm_send_hvpipe_msg(work_area, src_info->srcID);
30356dbc667SHaren Myneni 		if (!ret)
30456dbc667SHaren Myneni 			ret = size + HVPIPE_HDR_LEN;
30556dbc667SHaren Myneni 	} else
30656dbc667SHaren Myneni 		ret = -EPERM;
30756dbc667SHaren Myneni 
30856dbc667SHaren Myneni 	rtas_work_area_free(work_buf);
30956dbc667SHaren Myneni out_work:
31056dbc667SHaren Myneni 	rtas_work_area_free(work_area);
31156dbc667SHaren Myneni out:
31256dbc667SHaren Myneni 	mutex_unlock(&rtas_ibm_send_hvpipe_msg_lock);
31356dbc667SHaren Myneni 	return ret;
314814ef095SHaren Myneni }
315814ef095SHaren Myneni 
316814ef095SHaren Myneni /*
317814ef095SHaren Myneni  * papr_hvpipe_handle_read - If the payload for the specific
318814ef095SHaren Myneni  * source is pending in the hypervisor, issue recv HVPIPE RTAS
319814ef095SHaren Myneni  * and return the payload to the user space.
320814ef095SHaren Myneni  *
321814ef095SHaren Myneni  * When the payload is available for the partition, the
322814ef095SHaren Myneni  * hypervisor notifies HVPIPE event with the source ID
323814ef095SHaren Myneni  * and the event handler wakeup FD(s) that are waiting.
324814ef095SHaren Myneni  */
papr_hvpipe_handle_read(struct file * file,char __user * buf,size_t size,loff_t * off)325814ef095SHaren Myneni static ssize_t papr_hvpipe_handle_read(struct file *file,
326814ef095SHaren Myneni 		char __user *buf, size_t size, loff_t *off)
327814ef095SHaren Myneni {
328814ef095SHaren Myneni 
329814ef095SHaren Myneni 	struct hvpipe_source_info *src_info = file->private_data;
330cebdb522SHaren Myneni 	struct papr_hvpipe_hdr hdr;
331cebdb522SHaren Myneni 	long ret;
332814ef095SHaren Myneni 
333*6d84f851SHaren Myneni 	/*
334*6d84f851SHaren Myneni 	 * Return -ENXIO during migration
335*6d84f851SHaren Myneni 	 */
336*6d84f851SHaren Myneni 	if (!hvpipe_feature)
337*6d84f851SHaren Myneni 		return -ENXIO;
338*6d84f851SHaren Myneni 
339814ef095SHaren Myneni 	if (!src_info)
340814ef095SHaren Myneni 		return -EIO;
341814ef095SHaren Myneni 
342cebdb522SHaren Myneni 	/*
343cebdb522SHaren Myneni 	 * Max payload is 4048 (HVPIPE_MAX_WRITE_BUFFER_SIZE)
344cebdb522SHaren Myneni 	 */
345cebdb522SHaren Myneni 	if ((size > (HVPIPE_HDR_LEN + HVPIPE_MAX_WRITE_BUFFER_SIZE)) ||
346cebdb522SHaren Myneni 		(size < HVPIPE_HDR_LEN))
347cebdb522SHaren Myneni 		return -EINVAL;
348cebdb522SHaren Myneni 
349cebdb522SHaren Myneni 	/*
350cebdb522SHaren Myneni 	 * Payload is not available to receive or source pipe
351cebdb522SHaren Myneni 	 * is not closed.
352cebdb522SHaren Myneni 	 */
353cebdb522SHaren Myneni 	if (!src_info->hvpipe_status)
354814ef095SHaren Myneni 		return 0;
355cebdb522SHaren Myneni 
356cebdb522SHaren Myneni 	hdr.version = 0;
357cebdb522SHaren Myneni 	hdr.flags = 0;
358cebdb522SHaren Myneni 
359cebdb522SHaren Myneni 	/*
360cebdb522SHaren Myneni 	 * In case if the hvpipe has payload and also the
361cebdb522SHaren Myneni 	 * hypervisor closed the pipe to the source, retrieve
362cebdb522SHaren Myneni 	 * the payload and return to the user space first and
363cebdb522SHaren Myneni 	 * then notify the userspace about the hvpipe close in
364cebdb522SHaren Myneni 	 * next read().
365cebdb522SHaren Myneni 	 */
366cebdb522SHaren Myneni 	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE)
367cebdb522SHaren Myneni 		hdr.flags = HVPIPE_MSG_AVAILABLE;
368cebdb522SHaren Myneni 	else if (src_info->hvpipe_status & HVPIPE_LOST_CONNECTION)
369cebdb522SHaren Myneni 		hdr.flags = HVPIPE_LOST_CONNECTION;
370cebdb522SHaren Myneni 	else
371cebdb522SHaren Myneni 		/*
372cebdb522SHaren Myneni 		 * Should not be here without one of the above
373cebdb522SHaren Myneni 		 * flags set
374cebdb522SHaren Myneni 		 */
375cebdb522SHaren Myneni 		return -EIO;
376cebdb522SHaren Myneni 
377cebdb522SHaren Myneni 	ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN);
378cebdb522SHaren Myneni 	if (ret)
379cebdb522SHaren Myneni 		return ret;
380cebdb522SHaren Myneni 
381cebdb522SHaren Myneni 	/*
382cebdb522SHaren Myneni 	 * Message event has payload, so get the payload with
383cebdb522SHaren Myneni 	 * recv HVPIPE RTAS.
384cebdb522SHaren Myneni 	 */
385cebdb522SHaren Myneni 	if (hdr.flags & HVPIPE_MSG_AVAILABLE) {
386cebdb522SHaren Myneni 		ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN,
387cebdb522SHaren Myneni 				size - HVPIPE_HDR_LEN);
388cebdb522SHaren Myneni 		if (ret > 0) {
389cebdb522SHaren Myneni 			src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE;
390cebdb522SHaren Myneni 			ret += HVPIPE_HDR_LEN;
391cebdb522SHaren Myneni 		}
392cebdb522SHaren Myneni 	} else if (hdr.flags & HVPIPE_LOST_CONNECTION) {
393cebdb522SHaren Myneni 		/*
394cebdb522SHaren Myneni 		 * Hypervisor is closing the pipe for the specific
395cebdb522SHaren Myneni 		 * source. So notify user space.
396cebdb522SHaren Myneni 		 */
397cebdb522SHaren Myneni 		src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION;
398cebdb522SHaren Myneni 		ret = HVPIPE_HDR_LEN;
399cebdb522SHaren Myneni 	}
400cebdb522SHaren Myneni 
401cebdb522SHaren Myneni 	return ret;
402814ef095SHaren Myneni }
403814ef095SHaren Myneni 
404814ef095SHaren Myneni /*
405814ef095SHaren Myneni  * The user space waits for the payload to receive.
406814ef095SHaren Myneni  * The hypervisor sends HVPIPE event message to the partition
407814ef095SHaren Myneni  * when the payload is available. The event handler wakeup FD
408814ef095SHaren Myneni  * depends on the source ID in the message event.
409814ef095SHaren Myneni  */
papr_hvpipe_handle_poll(struct file * filp,struct poll_table_struct * wait)410814ef095SHaren Myneni static __poll_t papr_hvpipe_handle_poll(struct file *filp,
411814ef095SHaren Myneni 		struct poll_table_struct *wait)
412814ef095SHaren Myneni {
413814ef095SHaren Myneni 	struct hvpipe_source_info *src_info = filp->private_data;
414814ef095SHaren Myneni 
415*6d84f851SHaren Myneni 	/*
416*6d84f851SHaren Myneni 	 * HVPIPE is disabled during SUSPEND and enabled after migration.
417*6d84f851SHaren Myneni 	 * So return POLLRDHUP during migration
418*6d84f851SHaren Myneni 	 */
419*6d84f851SHaren Myneni 	if (!hvpipe_feature)
420*6d84f851SHaren Myneni 		return POLLRDHUP;
421*6d84f851SHaren Myneni 
422814ef095SHaren Myneni 	if (!src_info)
423814ef095SHaren Myneni 		return POLLNVAL;
424814ef095SHaren Myneni 
425da24fb99SHaren Myneni 	/*
426da24fb99SHaren Myneni 	 * If hvpipe already has pending payload, return so that
427da24fb99SHaren Myneni 	 * the user space can issue read().
428da24fb99SHaren Myneni 	 */
429da24fb99SHaren Myneni 	if (src_info->hvpipe_status)
430da24fb99SHaren Myneni 		return POLLIN | POLLRDNORM;
431da24fb99SHaren Myneni 
432da24fb99SHaren Myneni 	/*
433da24fb99SHaren Myneni 	 * Wait for the message event
434da24fb99SHaren Myneni 	 * hvpipe_event_interrupt() wakes up this wait_queue
435da24fb99SHaren Myneni 	 */
436da24fb99SHaren Myneni 	poll_wait(filp, &src_info->recv_wqh, wait);
437da24fb99SHaren Myneni 	if (src_info->hvpipe_status)
438da24fb99SHaren Myneni 		return POLLIN | POLLRDNORM;
439da24fb99SHaren Myneni 
440814ef095SHaren Myneni 	return 0;
441814ef095SHaren Myneni }
442814ef095SHaren Myneni 
papr_hvpipe_handle_release(struct inode * inode,struct file * file)443814ef095SHaren Myneni static int papr_hvpipe_handle_release(struct inode *inode,
444814ef095SHaren Myneni 				struct file *file)
445814ef095SHaren Myneni {
446814ef095SHaren Myneni 	struct hvpipe_source_info *src_info;
447814ef095SHaren Myneni 
448814ef095SHaren Myneni 	/*
449814ef095SHaren Myneni 	 * Hold the lock, remove source from src_list, reset the
450814ef095SHaren Myneni 	 * hvpipe status and release the lock to prevent any race
451814ef095SHaren Myneni 	 * with message event IRQ.
452814ef095SHaren Myneni 	 */
453814ef095SHaren Myneni 	spin_lock(&hvpipe_src_list_lock);
454814ef095SHaren Myneni 	src_info = file->private_data;
455814ef095SHaren Myneni 	list_del(&src_info->list);
456814ef095SHaren Myneni 	file->private_data = NULL;
457da24fb99SHaren Myneni 	/*
458da24fb99SHaren Myneni 	 * If the pipe for this specific source has any pending
459da24fb99SHaren Myneni 	 * payload, issue recv HVPIPE RTAS so that pipe will not
460da24fb99SHaren Myneni 	 * be blocked.
461da24fb99SHaren Myneni 	 */
462da24fb99SHaren Myneni 	if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
463da24fb99SHaren Myneni 		src_info->hvpipe_status = 0;
464814ef095SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
465da24fb99SHaren Myneni 		hvpipe_rtas_recv_msg(NULL, 0);
466da24fb99SHaren Myneni 	} else
467da24fb99SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
468da24fb99SHaren Myneni 
469814ef095SHaren Myneni 	kfree(src_info);
470814ef095SHaren Myneni 	return 0;
471814ef095SHaren Myneni }
472814ef095SHaren Myneni 
473814ef095SHaren Myneni static const struct file_operations papr_hvpipe_handle_ops = {
474814ef095SHaren Myneni 	.read		=	papr_hvpipe_handle_read,
475814ef095SHaren Myneni 	.write		=	papr_hvpipe_handle_write,
476814ef095SHaren Myneni 	.release	=	papr_hvpipe_handle_release,
477814ef095SHaren Myneni 	.poll		=	papr_hvpipe_handle_poll,
478814ef095SHaren Myneni };
479814ef095SHaren Myneni 
papr_hvpipe_dev_create_handle(u32 srcID)480814ef095SHaren Myneni static int papr_hvpipe_dev_create_handle(u32 srcID)
481814ef095SHaren Myneni {
482814ef095SHaren Myneni 	struct hvpipe_source_info *src_info;
483814ef095SHaren Myneni 	struct file *file;
484814ef095SHaren Myneni 	long err;
485814ef095SHaren Myneni 	int fd;
486814ef095SHaren Myneni 
487814ef095SHaren Myneni 	spin_lock(&hvpipe_src_list_lock);
488814ef095SHaren Myneni 	/*
489814ef095SHaren Myneni 	 * Do not allow more than one process communicates with
490814ef095SHaren Myneni 	 * each source.
491814ef095SHaren Myneni 	 */
492814ef095SHaren Myneni 	src_info = hvpipe_find_source(srcID);
493814ef095SHaren Myneni 	if (src_info) {
494814ef095SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
495814ef095SHaren Myneni 		pr_err("pid(%d) is already using the source(%d)\n",
496814ef095SHaren Myneni 				src_info->tsk->pid, srcID);
497814ef095SHaren Myneni 		return -EALREADY;
498814ef095SHaren Myneni 	}
499814ef095SHaren Myneni 	spin_unlock(&hvpipe_src_list_lock);
500814ef095SHaren Myneni 
501814ef095SHaren Myneni 	src_info = kzalloc(sizeof(*src_info), GFP_KERNEL_ACCOUNT);
502814ef095SHaren Myneni 	if (!src_info)
503814ef095SHaren Myneni 		return -ENOMEM;
504814ef095SHaren Myneni 
505814ef095SHaren Myneni 	src_info->srcID = srcID;
506814ef095SHaren Myneni 	src_info->tsk = current;
507814ef095SHaren Myneni 	init_waitqueue_head(&src_info->recv_wqh);
508814ef095SHaren Myneni 
509814ef095SHaren Myneni 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
510814ef095SHaren Myneni 	if (fd < 0) {
511814ef095SHaren Myneni 		err = fd;
512814ef095SHaren Myneni 		goto free_buf;
513814ef095SHaren Myneni 	}
514814ef095SHaren Myneni 
515814ef095SHaren Myneni 	file = anon_inode_getfile("[papr-hvpipe]",
516814ef095SHaren Myneni 			&papr_hvpipe_handle_ops, (void *)src_info,
517814ef095SHaren Myneni 			O_RDWR);
518814ef095SHaren Myneni 	if (IS_ERR(file)) {
519814ef095SHaren Myneni 		err = PTR_ERR(file);
520814ef095SHaren Myneni 		goto free_fd;
521814ef095SHaren Myneni 	}
522814ef095SHaren Myneni 
523814ef095SHaren Myneni 	spin_lock(&hvpipe_src_list_lock);
524814ef095SHaren Myneni 	/*
525814ef095SHaren Myneni 	 * If two processes are executing ioctl() for the same
526814ef095SHaren Myneni 	 * source ID concurrently, prevent the second process to
527814ef095SHaren Myneni 	 * acquire FD.
528814ef095SHaren Myneni 	 */
529814ef095SHaren Myneni 	if (hvpipe_find_source(srcID)) {
530814ef095SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
531814ef095SHaren Myneni 		err = -EALREADY;
532814ef095SHaren Myneni 		goto free_file;
533814ef095SHaren Myneni 	}
534814ef095SHaren Myneni 	list_add(&src_info->list, &hvpipe_src_list);
535814ef095SHaren Myneni 	spin_unlock(&hvpipe_src_list_lock);
536814ef095SHaren Myneni 
537814ef095SHaren Myneni 	fd_install(fd, file);
538814ef095SHaren Myneni 	return fd;
539814ef095SHaren Myneni 
540814ef095SHaren Myneni free_file:
541814ef095SHaren Myneni 	fput(file);
542814ef095SHaren Myneni free_fd:
543814ef095SHaren Myneni 	put_unused_fd(fd);
544814ef095SHaren Myneni free_buf:
545814ef095SHaren Myneni 	kfree(src_info);
546814ef095SHaren Myneni 	return err;
547814ef095SHaren Myneni }
548814ef095SHaren Myneni 
549814ef095SHaren Myneni /*
550814ef095SHaren Myneni  * Top-level ioctl handler for /dev/papr_hvpipe
551814ef095SHaren Myneni  *
552814ef095SHaren Myneni  * Use separate FD for each source (exa :HMC). So ioctl is called
553814ef095SHaren Myneni  * with source ID which returns FD.
554814ef095SHaren Myneni  */
papr_hvpipe_dev_ioctl(struct file * filp,unsigned int ioctl,unsigned long arg)555814ef095SHaren Myneni static long papr_hvpipe_dev_ioctl(struct file *filp, unsigned int ioctl,
556814ef095SHaren Myneni 		unsigned long arg)
557814ef095SHaren Myneni {
558814ef095SHaren Myneni 	u32 __user *argp = (void __user *)arg;
559814ef095SHaren Myneni 	u32 srcID;
560814ef095SHaren Myneni 	long ret;
561814ef095SHaren Myneni 
562*6d84f851SHaren Myneni 	/*
563*6d84f851SHaren Myneni 	 * Return -ENXIO during migration
564*6d84f851SHaren Myneni 	 */
565*6d84f851SHaren Myneni 	if (!hvpipe_feature)
566*6d84f851SHaren Myneni 		return -ENXIO;
567*6d84f851SHaren Myneni 
568814ef095SHaren Myneni 	if (get_user(srcID, argp))
569814ef095SHaren Myneni 		return -EFAULT;
570814ef095SHaren Myneni 
571814ef095SHaren Myneni 	/*
572814ef095SHaren Myneni 	 * Support only HMC source right now
573814ef095SHaren Myneni 	 */
574814ef095SHaren Myneni 	if (!(srcID & HVPIPE_HMC_ID_MASK))
575814ef095SHaren Myneni 		return -EINVAL;
576814ef095SHaren Myneni 
577814ef095SHaren Myneni 	switch (ioctl) {
578814ef095SHaren Myneni 	case PAPR_HVPIPE_IOC_CREATE_HANDLE:
579814ef095SHaren Myneni 		ret = papr_hvpipe_dev_create_handle(srcID);
580814ef095SHaren Myneni 		break;
581814ef095SHaren Myneni 	default:
582814ef095SHaren Myneni 		ret = -ENOIOCTLCMD;
583814ef095SHaren Myneni 		break;
584814ef095SHaren Myneni 	}
585814ef095SHaren Myneni 
586814ef095SHaren Myneni 	return ret;
587814ef095SHaren Myneni }
588814ef095SHaren Myneni 
589b48b6cc8SHaren Myneni /*
590b48b6cc8SHaren Myneni  * papr_hvpipe_work_fn - called to issue recv HVPIPE RTAS for
591b48b6cc8SHaren Myneni  * sources that are not monitored by user space so that pipe
592b48b6cc8SHaren Myneni  * will not be blocked.
593b48b6cc8SHaren Myneni  */
papr_hvpipe_work_fn(struct work_struct * work)594b48b6cc8SHaren Myneni static void papr_hvpipe_work_fn(struct work_struct *work)
595b48b6cc8SHaren Myneni {
596b48b6cc8SHaren Myneni 	hvpipe_rtas_recv_msg(NULL, 0);
597b48b6cc8SHaren Myneni }
598b48b6cc8SHaren Myneni 
599b48b6cc8SHaren Myneni /*
600b48b6cc8SHaren Myneni  * HVPIPE event message IRQ handler.
601b48b6cc8SHaren Myneni  * The hypervisor sends event IRQ if the partition has payload
602b48b6cc8SHaren Myneni  * and generates another event only after payload is read with
603b48b6cc8SHaren Myneni  * recv HVPIPE RTAS.
604b48b6cc8SHaren Myneni  */
hvpipe_event_interrupt(int irq,void * dev_id)605b48b6cc8SHaren Myneni static irqreturn_t hvpipe_event_interrupt(int irq, void *dev_id)
606b48b6cc8SHaren Myneni {
607b48b6cc8SHaren Myneni 	struct hvpipe_event_buf *hvpipe_event;
608b48b6cc8SHaren Myneni 	struct pseries_errorlog *pseries_log;
609b48b6cc8SHaren Myneni 	struct hvpipe_source_info *src_info;
610b48b6cc8SHaren Myneni 	struct rtas_error_log *elog;
611b48b6cc8SHaren Myneni 	int rc;
612b48b6cc8SHaren Myneni 
613b48b6cc8SHaren Myneni 	rc = rtas_call(hvpipe_check_exception_token, 6, 1, NULL,
614b48b6cc8SHaren Myneni 		RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
615b48b6cc8SHaren Myneni 		RTAS_HVPIPE_MSG_EVENTS, 1, __pa(&hvpipe_ras_buf),
616b48b6cc8SHaren Myneni 		rtas_get_error_log_max());
617b48b6cc8SHaren Myneni 
618b48b6cc8SHaren Myneni 	if (rc != 0) {
619b48b6cc8SHaren Myneni 		pr_err_ratelimited("unexpected hvpipe-event-notification failed %d\n", rc);
620b48b6cc8SHaren Myneni 		return IRQ_HANDLED;
621b48b6cc8SHaren Myneni 	}
622b48b6cc8SHaren Myneni 
623b48b6cc8SHaren Myneni 	elog = (struct rtas_error_log *)hvpipe_ras_buf;
624b48b6cc8SHaren Myneni 	if (unlikely(rtas_error_type(elog) != RTAS_TYPE_HVPIPE)) {
625b48b6cc8SHaren Myneni 		pr_warn_ratelimited("Unexpected event type %d\n",
626b48b6cc8SHaren Myneni 				rtas_error_type(elog));
627b48b6cc8SHaren Myneni 		return IRQ_HANDLED;
628b48b6cc8SHaren Myneni 	}
629b48b6cc8SHaren Myneni 
630b48b6cc8SHaren Myneni 	pseries_log = get_pseries_errorlog(elog,
631b48b6cc8SHaren Myneni 				PSERIES_ELOG_SECT_ID_HVPIPE_EVENT);
632b48b6cc8SHaren Myneni 	hvpipe_event = (struct hvpipe_event_buf *)pseries_log->data;
633b48b6cc8SHaren Myneni 
634b48b6cc8SHaren Myneni 	/*
635b48b6cc8SHaren Myneni 	 * The hypervisor notifies partition when the payload is
636b48b6cc8SHaren Myneni 	 * available to read with recv HVPIPE RTAS and it will not
637b48b6cc8SHaren Myneni 	 * notify another event for any source until the previous
638b48b6cc8SHaren Myneni 	 * payload is read. Means the pipe is blocked in the
639b48b6cc8SHaren Myneni 	 * hypervisor until the payload is read.
640b48b6cc8SHaren Myneni 	 *
641b48b6cc8SHaren Myneni 	 * If the source is ready to accept payload and wakeup the
642b48b6cc8SHaren Myneni 	 * corresponding FD. Hold lock and update hvpipe_status
643b48b6cc8SHaren Myneni 	 * and this lock is needed in case the user space process
644b48b6cc8SHaren Myneni 	 * is in release FD instead of poll() so that release()
645b48b6cc8SHaren Myneni 	 * reads the payload to unblock pipe before closing FD.
646b48b6cc8SHaren Myneni 	 *
647b48b6cc8SHaren Myneni 	 * otherwise (means no other user process waiting for the
648b48b6cc8SHaren Myneni 	 * payload, issue recv HVPIPE RTAS (papr_hvpipe_work_fn())
649b48b6cc8SHaren Myneni 	 * to unblock pipe.
650b48b6cc8SHaren Myneni 	 */
651b48b6cc8SHaren Myneni 	spin_lock(&hvpipe_src_list_lock);
652b48b6cc8SHaren Myneni 	src_info = hvpipe_find_source(be32_to_cpu(hvpipe_event->srcID));
653b48b6cc8SHaren Myneni 	if (src_info) {
654b48b6cc8SHaren Myneni 		u32 flags = 0;
655b48b6cc8SHaren Myneni 
656b48b6cc8SHaren Myneni 		if (hvpipe_event->event_type & HVPIPE_LOST_CONNECTION)
657b48b6cc8SHaren Myneni 			flags = HVPIPE_LOST_CONNECTION;
658b48b6cc8SHaren Myneni 		else if (hvpipe_event->event_type & HVPIPE_MSG_AVAILABLE)
659b48b6cc8SHaren Myneni 			flags = HVPIPE_MSG_AVAILABLE;
660b48b6cc8SHaren Myneni 
661b48b6cc8SHaren Myneni 		src_info->hvpipe_status |= flags;
662b48b6cc8SHaren Myneni 		wake_up(&src_info->recv_wqh);
663b48b6cc8SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
664b48b6cc8SHaren Myneni 	} else {
665b48b6cc8SHaren Myneni 		spin_unlock(&hvpipe_src_list_lock);
666b48b6cc8SHaren Myneni 		/*
667b48b6cc8SHaren Myneni 		 * user space is not waiting on this source. So
668b48b6cc8SHaren Myneni 		 * execute receive pipe RTAS so that pipe will not
669b48b6cc8SHaren Myneni 		 * be blocked.
670b48b6cc8SHaren Myneni 		 */
671b48b6cc8SHaren Myneni 		if (hvpipe_event->event_type & HVPIPE_MSG_AVAILABLE)
672b48b6cc8SHaren Myneni 			queue_work(papr_hvpipe_wq, papr_hvpipe_work);
673b48b6cc8SHaren Myneni 	}
674b48b6cc8SHaren Myneni 
675b48b6cc8SHaren Myneni 	return IRQ_HANDLED;
676b48b6cc8SHaren Myneni }
677b48b6cc8SHaren Myneni 
67839a08a4fSHaren Myneni /*
67939a08a4fSHaren Myneni  * Enable hvpipe by system parameter set with parameter
68039a08a4fSHaren Myneni  * token = 64 and with 1 byte buffer data:
68139a08a4fSHaren Myneni  * 0 = hvpipe not in use/disable
68239a08a4fSHaren Myneni  * 1 = hvpipe in use/enable
68339a08a4fSHaren Myneni  */
set_hvpipe_sys_param(u8 val)68439a08a4fSHaren Myneni static int set_hvpipe_sys_param(u8 val)
68539a08a4fSHaren Myneni {
68639a08a4fSHaren Myneni 	struct papr_sysparm_buf *buf;
68739a08a4fSHaren Myneni 	int ret;
68839a08a4fSHaren Myneni 
68939a08a4fSHaren Myneni 	buf = papr_sysparm_buf_alloc();
69039a08a4fSHaren Myneni 	if (!buf)
69139a08a4fSHaren Myneni 		return -ENOMEM;
69239a08a4fSHaren Myneni 
69339a08a4fSHaren Myneni 	buf->len = cpu_to_be16(1);
69439a08a4fSHaren Myneni 	buf->val[0] = val;
69539a08a4fSHaren Myneni 	ret = papr_sysparm_set(PAPR_SYSPARM_HVPIPE_ENABLE, buf);
69639a08a4fSHaren Myneni 	if (ret)
69739a08a4fSHaren Myneni 		pr_err("Can not enable hvpipe %d\n", ret);
69839a08a4fSHaren Myneni 
69939a08a4fSHaren Myneni 	papr_sysparm_buf_free(buf);
70039a08a4fSHaren Myneni 
70139a08a4fSHaren Myneni 	return ret;
70239a08a4fSHaren Myneni }
70339a08a4fSHaren Myneni 
enable_hvpipe_IRQ(void)704b48b6cc8SHaren Myneni static int __init enable_hvpipe_IRQ(void)
705b48b6cc8SHaren Myneni {
706b48b6cc8SHaren Myneni 	struct device_node *np;
707b48b6cc8SHaren Myneni 
708b48b6cc8SHaren Myneni 	hvpipe_check_exception_token = rtas_function_token(RTAS_FN_CHECK_EXCEPTION);
709b48b6cc8SHaren Myneni 	if (hvpipe_check_exception_token  == RTAS_UNKNOWN_SERVICE)
710b48b6cc8SHaren Myneni 		return -ENODEV;
711b48b6cc8SHaren Myneni 
712b48b6cc8SHaren Myneni 	/* hvpipe events */
713b48b6cc8SHaren Myneni 	np = of_find_node_by_path("/event-sources/ibm,hvpipe-msg-events");
714b48b6cc8SHaren Myneni 	if (np != NULL) {
715b48b6cc8SHaren Myneni 		request_event_sources_irqs(np, hvpipe_event_interrupt,
716b48b6cc8SHaren Myneni 					"HPIPE_EVENT");
717b48b6cc8SHaren Myneni 		of_node_put(np);
718b48b6cc8SHaren Myneni 	} else {
719b48b6cc8SHaren Myneni 		pr_err("Can not enable hvpipe event IRQ\n");
720b48b6cc8SHaren Myneni 		return -ENODEV;
721b48b6cc8SHaren Myneni 	}
722b48b6cc8SHaren Myneni 
723b48b6cc8SHaren Myneni 	return 0;
724b48b6cc8SHaren Myneni }
725b48b6cc8SHaren Myneni 
hvpipe_migration_handler(int action)726*6d84f851SHaren Myneni void hvpipe_migration_handler(int action)
727*6d84f851SHaren Myneni {
728*6d84f851SHaren Myneni 	pr_info("hvpipe migration event %d\n", action);
729*6d84f851SHaren Myneni 
730*6d84f851SHaren Myneni 	/*
731*6d84f851SHaren Myneni 	 * HVPIPE is not used (Failed to create /dev/papr-hvpipe).
732*6d84f851SHaren Myneni 	 * So nothing to do for migration.
733*6d84f851SHaren Myneni 	 */
734*6d84f851SHaren Myneni 	if (!papr_hvpipe_work)
735*6d84f851SHaren Myneni 		return;
736*6d84f851SHaren Myneni 
737*6d84f851SHaren Myneni 	switch (action) {
738*6d84f851SHaren Myneni 	case HVPIPE_SUSPEND:
739*6d84f851SHaren Myneni 		if (hvpipe_feature) {
740*6d84f851SHaren Myneni 			/*
741*6d84f851SHaren Myneni 			 * Disable hvpipe_feature to the user space.
742*6d84f851SHaren Myneni 			 * It will be enabled with RESUME event.
743*6d84f851SHaren Myneni 			 */
744*6d84f851SHaren Myneni 			hvpipe_feature = false;
745*6d84f851SHaren Myneni 			/*
746*6d84f851SHaren Myneni 			 * set system parameter hvpipe 'disable'
747*6d84f851SHaren Myneni 			 */
748*6d84f851SHaren Myneni 			set_hvpipe_sys_param(0);
749*6d84f851SHaren Myneni 		}
750*6d84f851SHaren Myneni 		break;
751*6d84f851SHaren Myneni 	case HVPIPE_RESUME:
752*6d84f851SHaren Myneni 		/*
753*6d84f851SHaren Myneni 		 * set system parameter hvpipe 'enable'
754*6d84f851SHaren Myneni 		 */
755*6d84f851SHaren Myneni 		if (!set_hvpipe_sys_param(1))
756*6d84f851SHaren Myneni 			hvpipe_feature = true;
757*6d84f851SHaren Myneni 		else
758*6d84f851SHaren Myneni 			pr_err("hvpipe is not enabled after migration\n");
759*6d84f851SHaren Myneni 
760*6d84f851SHaren Myneni 		break;
761*6d84f851SHaren Myneni 	}
762*6d84f851SHaren Myneni }
763*6d84f851SHaren Myneni 
764814ef095SHaren Myneni static const struct file_operations papr_hvpipe_ops = {
765814ef095SHaren Myneni 	.unlocked_ioctl	=	papr_hvpipe_dev_ioctl,
766814ef095SHaren Myneni };
767814ef095SHaren Myneni 
768814ef095SHaren Myneni static struct miscdevice papr_hvpipe_dev = {
769814ef095SHaren Myneni 	.minor	=	MISC_DYNAMIC_MINOR,
770814ef095SHaren Myneni 	.name	=	"papr-hvpipe",
771814ef095SHaren Myneni 	.fops	=	&papr_hvpipe_ops,
772814ef095SHaren Myneni };
773814ef095SHaren Myneni 
papr_hvpipe_init(void)774814ef095SHaren Myneni static int __init papr_hvpipe_init(void)
775814ef095SHaren Myneni {
776814ef095SHaren Myneni 	int ret;
777814ef095SHaren Myneni 
778814ef095SHaren Myneni 	if (!of_find_property(rtas.dev, "ibm,hypervisor-pipe-capable",
779814ef095SHaren Myneni 		NULL))
780814ef095SHaren Myneni 		return -ENODEV;
781814ef095SHaren Myneni 
782814ef095SHaren Myneni 	if (!rtas_function_implemented(RTAS_FN_IBM_SEND_HVPIPE_MSG) ||
783814ef095SHaren Myneni 		!rtas_function_implemented(RTAS_FN_IBM_RECEIVE_HVPIPE_MSG))
784814ef095SHaren Myneni 		return -ENODEV;
785814ef095SHaren Myneni 
786b48b6cc8SHaren Myneni 	papr_hvpipe_work = kzalloc(sizeof(struct work_struct), GFP_ATOMIC);
787b48b6cc8SHaren Myneni 	if (!papr_hvpipe_work)
788b48b6cc8SHaren Myneni 		return -ENOMEM;
789b48b6cc8SHaren Myneni 
790b48b6cc8SHaren Myneni 	INIT_WORK(papr_hvpipe_work, papr_hvpipe_work_fn);
791b48b6cc8SHaren Myneni 
792b48b6cc8SHaren Myneni 	papr_hvpipe_wq = alloc_ordered_workqueue("papr hvpipe workqueue", 0);
793b48b6cc8SHaren Myneni 	if (!papr_hvpipe_wq) {
794b48b6cc8SHaren Myneni 		ret = -ENOMEM;
795b48b6cc8SHaren Myneni 		goto out;
796814ef095SHaren Myneni 	}
797814ef095SHaren Myneni 
798b48b6cc8SHaren Myneni 	ret = enable_hvpipe_IRQ();
79939a08a4fSHaren Myneni 	if (!ret) {
80039a08a4fSHaren Myneni 		ret = set_hvpipe_sys_param(1);
801b48b6cc8SHaren Myneni 		if (!ret)
802b48b6cc8SHaren Myneni 			ret = misc_register(&papr_hvpipe_dev);
80339a08a4fSHaren Myneni 	}
804b48b6cc8SHaren Myneni 
805b48b6cc8SHaren Myneni 	if (!ret) {
806b48b6cc8SHaren Myneni 		pr_info("hvpipe feature is enabled\n");
807*6d84f851SHaren Myneni 		hvpipe_feature = true;
808814ef095SHaren Myneni 		return 0;
809814ef095SHaren Myneni 	}
810b48b6cc8SHaren Myneni 
811b48b6cc8SHaren Myneni 	pr_err("hvpipe feature is not enabled %d\n", ret);
812b48b6cc8SHaren Myneni 	destroy_workqueue(papr_hvpipe_wq);
813b48b6cc8SHaren Myneni out:
814b48b6cc8SHaren Myneni 	kfree(papr_hvpipe_work);
815b48b6cc8SHaren Myneni 	papr_hvpipe_work = NULL;
816b48b6cc8SHaren Myneni 	return ret;
817b48b6cc8SHaren Myneni }
818814ef095SHaren Myneni machine_device_initcall(pseries, papr_hvpipe_init);
819