Blame view

include/linux/hyperv.h 41.4 KB
5c4734006   K. Y. Srinivasan   Staging: hv: Crea...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   *
   * Copyright (c) 2011, 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 <haiyangz@microsoft.com>
   *   Hank Janssen  <hjanssen@microsoft.com>
   *   K. Y. Srinivasan <kys@microsoft.com>
   *
   */
3f335ea21   K. Y. Srinivasan   Staging: hv: Incl...
24
25
26
  
  #ifndef _HYPERV_H
  #define _HYPERV_H
5267cf02c   Bjarke Istrup Pedersen   hv: Add hyperv.h ...
27
  #include <uapi/linux/hyperv.h>
c75efa974   Andrey Smetanin   drivers/hv: share...
28
  #include <uapi/asm/hyperv.h>
2939437ce   K. Y. Srinivasan   drivers: hv: kvp:...
29

5267cf02c   Bjarke Istrup Pedersen   hv: Add hyperv.h ...
30
  #include <linux/types.h>
8ff3e6fc5   K. Y. Srinivasan   Staging: hv: Incl...
31
32
33
34
35
36
  #include <linux/scatterlist.h>
  #include <linux/list.h>
  #include <linux/timer.h>
  #include <linux/workqueue.h>
  #include <linux/completion.h>
  #include <linux/device.h>
2e2c1d17a   K. Y. Srinivasan   Staging: hv: vmbu...
37
  #include <linux/mod_devicetable.h>
8ff3e6fc5   K. Y. Srinivasan   Staging: hv: Incl...
38

7e5ec3683   K. Y. Srinivasan   Drivers: hv: vmbu...
39
  #define MAX_PAGE_BUFFER_COUNT				32
a363bf7bd   K. Y. Srinivasan   Staging: hv: Add ...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  #define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
  
  #pragma pack(push, 1)
  
  /* Single-page buffer */
  struct hv_page_buffer {
  	u32 len;
  	u32 offset;
  	u64 pfn;
  };
  
  /* Multiple-page buffer */
  struct hv_multipage_buffer {
  	/* Length and Offset determines the # of pfns in the array */
  	u32 len;
  	u32 offset;
  	u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT];
  };
d61031ee8   K. Y. Srinivasan   Drivers: hv: vmbu...
58
59
60
61
62
63
64
65
66
67
68
  /*
   * Multiple-page buffer array; the pfn array is variable size:
   * The number of entries in the PFN array is determined by
   * "len" and "offset".
   */
  struct hv_mpb_array {
  	/* Length and Offset determines the # of pfns in the array */
  	u32 len;
  	u32 offset;
  	u64 pfn_array[];
  };
a363bf7bd   K. Y. Srinivasan   Staging: hv: Add ...
69
70
71
72
73
74
75
76
77
  /* 0x18 includes the proprietary packet header */
  #define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
  					(sizeof(struct hv_page_buffer) * \
  					 MAX_PAGE_BUFFER_COUNT))
  #define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
  					 sizeof(struct hv_multipage_buffer))
  
  
  #pragma pack(pop)
7effffb7a   K. Y. Srinivasan   Staging: hv: Move...
78
79
80
81
82
83
84
85
  struct hv_ring_buffer {
  	/* Offset in bytes from the start of ring data below */
  	u32 write_index;
  
  	/* Offset in bytes from the start of ring data below */
  	u32 read_index;
  
  	u32 interrupt_mask;
2416603ef   K. Y. Srinivasan   Drivers: hv: Upda...
86
87
88
89
90
91
92
93
  	/*
  	 * Win8 uses some of the reserved bits to implement
  	 * interrupt driven flow management. On the send side
  	 * we can request that the receiver interrupt the sender
  	 * when the ring transitions from being full to being able
  	 * to handle a message of size "pending_send_sz".
  	 *
  	 * Add necessary state for this enhancement.
7effffb7a   K. Y. Srinivasan   Staging: hv: Move...
94
  	 */
2416603ef   K. Y. Srinivasan   Drivers: hv: Upda...
95
96
97
98
99
100
101
102
103
104
105
106
107
  	u32 pending_send_sz;
  
  	u32 reserved1[12];
  
  	union {
  		struct {
  			u32 feat_pending_send_sz:1;
  		};
  		u32 value;
  	} feature_bits;
  
  	/* Pad it to PAGE_SIZE so that data starts on page boundary */
  	u8	reserved2[4028];
7effffb7a   K. Y. Srinivasan   Staging: hv: Move...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  
  	/*
  	 * Ring data starts here + RingDataStartOffset
  	 * !!! DO NOT place any fields below this !!!
  	 */
  	u8 buffer[0];
  } __packed;
  
  struct hv_ring_buffer_info {
  	struct hv_ring_buffer *ring_buffer;
  	u32 ring_size;			/* Include the shared header */
  	spinlock_t ring_lock;
  
  	u32 ring_datasize;		/* < ring_size */
  	u32 ring_data_startoffset;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
123
124
  	u32 priv_write_index;
  	u32 priv_read_index;
7effffb7a   K. Y. Srinivasan   Staging: hv: Move...
125
  };
33be96e47   Haiyang Zhang   net/hyperv: Add f...
126
127
128
129
130
131
132
133
134
135
136
137
  /*
   *
   * hv_get_ringbuffer_availbytes()
   *
   * Get number of bytes available to read and to write to
   * for the specified ring buffer
   */
  static inline void
  hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
  			  u32 *read, u32 *write)
  {
  	u32 read_loc, write_loc, dsize;
33be96e47   Haiyang Zhang   net/hyperv: Add f...
138
139
140
141
142
143
144
145
146
  	/* Capture the read/write indices before they changed */
  	read_loc = rbi->ring_buffer->read_index;
  	write_loc = rbi->ring_buffer->write_index;
  	dsize = rbi->ring_datasize;
  
  	*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
  		read_loc - write_loc;
  	*read = dsize - *write;
  }
a6341f000   K. Y. Srinivasan   Drivers: hv: vmbu...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  static inline u32 hv_get_bytes_to_read(struct hv_ring_buffer_info *rbi)
  {
  	u32 read_loc, write_loc, dsize, read;
  
  	dsize = rbi->ring_datasize;
  	read_loc = rbi->ring_buffer->read_index;
  	write_loc = READ_ONCE(rbi->ring_buffer->write_index);
  
  	read = write_loc >= read_loc ? (write_loc - read_loc) :
  		(dsize - read_loc) + write_loc;
  
  	return read;
  }
  
  static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
  {
  	u32 read_loc, write_loc, dsize, write;
  
  	dsize = rbi->ring_datasize;
  	read_loc = READ_ONCE(rbi->ring_buffer->read_index);
  	write_loc = rbi->ring_buffer->write_index;
  
  	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
  		read_loc - write_loc;
  	return write;
  }
eafa7072e   K. Y. Srinivasan   Drivers: hv: Move...
173
174
175
176
177
178
179
  /*
   * VMBUS version is 32 bit entity broken up into
   * two 16 bit quantities: major_number. minor_number.
   *
   * 0 . 13 (Windows Server 2008)
   * 1 . 1  (Windows 7)
   * 2 . 4  (Windows 8)
03367ef5e   K. Y. Srinivasan   Drivers: hv: vmbu...
180
   * 3 . 0  (Windows 8 R2)
6c4e5f9c9   Keith Mange   Drivers: hv: vmbu...
181
   * 4 . 0  (Windows 10)
eafa7072e   K. Y. Srinivasan   Drivers: hv: Move...
182
183
184
185
186
   */
  
  #define VERSION_WS2008  ((0 << 16) | (13))
  #define VERSION_WIN7    ((1 << 16) | (1))
  #define VERSION_WIN8    ((2 << 16) | (4))
