xref: /openbmc/linux/drivers/hv/hyperv_vmbus.h (revision 55e43d6abd078ed6d219902ce8cb4d68e3c993ba)
13b20eb23SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
246a97191SGreg Kroah-Hartman /*
346a97191SGreg Kroah-Hartman  *
446a97191SGreg Kroah-Hartman  * Copyright (c) 2011, Microsoft Corporation.
546a97191SGreg Kroah-Hartman  *
646a97191SGreg Kroah-Hartman  * Authors:
746a97191SGreg Kroah-Hartman  *   Haiyang Zhang <haiyangz@microsoft.com>
846a97191SGreg Kroah-Hartman  *   Hank Janssen  <hjanssen@microsoft.com>
946a97191SGreg Kroah-Hartman  *   K. Y. Srinivasan <kys@microsoft.com>
1046a97191SGreg Kroah-Hartman  */
1146a97191SGreg Kroah-Hartman 
1246a97191SGreg Kroah-Hartman #ifndef _HYPERV_VMBUS_H
1346a97191SGreg Kroah-Hartman #define _HYPERV_VMBUS_H
1446a97191SGreg Kroah-Hartman 
1546a97191SGreg Kroah-Hartman #include <linux/list.h>
168017c996SArnd Bergmann #include <linux/bitops.h>
1746a97191SGreg Kroah-Hartman #include <asm/sync_bitops.h>
185a485803SVitaly Kuznetsov #include <asm/hyperv-tlfs.h>
1946a97191SGreg Kroah-Hartman #include <linux/atomic.h>
2046a97191SGreg Kroah-Hartman #include <linux/hyperv.h>
2137cdd991SStephen Hemminger #include <linux/interrupt.h>
2246a97191SGreg Kroah-Hartman 
23c9fe0f8fSVitaly Kuznetsov #include "hv_trace.h"
24c9fe0f8fSVitaly Kuznetsov 
2546a97191SGreg Kroah-Hartman /*
26c0b200cfSK. Y. Srinivasan  * Timeout for services such as KVP and fcopy.
27c0b200cfSK. Y. Srinivasan  */
28c0b200cfSK. Y. Srinivasan #define HV_UTIL_TIMEOUT 30
29c0b200cfSK. Y. Srinivasan 
30c0b200cfSK. Y. Srinivasan /*
314dbfc2e6SVitaly Kuznetsov  * Timeout for guest-host handshake for services.
324dbfc2e6SVitaly Kuznetsov  */
33d7edd31bSVitaly Kuznetsov #define HV_UTIL_NEGO_TIMEOUT 55
344dbfc2e6SVitaly Kuznetsov 
3546a97191SGreg Kroah-Hartman 
3646a97191SGreg Kroah-Hartman /* Definitions for the monitored notification facility */
3746a97191SGreg Kroah-Hartman union hv_monitor_trigger_group {
3846a97191SGreg Kroah-Hartman 	u64 as_uint64;
3946a97191SGreg Kroah-Hartman 	struct {
4046a97191SGreg Kroah-Hartman 		u32 pending;
4146a97191SGreg Kroah-Hartman 		u32 armed;
4246a97191SGreg Kroah-Hartman 	};
4346a97191SGreg Kroah-Hartman };
4446a97191SGreg Kroah-Hartman 
4546a97191SGreg Kroah-Hartman struct hv_monitor_parameter {
4646a97191SGreg Kroah-Hartman 	union hv_connection_id connectionid;
4746a97191SGreg Kroah-Hartman 	u16 flagnumber;
4846a97191SGreg Kroah-Hartman 	u16 rsvdz;
4946a97191SGreg Kroah-Hartman };
5046a97191SGreg Kroah-Hartman 
5146a97191SGreg Kroah-Hartman union hv_monitor_trigger_state {
5246a97191SGreg Kroah-Hartman 	u32 asu32;
5346a97191SGreg Kroah-Hartman 
5446a97191SGreg Kroah-Hartman 	struct {
5546a97191SGreg Kroah-Hartman 		u32 group_enable:4;
5646a97191SGreg Kroah-Hartman 		u32 rsvdz:28;
5746a97191SGreg Kroah-Hartman 	};
5846a97191SGreg Kroah-Hartman };
5946a97191SGreg Kroah-Hartman 
6046a97191SGreg Kroah-Hartman /* struct hv_monitor_page Layout */
6146a97191SGreg Kroah-Hartman /* ------------------------------------------------------ */
6246a97191SGreg Kroah-Hartman /* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
6346a97191SGreg Kroah-Hartman /* | 8   | TriggerGroup[0]                              | */
6446a97191SGreg Kroah-Hartman /* | 10  | TriggerGroup[1]                              | */
6546a97191SGreg Kroah-Hartman /* | 18  | TriggerGroup[2]                              | */
6646a97191SGreg Kroah-Hartman /* | 20  | TriggerGroup[3]                              | */
6746a97191SGreg Kroah-Hartman /* | 28  | Rsvd2[0]                                     | */
6846a97191SGreg Kroah-Hartman /* | 30  | Rsvd2[1]                                     | */
6946a97191SGreg Kroah-Hartman /* | 38  | Rsvd2[2]                                     | */
7046a97191SGreg Kroah-Hartman /* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
7146a97191SGreg Kroah-Hartman /* | ...                                                | */
7246a97191SGreg Kroah-Hartman /* | 240 | Latency[0][0..3]                             | */
7346a97191SGreg Kroah-Hartman /* | 340 | Rsvz3[0]                                     | */
7446a97191SGreg Kroah-Hartman /* | 440 | Parameter[0][0]                              | */
7546a97191SGreg Kroah-Hartman /* | 448 | Parameter[0][1]                              | */
7646a97191SGreg Kroah-Hartman /* | ...                                                | */
7746a97191SGreg Kroah-Hartman /* | 840 | Rsvd4[0]                                     | */
7846a97191SGreg Kroah-Hartman /* ------------------------------------------------------ */
7946a97191SGreg Kroah-Hartman struct hv_monitor_page {
8046a97191SGreg Kroah-Hartman 	union hv_monitor_trigger_state trigger_state;
8146a97191SGreg Kroah-Hartman 	u32 rsvdz1;
8246a97191SGreg Kroah-Hartman 
8346a97191SGreg Kroah-Hartman 	union hv_monitor_trigger_group trigger_group[4];
8446a97191SGreg Kroah-Hartman 	u64 rsvdz2[3];
8546a97191SGreg Kroah-Hartman 
8646a97191SGreg Kroah-Hartman 	s32 next_checktime[4][32];
8746a97191SGreg Kroah-Hartman 
8846a97191SGreg Kroah-Hartman 	u16 latency[4][32];
8946a97191SGreg Kroah-Hartman 	u64 rsvdz3[32];
9046a97191SGreg Kroah-Hartman 
9146a97191SGreg Kroah-Hartman 	struct hv_monitor_parameter parameter[4][32];
9246a97191SGreg Kroah-Hartman 
9346a97191SGreg Kroah-Hartman 	u8 rsvdz4[1984];
9446a97191SGreg Kroah-Hartman };
9546a97191SGreg Kroah-Hartman 
968e27a236SK. Y. Srinivasan #define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
978e27a236SK. Y. Srinivasan 
9846a97191SGreg Kroah-Hartman /* Definition of the hv_post_message hypercall input structure. */
9946a97191SGreg Kroah-Hartman struct hv_input_post_message {
10046a97191SGreg Kroah-Hartman 	union hv_connection_id connectionid;
10146a97191SGreg Kroah-Hartman 	u32 reserved;
1027797dcf6SAndrey Smetanin 	u32 message_type;
10346a97191SGreg Kroah-Hartman 	u32 payload_size;
10446a97191SGreg Kroah-Hartman 	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
10546a97191SGreg Kroah-Hartman };
10646a97191SGreg Kroah-Hartman 
10746a97191SGreg Kroah-Hartman 
10846a97191SGreg Kroah-Hartman enum {
10946a97191SGreg Kroah-Hartman 	VMBUS_MESSAGE_CONNECTION_ID	= 1,
110ae20b254SDexuan Cui 	VMBUS_MESSAGE_CONNECTION_ID_4	= 4,
11146a97191SGreg Kroah-Hartman 	VMBUS_MESSAGE_PORT_ID		= 1,
11246a97191SGreg Kroah-Hartman 	VMBUS_EVENT_CONNECTION_ID	= 2,
11346a97191SGreg Kroah-Hartman 	VMBUS_EVENT_PORT_ID		= 2,
11446a97191SGreg Kroah-Hartman 	VMBUS_MONITOR_CONNECTION_ID	= 3,
11546a97191SGreg Kroah-Hartman 	VMBUS_MONITOR_PORT_ID		= 3,
11646a97191SGreg Kroah-Hartman 	VMBUS_MESSAGE_SINT		= 2,
11746a97191SGreg Kroah-Hartman };
11846a97191SGreg Kroah-Hartman 
11937cdd991SStephen Hemminger /*
12037cdd991SStephen Hemminger  * Per cpu state for channel handling
12137cdd991SStephen Hemminger  */
12237cdd991SStephen Hemminger struct hv_per_cpu_context {
12337cdd991SStephen Hemminger 	void *synic_message_page;
12437cdd991SStephen Hemminger 	void *synic_event_page;
12537cdd991SStephen Hemminger 
12637cdd991SStephen Hemminger 	/*
12723378295SDexuan Cui 	 * The page is only used in hv_post_message() for a TDX VM (with the
12823378295SDexuan Cui 	 * paravisor) to post a messages to Hyper-V: when such a VM calls
12923378295SDexuan Cui 	 * HVCALL_POST_MESSAGE, it can't use the hyperv_pcpu_input_arg (which
13023378295SDexuan Cui 	 * is encrypted in such a VM) as the hypercall input page, because
13123378295SDexuan Cui 	 * the input page for HVCALL_POST_MESSAGE must be decrypted in such a
13223378295SDexuan Cui 	 * VM, so post_msg_page (which is decrypted in hv_synic_alloc()) is
13323378295SDexuan Cui 	 * introduced for this purpose. See hyperv_init() for more comments.
13423378295SDexuan Cui 	 */
13523378295SDexuan Cui 	void *post_msg_page;
13623378295SDexuan Cui 
13723378295SDexuan Cui 	/*
13837cdd991SStephen Hemminger 	 * Starting with win8, we can take channel interrupts on any CPU;
13937cdd991SStephen Hemminger 	 * we will manage the tasklet that handles events messages on a per CPU
14037cdd991SStephen Hemminger 	 * basis.
14137cdd991SStephen Hemminger 	 */
14237cdd991SStephen Hemminger 	struct tasklet_struct msg_dpc;
14337cdd991SStephen Hemminger };
14437cdd991SStephen Hemminger 
14546a97191SGreg Kroah-Hartman struct hv_context {
14646a97191SGreg Kroah-Hartman 	/* We only support running on top of Hyper-V
14746a97191SGreg Kroah-Hartman 	 * So at this point this really can only contain the Hyper-V ID
14846a97191SGreg Kroah-Hartman 	 */
14946a97191SGreg Kroah-Hartman 	u64 guestid;
15046a97191SGreg Kroah-Hartman 
15137cdd991SStephen Hemminger 	struct hv_per_cpu_context __percpu *cpu_context;
15237cdd991SStephen Hemminger 
153917ea427SK. Y. Srinivasan 	/*
1549f01ec53SK. Y. Srinivasan 	 * To manage allocations in a NUMA node.
1559f01ec53SK. Y. Srinivasan 	 * Array indexed by numa node ID.
1569f01ec53SK. Y. Srinivasan 	 */
1579f01ec53SK. Y. Srinivasan 	struct cpumask *hv_numa_map;
15846a97191SGreg Kroah-Hartman };
15946a97191SGreg Kroah-Hartman 
16046a97191SGreg Kroah-Hartman extern struct hv_context hv_context;
16146a97191SGreg Kroah-Hartman 
16246a97191SGreg Kroah-Hartman /* Hv Interface */
16346a97191SGreg Kroah-Hartman 
16446a97191SGreg Kroah-Hartman extern int hv_init(void);
16546a97191SGreg Kroah-Hartman 
166415f0a02SDan Carpenter extern int hv_post_message(union hv_connection_id connection_id,
16746a97191SGreg Kroah-Hartman 			 enum hv_message_type message_type,
16846a97191SGreg Kroah-Hartman 			 void *payload, size_t payload_size);
16946a97191SGreg Kroah-Hartman 
1702608fb65SJason Wang extern int hv_synic_alloc(void);
1712608fb65SJason Wang 
1722608fb65SJason Wang extern void hv_synic_free(void);
1732608fb65SJason Wang 
174dba61cdaSDexuan Cui extern void hv_synic_enable_regs(unsigned int cpu);
17576d36ab7SVitaly Kuznetsov extern int hv_synic_init(unsigned int cpu);
17646a97191SGreg Kroah-Hartman 
177dba61cdaSDexuan Cui extern void hv_synic_disable_regs(unsigned int cpu);
17876d36ab7SVitaly Kuznetsov extern int hv_synic_cleanup(unsigned int cpu);
17946a97191SGreg Kroah-Hartman 
18046a97191SGreg Kroah-Hartman /* Interface */
18146a97191SGreg Kroah-Hartman 
18214948e39SKimberly Brown void hv_ringbuffer_pre_init(struct vmbus_channel *channel);
18346a97191SGreg Kroah-Hartman 
1849988ce68SVitaly Kuznetsov int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
185adae1e93SAndres Beltran 		       struct page *pages, u32 pagecnt, u32 max_pkt_size);
18646a97191SGreg Kroah-Hartman 
18746a97191SGreg Kroah-Hartman void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
18846a97191SGreg Kroah-Hartman 
1891f6ee4e7SK. Y. Srinivasan int hv_ringbuffer_write(struct vmbus_channel *channel,
190e8b7db38SAndres Beltran 			const struct kvec *kv_list, u32 kv_count,
191b03afa57SAndrea Parri (Microsoft) 			u64 requestid, u64 *trans_id);
19246a97191SGreg Kroah-Hartman 
1933372592aSK. Y. Srinivasan int hv_ringbuffer_read(struct vmbus_channel *channel,
194940b68e2SVitaly Kuznetsov 		       void *buffer, u32 buflen, u32 *buffer_actual_len,
1953372592aSK. Y. Srinivasan 		       u64 *requestid, bool raw);
19646a97191SGreg Kroah-Hartman 
19746a97191SGreg Kroah-Hartman /*
1985c641feeSStefan Eschenbacher  * The Maximum number of channels (16384) is determined by the size of the
19983527ef7SMaya Nakamura  * interrupt page, which is HV_HYP_PAGE_SIZE. 1/2 of HV_HYP_PAGE_SIZE is to
20083527ef7SMaya Nakamura  * send endpoint interrupts, and the other is to receive endpoint interrupts.
20146a97191SGreg Kroah-Hartman  */
20283527ef7SMaya Nakamura #define MAX_NUM_CHANNELS	((HV_HYP_PAGE_SIZE >> 1) << 3)
20346a97191SGreg Kroah-Hartman 
20446a97191SGreg Kroah-Hartman /* The value here must be in multiple of 32 */
20546a97191SGreg Kroah-Hartman #define MAX_NUM_CHANNELS_SUPPORTED	256
20646a97191SGreg Kroah-Hartman 
2078b6a877cSAndrea Parri (Microsoft) #define MAX_CHANNEL_RELIDS					\
2088b6a877cSAndrea Parri (Microsoft) 	max(MAX_NUM_CHANNELS_SUPPORTED, HV_EVENT_FLAGS_COUNT)
20946a97191SGreg Kroah-Hartman 
21046a97191SGreg Kroah-Hartman enum vmbus_connect_state {
21146a97191SGreg Kroah-Hartman 	DISCONNECTED,
21246a97191SGreg Kroah-Hartman 	CONNECTING,
21346a97191SGreg Kroah-Hartman 	CONNECTED,
21446a97191SGreg Kroah-Hartman 	DISCONNECTING
21546a97191SGreg Kroah-Hartman };
21646a97191SGreg Kroah-Hartman 
21746a97191SGreg Kroah-Hartman #define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
21846a97191SGreg Kroah-Hartman 
21954a66265SK. Y. Srinivasan /*
2208a857c55SAndrea Parri (Microsoft)  * The CPU that Hyper-V will interrupt for VMBUS messages, such as
2218a857c55SAndrea Parri (Microsoft)  * CHANNELMSG_OFFERCHANNEL and CHANNELMSG_RESCIND_CHANNELOFFER.
22254a66265SK. Y. Srinivasan  */
2238a857c55SAndrea Parri (Microsoft) #define VMBUS_CONNECT_CPU	0
22454a66265SK. Y. Srinivasan 
2258a857c55SAndrea Parri (Microsoft) struct vmbus_connection {
226ae20b254SDexuan Cui 	u32 msg_conn_id;
227ae20b254SDexuan Cui 
22854a66265SK. Y. Srinivasan 	atomic_t offer_in_progress;
22954a66265SK. Y. Srinivasan 
23046a97191SGreg Kroah-Hartman 	enum vmbus_connect_state conn_state;
23146a97191SGreg Kroah-Hartman 
23246a97191SGreg Kroah-Hartman 	atomic_t next_gpadl_handle;
23346a97191SGreg Kroah-Hartman 
2342db84effSK. Y. Srinivasan 	struct completion  unload_event;
23546a97191SGreg Kroah-Hartman 	/*
23646a97191SGreg Kroah-Hartman 	 * Represents channel interrupts. Each bit position represents a
23746a97191SGreg Kroah-Hartman 	 * channel.  When a channel sends an interrupt via VMBUS, it finds its
23846a97191SGreg Kroah-Hartman 	 * bit in the sendInterruptPage, set it and calls Hv to generate a port
23946a97191SGreg Kroah-Hartman 	 * event. The other end receives the port event and parse the
24046a97191SGreg Kroah-Hartman 	 * recvInterruptPage to see which bit is set
24146a97191SGreg Kroah-Hartman 	 */
24246a97191SGreg Kroah-Hartman 	void *int_page;
24346a97191SGreg Kroah-Hartman 	void *send_int_page;
24446a97191SGreg Kroah-Hartman 	void *recv_int_page;
24546a97191SGreg Kroah-Hartman 
24646a97191SGreg Kroah-Hartman 	/*
24746a97191SGreg Kroah-Hartman 	 * 2 pages - 1st page for parent->child notification and 2nd
24846a97191SGreg Kroah-Hartman 	 * is child->parent notification
24946a97191SGreg Kroah-Hartman 	 */
2508681db44SGreg Kroah-Hartman 	struct hv_monitor_page *monitor_pages[2];
25146a97191SGreg Kroah-Hartman 	struct list_head chn_msg_list;
25246a97191SGreg Kroah-Hartman 	spinlock_t channelmsg_lock;
25346a97191SGreg Kroah-Hartman 
25446a97191SGreg Kroah-Hartman 	/* List of channels */
25546a97191SGreg Kroah-Hartman 	struct list_head chn_list;
256d6f591e3SDexuan Cui 	struct mutex channel_mutex;
25746a97191SGreg Kroah-Hartman 
2588b6a877cSAndrea Parri (Microsoft) 	/* Array of channels */
2598b6a877cSAndrea Parri (Microsoft) 	struct vmbus_channel **channels;
2608b6a877cSAndrea Parri (Microsoft) 
26137c2578cSDexuan Cui 	/*
26237c2578cSDexuan Cui 	 * An offer message is handled first on the work_queue, and then
26337c2578cSDexuan Cui 	 * is further handled on handle_primary_chan_wq or
26437c2578cSDexuan Cui 	 * handle_sub_chan_wq.
26537c2578cSDexuan Cui 	 */
26646a97191SGreg Kroah-Hartman 	struct workqueue_struct *work_queue;
26737c2578cSDexuan Cui 	struct workqueue_struct *handle_primary_chan_wq;
26837c2578cSDexuan Cui 	struct workqueue_struct *handle_sub_chan_wq;
26952be9355SShradha Gupta 	struct workqueue_struct *rescind_work_queue;
27052be9355SShradha Gupta 
27152be9355SShradha Gupta 	/*
27252be9355SShradha Gupta 	 * On suspension of the vmbus, the accumulated offer messages
27352be9355SShradha Gupta 	 * must be dropped.
27452be9355SShradha Gupta 	 */
27552be9355SShradha Gupta 	bool ignore_any_offer_msg;
276b307b389SDexuan Cui 
277b307b389SDexuan Cui 	/*
278b307b389SDexuan Cui 	 * The number of sub-channels and hv_sock channels that should be
279b307b389SDexuan Cui 	 * cleaned up upon suspend: sub-channels will be re-created upon
280b307b389SDexuan Cui 	 * resume, and hv_sock channels should not survive suspend.
281b307b389SDexuan Cui 	 */
282b307b389SDexuan Cui 	atomic_t nr_chan_close_on_suspend;
283b307b389SDexuan Cui 	/*
284b307b389SDexuan Cui 	 * vmbus_bus_suspend() waits for "nr_chan_close_on_suspend" to
285b307b389SDexuan Cui 	 * drop to zero.
286b307b389SDexuan Cui 	 */
287b307b389SDexuan Cui 	struct completion ready_for_suspend_event;
288d8bd2d44SDexuan Cui 
289d8bd2d44SDexuan Cui 	/*
290d8bd2d44SDexuan Cui 	 * The number of primary channels that should be "fixed up"
291d8bd2d44SDexuan Cui 	 * upon resume: these channels are re-offered upon resume, and some
292d8bd2d44SDexuan Cui 	 * fields of the channel offers (i.e. child_relid and connection_id)
293d8bd2d44SDexuan Cui 	 * can change, so the old offermsg must be fixed up, before the resume
294d8bd2d44SDexuan Cui 	 * callbacks of the VSC drivers start to further touch the channels.
295d8bd2d44SDexuan Cui 	 */
296d8bd2d44SDexuan Cui 	atomic_t nr_chan_fixup_on_resume;
297d8bd2d44SDexuan Cui 	/*
298d8bd2d44SDexuan Cui 	 * vmbus_bus_resume() waits for "nr_chan_fixup_on_resume" to
299d8bd2d44SDexuan Cui 	 * drop to zero.
300d8bd2d44SDexuan Cui 	 */
301d8bd2d44SDexuan Cui 	struct completion ready_for_resume_event;
30246a97191SGreg Kroah-Hartman };
30346a97191SGreg Kroah-Hartman 
30446a97191SGreg Kroah-Hartman 
30546a97191SGreg Kroah-Hartman struct vmbus_msginfo {
30646a97191SGreg Kroah-Hartman 	/* Bookkeeping stuff */
30746a97191SGreg Kroah-Hartman 	struct list_head msglist_entry;
30846a97191SGreg Kroah-Hartman 
30946a97191SGreg Kroah-Hartman 	/* The message itself */
310032d4a48SGustavo A. R. Silva 	unsigned char msg[];
31146a97191SGreg Kroah-Hartman };
31246a97191SGreg Kroah-Hartman 
31346a97191SGreg Kroah-Hartman 
31446a97191SGreg Kroah-Hartman extern struct vmbus_connection vmbus_connection;
31546a97191SGreg Kroah-Hartman 
316f53335e3SDexuan Cui int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version);
317f53335e3SDexuan Cui 
vmbus_send_interrupt(u32 relid)3185c1bec61SStephen Hemminger static inline void vmbus_send_interrupt(u32 relid)
3195c1bec61SStephen Hemminger {
3205c1bec61SStephen Hemminger 	sync_set_bit(relid, vmbus_connection.send_int_page);
3215c1bec61SStephen Hemminger }
3225c1bec61SStephen Hemminger 
323652594c7SDexuan Cui enum vmbus_message_handler_type {
324652594c7SDexuan Cui 	/* The related handler can sleep. */
325652594c7SDexuan Cui 	VMHT_BLOCKING = 0,
326652594c7SDexuan Cui 
327652594c7SDexuan Cui 	/* The related handler must NOT sleep. */
328652594c7SDexuan Cui 	VMHT_NON_BLOCKING = 1,
329652594c7SDexuan Cui };
330652594c7SDexuan Cui 
331652594c7SDexuan Cui struct vmbus_channel_message_table_entry {
332652594c7SDexuan Cui 	enum vmbus_channel_message_type message_type;
333652594c7SDexuan Cui 	enum vmbus_message_handler_type handler_type;
334652594c7SDexuan Cui 	void (*message_handler)(struct vmbus_channel_message_header *msg);
33552c7803fSVitaly Kuznetsov 	u32 min_payload_len;
336652594c7SDexuan Cui };
337652594c7SDexuan Cui 
338e6242fa0SStephen Hemminger extern const struct vmbus_channel_message_table_entry
339652594c7SDexuan Cui 	channel_message_table[CHANNELMSG_COUNT];
340652594c7SDexuan Cui 
3410f70b669SVitaly Kuznetsov 
34246a97191SGreg Kroah-Hartman /* General vmbus interface */
34346a97191SGreg Kroah-Hartman 
344593db803SAndy Shevchenko struct hv_device *vmbus_device_create(const guid_t *type,
345593db803SAndy Shevchenko 				      const guid_t *instance,
34646a97191SGreg Kroah-Hartman 				      struct vmbus_channel *channel);
34746a97191SGreg Kroah-Hartman 
34846a97191SGreg Kroah-Hartman int vmbus_device_register(struct hv_device *child_device_obj);
34946a97191SGreg Kroah-Hartman void vmbus_device_unregister(struct hv_device *device_obj);
350c2e5df61SStephen Hemminger int vmbus_add_channel_kobj(struct hv_device *device_obj,
351c2e5df61SStephen Hemminger 			   struct vmbus_channel *channel);
35246a97191SGreg Kroah-Hartman 
35346fc1548SKimberly Brown void vmbus_remove_channel_attr_group(struct vmbus_channel *channel);
35446fc1548SKimberly Brown 
3558b6a877cSAndrea Parri (Microsoft) void vmbus_channel_map_relid(struct vmbus_channel *channel);
3568b6a877cSAndrea Parri (Microsoft) void vmbus_channel_unmap_relid(struct vmbus_channel *channel);
3578b6a877cSAndrea Parri (Microsoft) 
358d43e2fe7SDexuan Cui struct vmbus_channel *relid2channel(u32 relid);
35946a97191SGreg Kroah-Hartman 
36093e5bd06SK. Y. Srinivasan void vmbus_free_channels(void);
36146a97191SGreg Kroah-Hartman 
36246a97191SGreg Kroah-Hartman /* Connection interface */
36346a97191SGreg Kroah-Hartman 
36446a97191SGreg Kroah-Hartman int vmbus_connect(void);
36509a19628SVitaly Kuznetsov void vmbus_disconnect(void);
36646a97191SGreg Kroah-Hartman 
367c0bb0392SVitaly Kuznetsov int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep);
36846a97191SGreg Kroah-Hartman 
36946a97191SGreg Kroah-Hartman void vmbus_on_event(unsigned long data);
370d81274aaSK. Y. Srinivasan void vmbus_on_msg_dpc(unsigned long data);
37146a97191SGreg Kroah-Hartman 
3722a9d7de2SStephen Hemminger int hv_kvp_init(struct hv_util_service *srv);
373*89fcec5eSMichael Kelley int hv_kvp_init_transport(void);
3743647a83dSVitaly Kuznetsov void hv_kvp_deinit(void);
37554e19d34SDexuan Cui int hv_kvp_pre_suspend(void);
37654e19d34SDexuan Cui int hv_kvp_pre_resume(void);
3772a9d7de2SStephen Hemminger void hv_kvp_onchannelcallback(void *context);
3783647a83dSVitaly Kuznetsov 
3792a9d7de2SStephen Hemminger int hv_vss_init(struct hv_util_service *srv);
380*89fcec5eSMichael Kelley int hv_vss_init_transport(void);
3813647a83dSVitaly Kuznetsov void hv_vss_deinit(void);
38254e19d34SDexuan Cui int hv_vss_pre_suspend(void);
38354e19d34SDexuan Cui int hv_vss_pre_resume(void);
3842a9d7de2SStephen Hemminger void hv_vss_onchannelcallback(void *context);
3853647a83dSVitaly Kuznetsov 
3862a9d7de2SStephen Hemminger int hv_fcopy_init(struct hv_util_service *srv);
38701325476SK. Y. Srinivasan void hv_fcopy_deinit(void);
38854e19d34SDexuan Cui int hv_fcopy_pre_suspend(void);
38954e19d34SDexuan Cui int hv_fcopy_pre_resume(void);
3902a9d7de2SStephen Hemminger void hv_fcopy_onchannelcallback(void *context);
39175ff3a8aSVitaly Kuznetsov void vmbus_initiate_unload(bool crash);
39201325476SK. Y. Srinivasan 
hv_poll_channel(struct vmbus_channel * channel,void (* cb)(void *))3938efe78fdSVitaly Kuznetsov static inline void hv_poll_channel(struct vmbus_channel *channel,
3948efe78fdSVitaly Kuznetsov 				   void (*cb)(void *))
3958efe78fdSVitaly Kuznetsov {
3968efe78fdSVitaly Kuznetsov 	if (!channel)
3978efe78fdSVitaly Kuznetsov 		return;
3981e052a16SK. Y. Srinivasan 	cb(channel);
3998efe78fdSVitaly Kuznetsov }
40046a97191SGreg Kroah-Hartman 
401636c88daSVitaly Kuznetsov enum hvutil_device_state {
402636c88daSVitaly Kuznetsov 	HVUTIL_DEVICE_INIT = 0,  /* driver is loaded, waiting for userspace */
403636c88daSVitaly Kuznetsov 	HVUTIL_READY,            /* userspace is registered */
404636c88daSVitaly Kuznetsov 	HVUTIL_HOSTMSG_RECEIVED, /* message from the host was received */
405636c88daSVitaly Kuznetsov 	HVUTIL_USERSPACE_REQ,    /* request to userspace was sent */
406636c88daSVitaly Kuznetsov 	HVUTIL_USERSPACE_RECV,   /* reply from userspace was received */
407636c88daSVitaly Kuznetsov 	HVUTIL_DEVICE_DYING,     /* driver unload is in progress */
408636c88daSVitaly Kuznetsov };
409636c88daSVitaly Kuznetsov 
410af9ca6f9SBranden Bonaby enum delay {
411af9ca6f9SBranden Bonaby 	INTERRUPT_DELAY = 0,
412af9ca6f9SBranden Bonaby 	MESSAGE_DELAY   = 1,
413af9ca6f9SBranden Bonaby };
414af9ca6f9SBranden Bonaby 
415afaa33daSAndrea Parri (Microsoft) extern const struct vmbus_device vmbus_devs[];
416afaa33daSAndrea Parri (Microsoft) 
hv_is_perf_channel(struct vmbus_channel * channel)417afaa33daSAndrea Parri (Microsoft) static inline bool hv_is_perf_channel(struct vmbus_channel *channel)
418afaa33daSAndrea Parri (Microsoft) {
419afaa33daSAndrea Parri (Microsoft) 	return vmbus_devs[channel->device_id].perf_device;
420afaa33daSAndrea Parri (Microsoft) }
421afaa33daSAndrea Parri (Microsoft) 
hv_is_allocated_cpu(unsigned int cpu)422de96e8a0SVitaly Kuznetsov static inline bool hv_is_allocated_cpu(unsigned int cpu)
423afaa33daSAndrea Parri (Microsoft) {
424afaa33daSAndrea Parri (Microsoft) 	struct vmbus_channel *channel, *sc;
425afaa33daSAndrea Parri (Microsoft) 
426afaa33daSAndrea Parri (Microsoft) 	lockdep_assert_held(&vmbus_connection.channel_mutex);
427afaa33daSAndrea Parri (Microsoft) 	/*
428afaa33daSAndrea Parri (Microsoft) 	 * List additions/deletions as well as updates of the target CPUs are
429afaa33daSAndrea Parri (Microsoft) 	 * protected by channel_mutex.
430afaa33daSAndrea Parri (Microsoft) 	 */
431afaa33daSAndrea Parri (Microsoft) 	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
432afaa33daSAndrea Parri (Microsoft) 		if (!hv_is_perf_channel(channel))
433afaa33daSAndrea Parri (Microsoft) 			continue;
434afaa33daSAndrea Parri (Microsoft) 		if (channel->target_cpu == cpu)
435afaa33daSAndrea Parri (Microsoft) 			return true;
436afaa33daSAndrea Parri (Microsoft) 		list_for_each_entry(sc, &channel->sc_list, sc_list) {
437afaa33daSAndrea Parri (Microsoft) 			if (sc->target_cpu == cpu)
438afaa33daSAndrea Parri (Microsoft) 				return true;
439afaa33daSAndrea Parri (Microsoft) 		}
440afaa33daSAndrea Parri (Microsoft) 	}
441afaa33daSAndrea Parri (Microsoft) 	return false;
442afaa33daSAndrea Parri (Microsoft) }
443afaa33daSAndrea Parri (Microsoft) 
hv_set_allocated_cpu(unsigned int cpu)444de96e8a0SVitaly Kuznetsov static inline void hv_set_allocated_cpu(unsigned int cpu)
445afaa33daSAndrea Parri (Microsoft) {
446afaa33daSAndrea Parri (Microsoft) 	cpumask_set_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]);
447afaa33daSAndrea Parri (Microsoft) }
448afaa33daSAndrea Parri (Microsoft) 
hv_clear_allocated_cpu(unsigned int cpu)449de96e8a0SVitaly Kuznetsov static inline void hv_clear_allocated_cpu(unsigned int cpu)
450afaa33daSAndrea Parri (Microsoft) {
451de96e8a0SVitaly Kuznetsov 	if (hv_is_allocated_cpu(cpu))
452afaa33daSAndrea Parri (Microsoft) 		return;
453afaa33daSAndrea Parri (Microsoft) 	cpumask_clear_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]);
454afaa33daSAndrea Parri (Microsoft) }
455afaa33daSAndrea Parri (Microsoft) 
hv_update_allocated_cpus(unsigned int old_cpu,unsigned int new_cpu)456de96e8a0SVitaly Kuznetsov static inline void hv_update_allocated_cpus(unsigned int old_cpu,
457afaa33daSAndrea Parri (Microsoft) 					  unsigned int new_cpu)
458afaa33daSAndrea Parri (Microsoft) {
459de96e8a0SVitaly Kuznetsov 	hv_set_allocated_cpu(new_cpu);
460de96e8a0SVitaly Kuznetsov 	hv_clear_allocated_cpu(old_cpu);
461afaa33daSAndrea Parri (Microsoft) }
462afaa33daSAndrea Parri (Microsoft) 
463af9ca6f9SBranden Bonaby #ifdef CONFIG_HYPERV_TESTING
464af9ca6f9SBranden Bonaby 
465af9ca6f9SBranden Bonaby int hv_debug_add_dev_dir(struct hv_device *dev);
466af9ca6f9SBranden Bonaby void hv_debug_rm_dev_dir(struct hv_device *dev);
467af9ca6f9SBranden Bonaby void hv_debug_rm_all_dir(void);
468af9ca6f9SBranden Bonaby int hv_debug_init(void);
469af9ca6f9SBranden Bonaby void hv_debug_delay_test(struct vmbus_channel *channel, enum delay delay_type);
470af9ca6f9SBranden Bonaby 
471af9ca6f9SBranden Bonaby #else /* CONFIG_HYPERV_TESTING */
472af9ca6f9SBranden Bonaby 
hv_debug_rm_dev_dir(struct hv_device * dev)473af9ca6f9SBranden Bonaby static inline void hv_debug_rm_dev_dir(struct hv_device *dev) {};
hv_debug_rm_all_dir(void)474af9ca6f9SBranden Bonaby static inline void hv_debug_rm_all_dir(void) {};
hv_debug_delay_test(struct vmbus_channel * channel,enum delay delay_type)475af9ca6f9SBranden Bonaby static inline void hv_debug_delay_test(struct vmbus_channel *channel,
476af9ca6f9SBranden Bonaby 				       enum delay delay_type) {};
hv_debug_init(void)477af9ca6f9SBranden Bonaby static inline int hv_debug_init(void)
478af9ca6f9SBranden Bonaby {
479af9ca6f9SBranden Bonaby 	return -1;
480af9ca6f9SBranden Bonaby }
481af9ca6f9SBranden Bonaby 
hv_debug_add_dev_dir(struct hv_device * dev)482af9ca6f9SBranden Bonaby static inline int hv_debug_add_dev_dir(struct hv_device *dev)
483af9ca6f9SBranden Bonaby {
484af9ca6f9SBranden Bonaby 	return -1;
485af9ca6f9SBranden Bonaby }
486af9ca6f9SBranden Bonaby 
487af9ca6f9SBranden Bonaby #endif /* CONFIG_HYPERV_TESTING */
488af9ca6f9SBranden Bonaby 
48946a97191SGreg Kroah-Hartman #endif /* _HYPERV_VMBUS_H */
490