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 = data;
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 if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
149 DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
150 "type %d\n", netvsc->name,
151 le32_to_cpu ( cmplt->header.type ) );
152 return -EPROTO;
153 }
154 if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
155 DBGC ( netvsc, "NETVSC %s initialisation failure status %d\n",
156 netvsc->name, le32_to_cpu ( cmplt->status ) );
157 return -EPROTO;
158 }
159
160 return 0;
161}
162
163/**
164 * Set NDIS version
165 *
166 * @v netvsc NetVSC device
167 * @ret rc Return status code
168 */
169static int netvsc_ndis_version ( struct netvsc_device *netvsc ) {
171 int rc;
172
173 /* Construct message */
174 memset ( &msg, 0, sizeof ( msg ) );
175 msg.header.type = cpu_to_le32 ( NETVSC_NDIS_VERSION_MSG );
178
179 /* Send message and wait for completion */
180 if ( ( rc = netvsc_control ( netvsc, NETVSC_NDIS_VERSION_XRID,
181 &msg, sizeof ( msg ) ) ) != 0 ) {
182 DBGC ( netvsc, "NETVSC %s could not set NDIS version: %s\n",
183 netvsc->name, strerror ( rc ) );
184 return rc;
185 }
186
187 return 0;
188}
189
190/**
191 * Establish data buffer
192 *
193 * @v netvsc NetVSC device
194 * @v buffer Data buffer
195 * @ret rc Return status code
196 */
197static int netvsc_establish_buffer ( struct netvsc_device *netvsc,
198 struct netvsc_buffer *buffer ) {
200 int rc;
201
202 /* Construct message */
203 memset ( &msg, 0, sizeof ( msg ) );
204 msg.header.type = cpu_to_le32 ( buffer->establish_type );
205 msg.gpadl = cpu_to_le32 ( buffer->gpadl );
206 msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
207
208 /* Send message and wait for completion */
209 if ( ( rc = netvsc_control ( netvsc, buffer->establish_xrid, &msg,
210 sizeof ( msg ) ) ) != 0 ) {
211 DBGC ( netvsc, "NETVSC %s could not establish buffer: %s\n",
212 netvsc->name, strerror ( rc ) );
213 return rc;
214 }
215
216 return 0;
217}
218
219/**
220 * Handle establish receive data buffer completion
221 *
222 * @v netvsc NetVSC device
223 * @v data Data
224 * @v len Length of data
225 * @ret rc Return status code
226 */
227static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
228 const void *data, size_t len ) {
229 const struct netvsc_rx_establish_buffer_completion *cmplt = data;
230
231 /* Check completion */
232 if ( len < sizeof ( *cmplt ) ) {
233 DBGC ( netvsc, "NETVSC %s underlength buffer completion (%zd "
234 "bytes)\n", netvsc->name, len );
235 return -EINVAL;
236 }
237 if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
238 DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
239 "%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
240 return -EPROTO;
241 }
242 if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
243 DBGC ( netvsc, "NETVSC %s buffer failure status %d\n",
244 netvsc->name, le32_to_cpu ( cmplt->status ) );
245 return -EPROTO;
246 }
247
248 return 0;
249}
250
251/**
252 * Revoke data buffer
253 *
254 * @v netvsc NetVSC device
255 * @v buffer Data buffer
256 * @ret rc Return status code
257 */
258static int netvsc_revoke_buffer ( struct netvsc_device *netvsc,
259 struct netvsc_buffer *buffer ) {
261 int rc;
262
263 /* If the buffer's GPADL is obsolete (i.e. was created before
264 * the most recent Hyper-V reset), then we will never receive
265 * a response to the revoke message. Since the GPADL is
266 * already destroyed as far as the hypervisor is concerned, no
267 * further action is required.
268 */
269 if ( netvsc_is_obsolete ( netvsc ) )
270 return 0;
271
272 /* Construct message */
273 memset ( &msg, 0, sizeof ( msg ) );
274 msg.header.type = cpu_to_le32 ( buffer->revoke_type );
275 msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
276
277 /* Send message and wait for completion */
278 if ( ( rc = netvsc_control ( netvsc, buffer->revoke_xrid,
279 &msg, sizeof ( msg ) ) ) != 0 ) {
280 DBGC ( netvsc, "NETVSC %s could not revoke buffer: %s\n",
281 netvsc->name, strerror ( rc ) );
282 return rc;
283 }
284
285 return 0;
286}
287
288/**
289 * Handle received control packet
290 *
291 * @v vmdev VMBus device
292 * @v xid Transaction ID
293 * @v data Data
294 * @v len Length of data
295 * @ret rc Return status code
296 */
297static int netvsc_recv_control ( struct vmbus_device *vmdev, uint64_t xid,
298 const void *data, size_t len ) {
299 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
300 struct netvsc_device *netvsc = rndis->priv;
301
302 DBGC ( netvsc, "NETVSC %s received unsupported control packet "
303 "(%08llx):\n", netvsc->name, xid );
304 DBGC_HDA ( netvsc, 0, data, len );
305 return -ENOTSUP;
306}
307
308/**
309 * Handle received data packet
310 *
311 * @v vmdev VMBus device
312 * @v xid Transaction ID
313 * @v data Data
314 * @v len Length of data
315 * @v list List of I/O buffers
316 * @ret rc Return status code
317 */
318static int netvsc_recv_data ( struct vmbus_device *vmdev, uint64_t xid,
319 const void *data, size_t len,
320 struct list_head *list ) {
321 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
322 struct netvsc_device *netvsc = rndis->priv;
323 const struct netvsc_rndis_message *msg = data;
324 struct io_buffer *iobuf;
325 struct io_buffer *tmp;
326 int rc;
327
328 /* Sanity check */
329 if ( len < sizeof ( *msg ) ) {
330 DBGC ( netvsc, "NETVSC %s received underlength RNDIS packet "
331 "(%zd bytes)\n", netvsc->name, len );
332 rc = -EINVAL;
333 goto err_sanity;
334 }
335 if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
336 DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
337 "type %d\n", netvsc->name,
338 le32_to_cpu ( msg->header.type ) );
339 rc = -EINVAL;
340 goto err_sanity;
341 }
342
343 /* Send completion back to host */
344 if ( ( rc = vmbus_send_completion ( vmdev, xid, NULL, 0 ) ) != 0 ) {
345 DBGC ( netvsc, "NETVSC %s could not send completion: %s\n",
346 netvsc->name, strerror ( rc ) );
347 goto err_completion;
348 }
349
350 /* Hand off to RNDIS */
352 list_del ( &iobuf->list );
353 rndis_rx ( rndis, iob_disown ( iobuf ) );
354 }
355
356 return 0;
357
358 err_completion:
359 err_sanity:
361 list_del ( &iobuf->list );
362 free_iob ( iobuf );
363 }
364 return rc;
365}
366
367/**
368 * Handle received completion packet
369 *
370 * @v vmdev VMBus device
371 * @v xid Transaction ID
372 * @v data Data
373 * @v len Length of data
374 * @ret rc Return status code
375 */
376static int netvsc_recv_completion ( struct vmbus_device *vmdev, uint64_t xid,
377 const void *data, size_t len ) {
378 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
379 struct netvsc_device *netvsc = rndis->priv;
380 struct io_buffer *iobuf;
381 int ( * completion ) ( struct netvsc_device *netvsc,
382 const void *data, size_t len );
383 unsigned int xrid = ( xid - NETVSC_BASE_XID );
384 unsigned int tx_id;
385 int rc;
386
387 /* Handle transmit completion, if applicable */
388 tx_id = ( xrid - NETVSC_TX_BASE_XRID );
389 if ( ( tx_id < NETVSC_TX_NUM_DESC ) &&
390 ( ( iobuf = netvsc->tx.iobufs[tx_id] ) != NULL ) ) {
391
392 /* Free buffer ID */
393 netvsc->tx.iobufs[tx_id] = NULL;
394 netvsc->tx.ids[ ( netvsc->tx.id_cons++ ) &
395 ( netvsc->tx.count - 1 ) ] = tx_id;
396
397 /* Hand back to RNDIS */
398 rndis_tx_complete ( rndis, iobuf );
399 return 0;
400 }
401
402 /* Otherwise determine completion handler */
403 if ( xrid == NETVSC_INIT_XRID ) {
405 } else if ( xrid == NETVSC_RX_ESTABLISH_XRID ) {
407 } else if ( ( netvsc->wait_xrid != 0 ) &&
408 ( xrid == netvsc->wait_xrid ) ) {
410 } else {
411 DBGC ( netvsc, "NETVSC %s received unexpected completion "
412 "(%08llx)\n", netvsc->name, xid );
413 return -EPIPE;
414 }
415
416 /* Hand off to completion handler */
417 rc = completion ( netvsc, data, len );
418
419 /* Record completion handler result if applicable */
420 if ( xrid == netvsc->wait_xrid ) {
421 netvsc->wait_xrid = 0;
422 netvsc->wait_rc = rc;
423 }
424
425 return rc;
426}
427
428/**
429 * Handle received cancellation packet
430 *
431 * @v vmdev VMBus device
432 * @v xid Transaction ID
433 * @ret rc Return status code
434 */
436 uint64_t xid ) {
437 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
438 struct netvsc_device *netvsc = rndis->priv;
439
440 DBGC ( netvsc, "NETVSC %s received unsupported cancellation packet "
441 "(%08llx):\n", netvsc->name, xid );
442 return -ENOTSUP;
443}
444
445/** VMBus channel operations */
447 .recv_control = netvsc_recv_control,
448 .recv_data = netvsc_recv_data,
449 .recv_completion = netvsc_recv_completion,
450 .recv_cancellation = netvsc_recv_cancellation,
451};
452
453/**
454 * Poll for completed and received packets
455 *
456 * @v rndis RNDIS device
457 */
458static void netvsc_poll ( struct rndis_device *rndis ) {
459 struct netvsc_device *netvsc = rndis->priv;
460 struct vmbus_device *vmdev = netvsc->vmdev;
461
462 /* Poll VMBus device */
463 while ( vmbus_has_data ( vmdev ) )
464 vmbus_poll ( vmdev );
465}
466
467/**
468 * Transmit packet
469 *
470 * @v rndis RNDIS device
471 * @v iobuf I/O buffer
472 * @ret rc Return status code
473 *
474 * If this method returns success then the RNDIS device must
475 * eventually report completion via rndis_tx_complete().
476 */
477static int netvsc_transmit ( struct rndis_device *rndis,
478 struct io_buffer *iobuf ) {
479 struct netvsc_device *netvsc = rndis->priv;
480 struct rndis_header *header = iobuf->data;
482 unsigned int tx_id;
483 unsigned int xrid;
484 uint64_t xid;
485 int rc;
486
487 /* If the device is obsolete (i.e. was opened before the most
488 * recent Hyper-V reset), then we will never receive transmit
489 * completions. Fail transmissions immediately to minimise
490 * the delay in closing and reopening the device.
491 */
492 if ( netvsc_is_obsolete ( netvsc ) )
493 return -EPIPE;
494
495 /* Sanity check */
496 assert ( iob_len ( iobuf ) >= sizeof ( *header ) );
497 assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) );
498
499 /* Check that we have space in the transmit ring */
500 if ( netvsc_ring_is_full ( &netvsc->tx ) )
501 return rndis_tx_defer ( rndis, iobuf );
502
503 /* Allocate buffer ID and calculate transaction ID */
504 tx_id = netvsc->tx.ids[ netvsc->tx.id_prod & ( netvsc->tx.count - 1 ) ];
505 assert ( netvsc->tx.iobufs[tx_id] == NULL );
506 xrid = ( NETVSC_TX_BASE_XRID + tx_id );
507 xid = ( NETVSC_BASE_XID + xrid );
508
509 /* Construct message */
510 memset ( &msg, 0, sizeof ( msg ) );
511 msg.header.type = cpu_to_le32 ( NETVSC_RNDIS_MSG );
512 msg.channel = ( ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) ?
515
516 /* Send message */
517 if ( ( rc = vmbus_send_data ( netvsc->vmdev, xid, &msg, sizeof ( msg ),
518 iobuf ) ) != 0 ) {
519 DBGC ( netvsc, "NETVSC %s could not send RNDIS message: %s\n",
520 netvsc->name, strerror ( rc ) );
521 return rc;
522 }
523
524 /* Store I/O buffer and consume buffer ID */
525 netvsc->tx.iobufs[tx_id] = iobuf;
526 netvsc->tx.id_prod++;
527
528 return 0;
529}
530
531/**
532 * Cancel transmission
533 *
534 * @v netvsc NetVSC device
535 * @v iobuf I/O buffer
536 * @v tx_id Transmission ID
537 */
538static void netvsc_cancel_transmit ( struct netvsc_device *netvsc,
539 struct io_buffer *iobuf,
540 unsigned int tx_id ) {
541 unsigned int xrid;
542 uint64_t xid;
543
544 /* Send cancellation */
545 xrid = ( NETVSC_TX_BASE_XRID + tx_id );
546 xid = ( NETVSC_BASE_XID + xrid );
547 DBGC ( netvsc, "NETVSC %s cancelling transmission %#x\n",
548 netvsc->name, tx_id );
549 vmbus_send_cancellation ( netvsc->vmdev, xid );
550
551 /* Report back to RNDIS */
552 rndis_tx_complete_err ( netvsc->rndis, iobuf, -ECANCELED );
553}
554
555/**
556 * Create descriptor ring
557 *
558 * @v netvsc NetVSC device
559 * @v ring Descriptor ring
560 * @ret rc Return status code
561 */
562static int netvsc_create_ring ( struct netvsc_device *netvsc __unused,
563 struct netvsc_ring *ring ) {
564 unsigned int i;
565
566 /* Initialise buffer ID ring */
567 for ( i = 0 ; i < ring->count ; i++ ) {
568 ring->ids[i] = i;
569 assert ( ring->iobufs[i] == NULL );
570 }
571 ring->id_prod = 0;
572 ring->id_cons = 0;
573
574 return 0;
575}
576
577/**
578 * Destroy descriptor ring
579 *
580 * @v netvsc NetVSC device
581 * @v ring Descriptor ring
582 * @v discard Method used to discard outstanding buffer, or NULL
583 */
584static void netvsc_destroy_ring ( struct netvsc_device *netvsc,
585 struct netvsc_ring *ring,
586 void ( * discard ) ( struct netvsc_device *,
587 struct io_buffer *,
588 unsigned int ) ) {
589 struct io_buffer *iobuf;
590 unsigned int i;
591
592 /* Flush any outstanding buffers */
593 for ( i = 0 ; i < ring->count ; i++ ) {
594 iobuf = ring->iobufs[i];
595 if ( ! iobuf )
596 continue;
597 ring->iobufs[i] = NULL;
598 ring->ids[ ( ring->id_cons++ ) & ( ring->count - 1 ) ] = i;
599 if ( discard )
600 discard ( netvsc, iobuf, i );
601 }
602
603 /* Sanity check */
604 assert ( netvsc_ring_is_empty ( ring ) );
605}
606
607/**
608 * Copy data from data buffer
609 *
610 * @v pages Transfer page set
611 * @v data Data buffer
612 * @v offset Offset within page set
613 * @v len Length within page set
614 * @ret rc Return status code
615 */
616static int netvsc_buffer_copy ( struct vmbus_xfer_pages *pages, void *data,
617 size_t offset, size_t len ) {
618 struct netvsc_buffer *buffer =
620
621 /* Sanity check */
622 if ( ( offset > buffer->len ) || ( len > ( buffer->len - offset ) ) )
623 return -ERANGE;
624
625 /* Copy data from buffer */
626 memcpy ( data, ( buffer->data + offset ), len );
627
628 return 0;
629}
630
631/** Transfer page set operations */
635
636/**
637 * Create data buffer
638 *
639 * @v netvsc NetVSC device
640 * @v buffer Data buffer
641 * @ret rc Return status code
642 */
643static int netvsc_create_buffer ( struct netvsc_device *netvsc,
644 struct netvsc_buffer *buffer ) {
645 struct vmbus_device *vmdev = netvsc->vmdev;
646 int gpadl;
647 int rc;
648
649 /* Allocate receive buffer */
650 buffer->data = umalloc ( buffer->len );
651 if ( ! buffer->data ) {
652 DBGC ( netvsc, "NETVSC %s could not allocate %zd-byte buffer\n",
653 netvsc->name, buffer->len );
654 rc = -ENOMEM;
655 goto err_alloc;
656 }
657
658 /* Establish GPA descriptor list */
659 gpadl = vmbus_establish_gpadl ( vmdev, buffer->data, buffer->len );
660 if ( gpadl < 0 ) {
661 rc = gpadl;
662 DBGC ( netvsc, "NETVSC %s could not establish GPADL: %s\n",
663 netvsc->name, strerror ( rc ) );
664 goto err_establish_gpadl;
665 }
666 buffer->gpadl = gpadl;
667
668 /* Register transfer page set */
669 if ( ( rc = vmbus_register_pages ( vmdev, &buffer->pages ) ) != 0 ) {
670 DBGC ( netvsc, "NETVSC %s could not register transfer pages: "
671 "%s\n", netvsc->name, strerror ( rc ) );
672 goto err_register_pages;
673 }
674
675 return 0;
676
677 vmbus_unregister_pages ( vmdev, &buffer->pages );
678 err_register_pages:
679 vmbus_gpadl_teardown ( vmdev, gpadl );
680 err_establish_gpadl:
681 ufree ( buffer->data );
682 err_alloc:
683 return rc;
684}
685
686/**
687 * Destroy data buffer
688 *
689 * @v netvsc NetVSC device
690 * @v buffer Data buffer
691 */
692static void netvsc_destroy_buffer ( struct netvsc_device *netvsc,
693 struct netvsc_buffer *buffer ) {
694 struct vmbus_device *vmdev = netvsc->vmdev;
695 int rc;
696
697 /* Unregister transfer pages */
698 vmbus_unregister_pages ( vmdev, &buffer->pages );
699
700 /* Tear down GPA descriptor list */
701 if ( ( rc = vmbus_gpadl_teardown ( vmdev, buffer->gpadl ) ) != 0 ) {
702 DBGC ( netvsc, "NETVSC %s could not tear down GPADL: %s\n",
703 netvsc->name, strerror ( rc ) );
704 /* Death is imminent. The host may well continue to
705 * write to the data buffer. The best we can do is
706 * leak memory for now and hope that the host doesn't
707 * write to this region after we load an OS.
708 */
709 return;
710 }
711
712 /* Free buffer */
713 ufree ( buffer->data );
714}
715
716/**
717 * Open device
718 *
719 * @v rndis RNDIS device
720 * @ret rc Return status code
721 */
722static int netvsc_open ( struct rndis_device *rndis ) {
723 struct netvsc_device *netvsc = rndis->priv;
724 int rc;
725
726 /* Initialise receive buffer */
727 if ( ( rc = netvsc_create_buffer ( netvsc, &netvsc->rx ) ) != 0 )
728 goto err_create_rx;
729
730 /* Open channel */
731 if ( ( rc = vmbus_open ( netvsc->vmdev, &netvsc_channel_operations,
732 PAGE_SIZE, PAGE_SIZE, NETVSC_MTU ) ) != 0 ) {
733 DBGC ( netvsc, "NETVSC %s could not open VMBus: %s\n",
734 netvsc->name, strerror ( rc ) );
735 goto err_vmbus_open;
736 }
737
738 /* Initialise communication with NetVSP */
739 if ( ( rc = netvsc_initialise ( netvsc ) ) != 0 )
740 goto err_initialise;
741 if ( ( rc = netvsc_ndis_version ( netvsc ) ) != 0 )
742 goto err_ndis_version;
743
744 /* Initialise transmit ring */
745 if ( ( rc = netvsc_create_ring ( netvsc, &netvsc->tx ) ) != 0 )
746 goto err_create_tx;
747
748 /* Establish receive buffer */
749 if ( ( rc = netvsc_establish_buffer ( netvsc, &netvsc->rx ) ) != 0 )
750 goto err_establish_rx;
751
752 return 0;
753
754 netvsc_revoke_buffer ( netvsc, &netvsc->rx );
755 err_establish_rx:
756 netvsc_destroy_ring ( netvsc, &netvsc->tx, NULL );
757 err_create_tx:
758 err_ndis_version:
759 err_initialise:
760 vmbus_close ( netvsc->vmdev );
761 err_vmbus_open:
762 netvsc_destroy_buffer ( netvsc, &netvsc->rx );
763 err_create_rx:
764 return rc;
765}
766
767/**
768 * Close device
769 *
770 * @v rndis RNDIS device
771 */
772static void netvsc_close ( struct rndis_device *rndis ) {
773 struct netvsc_device *netvsc = rndis->priv;
774
775 /* Revoke receive buffer */
776 netvsc_revoke_buffer ( netvsc, &netvsc->rx );
777
778 /* Destroy transmit ring */
779 netvsc_destroy_ring ( netvsc, &netvsc->tx, netvsc_cancel_transmit );
780
781 /* Close channel */
782 vmbus_close ( netvsc->vmdev );
783
784 /* Destroy receive buffer */
785 netvsc_destroy_buffer ( netvsc, &netvsc->rx );
786}
787
788/** RNDIS operations */
790 .open = netvsc_open,
791 .close = netvsc_close,
792 .transmit = netvsc_transmit,
793 .poll = netvsc_poll,
794};
795
796/**
797 * Probe device
798 *
799 * @v vmdev VMBus device
800 * @ret rc Return status code
801 */
802static int netvsc_probe ( struct vmbus_device *vmdev ) {
803 struct netvsc_device *netvsc;
804 struct rndis_device *rndis;
805 int rc;
806
807 /* Allocate and initialise structure */
808 rndis = alloc_rndis ( sizeof ( *netvsc ) );
809 if ( ! rndis ) {
810 rc = -ENOMEM;
811 goto err_alloc;
812 }
813 rndis_init ( rndis, &netvsc_operations );
814 rndis->netdev->dev = &vmdev->dev;
815 netvsc = rndis->priv;
816 netvsc->vmdev = vmdev;
817 netvsc->rndis = rndis;
818 netvsc->name = vmdev->dev.name;
819 netvsc_init_ring ( &netvsc->tx, NETVSC_TX_NUM_DESC,
820 netvsc->tx_iobufs, netvsc->tx_ids );
821 netvsc_init_buffer ( &netvsc->rx, NETVSC_RX_BUF_PAGESET,
826 vmbus_set_drvdata ( vmdev, rndis );
827
828 /* Register RNDIS device */
829 if ( ( rc = register_rndis ( rndis ) ) != 0 ) {
830 DBGC ( netvsc, "NETVSC %s could not register: %s\n",
831 netvsc->name, strerror ( rc ) );
832 goto err_register;
833 }
834
835 return 0;
836
837 unregister_rndis ( rndis );
838 err_register:
839 free_rndis ( rndis );
840 err_alloc:
841 return rc;
842}
843
844/**
845 * Reset device
846 *
847 * @v vmdev VMBus device
848 * @ret rc Return status code
849 */
850static int netvsc_reset ( struct vmbus_device *vmdev ) {
851 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
852 struct netvsc_device *netvsc = rndis->priv;
853 struct net_device *netdev = rndis->netdev;
854 int rc;
855
856 /* A closed device holds no NetVSC (or RNDIS) state, so there
857 * is nothing to reset.
858 */
859 if ( ! netdev_is_open ( netdev ) )
860 return 0;
861
862 /* Close and reopen device to reset any stale state */
864 if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
865 DBGC ( netvsc, "NETVSC %s could not reopen: %s\n",
866 netvsc->name, strerror ( rc ) );
867 return rc;
868 }
869
870 return 0;
871}
872
873/**
874 * Remove device
875 *
876 * @v vmdev VMBus device
877 */
878static void netvsc_remove ( struct vmbus_device *vmdev ) {
879 struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
880
881 /* Unregister RNDIS device */
882 unregister_rndis ( rndis );
883
884 /* Free RNDIS device */
885 free_rndis ( rndis );
886}
887
888/** NetVSC driver */
889struct vmbus_driver netvsc_driver __vmbus_driver = {
890 .name = "netvsc",
891 .type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f,
892 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ),
893 .probe = netvsc_probe,
894 .reset = netvsc_reset,
895 .remove = netvsc_remove,
896};
897
898/* Generate build rules */
899VMBUS_ROM ( "netvsc", "Hyper-V NetVSC RNDIS virtual NIC" );
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:50
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:573
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
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:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define EPROTO
Protocol error.
Definition errno.h:625
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define ERANGE
Result too large.
Definition errno.h:640
#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:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
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:862
void netdev_close(struct net_device *netdev)
Close network device.
Definition netdevice.c:896
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
static int netvsc_transmit(struct rndis_device *rndis, struct io_buffer *iobuf)
Transmit packet.
Definition netvsc.c:477
static int netvsc_reset(struct vmbus_device *vmdev)
Reset device.
Definition netvsc.c:850
static int netvsc_revoke_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Revoke data buffer.
Definition netvsc.c:258
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:376
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:197
static void netvsc_remove(struct vmbus_device *vmdev)
Remove device.
Definition netvsc.c:878
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:789
static void netvsc_poll(struct rndis_device *rndis)
Poll for completed and received packets.
Definition netvsc.c:458
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:584
static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
Transfer page set operations.
Definition netvsc.c:632
static int netvsc_probe(struct vmbus_device *vmdev)
Probe device.
Definition netvsc.c:802
static int netvsc_recv_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
Definition netvsc.c:435
static void netvsc_cancel_transmit(struct netvsc_device *netvsc, struct io_buffer *iobuf, unsigned int tx_id)
Cancel transmission.
Definition netvsc.c:538
static int netvsc_ndis_version(struct netvsc_device *netvsc)
Set NDIS version.
Definition netvsc.c:169
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:616
static int netvsc_open(struct rndis_device *rndis)
Open device.
Definition netvsc.c:722
static void netvsc_close(struct rndis_device *rndis)
Close device.
Definition netvsc.c:772
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:318
static int netvsc_create_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Create data buffer.
Definition netvsc.c:643
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:297
static struct vmbus_channel_operations netvsc_channel_operations
VMBus channel operations.
Definition netvsc.c:446
static int netvsc_create_ring(struct netvsc_device *netvsc __unused, struct netvsc_ring *ring)
Create descriptor ring.
Definition netvsc.c:562
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:227
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:692
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:38
void * data
Start of data.
Definition iobuf.h:53
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
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:1089
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