03367ef5e   K. Y. Srinivasan   Drivers: hv: vmbu...
187
  #define VERSION_WIN8_1    ((3 << 16) | (0))
6c4e5f9c9   Keith Mange   Drivers: hv: vmbu...
188
  #define VERSION_WIN10	((4 << 16) | (0))
eafa7072e   K. Y. Srinivasan   Drivers: hv: Move...
189
190
  
  #define VERSION_INVAL -1
6c4e5f9c9   Keith Mange   Drivers: hv: vmbu...
191
  #define VERSION_CURRENT VERSION_WIN10
f7c6dfda0   K. Y. Srinivasan   Staging: hv: Move...
192

517d8dc68   K. Y. Srinivasan   Staging: hv: Move...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  /* Make maximum size of pipe payload of 16K */
  #define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
  
  /* Define PipeMode values. */
  #define VMBUS_PIPE_TYPE_BYTE		0x00000000
  #define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
  
  /* The size of the user defined data buffer for non-pipe offers. */
  #define MAX_USER_DEFINED_BYTES		120
  
  /* The size of the user defined data buffer for pipe offers. */
  #define MAX_PIPE_USER_DEFINED_BYTES	116
  
  /*
   * At the center of the Channel Management library is the Channel Offer. This
   * struct contains the fundamental information about an offer.
   */
  struct vmbus_channel_offer {
358d2ee2e   K. Y. Srinivasan   Staging: hv: Repl...
211
212
  	uuid_le if_type;
  	uuid_le if_instance;
29423b7e5   K. Y. Srinivasan   Drivers: hv: Exte...
213
214
215
216
217
218
  
  	/*
  	 * These two fields are not currently used.
  	 */
  	u64 reserved1;
  	u64 reserved2;
517d8dc68   K. Y. Srinivasan   Staging: hv: Move...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  	u16 chn_flags;
  	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
  
  	union {
  		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
  		struct {
  			unsigned char user_def[MAX_USER_DEFINED_BYTES];
  		} std;
  
  		/*
  		 * Pipes:
  		 * The following sructure is an integrated pipe protocol, which
  		 * is implemented on top of standard user-defined data. Pipe
  		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
  		 * use.
  		 */
  		struct {
  			u32  pipe_mode;
  			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
  		} pipe;
  	} u;
29423b7e5   K. Y. Srinivasan   Drivers: hv: Exte...
240
241
242
243
244
  	/*
  	 * The sub_channel_index is defined in win8.
  	 */
  	u16 sub_channel_index;
  	u16 reserved3;
517d8dc68   K. Y. Srinivasan   Staging: hv: Move...
245
246
247
248
249
250
251
252
253
254
  } __packed;
  
  /* Server Flags */
  #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
  #define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
  #define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
  #define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
  #define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
  #define VMBUS_CHANNEL_PARENT_OFFER			0x200
  #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
e8d6ca023   Dexuan Cui   Drivers: hv: vmbu...
255
  #define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER		0x2000
517d8dc68   K. Y. Srinivasan   Staging: hv: Move...
256

50ed40e0d   K. Y. Srinivasan   Staging: hv: Move...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  struct vmpacket_descriptor {
  	u16 type;
  	u16 offset8;
  	u16 len8;
  	u16 flags;
  	u64 trans_id;
  } __packed;
  
  struct vmpacket_header {
  	u32 prev_pkt_start_offset;
  	struct vmpacket_descriptor descriptor;
  } __packed;
  
  struct vmtransfer_page_range {
  	u32 byte_count;
  	u32 byte_offset;
  } __packed;
  
  struct vmtransfer_page_packet_header {
  	struct vmpacket_descriptor d;
  	u16 xfer_pageset_id;
1508d8111   K. Y. Srinivasan   Drivers: hv: Expl...
278
  	u8  sender_owns_set;
50ed40e0d   K. Y. Srinivasan   Staging: hv: Move...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  	u8 reserved;
  	u32 range_cnt;
  	struct vmtransfer_page_range ranges[1];
  } __packed;
  
  struct vmgpadl_packet_header {
  	struct vmpacket_descriptor d;
  	u32 gpadl;
  	u32 reserved;
  } __packed;
  
  struct vmadd_remove_transfer_page_set {
  	struct vmpacket_descriptor d;
  	u32 gpadl;
  	u16 xfer_pageset_id;
  	u16 reserved;
  } __packed;
  
  /*
   * This structure defines a range in guest physical space that can be made to
   * look virtually contiguous.
   */
  struct gpa_range {
  	u32 byte_count;
  	u32 byte_offset;
  	u64 pfn_array[0];
  };
  
  /*
   * This is the format for an Establish Gpadl packet, which contains a handle by
   * which this GPADL will be known and a set of GPA ranges associated with it.
   * This can be converted to a MDL by the guest OS.  If there are multiple GPA
   * ranges, then the resulting MDL will be "chained," representing multiple VA
   * ranges.
   */
  struct vmestablish_gpadl {
  	struct vmpacket_descriptor d;
  	u32 gpadl;
  	u32 range_cnt;
  	struct gpa_range range[1];
  } __packed;
  
  /*
   * This is the format for a Teardown Gpadl packet, which indicates that the
   * GPADL handle in the Establish Gpadl packet will never be referenced again.
   */
  struct vmteardown_gpadl {
  	struct vmpacket_descriptor d;
  	u32 gpadl;
  	u32 reserved;	/* for alignment to a 8-byte boundary */
  } __packed;
  
  /*
   * This is the format for a GPA-Direct packet, which contains a set of GPA
   * ranges, in addition to commands and/or data.
   */
  struct vmdata_gpa_direct {
  	struct vmpacket_descriptor d;
  	u32 reserved;
  	u32 range_cnt;
  	struct gpa_range range[1];
  } __packed;
  
  /* This is the format for a Additional Data Packet. */
  struct vmadditional_data {
  	struct vmpacket_descriptor d;
  	u64 total_bytes;
  	u32 offset;
  	u32 byte_cnt;
  	unsigned char data[1];
  } __packed;
  
  union vmpacket_largest_possible_header {
  	struct vmpacket_descriptor simple_hdr;
  	struct vmtransfer_page_packet_header xfer_page_hdr;
  	struct vmgpadl_packet_header gpadl_hdr;
  	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
  	struct vmestablish_gpadl establish_gpadl_hdr;
  	struct vmteardown_gpadl teardown_gpadl_hdr;
  	struct vmdata_gpa_direct data_gpa_direct_hdr;
  };
  
  #define VMPACKET_DATA_START_ADDRESS(__packet)	\
  	(void *)(((unsigned char *)__packet) +	\
  	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
  
  #define VMPACKET_DATA_LENGTH(__packet)		\
  	((((struct vmpacket_descriptor)__packet)->len8 -	\
  	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
  
  #define VMPACKET_TRANSFER_MODE(__packet)	\
  	(((struct IMPACT)__packet)->type)
  
  enum vmbus_packet_type {
  	VM_PKT_INVALID				= 0x0,
  	VM_PKT_SYNCH				= 0x1,
  	VM_PKT_ADD_XFER_PAGESET			= 0x2,
  	VM_PKT_RM_XFER_PAGESET			= 0x3,
  	VM_PKT_ESTABLISH_GPADL			= 0x4,
  	VM_PKT_TEARDOWN_GPADL			= 0x5,
  	VM_PKT_DATA_INBAND			= 0x6,
  	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
  	VM_PKT_DATA_USING_GPADL			= 0x8,
  	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
  	VM_PKT_CANCEL_REQUEST			= 0xa,
  	VM_PKT_COMP				= 0xb,
  	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
  	VM_PKT_ADDITIONAL_DATA			= 0xd
  };
  
  #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
517d8dc68   K. Y. Srinivasan   Staging: hv: Move...
390

b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
391

b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  /* 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,
2db84eff1   K. Y. Srinivasan   Drivers: hv: vmbu...
411
  	CHANNELMSG_UNLOAD_RESPONSE		= 17,
5c23a1a5c   Dexuan Cui   Drivers: hv: vmbu...
412
413
414
415
  	CHANNELMSG_18				= 18,
  	CHANNELMSG_19				= 19,
  	CHANNELMSG_20				= 20,
  	CHANNELMSG_TL_CONNECT_REQUEST		= 21,
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  	CHANNELMSG_COUNT
  };
  
  struct vmbus_channel_message_header {
  	enum vmbus_channel_message_type msgtype;
  	u32 padding;
  } __packed;
  
  /* Query VMBus Version parameters */
  struct vmbus_channel_query_vmbus_version {
  	struct vmbus_channel_message_header header;
  	u32 version;
  } __packed;
  
  /* VMBus Version Supported parameters */
  struct vmbus_channel_version_supported {
  	struct vmbus_channel_message_header header;
1508d8111   K. Y. Srinivasan   Drivers: hv: Expl...
433
  	u8 version_supported;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
434
435
436
437
438
439
440
441
  } __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;
29423b7e5   K. Y. Srinivasan   Drivers: hv: Exte...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  	/*
  	 * win7 and beyond splits this field into a bit field.
  	 */
  	u8 monitor_allocated:1;
  	u8 reserved:7;
  	/*
  	 * These are new fields added in win7 and later.
  	 * Do not access these fields without checking the
  	 * negotiated protocol.
  	 *
  	 * If "is_dedicated_interrupt" is set, we must not set the
  	 * associated bit in the channel bitmap while sending the
  	 * interrupt to the host.
  	 *
  	 * connection_id is to be used in signaling the host.
  	 */
  	u16 is_dedicated_interrupt:1;
  	u16 reserved1:15;
  	u32 connection_id;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  } __packed;
  
  /* Rescind Offer parameters */
  struct vmbus_channel_rescind_offer {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  } __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;
abbf3b2aa   K. Y. Srinivasan   Drivers: hv: Add ...
490
491
492
493
494
495
496
497
498
  	/*
  	 * Starting with win8, this field will be used to specify
  	 * the target virtual processor on which to deliver the interrupt for
  	 * the host to guest communication.
  	 * Prior to win8, incoming channel interrupts would only
  	 * be delivered on cpu 0. Setting this value to 0 would
  	 * preserve the earlier behavior.
  	 */
  	u32 target_vp;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  
  	/*
  	* 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];
  } __packed;
  
  /* Open Channel Result parameters */
  struct vmbus_channel_open_result {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  	u32 openid;
  	u32 status;
  } __packed;
  
  /* Close channel parameters; */
  struct vmbus_channel_close_channel {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  } __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];
  } __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];
  } __packed;
  
  struct vmbus_channel_gpadl_created {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  	u32 gpadl;
  	u32 creation_status;
  } __packed;
  
  struct vmbus_channel_gpadl_teardown {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  	u32 gpadl;
  } __packed;
  
  struct vmbus_channel_gpadl_torndown {
  	struct vmbus_channel_message_header header;
  	u32 gpadl;
  } __packed;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
