iPXE
netvsc.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * Hyper-V network virtual service client
29 *
30 * The network virtual service client (NetVSC) connects to the network
31 * virtual service provider (NetVSP) via the Hyper-V virtual machine
32 * bus (VMBus). It provides a transport layer for RNDIS packets.
33 */
34
35#include <string.h>
36#include <errno.h>
37#include <unistd.h>
38#include <byteswap.h>
39#include <ipxe/umalloc.h>
40#include <ipxe/rndis.h>
41#include <ipxe/vmbus.h>
42#include "netvsc.h"
43
44/**
45 * Send control message and wait for completion
46 *
47 * @v netvsc NetVSC device
48 * @v xrid Relative transaction ID
49 * @v data Data
50 * @v len Length of data
51 * @ret rc Return status code
52 */
53static int netvsc_control ( struct netvsc_device *netvsc, unsigned int xrid,
54 const void *data, size_t len ) {
55 uint64_t xid = ( NETVSC_BASE_XID + xrid );
56 unsigned int i;
57 int rc;
58
59 /* Send control message */
60 if ( ( rc = vmbus_send_control ( netvsc->vmdev, xid, data, len ) ) !=0){
61 DBGC ( netvsc, "NETVSC %s could not send control message: %s\n",
62 netvsc->name, strerror ( rc ) );
63 return rc;
64 }
65
66 /* Record transaction ID */
67 netvsc->wait_xrid = xrid;
68
69 /* Wait for operation to complete */
70 for ( i = 0 ; i < NETVSC_MAX_WAIT_MS ; i++ ) {
71
72 /* Check for completion */
73 if ( ! netvsc->wait_xrid )
74 return netvsc->wait_rc;
75
76 /* Poll VMBus device */
77 vmbus_poll ( netvsc->vmdev );
78
79 /* Delay for 1ms */
80 mdelay ( 1 );
81 }
82
83 DBGC ( netvsc, "NETVSC %s timed out waiting for XRID %d\n",
84 netvsc->name, xrid );
85 vmbus_dump_channel ( netvsc->vmdev );
86 return -ETIMEDOUT;
87}
88
89/**
90 * Handle generic completion
91 *
92 * @v netvsc NetVSC device
93 * @v data Data
94 * @v len Length of data
95 * @ret rc Return status code
96 */
97static int netvsc_completed ( struct netvsc_device *netvsc __unused,
98 const void *data __unused, size_t len __unused ) {
99 return 0;
100}
101
102/**
103 * Initialise communication
104 *
105 * @v netvsc NetVSC device
106 * @ret rc Return status code
107 */
108static int netvsc_initialise ( struct netvsc_device *netvsc ) {
110 int rc;
111
112 /* Construct message */
113 memset ( &msg, 0, sizeof ( msg ) );
114 msg.header.type = cpu_to_le32 ( NETVSC_INIT_MSG );
117
118 /* Send message and wait for completion */
119 if ( ( rc = netvsc_control ( netvsc, NETVSC_INIT_XRID, &msg,
120 sizeof ( msg ) ) ) != 0 ) {
121 DBGC ( netvsc, "NETVSC %s could not initialise: %s\n",
122 netvsc->name, strerror ( rc ) );
123 return rc;
124 }
125
126 return 0;
127}
128
129/**
130 * Handle initialisation completion
131 *
132 * @v netvsc NetVSC device
133 * @v data Data
134 * @v len Length of data
135 * @ret rc Return status code
136 */
137static int
138netvsc_initialised ( struct netvsc_device *netvsc, const void *data,
139 size_t len ) {
140 const struct netvsc_init_completion *cmplt;
141
142 /* Check completion */
143 if ( len < sizeof ( *cmplt ) ) {
144 DBGC ( netvsc, "NETVSC %s underlength initialisation "
145 "completion (%zd bytes)\n", netvsc->name, len );
146 return -EINVAL;
147 }
148 cmplt = data;
149 if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
150 DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
151 "type %d\n", netvsc->name,
152 le32_to_cpu ( cmplt->header.type ) );
153 return -EPROTO;
154 }
155 if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
156 DBGC ( netvsc, "NETVSC %s initialisation failure status %d\n",
157 netvsc->name, le32_to_cpu ( cmplt->status ) );
158 return -EPROTO;
159 }
160
161 return 0;
162}
163
164/**
165 * Set NDIS version
166 *
167 * @v netvsc NetVSC device
168 * @ret rc Return status code
169 */
170static int netvsc_ndis_version ( struct netvsc_device *netvsc ) {
172 int rc;
173
174 /* Construct message */
175 memset ( &msg, 0, sizeof ( msg ) );
176 msg.header.type = cpu_to_le32 ( NETVSC_NDIS_VERSION_MSG );
179
180 /* Send message and wait for completion */
181 if ( ( rc = netvsc_control ( netvsc, NETVSC_NDIS_VERSION_XRID,
182 &msg, sizeof ( msg ) ) ) != 0 ) {
183 DBGC ( netvsc, "NETVSC %s could not set NDIS version: %s\n",
184 netvsc->name, strerror ( rc ) );
185 return rc;
186 }
187
188 return 0;
189}
190
191/**
192 * Establish data buffer
193 *
194 * @v netvsc NetVSC device
195 * @v buffer Data buffer
196 * @ret rc Return status code
197 */
198static int netvsc_establish_buffer ( struct netvsc_device *netvsc,
199 struct netvsc_buffer *buffer ) {
201 int rc;
202
203 /* Construct message */
204 memset ( &msg, 0, sizeof ( msg ) );
205 msg.header.type = cpu_to_le32 ( buffer->establish_type );
206 msg.gpadl = cpu_to_le32 ( buffer->gpadl );
207 msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
208
209 /* Send message and wait for completion */
210 if ( ( rc = netvsc_control ( netvsc, buffer->establish_xrid, &msg,
211 sizeof ( msg ) ) ) != 0 ) {
212 DBGC ( netvsc, "NETVSC %s could not establish buffer: %s\n",
213 netvsc->name, strerror ( rc ) );
214 return rc;
215 }
216
217 return 0;
218}
219
220/**
221 * Handle establish receive data buffer completion
222 *
223 * @v netvsc NetVSC device
224 * @v data Data
225 * @v len Length of data
226 * @ret rc Return status code
227 */
228static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
229 const void *data, size_t len ) {
230 const struct netvsc_rx_establish_buffer_completion *cmplt;
231
232 /* Check completion */
233 if ( len < sizeof ( *cmplt ) ) {
234 DBGC ( netvsc, "NETVSC %s underlength buffer completion (%zd "
235 "bytes)\n", netvsc->name, len );
236 return -EINVAL;
237 }
238 cmplt = data;
239 if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
240 DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
241 "%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
242 return -EPROTO;
243 }
244 if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
245 DBGC ( netvsc, "NETVSC %s buffer failure status %d\n",
246 netvsc->name, le32_to_cpu ( cmplt->status ) );
247 return -EPROTO;
248 }
249
250 return 0;
251}
252
253/**
254 * Revoke data buffer
255 *
256 * @v netvsc NetVSC device
257 * @v buffer Data buffer
258 * @ret rc Return status code
259 */
260static int netvsc_revoke_buffer ( struct netvsc_device *netvsc,
261 struct netvsc_buffer *buffer ) {
263 int rc;
264
265 /* If the buffer's GPADL is obsolete (i.e. was created before
266 * the most recent Hyper-V reset), then we will never receive
267 * a response to the revoke message. Since the GPADL is
268 * already destroyed as far as the hypervisor is concerned, no
269 * further action is required.
270 */
271 if ( netvsc_is_obsolete ( netvsc ) )
272 return 0;
273
274 /* Construct message */
275 memset ( &msg, 0, sizeof ( msg ) );
276 msg.header.type = cpu_to_le32 ( buffer->revoke_type );
277 msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
278
279 /* Send message and wait for completion */
280 if ( ( rc = netvsc_control ( netvsc, buffer->revoke_xrid,
281 &msg, sizeof ( msg ) ) ) != 0 ) {
282 DBGC ( netvsc, "NETVSC %s could not revoke buffer: %s\n",
283 netvsc->name, strerror ( rc ) );
284 return rc;
285 }
286
287 return 0;
288}
289
290/**
291 * Handle received control packet
292 *
293 * @v vmdev VMBus device
294 * @v xid Transaction ID
295 * @v data Data
296 * @v len Length of data
297 * @ret rc Return status code
298 */
299static int netvsc_recv_control ( struct vmbus_device *vmdev, uint64_t xid,
300 const void *data, size_t len ) {
301 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
302 struct netvsc_device *netvsc = rndis->priv;
303
304 DBGC ( netvsc, "NETVSC %s received unsupported control packet "
305 "(%08llx):\n", netvsc->name, xid );
306 DBGC_HDA ( netvsc, 0, data, len );
307 return -ENOTSUP;
308}
309
310/**
311 * Handle received data packet
312 *
313 * @v vmdev VMBus device
314 * @v xid Transaction ID
315 * @v data Data
316 * @v len Length of data
317 * @v list List of I/O buffers
318 * @ret rc Return status code
319 */
320static int netvsc_recv_data ( struct vmbus_device *vmdev, uint64_t xid,
321 const void *data, size_t len,
322 struct list_head *list ) {
323 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
324 struct netvsc_device *netvsc = rndis->priv;
325 const struct netvsc_rndis_message *msg;
326 struct io_buffer *iobuf;
327 struct io_buffer *tmp;
328 int rc;
329
330 /* Sanity check */
331 if ( len < sizeof ( *msg ) ) {
332 DBGC ( netvsc, "NETVSC %s received underlength RNDIS packet "
333 "(%zd bytes)\n", netvsc->name, len );
334 rc = -EINVAL;
335 goto err_sanity;
336 }
337 msg = data;
338 if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
339 DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
340 "type %d\n", netvsc->name,
341 le32_to_cpu ( msg->header.type ) );
342 rc = -EINVAL;
343 goto err_sanity;
344 }
345
346 /* Send completion back to host */
347 if ( ( rc = vmbus_send_completion ( vmdev, xid, NULL, 0 ) ) != 0 ) {
348 DBGC ( netvsc, "NETVSC %s could not send completion: %s\n",
349 netvsc->name, strerror ( rc ) );
350 goto err_completion;
351 }
352
353 /* Hand off to RNDIS */
355 list_del ( &iobuf->list );
356 rndis_rx ( rndis, iob_disown ( iobuf ) );
357 }
358
359 return 0;
360
361 err_completion:
362 err_sanity:
364 list_del ( &iobuf->list );
365 free_iob ( iobuf );
366 }
367 return rc;
368}
369
370/**
371 * Handle received completion packet
372 *
373 * @v vmdev VMBus device
374 * @v xid Transaction ID
375 * @v data Data
376 * @v len Length of data
377 * @ret rc Return status code
378 */
379static int netvsc_recv_completion ( struct vmbus_device *vmdev, uint64_t xid,
380 const void *data, size_t len ) {
381 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
382 struct netvsc_device *netvsc = rndis->priv;
383 struct io_buffer *iobuf;
384 int ( * completion ) ( struct netvsc_device *netvsc,
385 const void *data, size_t len );
386 unsigned int xrid = ( xid - NETVSC_BASE_XID );
387 unsigned int tx_id;
388 int rc;
389
390 /* Handle transmit completion, if applicable */
391 tx_id = ( xrid - NETVSC_TX_BASE_XRID );
392 if ( ( tx_id < NETVSC_TX_NUM_DESC ) &&
393 ( ( iobuf = netvsc->tx.iobufs[tx_id] ) != NULL ) ) {
394
395 /* Free buffer ID */
396 netvsc->tx.iobufs[tx_id] = NULL;
397 netvsc->tx.ids[ ( netvsc->tx.id_cons++ ) &
398 ( netvsc->tx.count - 1 ) ] = tx_id;
399
400 /* Hand back to RNDIS */
401 rndis_tx_complete ( rndis, iobuf );
402 return 0;
403 }
404
405 /* Otherwise determine completion handler */
406 if ( xrid == NETVSC_INIT_XRID ) {
408 } else if ( xrid == NETVSC_RX_ESTABLISH_XRID ) {
410 } else if ( ( netvsc->wait_xrid != 0 ) &&
411 ( xrid == netvsc->wait_xrid ) ) {
413 } else {
414 DBGC ( netvsc, "NETVSC %s received unexpected completion "
415 "(%08llx)\n", netvsc->name, xid );
416 return -EPIPE;
417 }
418
419 /* Hand off to completion handler */
420 rc = completion ( netvsc, data, len );
421
422 /* Record completion handler result if applicable */
423 if ( xrid == netvsc->wait_xrid ) {
424 netvsc->wait_xrid = 0;
425 netvsc->wait_rc = rc;
426 }
427
428 return rc;
429}
430
431/**
432 * Handle received cancellation packet
433 *
434 * @v vmdev VMBus device
435 * @v xid Transaction ID
436 * @ret rc Return status code
437 */
439 uint64_t xid ) {
440 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
441 struct netvsc_device *netvsc = rndis->priv;
442
443 DBGC ( netvsc, "NETVSC %s received unsupported cancellation packet "
444 "(%08llx):\n", netvsc->name, xid );
445 return -ENOTSUP;
446}
447
448/** VMBus channel operations */
450 .recv_control = netvsc_recv_control,
451 .recv_data = netvsc_recv_data,
452 .recv_completion = netvsc_recv_completion,
453 .recv_cancellation = netvsc_recv_cancellation,
454};
455
456/**
457 * Poll for completed and received packets
458 *
459 * @v rndis RNDIS device
460 */
461static void netvsc_poll ( struct rndis_device *rndis ) {
462 struct netvsc_device *netvsc = rndis->priv;
463 struct vmbus_device *vmdev = netvsc->vmdev;
464
465 /* Poll VMBus device */
466 while ( vmbus_has_data ( vmdev ) )
467 vmbus_poll ( vmdev );
468}
469
470/**
471 * Transmit packet
472 *
473 * @v rndis RNDIS device
474 * @v iobuf I/O buffer
475 * @ret rc Return status code
476 *
477 * If this method returns success then the RNDIS device must
478 * eventually report completion via rndis_tx_complete().
479 */
480static int netvsc_transmit ( struct rndis_device *rndis,
481 struct io_buffer *iobuf ) {
482 struct netvsc_device *netvsc = rndis->priv;
483 struct rndis_header *header = iobuf->data;
485 unsigned int tx_id;
486 unsigned int xrid;
487 uint64_t xid;
488 int rc;
489
490 /* If the device is obsolete (i.e. was opened before the most
491 * recent Hyper-V reset), then we will never receive transmit
492 * completions. Fail transmissions immediately to minimise
493 * the delay in closing and reopening the device.
494 */
495 if ( netvsc_is_obsolete ( netvsc ) )
496 return -EPIPE;
497
498 /* Sanity check */
499 assert ( iob_len ( iobuf ) >= sizeof ( *header ) );
500 assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) );
501
502 /* Check that we have space in the transmit ring */
503 if ( netvsc_ring_is_full ( &netvsc->tx ) )
504 return rndis_tx_defer ( rndis, iobuf );
505
506 /* Allocate buffer ID and calculate transaction ID */
507 tx_id = netvsc->tx.ids[ netvsc->tx.id_prod & ( netvsc->tx.count - 1 ) ];
508 assert ( netvsc->tx.iobufs[tx_id] == NULL );
509 xrid = ( NETVSC_TX_BASE_XRID + tx_id );
510 xid = ( NETVSC_BASE_XID + xrid );
511
512 /* Construct message */
513 memset ( &msg, 0, sizeof ( msg ) );
514 msg.header.type = cpu_to_le32 ( NETVSC_RNDIS_MSG );
515 msg.channel = ( ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) ?
518
519 /* Send message */
520 if ( ( rc = vmbus_send_data ( netvsc->vmdev, xid, &msg, sizeof ( msg ),
521 iobuf ) ) != 0 ) {
522 DBGC ( netvsc, "NETVSC %s could not send RNDIS message: %s\n",
523 netvsc->name, strerror ( rc ) );
524 return rc;
525 }
526
527 /* Store I/O buffer and consume buffer ID */
528 netvsc->tx.iobufs[tx_id] = iobuf;
529 netvsc->tx.id_prod++;
530
531 return 0;
532}
533
534/**
535 * Cancel transmission
536 *
537 * @v netvsc NetVSC device
538 * @v iobuf I/O buffer
539 * @v tx_id Transmission ID
540 */
541static void netvsc_cancel_transmit ( struct netvsc_device *netvsc,
542 struct io_buffer *iobuf,
543 unsigned int tx_id ) {
544 unsigned int xrid;
545 uint64_t xid;
546
547 /* Send cancellation */
548 xrid = ( NETVSC_TX_BASE_XRID + tx_id );
549 xid = ( NETVSC_BASE_XID + xrid );
550 DBGC ( netvsc, "NETVSC %s cancelling transmission %#x\n",
551 netvsc->name, tx_id );
552 vmbus_send_cancellation ( netvsc->vmdev, xid );
553
554 /* Report back to RNDIS */
555 rndis_tx_complete_err ( netvsc->rndis, iobuf, -ECANCELED );
556}
557
558/**
559 * Create descriptor ring
560 *
561 * @v netvsc NetVSC device
562 * @v ring Descriptor ring
563 * @ret rc Return status code
564 */
565static int netvsc_create_ring ( struct netvsc_device *netvsc __unused,
566 struct netvsc_ring *ring ) {
567 unsigned int i;
568
569 /* Initialise buffer ID ring */
570 for ( i = 0 ; i < ring->count ; i++ ) {
571 ring->ids[i] = i;
572 assert ( ring->iobufs[i] == NULL );
573 }
574 ring->id_prod = 0;
575 ring->id_cons = 0;
576
577 return 0;
578}
579
580/**
581 * Destroy descriptor ring
582 *
583 * @v netvsc NetVSC device
584 * @v ring Descriptor ring
585 * @v discard Method used to discard outstanding buffer, or NULL
586 */
587static void netvsc_destroy_ring ( struct netvsc_device *netvsc,
588 struct netvsc_ring *ring,
589 void ( * discard ) ( struct netvsc_device *,
590 struct io_buffer *,
591 unsigned int ) ) {
592 struct io_buffer *iobuf;
593 unsigned int i;
594
595 /* Flush any outstanding buffers */
596 for ( i = 0 ; i < ring->count ; i++ ) {
597 iobuf = ring->iobufs[i];
598 if ( ! iobuf )
599 continue;
600 ring->iobufs[i] = NULL;
601 ring->ids[ ( ring->id_cons++ ) & ( ring->count - 1 ) ] = i;
602 if ( discard )
603 discard ( netvsc, iobuf, i );
604 }
605
606 /* Sanity check */
607 assert ( netvsc_ring_is_empty ( ring ) );
608}
609
610/**
611 * Copy data from data buffer
612 *
613 * @v pages Transfer page set
614 * @v data Data buffer
615 * @v offset Offset within page set
616 * @v len Length within page set
617 * @ret rc Return status code
618 */
619static int netvsc_buffer_copy ( struct vmbus_xfer_pages *pages, void *data,
620 size_t offset, size_t len ) {
621 struct netvsc_buffer *buffer =
623
624 /* Sanity check */
625 if ( ( offset > buffer->len ) || ( len > ( buffer->len - offset ) ) )
626 return -ERANGE;
627
628 /* Copy data from buffer */
629 memcpy ( data, ( buffer->data + offset ), len );
630
631 return 0;
632}
633
634/** Transfer page set operations */
638
639/**
640 * Create data buffer
641 *
642 * @v netvsc NetVSC device
643 * @v buffer Data buffer
644 * @ret rc Return status code
645 */
646static int netvsc_create_buffer ( struct netvsc_device *netvsc,
647 struct netvsc_buffer *buffer ) {
648 struct vmbus_device *vmdev = netvsc->vmdev;
649 int gpadl;
650 int rc;
651
652 /* Allocate receive buffer */
653 buffer->data = umalloc ( buffer->len );
654 if ( ! buffer->data ) {
655 DBGC ( netvsc, "NETVSC %s could not allocate %zd-byte buffer\n",
656 netvsc->name, buffer->len );
657 rc = -ENOMEM;
658 goto err_alloc;
659 }
660
661 /* Establish GPA descriptor list */
662 gpadl = vmbus_establish_gpadl ( vmdev, buffer->data, buffer->len );
663 if ( gpadl < 0 ) {
664 rc = gpadl;
665 DBGC ( netvsc, "NETVSC %s could not establish GPADL: %s\n",
666 netvsc->name, strerror ( rc ) );
667 goto err_establish_gpadl;
668 }
669 buffer->gpadl = gpadl;
670
671 /* Register transfer page set */
672 if ( ( rc = vmbus_register_pages ( vmdev, &buffer->pages ) ) != 0 ) {
673 DBGC ( netvsc, "NETVSC %s could not register transfer pages: "
674 "%s\n", netvsc->name, strerror ( rc ) );
675 goto err_register_pages;
676 }
677
678 return 0;
679
680 vmbus_unregister_pages ( vmdev, &buffer->pages );
681 err_register_pages:
682 vmbus_gpadl_teardown ( vmdev, gpadl );
683 err_establish_gpadl:
684 ufree ( buffer->data );
685 err_alloc:
686 return rc;
687}
688
689/**
690 * Destroy data buffer
691 *
692 * @v netvsc NetVSC device
693 * @v buffer Data buffer
694 */
695static void netvsc_destroy_buffer ( struct netvsc_device *netvsc,
696 struct netvsc_buffer *buffer ) {
697 struct vmbus_device *vmdev = netvsc->vmdev;
698 int rc;
699
700 /* Unregister transfer pages */
701 vmbus_unregister_pages ( vmdev, &buffer->pages );
702
703 /* Tear down GPA descriptor list */
704 if ( ( rc = vmbus_gpadl_teardown ( vmdev, buffer->gpadl ) ) != 0 ) {
705 DBGC ( netvsc, "NETVSC %s could not tear down GPADL: %s\n",
706 netvsc->name, strerror ( rc ) );
707 /* Death is imminent. The host may well continue to
708 * write to the data buffer. The best we can do is
709 * leak memory for now and hope that the host doesn't
710 * write to this region after we load an OS.
711 */
712 return;
713 }
714
715 /* Free buffer */
716 ufree ( buffer->data );
717}
718
719/**
720 * Open device
721 *
722 * @v rndis RNDIS device
723 * @ret rc Return status code
724 */
725static int netvsc_open ( struct rndis_device *rndis ) {
726 struct netvsc_device *netvsc = rndis->priv;
727 int rc;
728
729 /* Initialise receive buffer */
730 if ( ( rc = netvsc_create_buffer ( netvsc, &netvsc->rx ) ) != 0 )
731 goto err_create_rx;
732
733 /* Open channel */
734 if ( ( rc = vmbus_open ( netvsc->vmdev, &netvsc_channel_operations,
735 PAGE_SIZE, PAGE_SIZE, NETVSC_MTU ) ) != 0 ) {
736 DBGC ( netvsc, "NETVSC %s could not open VMBus: %s\n",
737 netvsc->name, strerror ( rc ) );
738 goto err_vmbus_open;
739 }
740
741 /* Initialise communication with NetVSP */
742 if ( ( rc = netvsc_initialise ( netvsc ) ) != 0 )
743 goto err_initialise;
744 if ( ( rc = netvsc_ndis_version ( netvsc ) ) != 0 )
745 goto err_ndis_version;
746
747 /* Initialise transmit ring */
748 if ( ( rc = netvsc_create_ring ( netvsc, &netvsc->tx ) ) != 0 )
749 goto err_create_tx;
750
751 /* Establish receive buffer */
752 if ( ( rc = netvsc_establish_buffer ( netvsc, &netvsc->rx ) ) != 0 )
753 goto err_establish_rx;
754
755 return 0;
756
757 netvsc_revoke_buffer ( netvsc, &netvsc->rx );
758 err_establish_rx:
759 netvsc_destroy_ring ( netvsc, &netvsc->tx, NULL );
760 err_create_tx:
761 err_ndis_version:
762 err_initialise:
763 vmbus_close ( netvsc->vmdev );
764 err_vmbus_open:
765 netvsc_destroy_buffer ( netvsc, &netvsc->rx );
766 err_create_rx:
767 return rc;
768}
769
770/**
771 * Close device
772 *
773 * @v rndis RNDIS device
774 */
775static void netvsc_close ( struct rndis_device *rndis ) {
776 struct netvsc_device *netvsc = rndis->priv;
777
778 /* Revoke receive buffer */
779 netvsc_revoke_buffer ( netvsc, &netvsc->rx );
780
781 /* Destroy transmit ring */
782 netvsc_destroy_ring ( netvsc, &netvsc->tx, netvsc_cancel_transmit );
783
784 /* Close channel */
785 vmbus_close ( netvsc->vmdev );
786
787 /* Destroy receive buffer */
788 netvsc_destroy_buffer ( netvsc, &netvsc->rx );
789}
790
791/** RNDIS operations */
793 .open = netvsc_open,
794 .close = netvsc_close,
795 .transmit = netvsc_transmit,
796 .poll = netvsc_poll,
797};
798
799/**
800 * Probe device
801 *
802 * @v vmdev VMBus device
803 * @ret rc Return status code
804 */
805static int netvsc_probe ( struct vmbus_device *vmdev ) {
806 struct netvsc_device *netvsc;
807 struct rndis_device *rndis;
808 int rc;
809
810 /* Allocate and initialise structure */
811 rndis = alloc_rndis ( sizeof ( *netvsc ) );
812 if ( ! rndis ) {
813 rc = -ENOMEM;
814 goto err_alloc;
815 }
816 rndis_init ( rndis, &netvsc_operations );
817 rndis->netdev->dev = &vmdev->dev;
818 netvsc = rndis->priv;
819 netvsc->vmdev = vmdev;
820 netvsc->rndis = rndis;
821 netvsc->name = vmdev->dev.name;
822 netvsc_init_ring ( &netvsc->tx, NETVSC_TX_NUM_DESC,
823 netvsc->tx_iobufs, netvsc->tx_ids );
824 netvsc_init_buffer ( &netvsc->rx, NETVSC_RX_BUF_PAGESET,
829 vmbus_set_drvdata ( vmdev, rndis );
830
831 /* Register RNDIS device */
832 if ( ( rc = register_rndis ( rndis ) ) != 0 ) {
833 DBGC ( netvsc, "NETVSC %s could not register: %s\n",
834 netvsc->name, strerror ( rc ) );
835 goto err_register;
836 }
837
838 return 0;
839
840 unregister_rndis ( rndis );
841 err_register:
842 free_rndis ( rndis );
843 err_alloc:
844 return rc;
845}
846
847/**
848 * Reset device
849 *
850 * @v vmdev VMBus device
851 * @ret rc Return status code
852 */
853static int netvsc_reset ( struct vmbus_device *vmdev ) {
854 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
855 struct netvsc_device *netvsc = rndis->priv;
856 struct net_device *netdev = rndis->netdev;
857 int rc;
858
859 /* A closed device holds no NetVSC (or RNDIS) state, so there
860 * is nothing to reset.
861 */
862 if ( ! netdev_is_open ( netdev ) )
863 return 0;
864
865 /* Close and reopen device to reset any stale state */
867 if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
868 DBGC ( netvsc, "NETVSC %s could not reopen: %s\n",
869 netvsc->name, strerror ( rc ) );
870 return rc;
871 }
872
873 return 0;
874}
875
876/**
877 * Remove device
878 *
879 * @v vmdev VMBus device
880 */
881static void netvsc_remove ( struct vmbus_device *vmdev ) {
882 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
883
884 /* Unregister RNDIS device */
885 unregister_rndis ( rndis );
886
887 /* Free RNDIS device */
888 free_rndis ( rndis );
889}
890
891/** NetVSC driver */
892struct vmbus_driver netvsc_driver __vmbus_driver = {
893 .name = "netvsc",
894 .type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f,
895 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ),
896 .probe = netvsc_probe,
897 .reset = netvsc_reset,
898 .remove = netvsc_remove,
899};
900
901/* Generate build rules */
902VMBUS_ROM ( "netvsc", "Hyper-V NetVSC RNDIS virtual NIC" );
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t completion[0x00001]
Definition arbel.h:2
unsigned long long uint64_t
Definition stdint.h:13
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
struct ena_llq_option header
Header locations.
Definition ena.h:5
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER).
Definition netvsc.h:5
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define EINVAL
Invalid argument.
Definition errno.h:472
#define ETIMEDOUT
Connection timed out.
Definition errno.h:713
#define EPROTO
Protocol error.
Definition errno.h:668
#define EPIPE
Broken pipe.
Definition errno.h:663
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ECANCELED
Operation canceled.
Definition errno.h:387
#define ERANGE
Result too large.
Definition errno.h:683
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define PAGE_SIZE
Page size.
Definition io.h:28
User memory allocation.
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition umalloc.h:57
static __always_inline void ufree(void *ptr)
Free external memory.
Definition umalloc.h:68
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:277
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
int netdev_open(struct net_device *netdev)
Open network device.
Definition netdevice.c:866
void netdev_close(struct net_device *netdev)
Close network device.
Definition netdevice.c:900
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:665
static int netvsc_transmit(struct rndis_device *rndis, struct io_buffer *iobuf)
Transmit packet.
Definition netvsc.c:480
static int netvsc_reset(struct vmbus_device *vmdev)
Reset device.
Definition netvsc.c:853
static int netvsc_revoke_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Revoke data buffer.
Definition netvsc.c:260
static int netvsc_recv_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received completion packet.
Definition netvsc.c:379
static int netvsc_initialised(struct netvsc_device *netvsc, const void *data, size_t len)
Handle initialisation completion.
Definition netvsc.c:138
static int netvsc_establish_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Establish data buffer.
Definition netvsc.c:198
static void netvsc_remove(struct vmbus_device *vmdev)
Remove device.
Definition netvsc.c:881
static int netvsc_completed(struct netvsc_device *netvsc __unused, const void *data __unused, size_t len __unused)
Handle generic completion.
Definition netvsc.c:97
static struct rndis_operations netvsc_operations
RNDIS operations.
Definition netvsc.c:792
static void netvsc_poll(struct rndis_device *rndis)
Poll for completed and received packets.
Definition netvsc.c:461
static void netvsc_destroy_ring(struct netvsc_device *netvsc, struct netvsc_ring *ring, void(*discard)(struct netvsc_device *, struct io_buffer *, unsigned int))
Destroy descriptor ring.
Definition netvsc.c:587
static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
Transfer page set operations.
Definition netvsc.c:635
static int netvsc_probe(struct vmbus_device *vmdev)
Probe device.
Definition netvsc.c:805
static int netvsc_recv_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
Definition netvsc.c:438
static void netvsc_cancel_transmit(struct netvsc_device *netvsc, struct io_buffer *iobuf, unsigned int tx_id)
Cancel transmission.
Definition netvsc.c:541
static int netvsc_ndis_version(struct netvsc_device *netvsc)
Set NDIS version.
Definition netvsc.c:170
static int netvsc_control(struct netvsc_device *netvsc, unsigned int xrid, const void *data, size_t len)
Send control message and wait for completion.
Definition netvsc.c:53
static int netvsc_buffer_copy(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from data buffer.
Definition netvsc.c:619
static int netvsc_open(struct rndis_device *rndis)
Open device.
Definition netvsc.c:725
static void netvsc_close(struct rndis_device *rndis)
Close device.
Definition netvsc.c:775
static int netvsc_recv_data(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct list_head *list)
Handle received data packet.
Definition netvsc.c:320
static int netvsc_create_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Create data buffer.
Definition netvsc.c:646
static int netvsc_recv_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
Definition netvsc.c:299
static struct vmbus_channel_operations netvsc_channel_operations
VMBus channel operations.
Definition netvsc.c:449
static int netvsc_create_ring(struct netvsc_device *netvsc __unused, struct netvsc_ring *ring)
Create descriptor ring.
Definition netvsc.c:565
static int netvsc_rx_established_buffer(struct netvsc_device *netvsc, const void *data, size_t len)
Handle establish receive data buffer completion.
Definition netvsc.c:228
static int netvsc_initialise(struct netvsc_device *netvsc)
Initialise communication.
Definition netvsc.c:108
static void netvsc_destroy_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Destroy data buffer.
Definition netvsc.c:695
Hyper-V network virtual service client.
#define NETVSC_NDIS_MAJOR
NetVSC NDIS major version.
Definition netvsc.h:130
#define NETVSC_RNDIS_CONTROL
RNDIS control channel (for all other RNDIS messages).
Definition netvsc.h:230
#define NETVSC_RX_REVOKE_MSG
NetVSC revoke receive data buffer message.
Definition netvsc.h:142
@ NETVSC_RX_ESTABLISH_XRID
Establish receive buffer.
Definition netvsc.h:56
@ NETVSC_RX_REVOKE_XRID
Revoke receive buffer.
Definition netvsc.h:58
@ NETVSC_NDIS_VERSION_XRID
NDIS version.
Definition netvsc.h:54
@ NETVSC_INIT_XRID
Initialisation.
Definition netvsc.h:52
@ NETVSC_TX_BASE_XRID
Transmit descriptors (one per transmit buffer ID).
Definition netvsc.h:50
#define NETVSC_RX_BUF_LEN
RX data buffer length.
Definition netvsc.h:39
#define NETVSC_RNDIS_NO_BUFFER
"No buffer used" index
Definition netvsc.h:233
#define NETVSC_NDIS_MINOR
NetVSC NDIS minor version.
Definition netvsc.h:133
#define NETVSC_RNDIS_MSG
NetVSC RNDIS message.
Definition netvsc.h:210
#define NETVSC_BASE_XID
Base transaction ID.
Definition netvsc.h:45
@ NETVSC_OK
Definition netvsc.h:64
#define NETVSC_RX_ESTABLISH_CMPLT
NetVSC establish receive data buffer completion.
Definition netvsc.h:139
#define NETVSC_INIT_CMPLT
NetVSC initialisation completion.
Definition netvsc.h:98
#define NETVSC_TX_NUM_DESC
Number of transmit ring entries.
Definition netvsc.h:27
#define NETVSC_NDIS_VERSION_MSG
NetVSC NDIS version message.
Definition netvsc.h:115
#define NETVSC_RX_ESTABLISH_MSG
NetVSC establish receive data buffer message.
Definition netvsc.h:136
#define NETVSC_MTU
Maximum supported NetVSC message length.
Definition netvsc.h:13
uint32_t gpadl
GPADL ID.
Definition netvsc.h:3
#define NETVSC_RX_BUF_PAGESET
RX data buffer page set ID.
Definition netvsc.h:33
#define NETVSC_RNDIS_DATA
RNDIS data channel (for RNDIS_PACKET_MSG only).
Definition netvsc.h:227
#define NETVSC_MAX_WAIT_MS
Maximum time to wait for a transaction to complete.
Definition netvsc.h:19
#define NETVSC_INIT_MSG
NetVSC initialisation message.
Definition netvsc.h:80
#define NETVSC_VERSION_1
Oldest known NetVSC protocol version.
Definition netvsc.h:95
int rndis_tx_defer(struct rndis_device *rndis, struct io_buffer *iobuf)
Defer transmitted packet.
Definition rndis.c:191
int register_rndis(struct rndis_device *rndis)
Register RNDIS device.
Definition rndis.c:1027
void unregister_rndis(struct rndis_device *rndis)
Unregister RNDIS device.
Definition rndis.c:1055
void rndis_rx(struct rndis_device *rndis, struct io_buffer *iobuf)
Receive packet from underlying transport layer.
Definition rndis.c:830
void rndis_tx_complete_err(struct rndis_device *rndis, struct io_buffer *iobuf, int rc)
Complete message transmission.
Definition rndis.c:128
void free_rndis(struct rndis_device *rndis)
Free RNDIS device.
Definition rndis.c:1067
struct rndis_device * alloc_rndis(size_t priv_len)
Allocate RNDIS device.
Definition rndis.c:1001
Remote Network Driver Interface Specification.
#define RNDIS_PACKET_MSG
RNDIS packet message.
Definition rndis.h:220
static void rndis_tx_complete(struct rndis_device *rndis, struct io_buffer *iobuf)
Complete message transmission.
Definition rndis.h:365
static void rndis_init(struct rndis_device *rndis, struct rndis_operations *op)
Initialise an RNDIS device.
Definition rndis.h:340
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
char name[40]
Name.
Definition device.h:79
A persistent I/O buffer.
Definition iobuf.h:98
void * data
Start of data.
Definition iobuf.h:113
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
A doubly-linked list entry (or list head).
Definition list.h:19
A network device.
Definition netdevice.h:353
struct device * dev
Underlying hardware device.
Definition netdevice.h:365
A NetVSC data buffer.
Definition netvsc.h:294
struct vmbus_xfer_pages pages
Transfer page set.
Definition netvsc.h:296
A NetVSC device.
Definition netvsc.h:341
struct netvsc_buffer rx
Receive buffer.
Definition netvsc.h:357
const char * name
Name.
Definition netvsc.h:347
int wait_rc
Return status code for current blocking transaction.
Definition netvsc.h:362
struct io_buffer * tx_iobufs[NETVSC_TX_NUM_DESC]
Transmit I/O buffers.
Definition netvsc.h:354
struct vmbus_device * vmdev
VMBus device.
Definition netvsc.h:343
unsigned int wait_xrid
Relative transaction ID for current blocking transaction.
Definition netvsc.h:360
struct rndis_device * rndis
RNDIS device.
Definition netvsc.h:345
struct netvsc_ring tx
Transmit ring.
Definition netvsc.h:350
uint8_t tx_ids[NETVSC_TX_NUM_DESC]
Transmit buffer IDs.
Definition netvsc.h:352
NetVSC establish data buffer message.
Definition netvsc.h:154
uint32_t type
Type.
Definition netvsc.h:76
NetVSC initialisation completion.
Definition netvsc.h:101
struct netvsc_header header
Message header.
Definition netvsc.h:103
uint32_t status
Status.
Definition netvsc.h:109
NetVSC initialisation message.
Definition netvsc.h:83
NetVSC NDIS version message.
Definition netvsc.h:118
NetVSC revoke data buffer message.
Definition netvsc.h:200
A NetVSC descriptor ring.
Definition netvsc.h:236
unsigned int id_prod
Buffer ID producer counter.
Definition netvsc.h:244
struct io_buffer ** iobufs
I/O buffers, indexed by buffer ID.
Definition netvsc.h:240
unsigned int id_cons
Buffer ID consumer counter.
Definition netvsc.h:246
uint8_t * ids
Buffer ID ring.
Definition netvsc.h:242
unsigned int count
Number of descriptors.
Definition netvsc.h:238
NetVSC RNDIS message.
Definition netvsc.h:213
NetVSC establish receive data buffer completion.
Definition netvsc.h:178
struct netvsc_header header
Message header.
Definition netvsc.h:180
An RNDIS device.
Definition rndis.h:318
struct net_device * netdev
Network device.
Definition rndis.h:320
void * priv
Driver private data.
Definition rndis.h:326
RNDIS message header.
Definition rndis.h:24
RNDIS device operations.
Definition rndis.h:283
VMBus channel operations.
Definition vmbus.h:396
A VMBus device.
Definition vmbus.h:475
struct device dev
Generic iPXE device.
Definition vmbus.h:477
A VMBus device driver.
Definition vmbus.h:520
VMBus "GPADL teardown" message.
Definition vmbus.h:193
VMBus transfer page set operations.
Definition vmbus.h:450
VMBus transfer page set.
Definition vmbus.h:465
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
int vmbus_send_data(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct io_buffer *iobuf)
Send data packet via ring buffer.
Definition vmbus.c:794
void vmbus_close(struct vmbus_device *vmdev)
Close VMBus channel.
Definition vmbus.c:524
int vmbus_send_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send control packet via ring buffer.
Definition vmbus.c:765
int vmbus_send_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send completion packet via ring buffer.
Definition vmbus.c:834
int vmbus_send_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Send cancellation packet via ring buffer.
Definition vmbus.c:857
void vmbus_dump_channel(struct vmbus_device *vmdev)
Dump channel status (for debugging).
Definition vmbus.c:1096
int vmbus_establish_gpadl(struct vmbus_device *vmdev, void *data, size_t len)
Establish GPA descriptor list.
Definition vmbus.c:276
int vmbus_open(struct vmbus_device *vmdev, struct vmbus_channel_operations *op, size_t out_len, size_t in_len, size_t mtu)
Open VMBus channel.
Definition vmbus.c:403
int vmbus_poll(struct vmbus_device *vmdev)
Poll ring buffer.
Definition vmbus.c:972
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
Definition vmbus.c:347
Hyper-V virtual machine bus.
static void * vmbus_get_drvdata(struct vmbus_device *vmdev)
Get VMBus device driver-private data.
Definition vmbus.h:569
static void vmbus_set_drvdata(struct vmbus_device *vmdev, void *priv)
Set VMBus device driver-private data.
Definition vmbus.h:559
#define __vmbus_driver
Declare a VMBus device driver.
Definition vmbus.h:548
#define VMBUS_TYPE(a, b, c, d, e0, e1, e2, e3, e4, e5)
Construct VMBus type.
Definition vmbus.h:574
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
Definition vmbus.h:588
static void vmbus_unregister_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Unregister transfer page set.
Definition vmbus.h:615
#define VMBUS_ROM(_name, _desc)
Define build rules for a VMBus device driver.
Definition vmbus.h:551
static int vmbus_register_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Register transfer page set.
Definition vmbus.h:601