iPXE
netvsc.c File Reference

Hyper-V network virtual service client. More...

#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <byteswap.h>
#include <ipxe/umalloc.h>
#include <ipxe/rndis.h>
#include <ipxe/vmbus.h>
#include "netvsc.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int netvsc_control (struct netvsc_device *netvsc, unsigned int xrid, const void *data, size_t len)
 Send control message and wait for completion.
static int netvsc_completed (struct netvsc_device *netvsc __unused, const void *data __unused, size_t len __unused)
 Handle generic completion.
static int netvsc_initialise (struct netvsc_device *netvsc)
 Initialise communication.
static int netvsc_initialised (struct netvsc_device *netvsc, const void *data, size_t len)
 Handle initialisation completion.
static int netvsc_ndis_version (struct netvsc_device *netvsc)
 Set NDIS version.
static int netvsc_establish_buffer (struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
 Establish data buffer.
static int netvsc_rx_established_buffer (struct netvsc_device *netvsc, const void *data, size_t len)
 Handle establish receive data buffer completion.
static int netvsc_revoke_buffer (struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
 Revoke data buffer.
static int netvsc_recv_control (struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
 Handle received control packet.
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.
static int netvsc_recv_completion (struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
 Handle received completion packet.
static int netvsc_recv_cancellation (struct vmbus_device *vmdev, uint64_t xid)
 Handle received cancellation packet.
static void netvsc_poll (struct rndis_device *rndis)
 Poll for completed and received packets.
static int netvsc_transmit (struct rndis_device *rndis, struct io_buffer *iobuf)
 Transmit packet.
static void netvsc_cancel_transmit (struct netvsc_device *netvsc, struct io_buffer *iobuf, unsigned int tx_id)
 Cancel transmission.
static int netvsc_create_ring (struct netvsc_device *netvsc __unused, struct netvsc_ring *ring)
 Create descriptor ring.
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.
static int netvsc_buffer_copy (struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
 Copy data from data buffer.
static int netvsc_create_buffer (struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
 Create data buffer.
static void netvsc_destroy_buffer (struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
 Destroy data buffer.
static int netvsc_open (struct rndis_device *rndis)
 Open device.
static void netvsc_close (struct rndis_device *rndis)
 Close device.
static int netvsc_probe (struct vmbus_device *vmdev)
 Probe device.
static int netvsc_reset (struct vmbus_device *vmdev)
 Reset device.
static void netvsc_remove (struct vmbus_device *vmdev)
 Remove device.
 VMBUS_ROM ("netvsc", "Hyper-V NetVSC RNDIS virtual NIC")

Variables

static struct vmbus_channel_operations netvsc_channel_operations
 VMBus channel operations.
static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
 Transfer page set operations.
static struct rndis_operations netvsc_operations
 RNDIS operations.
struct vmbus_driver netvsc_driver __vmbus_driver
 NetVSC driver.

Detailed Description

Hyper-V network virtual service client.

The network virtual service client (NetVSC) connects to the network virtual service provider (NetVSP) via the Hyper-V virtual machine bus (VMBus). It provides a transport layer for RNDIS packets.

Definition in file netvsc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ netvsc_control()

int netvsc_control ( struct netvsc_device * netvsc,
unsigned int xrid,
const void * data,
size_t len )
static

Send control message and wait for completion.

Parameters
netvscNetVSC device
xridRelative transaction ID
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 53 of file netvsc.c.

54 {
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}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned long long uint64_t
Definition stdint.h:13
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC(...)
Definition compiler.h:530
#define ETIMEDOUT
Connection timed out.
Definition errno.h:713
#define NETVSC_BASE_XID
Base transaction ID.
Definition netvsc.h:45
#define NETVSC_MAX_WAIT_MS
Maximum time to wait for a transaction to complete.
Definition netvsc.h:19
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
const char * name
Name.
Definition netvsc.h:347
int wait_rc
Return status code for current blocking transaction.
Definition netvsc.h:362
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
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
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
void vmbus_dump_channel(struct vmbus_device *vmdev)
Dump channel status (for debugging).
Definition vmbus.c:1096
int vmbus_poll(struct vmbus_device *vmdev)
Poll ring buffer.
Definition vmbus.c:972

References data, DBGC, ETIMEDOUT, len, mdelay(), netvsc_device::name, NETVSC_BASE_XID, NETVSC_MAX_WAIT_MS, rc, strerror(), vmbus_dump_channel(), vmbus_poll(), vmbus_send_control(), netvsc_device::vmdev, netvsc_device::wait_rc, and netvsc_device::wait_xrid.

Referenced by netvsc_establish_buffer(), netvsc_initialise(), netvsc_ndis_version(), and netvsc_revoke_buffer().

◆ netvsc_completed()

int netvsc_completed ( struct netvsc_device *netvsc __unused,
const void *data __unused,
size_t len __unused )
static

Handle generic completion.

Parameters
netvscNetVSC device
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 97 of file netvsc.c.

98 {
99 return 0;
100}

References __unused, data, and len.

Referenced by netvsc_recv_completion().

◆ netvsc_initialise()

int netvsc_initialise ( struct netvsc_device * netvsc)
static

Initialise communication.

Parameters
netvscNetVSC device
Return values
rcReturn status code

Definition at line 108 of file netvsc.c.

108 {
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}
#define cpu_to_le32(value)
Definition byteswap.h:108
void * memset(void *dest, int character, size_t len) __nonnull
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
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
@ NETVSC_INIT_XRID
Initialisation.
Definition netvsc.h:52
#define NETVSC_INIT_MSG
NetVSC initialisation message.
Definition netvsc.h:80
#define NETVSC_VERSION_1
Oldest known NetVSC protocol version.
Definition netvsc.h:95
NetVSC initialisation message.
Definition netvsc.h:83

References cpu_to_le32, DBGC, memset(), msg(), netvsc_device::name, netvsc_control(), NETVSC_INIT_MSG, NETVSC_INIT_XRID, NETVSC_VERSION_1, rc, and strerror().

Referenced by netvsc_open().

◆ netvsc_initialised()

int netvsc_initialised ( struct netvsc_device * netvsc,
const void * data,
size_t len )
static

Handle initialisation completion.

Parameters
netvscNetVSC device
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 138 of file netvsc.c.

139 {
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}
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EPROTO
Protocol error.
Definition errno.h:668
#define le32_to_cpu(value)
Definition byteswap.h:114
@ NETVSC_OK
Definition netvsc.h:64
#define NETVSC_INIT_CMPLT
NetVSC initialisation completion.
Definition netvsc.h:98
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

References cpu_to_le32, data, DBGC, EINVAL, EPROTO, netvsc_init_completion::header, le32_to_cpu, len, netvsc_device::name, NETVSC_INIT_CMPLT, NETVSC_OK, netvsc_init_completion::status, and netvsc_header::type.

Referenced by netvsc_recv_completion().

◆ netvsc_ndis_version()

int netvsc_ndis_version ( struct netvsc_device * netvsc)
static

Set NDIS version.

Parameters
netvscNetVSC device
Return values
rcReturn status code

Definition at line 170 of file netvsc.c.

170 {
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}
#define NETVSC_NDIS_MAJOR
NetVSC NDIS major version.
Definition netvsc.h:130
@ NETVSC_NDIS_VERSION_XRID
NDIS version.
Definition netvsc.h:54
#define NETVSC_NDIS_MINOR
NetVSC NDIS minor version.
Definition netvsc.h:133
#define NETVSC_NDIS_VERSION_MSG
NetVSC NDIS version message.
Definition netvsc.h:115
NetVSC NDIS version message.
Definition netvsc.h:118

References cpu_to_le32, DBGC, memset(), msg(), netvsc_device::name, netvsc_control(), NETVSC_NDIS_MAJOR, NETVSC_NDIS_MINOR, NETVSC_NDIS_VERSION_MSG, NETVSC_NDIS_VERSION_XRID, rc, and strerror().

Referenced by netvsc_open().

◆ netvsc_establish_buffer()

int netvsc_establish_buffer ( struct netvsc_device * netvsc,
struct netvsc_buffer * buffer )
static

Establish data buffer.

Parameters
netvscNetVSC device
bufferData buffer
Return values
rcReturn status code

Definition at line 198 of file netvsc.c.

199 {
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}
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER).
Definition netvsc.h:5
NetVSC establish data buffer message.
Definition netvsc.h:154

References buffer, cpu_to_le32, DBGC, memset(), msg(), netvsc_device::name, netvsc_control(), rc, and strerror().

Referenced by netvsc_open().

◆ netvsc_rx_established_buffer()

int netvsc_rx_established_buffer ( struct netvsc_device * netvsc,
const void * data,
size_t len )
static

Handle establish receive data buffer completion.

Parameters
netvscNetVSC device
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 228 of file netvsc.c.

229 {
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}
#define NETVSC_RX_ESTABLISH_CMPLT
NetVSC establish receive data buffer completion.
Definition netvsc.h:139
NetVSC establish receive data buffer completion.
Definition netvsc.h:178
struct netvsc_header header
Message header.
Definition netvsc.h:180

References cpu_to_le32, data, DBGC, EINVAL, EPROTO, netvsc_rx_establish_buffer_completion::header, le32_to_cpu, len, netvsc_device::name, NETVSC_OK, NETVSC_RX_ESTABLISH_CMPLT, netvsc_rx_establish_buffer_completion::status, and netvsc_header::type.

Referenced by netvsc_recv_completion().

◆ netvsc_revoke_buffer()

int netvsc_revoke_buffer ( struct netvsc_device * netvsc,
struct netvsc_buffer * buffer )
static

Revoke data buffer.

Parameters
netvscNetVSC device
bufferData buffer
Return values
rcReturn status code

Definition at line 260 of file netvsc.c.

261 {
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}
NetVSC revoke data buffer message.
Definition netvsc.h:200

References buffer, cpu_to_le32, DBGC, memset(), msg(), netvsc_device::name, netvsc_control(), rc, and strerror().

Referenced by netvsc_close(), and netvsc_open().

◆ netvsc_recv_control()

int netvsc_recv_control ( struct vmbus_device * vmdev,
uint64_t xid,
const void * data,
size_t len )
static

Handle received control packet.

Parameters
vmdevVMBus device
xidTransaction ID
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 299 of file netvsc.c.

300 {
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}
#define DBGC_HDA(...)
Definition compiler.h:531
#define ENOTSUP
Operation not supported.
Definition errno.h:633
A NetVSC device.
Definition netvsc.h:341
struct rndis_device * rndis
RNDIS device.
Definition netvsc.h:345
An RNDIS device.
Definition rndis.h:318
void * priv
Driver private data.
Definition rndis.h:326
static void * vmbus_get_drvdata(struct vmbus_device *vmdev)
Get VMBus device driver-private data.
Definition vmbus.h:569

References data, DBGC, DBGC_HDA, ENOTSUP, len, netvsc_device::name, rndis_device::priv, netvsc_device::rndis, and vmbus_get_drvdata().

◆ netvsc_recv_data()

int netvsc_recv_data ( struct vmbus_device * vmdev,
uint64_t xid,
const void * data,
size_t len,
struct list_head * list )
static

Handle received data packet.

Parameters
vmdevVMBus device
xidTransaction ID
dataData
lenLength of data
listList of I/O buffers
Return values
rcReturn status code

Definition at line 320 of file netvsc.c.

322 {
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}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
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
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
#define NETVSC_RNDIS_MSG
NetVSC RNDIS message.
Definition netvsc.h:210
void rndis_rx(struct rndis_device *rndis, struct io_buffer *iobuf)
Receive packet from underlying transport layer.
Definition rndis.c:830
A persistent I/O buffer.
Definition iobuf.h:98
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
NetVSC RNDIS message.
Definition netvsc.h:213
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

References cpu_to_le32, data, DBGC, EINVAL, free_iob(), iob_disown, le32_to_cpu, len, io_buffer::list, list_del, list_for_each_entry_safe, msg(), netvsc_device::name, NETVSC_RNDIS_MSG, NULL, rndis_device::priv, rc, netvsc_device::rndis, rndis_rx(), strerror(), tmp, vmbus_get_drvdata(), and vmbus_send_completion().

◆ netvsc_recv_completion()

int netvsc_recv_completion ( struct vmbus_device * vmdev,
uint64_t xid,
const void * data,
size_t len )
static

Handle received completion packet.

Parameters
vmdevVMBus device
xidTransaction ID
dataData
lenLength of data
Return values
rcReturn status code

Definition at line 379 of file netvsc.c.

380 {
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}
pseudo_bit_t completion[0x00001]
Definition arbel.h:2
#define EPIPE
Broken pipe.
Definition errno.h:663
static int netvsc_initialised(struct netvsc_device *netvsc, const void *data, size_t len)
Handle initialisation completion.
Definition netvsc.c:138
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 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
@ NETVSC_RX_ESTABLISH_XRID
Establish receive buffer.
Definition netvsc.h:56
@ NETVSC_TX_BASE_XRID
Transmit descriptors (one per transmit buffer ID).
Definition netvsc.h:50
#define NETVSC_TX_NUM_DESC
Number of transmit ring entries.
Definition netvsc.h:27
static void rndis_tx_complete(struct rndis_device *rndis, struct io_buffer *iobuf)
Complete message transmission.
Definition rndis.h:365
struct netvsc_ring tx
Transmit ring.
Definition netvsc.h:350
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

References completion, netvsc_ring::count, data, DBGC, EPIPE, netvsc_ring::id_cons, netvsc_ring::ids, netvsc_ring::iobufs, len, netvsc_device::name, NETVSC_BASE_XID, netvsc_completed(), NETVSC_INIT_XRID, netvsc_initialised(), NETVSC_RX_ESTABLISH_XRID, netvsc_rx_established_buffer(), NETVSC_TX_BASE_XRID, NETVSC_TX_NUM_DESC, NULL, rndis_device::priv, rc, netvsc_device::rndis, rndis_tx_complete(), netvsc_device::tx, vmbus_get_drvdata(), netvsc_device::wait_rc, and netvsc_device::wait_xrid.

◆ netvsc_recv_cancellation()

int netvsc_recv_cancellation ( struct vmbus_device * vmdev,
uint64_t xid )
static

Handle received cancellation packet.

Parameters
vmdevVMBus device
xidTransaction ID
Return values
rcReturn status code

Definition at line 438 of file netvsc.c.

439 {
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}

References DBGC, ENOTSUP, netvsc_device::name, rndis_device::priv, netvsc_device::rndis, and vmbus_get_drvdata().

◆ netvsc_poll()

void netvsc_poll ( struct rndis_device * rndis)
static

Poll for completed and received packets.

Parameters
rndisRNDIS device

Definition at line 461 of file netvsc.c.

461 {
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}
A VMBus device.
Definition vmbus.h:475
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
Definition vmbus.h:588

References rndis_device::priv, netvsc_device::rndis, vmbus_has_data(), vmbus_poll(), and netvsc_device::vmdev.

◆ netvsc_transmit()

int netvsc_transmit ( struct rndis_device * rndis,
struct io_buffer * iobuf )
static

Transmit packet.

Parameters
rndisRNDIS device
iobufI/O buffer
Return values
rcReturn status code

If this method returns success then the RNDIS device must eventually report completion via rndis_tx_complete().

Definition at line 480 of file netvsc.c.

481 {
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}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct ena_llq_option header
Header locations.
Definition ena.h:5
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
#define NETVSC_RNDIS_CONTROL
RNDIS control channel (for all other RNDIS messages).
Definition netvsc.h:230
#define NETVSC_RNDIS_NO_BUFFER
"No buffer used" index
Definition netvsc.h:233
#define NETVSC_RNDIS_DATA
RNDIS data channel (for RNDIS_PACKET_MSG only).
Definition netvsc.h:227
int rndis_tx_defer(struct rndis_device *rndis, struct io_buffer *iobuf)
Defer transmitted packet.
Definition rndis.c:191
#define RNDIS_PACKET_MSG
RNDIS packet message.
Definition rndis.h:220
void * data
Start of data.
Definition iobuf.h:113
unsigned int id_prod
Buffer ID producer counter.
Definition netvsc.h:244
RNDIS message header.
Definition rndis.h:24
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

References assert, netvsc_ring::count, cpu_to_le32, io_buffer::data, DBGC, EPIPE, header, netvsc_ring::id_prod, netvsc_ring::ids, iob_len(), netvsc_ring::iobufs, le32_to_cpu, memset(), msg(), netvsc_device::name, NETVSC_BASE_XID, NETVSC_RNDIS_CONTROL, NETVSC_RNDIS_DATA, NETVSC_RNDIS_MSG, NETVSC_RNDIS_NO_BUFFER, NETVSC_TX_BASE_XRID, NULL, rndis_device::priv, rc, netvsc_device::rndis, RNDIS_PACKET_MSG, rndis_tx_defer(), strerror(), netvsc_device::tx, vmbus_send_data(), and netvsc_device::vmdev.

◆ netvsc_cancel_transmit()

void netvsc_cancel_transmit ( struct netvsc_device * netvsc,
struct io_buffer * iobuf,
unsigned int tx_id )
static

Cancel transmission.

Parameters
netvscNetVSC device
iobufI/O buffer
tx_idTransmission ID

Definition at line 541 of file netvsc.c.

543 {
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}
#define ECANCELED
Operation canceled.
Definition errno.h:387
void rndis_tx_complete_err(struct rndis_device *rndis, struct io_buffer *iobuf, int rc)
Complete message transmission.
Definition rndis.c:128
int vmbus_send_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Send cancellation packet via ring buffer.
Definition vmbus.c:857

References DBGC, ECANCELED, netvsc_device::name, NETVSC_BASE_XID, NETVSC_TX_BASE_XRID, netvsc_device::rndis, rndis_tx_complete_err(), vmbus_send_cancellation(), and netvsc_device::vmdev.

Referenced by netvsc_close().

◆ netvsc_create_ring()

int netvsc_create_ring ( struct netvsc_device *netvsc __unused,
struct netvsc_ring * ring )
static

Create descriptor ring.

Parameters
netvscNetVSC device
ringDescriptor ring
Return values
rcReturn status code

Definition at line 565 of file netvsc.c.

566 {
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}

References __unused, assert, netvsc_ring::count, netvsc_ring::id_cons, netvsc_ring::id_prod, netvsc_ring::ids, netvsc_ring::iobufs, and NULL.

Referenced by netvsc_open().

◆ netvsc_destroy_ring()

void netvsc_destroy_ring ( struct netvsc_device * netvsc,
struct netvsc_ring * ring,
void(* discard )(struct netvsc_device *, struct io_buffer *, unsigned int) )
static

Destroy descriptor ring.

Parameters
netvscNetVSC device
ringDescriptor ring
discardMethod used to discard outstanding buffer, or NULL

Definition at line 587 of file netvsc.c.

591 {
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}

References assert, netvsc_ring::count, netvsc_ring::id_cons, netvsc_ring::ids, netvsc_ring::iobufs, and NULL.

Referenced by netvsc_close(), and netvsc_open().

◆ netvsc_buffer_copy()

int netvsc_buffer_copy ( struct vmbus_xfer_pages * pages,
void * data,
size_t offset,
size_t len )
static

Copy data from data buffer.

Parameters
pagesTransfer page set
dataData buffer
offsetOffset within page set
lenLength within page set
Return values
rcReturn status code

Definition at line 619 of file netvsc.c.

620 {
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}
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define ERANGE
Result too large.
Definition errno.h:683
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A NetVSC data buffer.
Definition netvsc.h:294
struct vmbus_xfer_pages pages
Transfer page set.
Definition netvsc.h:296

References buffer, container_of, data, ERANGE, len, memcpy(), offset, and netvsc_buffer::pages.

◆ netvsc_create_buffer()

int netvsc_create_buffer ( struct netvsc_device * netvsc,
struct netvsc_buffer * buffer )
static

Create data buffer.

Parameters
netvscNetVSC device
bufferData buffer
Return values
rcReturn status code

Definition at line 646 of file netvsc.c.

647 {
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}
#define ENOMEM
Not enough space.
Definition errno.h:578
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
uint32_t gpadl
GPADL ID.
Definition netvsc.h:3
int vmbus_establish_gpadl(struct vmbus_device *vmdev, void *data, size_t len)
Establish GPA descriptor list.
Definition vmbus.c:276
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
Definition vmbus.c:347
static void vmbus_unregister_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Unregister transfer page set.
Definition vmbus.h:615
static int vmbus_register_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Register transfer page set.
Definition vmbus.h:601

References buffer, DBGC, ENOMEM, gpadl, netvsc_device::name, rc, strerror(), ufree(), umalloc(), vmbus_establish_gpadl(), vmbus_gpadl_teardown(), vmbus_register_pages(), vmbus_unregister_pages(), and netvsc_device::vmdev.

Referenced by netvsc_open().

◆ netvsc_destroy_buffer()

void netvsc_destroy_buffer ( struct netvsc_device * netvsc,
struct netvsc_buffer * buffer )
static

Destroy data buffer.

Parameters
netvscNetVSC device
bufferData buffer

Definition at line 695 of file netvsc.c.

696 {
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}
VMBus "GPADL teardown" message.
Definition vmbus.h:193

References buffer, DBGC, netvsc_device::name, rc, strerror(), ufree(), vmbus_unregister_pages(), and netvsc_device::vmdev.

Referenced by netvsc_close(), and netvsc_open().

◆ netvsc_open()

int netvsc_open ( struct rndis_device * rndis)
static

Open device.

Parameters
rndisRNDIS device
Return values
rcReturn status code

Definition at line 725 of file netvsc.c.

725 {
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}
#define PAGE_SIZE
Page size.
Definition io.h:28
static int netvsc_revoke_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Revoke data buffer.
Definition netvsc.c:260
static int netvsc_establish_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Establish data buffer.
Definition netvsc.c:198
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 int netvsc_ndis_version(struct netvsc_device *netvsc)
Set NDIS version.
Definition netvsc.c:170
static int netvsc_create_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Create data buffer.
Definition netvsc.c:646
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_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
#define NETVSC_MTU
Maximum supported NetVSC message length.
Definition netvsc.h:13
struct netvsc_buffer rx
Receive buffer.
Definition netvsc.h:357
void vmbus_close(struct vmbus_device *vmdev)
Close VMBus channel.
Definition vmbus.c:524
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

References DBGC, netvsc_device::name, netvsc_channel_operations, netvsc_create_buffer(), netvsc_create_ring(), netvsc_destroy_buffer(), netvsc_destroy_ring(), netvsc_establish_buffer(), netvsc_initialise(), NETVSC_MTU, netvsc_ndis_version(), netvsc_revoke_buffer(), NULL, PAGE_SIZE, rndis_device::priv, rc, netvsc_device::rndis, netvsc_device::rx, strerror(), netvsc_device::tx, vmbus_close(), vmbus_open(), and netvsc_device::vmdev.

◆ netvsc_close()

void netvsc_close ( struct rndis_device * rndis)
static

Close device.

Parameters
rndisRNDIS device

Definition at line 775 of file netvsc.c.

775 {
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}
static void netvsc_cancel_transmit(struct netvsc_device *netvsc, struct io_buffer *iobuf, unsigned int tx_id)
Cancel transmission.
Definition netvsc.c:541

References netvsc_cancel_transmit(), netvsc_destroy_buffer(), netvsc_destroy_ring(), netvsc_revoke_buffer(), rndis_device::priv, netvsc_device::rndis, netvsc_device::rx, netvsc_device::tx, vmbus_close(), and netvsc_device::vmdev.

◆ netvsc_probe()

int netvsc_probe ( struct vmbus_device * vmdev)
static

Probe device.

Parameters
vmdevVMBus device
Return values
rcReturn status code

Definition at line 805 of file netvsc.c.

805 {
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}
static struct rndis_operations netvsc_operations
RNDIS operations.
Definition netvsc.c:792
static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
Transfer page set operations.
Definition netvsc.c:635
#define NETVSC_RX_REVOKE_MSG
NetVSC revoke receive data buffer message.
Definition netvsc.h:142
@ NETVSC_RX_REVOKE_XRID
Revoke receive buffer.
Definition netvsc.h:58
#define NETVSC_RX_BUF_LEN
RX data buffer length.
Definition netvsc.h:39
#define NETVSC_RX_ESTABLISH_MSG
NetVSC establish receive data buffer message.
Definition netvsc.h:136
#define NETVSC_RX_BUF_PAGESET
RX data buffer page set ID.
Definition netvsc.h:33
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 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
static void rndis_init(struct rndis_device *rndis, struct rndis_operations *op)
Initialise an RNDIS device.
Definition rndis.h:340
char name[40]
Name.
Definition device.h:79
struct device * dev
Underlying hardware device.
Definition netdevice.h:365
struct io_buffer * tx_iobufs[NETVSC_TX_NUM_DESC]
Transmit I/O buffers.
Definition netvsc.h:354
uint8_t tx_ids[NETVSC_TX_NUM_DESC]
Transmit buffer IDs.
Definition netvsc.h:352
struct net_device * netdev
Network device.
Definition rndis.h:320
struct device dev
Generic iPXE device.
Definition vmbus.h:477
static void vmbus_set_drvdata(struct vmbus_device *vmdev, void *priv)
Set VMBus device driver-private data.
Definition vmbus.h:559

References alloc_rndis(), DBGC, net_device::dev, vmbus_device::dev, ENOMEM, free_rndis(), device::name, netvsc_device::name, rndis_device::netdev, netvsc_operations, NETVSC_RX_BUF_LEN, NETVSC_RX_BUF_PAGESET, NETVSC_RX_ESTABLISH_MSG, NETVSC_RX_ESTABLISH_XRID, NETVSC_RX_REVOKE_MSG, NETVSC_RX_REVOKE_XRID, NETVSC_TX_NUM_DESC, netvsc_xfer_pages_operations, rndis_device::priv, rc, register_rndis(), netvsc_device::rndis, rndis_init(), netvsc_device::rx, strerror(), netvsc_device::tx, netvsc_device::tx_ids, netvsc_device::tx_iobufs, unregister_rndis(), vmbus_set_drvdata(), and netvsc_device::vmdev.

◆ netvsc_reset()

int netvsc_reset ( struct vmbus_device * vmdev)
static

Reset device.

Parameters
vmdevVMBus device
Return values
rcReturn status code

Definition at line 853 of file netvsc.c.

853 {
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}
static struct net_device * netdev
Definition gdbudp.c:53
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
A network device.
Definition netdevice.h:353

References DBGC, netvsc_device::name, netdev, rndis_device::netdev, netdev_close(), netdev_is_open(), netdev_open(), rndis_device::priv, rc, netvsc_device::rndis, strerror(), and vmbus_get_drvdata().

◆ netvsc_remove()

void netvsc_remove ( struct vmbus_device * vmdev)
static

Remove device.

Parameters
vmdevVMBus device

Definition at line 881 of file netvsc.c.

881 {
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}

References free_rndis(), unregister_rndis(), and vmbus_get_drvdata().

◆ VMBUS_ROM()

VMBUS_ROM ( "netvsc" ,
"Hyper-V NetVSC RNDIS virtual NIC"  )

Variable Documentation

◆ netvsc_channel_operations

struct vmbus_channel_operations netvsc_channel_operations
static
Initial value:
= {
.recv_control = netvsc_recv_control,
.recv_data = netvsc_recv_data,
.recv_completion = netvsc_recv_completion,
.recv_cancellation = netvsc_recv_cancellation,
}
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_recv_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
Definition netvsc.c:438
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_recv_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
Definition netvsc.c:299

VMBus channel operations.

Definition at line 449 of file netvsc.c.

449 {
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};

Referenced by netvsc_open().

◆ netvsc_xfer_pages_operations

struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
static
Initial value:
= {
}
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

Transfer page set operations.

Definition at line 635 of file netvsc.c.

635 {
636 .copy = netvsc_buffer_copy,
637};

Referenced by netvsc_probe().

◆ netvsc_operations

struct rndis_operations netvsc_operations
static
Initial value:
= {
.open = netvsc_open,
.close = netvsc_close,
.transmit = netvsc_transmit,
.poll = netvsc_poll,
}
static int netvsc_transmit(struct rndis_device *rndis, struct io_buffer *iobuf)
Transmit packet.
Definition netvsc.c:480
static void netvsc_poll(struct rndis_device *rndis)
Poll for completed and received packets.
Definition netvsc.c:461
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

RNDIS operations.

Definition at line 792 of file netvsc.c.

792 {
793 .open = netvsc_open,
794 .close = netvsc_close,
795 .transmit = netvsc_transmit,
796 .poll = netvsc_poll,
797};

Referenced by netvsc_probe().

◆ __vmbus_driver

struct vmbus_driver netvsc_driver __vmbus_driver
Initial value:
= {
.name = "netvsc",
.type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f,
0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ),
.probe = netvsc_probe,
.reset = netvsc_reset,
.remove = netvsc_remove,
}
static int netvsc_reset(struct vmbus_device *vmdev)
Reset device.
Definition netvsc.c:853
static void netvsc_remove(struct vmbus_device *vmdev)
Remove device.
Definition netvsc.c:881
static int netvsc_probe(struct vmbus_device *vmdev)
Probe device.
Definition netvsc.c:805
#define VMBUS_TYPE(a, b, c, d, e0, e1, e2, e3, e4, e5)
Construct VMBus type.
Definition vmbus.h:574

NetVSC driver.

Definition at line 892 of file netvsc.c.

892 {
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};