570
571
572
573
574
575
576
577
  struct vmbus_channel_relid_released {
  	struct vmbus_channel_message_header header;
  	u32 child_relid;
  } __packed;
  
  struct vmbus_channel_initiate_contact {
  	struct vmbus_channel_message_header header;
  	u32 vmbus_version_requested;
e28bab482   K. Y. Srinivasan   Drivers: hv: vmbu...
578
  	u32 target_vcpu; /* The VCPU the host should respond to */
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
579
580
581
582
  	u64 interrupt_page;
  	u64 monitor_page1;
  	u64 monitor_page2;
  } __packed;
5c23a1a5c   Dexuan Cui   Drivers: hv: vmbu...
583
584
585
586
587
588
  /* Hyper-V socket: guest's connect()-ing to host */
  struct vmbus_channel_tl_connect_request {
  	struct vmbus_channel_message_header header;
  	uuid_le guest_endpoint_id;
  	uuid_le host_service_id;
  } __packed;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
589
590
  struct vmbus_channel_version_response {
  	struct vmbus_channel_message_header header;
1508d8111   K. Y. Srinivasan   Drivers: hv: Expl...
591
  	u8 version_supported;
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
592
593
594
595
596
597
  } __packed;
  
  enum vmbus_channel_state {
  	CHANNEL_OFFER_STATE,
  	CHANNEL_OPENING_STATE,
  	CHANNEL_OPEN_STATE,
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
598
  	CHANNEL_OPENED_STATE,
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
599
  };
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  /*
   * 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 completion  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];
  };
f9f1db832   K. Y. Srinivasan   Staging: hv: vmbu...
628
629
630
631
  struct vmbus_close_msg {
  	struct vmbus_channel_msginfo info;
  	struct vmbus_channel_close_channel msg;
  };
b3bf60c7b   K. Y. Srinivasan   Drivers: hv: Mana...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  /* Define connection identifier type. */
  union hv_connection_id {
  	u32 asu32;
  	struct {
  		u32 id:24;
  		u32 reserved:8;
  	} u;
  };
  
  /* Definition of the hv_signal_event hypercall input structure. */
  struct hv_input_signal_event {
  	union hv_connection_id connectionid;
  	u16 flag_number;
  	u16 rsvdz;
  };
  
  struct hv_input_signal_event_buffer {
  	u64 align8;
  	struct hv_input_signal_event event;
  };
8599846d7   K. Y. Srinivasan   Drivers: hv: vmbu...
652
653
654
655
  enum hv_signal_policy {
  	HV_SIGNAL_POLICY_DEFAULT = 0,
  	HV_SIGNAL_POLICY_EXPLICIT,
  };
509879bdb   K. Y. Srinivasan   Drivers: hv: Intr...
656
657
658
659
  enum hv_numa_policy {
  	HV_BALANCED = 0,
  	HV_LOCALIZED,
  };
