/* * * Copyright (c) 2009, Microsoft Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Authors: * Haiyang Zhang * Hank Janssen * */ #ifndef _CHANNEL_MGMT_H_ #define _CHANNEL_MGMT_H_ #include #include #include "ring_buffer.h" #include "vmbus_channel_interface.h" #include "vmbus_packet_format.h" /* Version 1 messages */ enum vmbus_channel_message_type { CHANNELMSG_INVALID = 0, CHANNELMSG_OFFERCHANNEL = 1, CHANNELMSG_RESCIND_CHANNELOFFER = 2, CHANNELMSG_REQUESTOFFERS = 3, CHANNELMSG_ALLOFFERS_DELIVERED = 4, CHANNELMSG_OPENCHANNEL = 5, CHANNELMSG_OPENCHANNEL_RESULT = 6, CHANNELMSG_CLOSECHANNEL = 7, CHANNELMSG_GPADL_HEADER = 8, CHANNELMSG_GPADL_BODY = 9, CHANNELMSG_GPADL_CREATED = 10, CHANNELMSG_GPADL_TEARDOWN = 11, CHANNELMSG_GPADL_TORNDOWN = 12, CHANNELMSG_RELID_RELEASED = 13, CHANNELMSG_INITIATE_CONTACT = 14, CHANNELMSG_VERSION_RESPONSE = 15, CHANNELMSG_UNLOAD = 16, #ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD CHANNELMSG_VIEWRANGE_ADD = 17, CHANNELMSG_VIEWRANGE_REMOVE = 18, #endif CHANNELMSG_COUNT }; struct vmbus_channel_message_header { enum vmbus_channel_message_type msgtype; u32 padding; } __attribute__((packed)); /* Query VMBus Version parameters */ struct vmbus_channel_query_vmbus_version { struct vmbus_channel_message_header header; u32 version; } __attribute__((packed)); /* VMBus Version Supported parameters */ struct vmbus_channel_version_supported { struct vmbus_channel_message_header header; bool version_supported; } __attribute__((packed)); /* Offer Channel parameters */ struct vmbus_channel_offer_channel { struct vmbus_channel_message_header header; struct vmbus_channel_offer offer; u32 child_relid; u8 monitorid; bool monitor_allocated; } __attribute__((packed)); /* Rescind Offer parameters */ struct vmbus_channel_rescind_offer { struct vmbus_channel_message_header header; u32 child_relid; } __attribute__((packed)); /* * Request Offer -- no parameters, SynIC message contains the partition ID * Set Snoop -- no parameters, SynIC message contains the partition ID * Clear Snoop -- no parameters, SynIC message contains the partition ID * All Offers Delivered -- no parameters, SynIC message contains the partition * ID * Flush Client -- no parameters, SynIC message contains the partition ID */ /* Open Channel parameters */ struct vmbus_channel_open_channel { struct vmbus_channel_message_header header; /* Identifies the specific VMBus channel that is being opened. */ u32 child_relid; /* ID making a particular open request at a channel offer unique. */ u32 openid; /* GPADL for the channel's ring buffer. */ u32 ringbuffer_gpadlhandle; /* GPADL for the channel's server context save area. */ u32 server_contextarea_gpadlhandle; /* * The upstream ring buffer begins at offset zero in the memory * described by RingBufferGpadlHandle. The downstream ring buffer * follows it at this offset (in pages). */ u32 downstream_ringbuffer_pageoffset; /* User-specific data to be passed along to the server endpoint. */ unsigned char userdata[MAX_USER_DEFINED_BYTES]; } __attribute__((packed)); /* Open Channel Result parameters */ struct vmbus_channel_open_result { struct vmbus_channel_message_header header; u32 child_relid; u32 openid; u32 status; } __attribute__((packed)); /* Close channel parameters; */ struct vmbus_channel_close_channel { struct vmbus_channel_message_header header; u32 child_relid; } __attribute__((packed)); /* Channel Message GPADL */ #define GPADL_TYPE_RING_BUFFER 1 #define GPADL_TYPE_SERVER_SAVE_AREA 2 #define GPADL_TYPE_TRANSACTION 8 /* * The number of PFNs in a GPADL message is defined by the number of * pages that would be spanned by ByteCount and ByteOffset. If the * implied number of PFNs won't fit in this packet, there will be a * follow-up packet that contains more. */ struct vmbus_channel_gpadl_header { struct vmbus_channel_message_header header; u32 child_relid; u32 gpadl; u16 range_buflen; u16 rangecount; struct gpa_range range[0]; } __attribute__((packed)); /* This is the followup packet that contains more PFNs. */ struct vmbus_channel_gpadl_body { struct vmbus_channel_message_header header; u32 msgnumber; u32 gpadl; u64 pfn[0]; } __attribute__((packed)); struct vmbus_channel_gpadl_created { struct vmbus_channel_message_header header; u32 child_relid; u32 gpadl; u32 creation_status; } __attribute__((packed)); struct vmbus_channel_gpadl_teardown { struct vmbus_channel_message_header header; u32 child_relid; u32 gpadl; } __attribute__((packed)); struct vmbus_channel_gpadl_torndown { struct vmbus_channel_message_header header; u32 gpadl; } __attribute__((packed)); #ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD struct vmbus_channel_view_range_add { struct vmbus_channel_message_header header; PHYSICAL_ADDRESS viewrange_base; u64 viewrange_length; u32 child_relid; } __attribute__((packed)); struct vmbus_channel_view_range_remove { struct vmbus_channel_message_header header; PHYSICAL_ADDRESS viewrange_base; u32 child_relid; } __attribute__((packed)); #endif struct vmbus_channel_relid_released { struct vmbus_channel_message_header header; u32 child_relid; } __attribute__((packed)); struct vmbus_channel_initiate_contact { struct vmbus_channel_message_header header; u32 vmbus_version_requested; u32 padding2; u64 interrupt_page; u64 monitor_page1; u64 monitor_page2; } __attribute__((packed)); struct vmbus_channel_version_response { struct vmbus_channel_message_header header; bool version_supported; } __attribute__((packed)); enum vmbus_channel_state { CHANNEL_OFFER_STATE, CHANNEL_OPENING_STATE, CHANNEL_OPEN_STATE, }; struct vmbus_channel { struct list_head listentry; struct hv_device *device_obj; struct timer_list poll_timer; /* SA-111 workaround */ struct work_struct work; enum vmbus_channel_state state; struct vmbus_channel_offer_channel offermsg; /* * These are based on the OfferMsg.MonitorId. * Save it here for easy access. */ u8 monitor_grp; u8 monitor_bit; u32 ringbuffer_gpadlhandle; /* Allocated memory for ring buffer */ void *ringbuffer_pages; u32 ringbuffer_pagecount; struct hv_ring_buffer_info outbound; /* send to parent */ struct hv_ring_buffer_info inbound; /* receive from parent */ spinlock_t inbound_lock; struct workqueue_struct *controlwq; /* Channel callback are invoked in this workqueue context */ /* HANDLE dataWorkQueue; */ void (*onchannel_callback)(void *context); void *channel_callback_context; }; struct vmbus_channel_debug_info { u32 relid; enum vmbus_channel_state state; struct hv_guid interfacetype; struct hv_guid interface_instance; u32 monitorid; u32 servermonitor_pending; u32 servermonitor_latency; u32 servermonitor_connectionid; u32 clientmonitor_pending; u32 clientmonitor_latency; u32 clientmonitor_connectionid; struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info outbound; }; /* * Represents each channel msg on the vmbus connection This is a * variable-size data structure depending on the msg type itself */ struct vmbus_channel_msginfo { /* Bookkeeping stuff */ struct list_head msglistentry; /* So far, this is only used to handle gpadl body message */ struct list_head submsglist; /* Synchronize the request/response if needed */ struct osd_waitevent *waitevent; union { struct vmbus_channel_version_supported version_supported; struct vmbus_channel_open_result open_result; struct vmbus_channel_gpadl_torndown gpadl_torndown; struct vmbus_channel_gpadl_created gpadl_created; struct vmbus_channel_version_response version_response; } response; u32 msgsize; /* * The channel message that goes out on the "wire". * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header */ unsigned char msg[0]; }; void free_channel(struct vmbus_channel *channel); void vmbus_onmessage(void *context); int vmbus_request_offers(void); void vmbus_release_unattached_channels(void); #endif /* _CHANNEL_MGMT_H_ */