7047f17d7   K. Y. Srinivasan   Drivers: hv: vmbu...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  enum vmbus_device_type {
  	HV_IDE = 0,
  	HV_SCSI,
  	HV_FC,
  	HV_NIC,
  	HV_ND,
  	HV_PCIE,
  	HV_FB,
  	HV_KBD,
  	HV_MOUSE,
  	HV_KVP,
  	HV_TS,
  	HV_HB,
  	HV_SHUTDOWN,
  	HV_FCOPY,
  	HV_BACKUP,
  	HV_DM,
  	HV_UNKOWN,
  };
  
  struct vmbus_device {
  	u16  dev_type;
  	uuid_le guid;
  	bool perf_device;
  };
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
685
686
687
688
  struct vmbus_channel {
  	struct list_head listentry;
  
  	struct hv_device *device_obj;
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
689
  	enum vmbus_channel_state state;
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
690
691
692
693
694
695
696
697
  
  	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;
c3582a2c4   Haiyang Zhang   hyperv: Add suppo...
698
  	bool rescind; /* got rescind msg */
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
699
700
701
702
703
704
705
706
  	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;
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
707

f9f1db832   K. Y. Srinivasan   Staging: hv: vmbu...
708
  	struct vmbus_close_msg close_msg;
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
709
710
711
712
713
  	/* Channel callback are invoked in this workqueue context */
  	/* HANDLE dataWorkQueue; */
  
  	void (*onchannel_callback)(void *context);
  	void *channel_callback_context;
132368bd0   K. Y. Srinivasan   Drivers: hv: Add ...
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  
  	/*
  	 * A channel can be marked for efficient (batched)
  	 * reading:
  	 * If batched_reading is set to "true", we read until the
  	 * channel is empty and hold off interrupts from the host
  	 * during the entire read process.
  	 * If batched_reading is set to "false", the client is not
  	 * going to perform batched reading.
  	 *
  	 * By default we will enable batched reading; specific
  	 * drivers that don't want this behavior can turn it off.
  	 */
  
  	bool batched_reading;
b3bf60c7b   K. Y. Srinivasan   Drivers: hv: Mana...
729
730
731
732
  
  	bool is_dedicated_interrupt;
  	struct hv_input_signal_event_buffer sig_buf;
  	struct hv_input_signal_event *sig_event;
abbf3b2aa   K. Y. Srinivasan   Drivers: hv: Add ...
733
734
735
736
737
738
739
740
741
742
  
  	/*
  	 * Starting with win8, this field will be used to specify
  	 * the target virtual processor on which to deliver the interrupt for
  	 * the host to guest communication.
  	 * Prior to win8, incoming channel interrupts would only
  	 * be delivered on cpu 0. Setting this value to 0 would
  	 * preserve the earlier behavior.
  	 */
  	u32 target_vp;
d3ba720dd   K. Y. Srinivasan   Drivers: hv: Elim...
743
744
  	/* The corresponding CPUID in the guest */
  	u32 target_cpu;
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
745
  	/*
1f656ff3f   K. Y. Srinivasan   Drivers: hv: vmbu...
746
747
  	 * State to manage the CPU affiliation of channels.
  	 */
3b71107d7   Dexuan Cui   Drivers: hv: vmbu...
748
  	struct cpumask alloced_cpus_in_node;
1f656ff3f   K. Y. Srinivasan   Drivers: hv: vmbu...
749
750
  	int numa_node;
  	/*
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  	 * Support for sub-channels. For high performance devices,
  	 * it will be useful to have multiple sub-channels to support
  	 * a scalable communication infrastructure with the host.
  	 * The support for sub-channels is implemented as an extention
  	 * to the current infrastructure.
  	 * The initial offer is considered the primary channel and this
  	 * offer message will indicate if the host supports sub-channels.
  	 * The guest is free to ask for sub-channels to be offerred and can
  	 * open these sub-channels as a normal "primary" channel. However,
  	 * all sub-channels will have the same type and instance guids as the
  	 * primary channel. Requests sent on a given channel will result in a
  	 * response on the same channel.
  	 */
  
  	/*
  	 * Sub-channel creation callback. This callback will be called in
  	 * process context when a sub-channel offer is received from the host.
  	 * The guest can open the sub-channel in the context of this callback.
  	 */
  	void (*sc_creation_callback)(struct vmbus_channel *new_sc);
67fae053b   Vitaly Kuznetsov   Drivers: hv: rena...
771
  	/*
499e8401a   Dexuan Cui   Drivers: hv: vmbu...
772
773
774
775
776
777
  	 * Channel rescind callback. Some channels (the hvsock ones), need to
  	 * register a callback which is invoked in vmbus_onoffer_rescind().
  	 */
  	void (*chn_rescind_callback)(struct vmbus_channel *channel);
  
  	/*
67fae053b   Vitaly Kuznetsov   Drivers: hv: rena...
778
779
780
781
782
  	 * The spinlock to protect the structure. It is being used to protect
  	 * test-and-set access to various attributes of the structure as well
  	 * as all sc_list operations.
  	 */
  	spinlock_t lock;
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
783
784
785
786
787
  	/*
  	 * All Sub-channels of a primary channel are linked here.
  	 */
  	struct list_head sc_list;
  	/*
fea844a2b   Vitaly Kuznetsov   Drivers: hv: vmbu...
788
789
790
791
792
793
794
795
796
  	 * Current number of sub-channels.
  	 */
  	int num_sc;
  	/*
  	 * Number of a sub-channel (position within sc_list) which is supposed
  	 * to be used as the next outgoing channel.
  	 */
  	int next_oc;
  	/*
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
797
798
799
800
  	 * The primary channel this sub-channel belongs to.
  	 * This will be NULL for the primary channel.
  	 */
  	struct vmbus_channel *primary_channel;
8a7206a89   K. Y. Srinivasan   Drivers: hv: vmbu...
801
802
803
804
  	/*
  	 * Support per-channel state for use by vmbus drivers.
  	 */
  	void *per_channel_state;
3a28fa35d   K. Y. Srinivasan   Drivers: hv: vmbu...
805
806
807
808
809
  	/*
  	 * To support per-cpu lookup mapping of relid to channel,
  	 * link up channels based on their CPU affinity.
  	 */
  	struct list_head percpu_list;
8599846d7   K. Y. Srinivasan   Drivers: hv: vmbu...
810
811
812
813
814
815
816
  	/*
  	 * Host signaling policy: The default policy will be
  	 * based on the ring buffer state. We will also support
  	 * a policy where the client driver can have explicit
  	 * signaling control.
  	 */
  	enum hv_signal_policy  signal_policy;
fe760e4d6   K. Y. Srinivasan   Drivers: hv: vmbu...
817
818
819
820
821
822
823
824
825
826
  	/*
  	 * On the channel send side, many of the VMBUS
  	 * device drivers explicity serialize access to the
  	 * outgoing ring buffer. Give more control to the
  	 * VMBUS device drivers in terms how to serialize
  	 * accesss to the outgoing ring buffer.
  	 * The default behavior will be to aquire the
  	 * ring lock to preserve the current behavior.
  	 */
  	bool acquire_ring_lock;
3724287c0   K. Y. Srinivasan   Drivers: hv: vmbu...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  	/*
  	 * For performance critical channels (storage, networking
  	 * etc,), Hyper-V has a mechanism to enhance the throughput
  	 * at the expense of latency:
  	 * When the host is to be signaled, we just set a bit in a shared page
  	 * and this bit will be inspected by the hypervisor within a certain
  	 * window and if the bit is set, the host will be signaled. The window
  	 * of time is the monitor latency - currently around 100 usecs. This
  	 * mechanism improves throughput by:
  	 *
  	 * A) Making the host more efficient - each time it wakes up,
  	 *    potentially it will process morev number of packets. The
  	 *    monitor latency allows a batch to build up.
  	 * B) By deferring the hypercall to signal, we will also minimize
  	 *    the interrupts.
  	 *
  	 * Clearly, these optimizations improve throughput at the expense of
  	 * latency. Furthermore, since the channel is shared for both
  	 * control and data messages, control messages currently suffer
  	 * unnecessary latency adversley impacting performance and boot
  	 * time. To fix this issue, permit tagging the channel as being
  	 * in "low latency" mode. In this mode, we will bypass the monitor
  	 * mechanism.
  	 */
  	bool low_latency;
fe760e4d6   K. Y. Srinivasan   Drivers: hv: vmbu...
852

509879bdb   K. Y. Srinivasan   Drivers: hv: Intr...
853
854
855
856
857
858
859
860
861
862
863
  	/*
  	 * NUMA distribution policy:
  	 * We support teo policies:
  	 * 1) Balanced: Here all performance critical channels are
  	 *    distributed evenly amongst all the NUMA nodes.
  	 *    This policy will be the default policy.
  	 * 2) Localized: All channels of a given instance of a
  	 *    performance critical service will be assigned CPUs
  	 *    within a selected NUMA node.
  	 */
  	enum hv_numa_policy affinity_policy;
7d7c75cd4   K. Y. Srinivasan   Staging: hv: vmbu...
864
  };
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
865

fe760e4d6   K. Y. Srinivasan   Drivers: hv: vmbu...
866
867
868
869
  static inline void set_channel_lock_state(struct vmbus_channel *c, bool state)
  {
  	c->acquire_ring_lock = state;
  }
e8d6ca023   Dexuan Cui   Drivers: hv: vmbu...
870
871
872
873
874
  static inline bool is_hvsock_channel(const struct vmbus_channel *c)
  {
  	return !!(c->offermsg.offer.chn_flags &
  		  VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER);
  }
8599846d7   K. Y. Srinivasan   Drivers: hv: vmbu...
875
876
877
878
879
  static inline void set_channel_signal_state(struct vmbus_channel *c,
  					    enum hv_signal_policy policy)
  {
  	c->signal_policy = policy;
  }
509879bdb   K. Y. Srinivasan   Drivers: hv: Intr...
880
881
882
883
884
  static inline void set_channel_affinity_state(struct vmbus_channel *c,
  					      enum hv_numa_policy policy)
  {
  	c->affinity_policy = policy;
  }
132368bd0   K. Y. Srinivasan   Drivers: hv: Add ...
885
886
887
888
  static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
  {
  	c->batched_reading = state;
  }
8a7206a89   K. Y. Srinivasan   Drivers: hv: vmbu...
889
890
891
892
893
894
895
896
897
  static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
  {
  	c->per_channel_state = s;
  }
  
  static inline void *get_per_channel_state(struct vmbus_channel *c)
  {
  	return c->per_channel_state;
  }
3c75354d0   Dexuan Cui   Drivers: hv: vmbu...
898
899
900
901
902
  static inline void set_channel_pending_send_size(struct vmbus_channel *c,
  						 u32 size)
  {
  	c->outbound.ring_buffer->pending_send_sz = size;
  }
3724287c0   K. Y. Srinivasan   Drivers: hv: vmbu...
903
904
905
906
907
908
909
910
911
  static inline void set_low_latency_mode(struct vmbus_channel *c)
  {
  	c->low_latency = true;
  }
  
  static inline void clear_low_latency_mode(struct vmbus_channel *c)
  {
  	c->low_latency = false;
  }
b56dda06b   K. Y. Srinivasan   Staging: hv: Move...
912
913
914
  void vmbus_onmessage(void *context);
  
  int vmbus_request_offers(void);
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
915
916
917
918
919
920
  /*
   * APIs for managing sub-channels.
   */
  
  void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
  			void (*sc_cr_cb)(struct vmbus_channel *new_sc));
499e8401a   Dexuan Cui   Drivers: hv: vmbu...
921
922
  void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
  		void (*chn_rescind_cb)(struct vmbus_channel *));
e68d2971d   K. Y. Srinivasan   Drivers: hv: vmbu...
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  /*
   * Retrieve the (sub) channel on which to send an outgoing request.
   * When a primary channel has multiple sub-channels, we choose a
   * channel whose VCPU binding is closest to the VCPU on which
   * this call is being made.
   */
  struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary);
  
  /*
   * Check if sub-channels have already been offerred. This API will be useful
   * when the driver is unloaded after establishing sub-channels. In this case,
   * when the driver is re-loaded, the driver would have to check if the
   * subchannels have already been established before attempting to request
   * the creation of sub-channels.
   * This function returns TRUE to indicate that subchannels have already been
   * created.
   * This function should be invoked after setting the callback function for
   * sub-channel creation.
   */
  bool vmbus_are_subchannels_present(struct vmbus_channel *primary);
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
  /* The format must be the same as struct vmdata_gpa_direct */
  struct vmbus_channel_packet_page_buffer {
  	u16 type;
  	u16 dataoffset8;
  	u16 length8;
  	u16 flags;
  	u64 transactionid;
  	u32 reserved;
  	u32 rangecount;
  	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
  } __packed;
  
  /* The format must be the same as struct vmdata_gpa_direct */
  struct vmbus_channel_packet_multipage_buffer {
  	u16 type;
  	u16 dataoffset8;
  	u16 length8;
  	u16 flags;
  	u64 transactionid;
  	u32 reserved;
  	u32 rangecount;		/* Always 1 in this case */
  	struct hv_multipage_buffer range;
  } __packed;
d61031ee8   K. Y. Srinivasan   Drivers: hv: vmbu...
966
967
968
969
970
971
972
973
974
975
976
  /* The format must be the same as struct vmdata_gpa_direct */
  struct vmbus_packet_mpb_array {
  	u16 type;
  	u16 dataoffset8;
  	u16 length8;
  	u16 flags;
  	u64 transactionid;
  	u32 reserved;
  	u32 rangecount;         /* Always 1 in this case */
  	struct hv_mpb_array range;
  } __packed;
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
977
978
979
980
981
982
983
984
985
986
987
988
  
  extern int vmbus_open(struct vmbus_channel *channel,
  			    u32 send_ringbuffersize,
  			    u32 recv_ringbuffersize,
  			    void *userdata,
  			    u32 userdatalen,
  			    void(*onchannel_callback)(void *context),
  			    void *context);
  
  extern void vmbus_close(struct vmbus_channel *channel);
  
  extern int vmbus_sendpacket(struct vmbus_channel *channel,
011a7c3cc   K. Y. Srinivasan   Drivers: hv: vmbu...
989
  				  void *buffer,
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
990
991
992
993
  				  u32 bufferLen,
  				  u64 requestid,
  				  enum vmbus_packet_type type,
  				  u32 flags);
e9395e3f8   K. Y. Srinivasan   Drivers: hv: vmbu...
994
995
996
997
998
999
1000
  extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel,
  				  void *buffer,
  				  u32 bufferLen,
  				  u64 requestid,
  				  enum vmbus_packet_type type,
  				  u32 flags,
  				  bool kick_q);
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
1001
1002
1003
1004
1005
1006
  extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
  					    struct hv_page_buffer pagebuffers[],
  					    u32 pagecount,
  					    void *buffer,
  					    u32 bufferlen,
  					    u64 requestid);
87e93d617   K. Y. Srinivasan   Drivers: hv: vmbu...
1007
1008
1009
1010
1011
1012
1013
1014
  extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
  					   struct hv_page_buffer pagebuffers[],
  					   u32 pagecount,
  					   void *buffer,
  					   u32 bufferlen,
  					   u64 requestid,
  					   u32 flags,
  					   bool kick_q);
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
1015
1016
1017
1018
1019
  extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
  					struct hv_multipage_buffer *mpb,
  					void *buffer,
  					u32 bufferlen,
  					u64 requestid);
d61031ee8   K. Y. Srinivasan   Drivers: hv: vmbu...
1020
1021
1022
1023
1024
1025
  extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
  				     struct vmbus_packet_mpb_array *mpb,
  				     u32 desc_size,
  				     void *buffer,
  				     u32 bufferlen,
  				     u64 requestid);
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
  				      void *kbuffer,
  				      u32 size,
  				      u32 *gpadl_handle);
  
  extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
  				     u32 gpadl_handle);
  
  extern int vmbus_recvpacket(struct vmbus_channel *channel,
  				  void *buffer,
  				  u32 bufferlen,
  				  u32 *buffer_actual_len,
  				  u64 *requestid);
  
  extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
  				     void *buffer,
  				     u32 bufferlen,
  				     u32 *buffer_actual_len,
  				     u64 *requestid);
c35470b22   K. Y. Srinivasan   Staging: hv: Move...
1045

c35470b22   K. Y. Srinivasan   Staging: hv: Move...
1046
  extern void vmbus_ontimer(unsigned long data);
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1047
1048
1049
  /* Base driver object */
  struct hv_driver {
  	const char *name;
8981da320   Dexuan Cui   Drivers: hv: vmbu...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
  	/*
  	 * A hvsock offer, which has a VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER
  	 * channel flag, actually doesn't mean a synthetic device because the
  	 * offer's if_type/if_instance can change for every new hvsock
  	 * connection.
  	 *
  	 * However, to facilitate the notification of new-offer/rescind-offer
  	 * from vmbus driver to hvsock driver, we can handle hvsock offer as
  	 * a special vmbus device, and hence we need the below flag to
  	 * indicate if the driver is the hvsock driver or not: we need to
  	 * specially treat the hvosck offer & driver in vmbus_match().
  	 */
  	bool hvsock;
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1063
  	/* the device type supported by this driver */
358d2ee2e   K. Y. Srinivasan   Staging: hv: Repl...
1064
  	uuid_le dev_type;
2e2c1d17a   K. Y. Srinivasan   Staging: hv: vmbu...
1065
  	const struct hv_vmbus_device_id *id_table;
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1066
1067
  
  	struct device_driver driver;
84946899b   K. Y. Srinivasan   Staging: hv: vmbu...
1068
  	int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *);
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1069
1070
1071
1072
1073
1074
1075
1076
  	int (*remove)(struct hv_device *);
  	void (*shutdown)(struct hv_device *);
  
  };
  
  /* Base device object */
  struct hv_device {
  	/* the device type id of this device */
358d2ee2e   K. Y. Srinivasan   Staging: hv: Repl...
1077
  	uuid_le dev_type;
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1078
1079
  
  	/* the device instance id of this device */
358d2ee2e   K. Y. Srinivasan   Staging: hv: Repl...
1080
  	uuid_le dev_instance;
7047f17d7   K. Y. Srinivasan   Drivers: hv: vmbu...
1081
1082
  	u16 vendor_id;
  	u16 device_id;
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1083
1084
1085
1086
  
  	struct device device;
  
  	struct vmbus_channel *channel;
35ea09c39   K. Y. Srinivasan   Staging: hv: Move...
1087
  };
27b5b3ca6   K. Y. Srinivasan   Staging: hv: Move...
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
  
  static inline struct hv_device *device_to_hv_device(struct device *d)
  {
  	return container_of(d, struct hv_device, device);
  }
  
  static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
  {
  	return container_of(d, struct hv_driver, driver);
  }
ab101e86d   K. Y. Srinivasan   Staging: hv: vmbu...
1098
1099
1100
1101
1102
1103
1104
1105
1106
  static inline void hv_set_drvdata(struct hv_device *dev, void *data)
  {
  	dev_set_drvdata(&dev->device, data);
  }
  
  static inline void *hv_get_drvdata(struct hv_device *dev)
  {
  	return dev_get_drvdata(&dev->device);
  }
27b5b3ca6   K. Y. Srinivasan   Staging: hv: Move...
1107
1108
  
  /* Vmbus interface */
768fa2191   Greg Kroah-Hartman   Staging: hv: fix ...
1109
1110
1111
1112
1113
1114
  #define vmbus_driver_register(driver)	\
  	__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
  int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
  					 struct module *owner,
  					 const char *mod_name);
  void vmbus_driver_unregister(struct hv_driver *hv_driver);
27b5b3ca6   K. Y. Srinivasan   Staging: hv: Move...
1115

85d9aa705   Dexuan Cui   Drivers: hv: vmbu...
1116
  void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
354644833   Jake Oshins   drivers:hv: Move ...
1117
1118
1119
1120
  int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
  			resource_size_t min, resource_size_t max,
  			resource_size_t size, resource_size_t align,
  			bool fb_overlap_ok);
97fb77dc8   Jake Oshins   drivers:hv: Make ...
1121
  void vmbus_free_mmio(resource_size_t start, resource_size_t size);
619848bd0   Jake Oshins   drivers:hv: Expor...
1122
  int vmbus_cpu_number_to_vp_number(int cpu_number);
a108393db   Jake Oshins   drivers:hv: Expor...
1123
  u64 hv_do_hypercall(u64 control, void *input, void *output);
619848bd0   Jake Oshins   drivers:hv: Expor...
1124

b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1125
  /*
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1126
1127
1128
1129
1130
1131
1132
1133
   * GUID definitions of various offer types - services offered to the guest.
   */
  
  /*
   * Network GUID
   * {f8615163-df3e-46c5-913f-f2d2f965ed0e}
   */
  #define HV_NIC_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1134
1135
  	.guid = UUID_LE(0xf8615163, 0xdf3e, 0x46c5, 0x91, 0x3f, \
  			0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1136
1137
1138
1139
1140
1141
  
  /*
   * IDE GUID
   * {32412632-86cb-44a2-9b5c-50d1417354f5}
   */
  #define HV_IDE_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1142
1143
  	.guid = UUID_LE(0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, \
  			0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1144
1145
1146
1147
1148
1149
  
  /*
   * SCSI GUID
   * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
   */
  #define HV_SCSI_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1150
1151
  	.guid = UUID_LE(0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, \
  			0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1152
1153
1154
1155
1156
1157
  
  /*
   * Shutdown GUID
   * {0e0b6031-5213-4934-818b-38d90ced39db}
   */
  #define HV_SHUTDOWN_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1158
1159
  	.guid = UUID_LE(0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8b, \
  			0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1160
1161
1162
1163
1164
1165
  
  /*
   * Time Synch GUID
   * {9527E630-D0AE-497b-ADCE-E80AB0175CAF}
   */
  #define HV_TS_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1166
1167
  	.guid = UUID_LE(0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, \
  			0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1168
1169
1170
1171
1172
1173
  
  /*
   * Heartbeat GUID
   * {57164f39-9115-4e78-ab55-382f3bd5422d}
   */
  #define HV_HEART_BEAT_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1174
1175
  	.guid = UUID_LE(0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, \
  			0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1176
1177
1178
1179
1180
1181
  
  /*
   * KVP GUID
   * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}
   */
  #define HV_KVP_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1182
1183
  	.guid = UUID_LE(0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, \
  			0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1184
1185
1186
1187
1188
1189
  
  /*
   * Dynamic memory GUID
   * {525074dc-8985-46e2-8057-a307dc18a502}
   */
  #define HV_DM_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1190
1191
  	.guid = UUID_LE(0x525074dc, 0x8985, 0x46e2, 0x80, 0x57, \
  			0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1192
1193
1194
1195
1196
1197
  
  /*
   * Mouse GUID
   * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}
   */
  #define HV_MOUSE_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1198
1199
  	.guid = UUID_LE(0xcfa8b69e, 0x5b4a, 0x4cc0, 0xb9, 0x8b, \
  			0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a)
7fb96565e   K. Y. Srinivasan   Drivers: hv: vmbu...
1200
1201
  
  /*
2048157ad   Dexuan Cui   Drivers: hv: vmbu...
1202
1203
1204
1205
1206
1207
1208
1209
   * Keyboard GUID
   * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
   */
  #define HV_KBD_GUID \
  	.guid = UUID_LE(0xf912ad6d, 0x2b17, 0x48ea, 0xbd, 0x65, \
  			0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84)
  
  /*
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
1210
1211
1212
   * VSS (Backup/Restore) GUID
   */
  #define HV_VSS_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1213
1214
  	.guid = UUID_LE(0x35fa2e29, 0xea23, 0x4236, 0x96, 0xae, \
  			0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40)
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
1215
  /*
68a2d20b7   Haiyang Zhang   drivers/video: ad...
1216
1217
1218
1219
   * Synthetic Video GUID
   * {DA0A7802-E377-4aac-8E77-0558EB1073F8}
   */
  #define HV_SYNTHVID_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1220
1221
  	.guid = UUID_LE(0xda0a7802, 0xe377, 0x4aac, 0x8e, 0x77, \
  			0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8)
68a2d20b7   Haiyang Zhang   drivers/video: ad...
1222

68a2d20b7   Haiyang Zhang   drivers/video: ad...
1223
  /*
98b80d893   K. Y. Srinivasan   Drivers: hv: Add ...
1224
1225
1226
1227
   * Synthetic FC GUID
   * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda}
   */
  #define HV_SYNTHFC_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1228
1229
  	.guid = UUID_LE(0x2f9bcc4a, 0x0069, 0x4af3, 0xb7, 0x6b, \
  			0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda)
98b80d893   K. Y. Srinivasan   Drivers: hv: Add ...
1230
1231
  
  /*
01325476d   K. Y. Srinivasan   Drivers: hv: Impl...
1232
1233
1234
1235
1236
   * Guest File Copy Service
   * {34D14BE3-DEE4-41c8-9AE7-6B174977C192}
   */
  
  #define HV_FCOPY_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1237
1238
  	.guid = UUID_LE(0x34d14be3, 0xdee4, 0x41c8, 0x9a, 0xe7, \
  			0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92)
01325476d   K. Y. Srinivasan   Drivers: hv: Impl...
1239
1240
  
  /*
04653a009   K. Y. Srinivasan   Drivers: hv: vmbu...
1241
1242
1243
1244
   * NetworkDirect. This is the guest RDMA service.
   * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}
   */
  #define HV_ND_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1245
1246
  	.guid = UUID_LE(0x8c2eaf3d, 0x32a7, 0x4b09, 0xab, 0x99, \
  			0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01)
04653a009   K. Y. Srinivasan   Drivers: hv: vmbu...
1247
1248
  
  /*
3053c7624   Jake Oshins   drivers:hv: Defin...
1249
1250
1251
1252
1253
   * PCI Express Pass Through
   * {44C4F61D-4444-4400-9D52-802E27EDE19F}
   */
  
  #define HV_PCIE_GUID \
af3ff643e   K. Y. Srinivasan   Drivers: hv: vmbu...
1254
1255
  	.guid = UUID_LE(0x44c4f61d, 0x4444, 0x4400, 0x9d, 0x52, \
  			0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f)
3053c7624   Jake Oshins   drivers:hv: Defin...
1256
1257
  
  /*
0f98829a9   Dexuan Cui   Drivers: hv: vmbu...
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
   * Linux doesn't support the 3 devices: the first two are for
   * Automatic Virtual Machine Activation, and the third is for
   * Remote Desktop Virtualization.
   * {f8e65716-3cb3-4a06-9a60-1889c5cccab5}
   * {3375baf4-9e15-4b30-b765-67acb10d607b}
   * {276aacf4-ac15-426c-98dd-7521ad3f01fe}
   */
  
  #define HV_AVMA1_GUID \
  	.guid = UUID_LE(0xf8e65716, 0x3cb3, 0x4a06, 0x9a, 0x60, \
  			0x18, 0x89, 0xc5, 0xcc, 0xca, 0xb5)
  
  #define HV_AVMA2_GUID \
  	.guid = UUID_LE(0x3375baf4, 0x9e15, 0x4b30, 0xb7, 0x65, \
  			0x67, 0xac, 0xb1, 0x0d, 0x60, 0x7b)
  
  #define HV_RDV_GUID \
  	.guid = UUID_LE(0x276aacf4, 0xac15, 0x426c, 0x98, 0xdd, \
  			0x75, 0x21, 0xad, 0x3f, 0x01, 0xfe)
  
  /*
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
   * Common header for Hyper-V ICs
   */
  
  #define ICMSGTYPE_NEGOTIATE		0
  #define ICMSGTYPE_HEARTBEAT		1
  #define ICMSGTYPE_KVPEXCHANGE		2
  #define ICMSGTYPE_SHUTDOWN		3
  #define ICMSGTYPE_TIMESYNC		4
  #define ICMSGTYPE_VSS			5
  
  #define ICMSGHDRFLAG_TRANSACTION	1
  #define ICMSGHDRFLAG_REQUEST		2
  #define ICMSGHDRFLAG_RESPONSE		4
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1292

a29b643c5   K. Y. Srinivasan   Staging: hv: util...
1293
1294
1295
1296
1297
1298
1299
1300
  /*
   * While we want to handle util services as regular devices,
   * there is only one instance of each of these services; so
   * we statically allocate the service specific state.
   */
  
  struct hv_util_service {
  	u8 *recv_buffer;
b9830d120   K. Y. Srinivasan   Drivers: hv: util...
1301
  	void *channel;
a29b643c5   K. Y. Srinivasan   Staging: hv: util...
1302
1303
1304
1305
  	void (*util_cb)(void *);
  	int (*util_init)(struct hv_util_service *);
  	void (*util_deinit)(void);
  };
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  struct vmbuspipe_hdr {
  	u32 flags;
  	u32 msgsize;
  } __packed;
  
  struct ic_version {
  	u16 major;
  	u16 minor;
  } __packed;
  
  struct icmsg_hdr {
  	struct ic_version icverframe;
  	u16 icmsgtype;
  	struct ic_version icvermsg;
  	u16 icmsgsize;
  	u32 status;
  	u8 ictransaction_id;
  	u8 icflags;
  	u8 reserved[2];
  } __packed;
  
  struct icmsg_negotiate {
  	u16 icframe_vercnt;
  	u16 icmsg_vercnt;
  	u32 reserved;
  	struct ic_version icversion_data[1]; /* any size array */
  } __packed;
  
  struct shutdown_msg_data {
  	u32 reason_code;
  	u32 timeout_seconds;
  	u32 flags;
  	u8  display_message[2048];
  } __packed;
  
  struct heartbeat_msg_data {
  	u64 seq_num;
  	u32 reserved[8];
  } __packed;
  
  /* Time Sync IC defs */
  #define ICTIMESYNCFLAG_PROBE	0
  #define ICTIMESYNCFLAG_SYNC	1
  #define ICTIMESYNCFLAG_SAMPLE	2
  
  #ifdef __x86_64__
  #define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
  #else
  #define WLTIMEDELTA	116444736000000000LL
  #endif
  
  struct ictimesync_data {
  	u64 parenttime;
  	u64 childtime;
  	u64 roundtriptime;
  	u8 flags;
  } __packed;
8e1d26073   Alex Ng   Drivers: hv: util...
1363
1364
1365
1366
1367
1368
1369
1370
  struct ictimesync_ref_data {
  	u64 parenttime;
  	u64 vmreferencetime;
  	u8 flags;
  	char leapflags;
  	char stratum;
  	u8 reserved[3];
  } __packed;
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1371
1372
1373
  struct hyperv_service_callback {
  	u8 msg_type;
  	char *log_msg;
358d2ee2e   K. Y. Srinivasan   Staging: hv: Repl...
1374
  	uuid_le data;
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1375
1376
1377
  	struct vmbus_channel *channel;
  	void (*callback) (void *context);
  };
c836d0ab7   K. Y. Srinivasan   Drivers: hv: util...
1378
  #define MAX_SRV_VER	0x7ffffff
6741335bc   K. Y. Srinivasan   Drivers: hv: util...
1379
  extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
c836d0ab7   K. Y. Srinivasan   Drivers: hv: util...
1380
1381
  					struct icmsg_negotiate *, u8 *, int,
  					int);
b189702dd   K. Y. Srinivasan   Staging: hv: Move...
1382

638fea33a   Dexuan Cui   Drivers: hv: vmbu...
1383
1384
  void hv_event_tasklet_disable(struct vmbus_channel *channel);
  void hv_event_tasklet_enable(struct vmbus_channel *channel);
ed6cfcc5f   K. Y. Srinivasan   Drivers: hv: vmbu...
1385
  void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
96dd86fa5   K. Y. Srinivasan   Drivers: hv: Add ...
1386

37f7278b8   K. Y. Srinivasan   Drivers: hv: Save...
1387
1388
1389
1390
1391
  /*
   * Negotiated version with the Host.
   */
  
  extern __u32 vmbus_proto_version;
5c23a1a5c   Dexuan Cui   Drivers: hv: vmbu...
1392
1393
  int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
  				  const uuid_le *shv_host_servie_id);
5cc472477   K. Y. Srinivasan   Drivers: hv: vmbu...
1394
  void vmbus_set_event(struct vmbus_channel *channel);
687f32e6d   K. Y. Srinivasan   Drivers: hv: vmbu...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
  
  /* Get the start of the ring buffer. */
  static inline void *
  hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
  {
  	return (void *)ring_info->ring_buffer->buffer;
  }
  
  /*
   * To optimize the flow management on the send-side,
   * when the sender is blocked because of lack of
   * sufficient space in the ring buffer, potential the
   * consumer of the ring buffer can signal the producer.
   * This is controlled by the following parameters:
   *
   * 1. pending_send_sz: This is the size in bytes that the
   *    producer is trying to send.
   * 2. The feature bit feat_pending_send_sz set to indicate if
   *    the consumer of the ring will signal when the ring
   *    state transitions from being full to a state where
   *    there is room for the producer to send the pending packet.
   */
  
  static inline  bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
  {
  	u32 cur_write_sz;
  	u32 pending_sz;
  
  	/*
  	 * Issue a full memory barrier before making the signaling decision.
  	 * Here is the reason for having this barrier:
  	 * If the reading of the pend_sz (in this function)
  	 * were to be reordered and read before we commit the new read
  	 * index (in the calling function)  we could
  	 * have a problem. If the host were to set the pending_sz after we
  	 * have sampled pending_sz and go to sleep before we commit the
  	 * read index, we could miss sending the interrupt. Issue a full
  	 * memory barrier to address this.
  	 */
  	virt_mb();
  
  	pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
  	/* If the other end is not blocked on write don't bother. */
  	if (pending_sz == 0)
  		return false;
  
  	cur_write_sz = hv_get_bytes_to_write(rbi);
  
  	if (cur_write_sz >= pending_sz)
  		return true;
  
  	return false;
  }
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1448
1449
1450
1451
1452
1453
1454
1455
1456
  /*
   * An API to support in-place processing of incoming VMBUS packets.
   */
  #define VMBUS_PKT_TRAILER	8
  
  static inline struct vmpacket_descriptor *
  get_next_pkt_raw(struct vmbus_channel *channel)
  {
  	struct hv_ring_buffer_info *ring_info = &channel->inbound;
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1457
  	u32 read_loc = ring_info->priv_read_index;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1458
  	void *ring_buffer = hv_get_ring_buffer(ring_info);
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1459
1460
  	struct vmpacket_descriptor *cur_desc;
  	u32 packetlen;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1461
  	u32 dsize = ring_info->ring_datasize;
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1462
  	u32 delta = read_loc - ring_info->ring_buffer->read_index;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1463
1464
1465
1466
  	u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
  
  	if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
  		return NULL;
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
  	if ((read_loc + sizeof(*cur_desc)) > dsize)
  		return NULL;
  
  	cur_desc = ring_buffer + read_loc;
  	packetlen = cur_desc->len8 << 3;
  
  	/*
  	 * If the packet under consideration is wrapping around,
  	 * return failure.
  	 */
  	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1))
  		return NULL;
  
  	return cur_desc;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
  }
  
  /*
   * A helper function to step through packets "in-place"
   * This API is to be called after each successful call
   * get_next_pkt_raw().
   */
  static inline void put_pkt_raw(struct vmbus_channel *channel,
  				struct vmpacket_descriptor *desc)
  {
  	struct hv_ring_buffer_info *ring_info = &channel->inbound;
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1492
  	u32 read_loc = ring_info->priv_read_index;
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1493
1494
  	u32 packetlen = desc->len8 << 3;
  	u32 dsize = ring_info->ring_datasize;
65a532f3d   K. Y. Srinivasan   Revert "Drivers: ...
1495
1496
  	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize)
  		BUG();
ab028db41   K. Y. Srinivasan   Drivers: hv: vmbu...
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
  	/*
  	 * Include the packet trailer.
  	 */
  	ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
  }
  
  /*
   * This call commits the read index and potentially signals the host.
   * Here is the pattern for using the "in-place" consumption APIs:
   *
   * while (get_next_pkt_raw() {
   *	process the packet "in-place";
   *	put_pkt_raw();
   * }
   * if (packets processed in place)
   *	commit_rd_index();
   */
  static inline void commit_rd_index(struct vmbus_channel *channel)
  {
  	struct hv_ring_buffer_info *ring_info = &channel->inbound;
  	/*
  	 * Make sure all reads are done before we update the read index since
  	 * the writer may start writing to the read area once the read index
  	 * is updated.
  	 */
  	virt_rmb();
  	ring_info->ring_buffer->read_index = ring_info->priv_read_index;
  
  	if (hv_need_to_signal_on_read(ring_info))
  		vmbus_set_event(channel);
  }
3f335ea21   K. Y. Srinivasan   Staging: hv: Incl...
1528
  #endif /* _HYPERV_H */