From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: Adding qemu as a submodule of KVMFORNFV This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY --- qemu/roms/ipxe/src/drivers/net/netvsc.c | 848 -------------------------------- 1 file changed, 848 deletions(-) delete mode 100644 qemu/roms/ipxe/src/drivers/net/netvsc.c (limited to 'qemu/roms/ipxe/src/drivers/net/netvsc.c') diff --git a/qemu/roms/ipxe/src/drivers/net/netvsc.c b/qemu/roms/ipxe/src/drivers/net/netvsc.c deleted file mode 100644 index d269cd63e..000000000 --- a/qemu/roms/ipxe/src/drivers/net/netvsc.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Copyright (C) 2014 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include "netvsc.h" - -/** - * Send control message and wait for completion - * - * @v netvsc NetVSC device - * @v xrid Relative transaction ID - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int netvsc_control ( struct netvsc_device *netvsc, unsigned int xrid, - const void *data, size_t len ) { - uint64_t xid = ( NETVSC_BASE_XID + xrid ); - unsigned int i; - int rc; - - /* Send control message */ - if ( ( rc = vmbus_send_control ( netvsc->vmdev, xid, data, len ) ) !=0){ - DBGC ( netvsc, "NETVSC %s could not send control message: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - /* Record transaction ID */ - netvsc->wait_xrid = xrid; - - /* Wait for operation to complete */ - for ( i = 0 ; i < NETVSC_MAX_WAIT_MS ; i++ ) { - - /* Check for completion */ - if ( ! netvsc->wait_xrid ) - return netvsc->wait_rc; - - /* Poll VMBus device */ - vmbus_poll ( netvsc->vmdev ); - - /* Delay for 1ms */ - mdelay ( 1 ); - } - - DBGC ( netvsc, "NETVSC %s timed out waiting for XRID %d\n", - netvsc->name, xrid ); - vmbus_dump_channel ( netvsc->vmdev ); - return -ETIMEDOUT; -} - -/** - * Handle generic completion - * - * @v netvsc NetVSC device - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int netvsc_completed ( struct netvsc_device *netvsc __unused, - const void *data __unused, size_t len __unused ) { - return 0; -} - -/** - * Initialise communication - * - * @v netvsc NetVSC device - * @ret rc Return status code - */ -static int netvsc_initialise ( struct netvsc_device *netvsc ) { - struct netvsc_init_message msg; - int rc; - - /* Construct message */ - memset ( &msg, 0, sizeof ( msg ) ); - msg.header.type = cpu_to_le32 ( NETVSC_INIT_MSG ); - msg.min = cpu_to_le32 ( NETVSC_VERSION_1 ); - msg.max = cpu_to_le32 ( NETVSC_VERSION_1 ); - - /* Send message and wait for completion */ - if ( ( rc = netvsc_control ( netvsc, NETVSC_INIT_XRID, &msg, - sizeof ( msg ) ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not initialise: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Handle initialisation completion - * - * @v netvsc NetVSC device - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int -netvsc_initialised ( struct netvsc_device *netvsc, const void *data, - size_t len ) { - const struct netvsc_init_completion *cmplt = data; - - /* Check completion */ - if ( len < sizeof ( *cmplt ) ) { - DBGC ( netvsc, "NETVSC %s underlength initialisation " - "completion (%zd bytes)\n", netvsc->name, len ); - return -EINVAL; - } - if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) { - DBGC ( netvsc, "NETVSC %s unexpected initialisation completion " - "type %d\n", netvsc->name, - le32_to_cpu ( cmplt->header.type ) ); - return -EPROTO; - } - if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) { - DBGC ( netvsc, "NETVSC %s initialisation failure status %d\n", - netvsc->name, le32_to_cpu ( cmplt->status ) ); - return -EPROTO; - } - - return 0; -} - -/** - * Set NDIS version - * - * @v netvsc NetVSC device - * @ret rc Return status code - */ -static int netvsc_ndis_version ( struct netvsc_device *netvsc ) { - struct netvsc_ndis_version_message msg; - int rc; - - /* Construct message */ - memset ( &msg, 0, sizeof ( msg ) ); - msg.header.type = cpu_to_le32 ( NETVSC_NDIS_VERSION_MSG ); - msg.major = cpu_to_le32 ( NETVSC_NDIS_MAJOR ); - msg.minor = cpu_to_le32 ( NETVSC_NDIS_MINOR ); - - /* Send message and wait for completion */ - if ( ( rc = netvsc_control ( netvsc, NETVSC_NDIS_VERSION_XRID, - &msg, sizeof ( msg ) ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not set NDIS version: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Establish data buffer - * - * @v netvsc NetVSC device - * @v buffer Data buffer - * @ret rc Return status code - */ -static int netvsc_establish_buffer ( struct netvsc_device *netvsc, - struct netvsc_buffer *buffer ) { - struct netvsc_establish_buffer_message msg; - int rc; - - /* Construct message */ - memset ( &msg, 0, sizeof ( msg ) ); - msg.header.type = cpu_to_le32 ( buffer->establish_type ); - msg.gpadl = cpu_to_le32 ( buffer->gpadl ); - msg.pageset = buffer->pages.pageset; /* Already protocol-endian */ - - /* Send message and wait for completion */ - if ( ( rc = netvsc_control ( netvsc, buffer->establish_xrid, &msg, - sizeof ( msg ) ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not establish buffer: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Handle establish receive data buffer completion - * - * @v netvsc NetVSC device - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc, - const void *data, size_t len ) { - const struct netvsc_rx_establish_buffer_completion *cmplt = data; - - /* Check completion */ - if ( len < sizeof ( *cmplt ) ) { - DBGC ( netvsc, "NETVSC %s underlength buffer completion (%zd " - "bytes)\n", netvsc->name, len ); - return -EINVAL; - } - if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) { - DBGC ( netvsc, "NETVSC %s unexpected buffer completion type " - "%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type)); - return -EPROTO; - } - if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) { - DBGC ( netvsc, "NETVSC %s buffer failure status %d\n", - netvsc->name, le32_to_cpu ( cmplt->status ) ); - return -EPROTO; - } - - return 0; -} - -/** - * Revoke data buffer - * - * @v netvsc NetVSC device - * @v buffer Data buffer - * @ret rc Return status code - */ -static int netvsc_revoke_buffer ( struct netvsc_device *netvsc, - struct netvsc_buffer *buffer ) { - struct netvsc_revoke_buffer_message msg; - int rc; - - /* Construct message */ - memset ( &msg, 0, sizeof ( msg ) ); - msg.header.type = cpu_to_le32 ( buffer->revoke_type ); - msg.pageset = buffer->pages.pageset; /* Already protocol-endian */ - - /* Send message and wait for completion */ - if ( ( rc = netvsc_control ( netvsc, buffer->revoke_xrid, - &msg, sizeof ( msg ) ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not revoke buffer: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Handle received control packet - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int netvsc_recv_control ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len ) { - struct rndis_device *rndis = vmbus_get_drvdata ( vmdev ); - struct netvsc_device *netvsc = rndis->priv; - - DBGC ( netvsc, "NETVSC %s received unsupported control packet " - "(%08llx):\n", netvsc->name, xid ); - DBGC_HDA ( netvsc, 0, data, len ); - return -ENOTSUP; -} - -/** - * Handle received data packet - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @v data Data - * @v len Length of data - * @v list List of I/O buffers - * @ret rc Return status code - */ -static int netvsc_recv_data ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len, - struct list_head *list ) { - struct rndis_device *rndis = vmbus_get_drvdata ( vmdev ); - struct netvsc_device *netvsc = rndis->priv; - const struct netvsc_rndis_message *msg = data; - struct io_buffer *iobuf; - struct io_buffer *tmp; - int rc; - - /* Sanity check */ - if ( len < sizeof ( *msg ) ) { - DBGC ( netvsc, "NETVSC %s received underlength RNDIS packet " - "(%zd bytes)\n", netvsc->name, len ); - rc = -EINVAL; - goto err_sanity; - } - if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) { - DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet " - "type %d\n", netvsc->name, - le32_to_cpu ( msg->header.type ) ); - rc = -EINVAL; - goto err_sanity; - } - - /* Send completion back to host */ - if ( ( rc = vmbus_send_completion ( vmdev, xid, NULL, 0 ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not send completion: %s\n", - netvsc->name, strerror ( rc ) ); - goto err_completion; - } - - /* Hand off to RNDIS */ - list_for_each_entry_safe ( iobuf, tmp, list, list ) { - list_del ( &iobuf->list ); - rndis_rx ( rndis, iob_disown ( iobuf ) ); - } - - return 0; - - err_completion: - err_sanity: - list_for_each_entry_safe ( iobuf, tmp, list, list ) { - list_del ( &iobuf->list ); - free_iob ( iobuf ); - } - return rc; -} - -/** - * Handle received completion packet - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @v data Data - * @v len Length of data - * @ret rc Return status code - */ -static int netvsc_recv_completion ( struct vmbus_device *vmdev, uint64_t xid, - const void *data, size_t len ) { - struct rndis_device *rndis = vmbus_get_drvdata ( vmdev ); - struct netvsc_device *netvsc = rndis->priv; - struct io_buffer *iobuf; - int ( * completion ) ( struct netvsc_device *netvsc, - const void *data, size_t len ); - unsigned int xrid = ( xid - NETVSC_BASE_XID ); - unsigned int tx_id; - int rc; - - /* Handle transmit completion, if applicable */ - tx_id = ( xrid - NETVSC_TX_BASE_XRID ); - if ( ( tx_id < NETVSC_TX_NUM_DESC ) && - ( ( iobuf = netvsc->tx.iobufs[tx_id] ) != NULL ) ) { - - /* Free buffer ID */ - netvsc->tx.iobufs[tx_id] = NULL; - netvsc->tx.ids[ ( netvsc->tx.id_cons++ ) & - ( netvsc->tx.count - 1 ) ] = tx_id; - - /* Hand back to RNDIS */ - rndis_tx_complete ( rndis, iobuf ); - return 0; - } - - /* Otherwise determine completion handler */ - if ( xrid == NETVSC_INIT_XRID ) { - completion = netvsc_initialised; - } else if ( xrid == NETVSC_RX_ESTABLISH_XRID ) { - completion = netvsc_rx_established_buffer; - } else if ( ( netvsc->wait_xrid != 0 ) && - ( xrid == netvsc->wait_xrid ) ) { - completion = netvsc_completed; - } else { - DBGC ( netvsc, "NETVSC %s received unexpected completion " - "(%08llx)\n", netvsc->name, xid ); - return -EPIPE; - } - - /* Hand off to completion handler */ - rc = completion ( netvsc, data, len ); - - /* Record completion handler result if applicable */ - if ( xrid == netvsc->wait_xrid ) { - netvsc->wait_xrid = 0; - netvsc->wait_rc = rc; - } - - return rc; -} - -/** - * Handle received cancellation packet - * - * @v vmdev VMBus device - * @v xid Transaction ID - * @ret rc Return status code - */ -static int netvsc_recv_cancellation ( struct vmbus_device *vmdev, - uint64_t xid ) { - struct rndis_device *rndis = vmbus_get_drvdata ( vmdev ); - struct netvsc_device *netvsc = rndis->priv; - - DBGC ( netvsc, "NETVSC %s received unsupported cancellation packet " - "(%08llx):\n", netvsc->name, xid ); - return -ENOTSUP; -} - -/** VMBus channel operations */ -static struct vmbus_channel_operations netvsc_channel_operations = { - .recv_control = netvsc_recv_control, - .recv_data = netvsc_recv_data, - .recv_completion = netvsc_recv_completion, - .recv_cancellation = netvsc_recv_cancellation, -}; - -/** - * Poll for completed and received packets - * - * @v rndis RNDIS device - */ -static void netvsc_poll ( struct rndis_device *rndis ) { - struct netvsc_device *netvsc = rndis->priv; - struct vmbus_device *vmdev = netvsc->vmdev; - - /* Poll VMBus device */ - while ( vmbus_has_data ( vmdev ) ) - vmbus_poll ( vmdev ); -} - -/** - * Transmit packet - * - * @v rndis RNDIS device - * @v iobuf I/O buffer - * @ret rc Return status code - * - * If this method returns success then the RNDIS device must - * eventually report completion via rndis_tx_complete(). - */ -static int netvsc_transmit ( struct rndis_device *rndis, - struct io_buffer *iobuf ) { - struct netvsc_device *netvsc = rndis->priv; - struct rndis_header *header = iobuf->data; - struct netvsc_rndis_message msg; - unsigned int tx_id; - unsigned int xrid; - uint64_t xid; - int rc; - - /* Sanity check */ - assert ( iob_len ( iobuf ) >= sizeof ( *header ) ); - assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) ); - - /* Check that we have space in the transmit ring */ - if ( netvsc_ring_is_full ( &netvsc->tx ) ) - return rndis_tx_defer ( rndis, iobuf ); - - /* Allocate buffer ID and calculate transaction ID */ - tx_id = netvsc->tx.ids[ netvsc->tx.id_prod & ( netvsc->tx.count - 1 ) ]; - assert ( netvsc->tx.iobufs[tx_id] == NULL ); - xrid = ( NETVSC_TX_BASE_XRID + tx_id ); - xid = ( NETVSC_BASE_XID + xrid ); - - /* Construct message */ - memset ( &msg, 0, sizeof ( msg ) ); - msg.header.type = cpu_to_le32 ( NETVSC_RNDIS_MSG ); - msg.channel = ( ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) ? - NETVSC_RNDIS_DATA : NETVSC_RNDIS_CONTROL ); - msg.buffer = cpu_to_le32 ( NETVSC_RNDIS_NO_BUFFER ); - - /* Send message */ - if ( ( rc = vmbus_send_data ( netvsc->vmdev, xid, &msg, sizeof ( msg ), - iobuf ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not send RNDIS message: %s\n", - netvsc->name, strerror ( rc ) ); - return rc; - } - - /* Store I/O buffer and consume buffer ID */ - netvsc->tx.iobufs[tx_id] = iobuf; - netvsc->tx.id_prod++; - - return 0; -} - -/** - * Cancel transmission - * - * @v netvsc NetVSC device - * @v iobuf I/O buffer - * @v tx_id Transmission ID - */ -static void netvsc_cancel_transmit ( struct netvsc_device *netvsc, - struct io_buffer *iobuf, - unsigned int tx_id ) { - unsigned int xrid; - uint64_t xid; - - /* Send cancellation */ - xrid = ( NETVSC_TX_BASE_XRID + tx_id ); - xid = ( NETVSC_BASE_XID + xrid ); - DBGC ( netvsc, "NETVSC %s cancelling transmission %#x\n", - netvsc->name, tx_id ); - vmbus_send_cancellation ( netvsc->vmdev, xid ); - - /* Report back to RNDIS */ - rndis_tx_complete_err ( netvsc->rndis, iobuf, -ECANCELED ); -} - -/** - * Create descriptor ring - * - * @v netvsc NetVSC device - * @v ring Descriptor ring - * @ret rc Return status code - */ -static int netvsc_create_ring ( struct netvsc_device *netvsc __unused, - struct netvsc_ring *ring ) { - unsigned int i; - - /* Initialise buffer ID ring */ - for ( i = 0 ; i < ring->count ; i++ ) { - ring->ids[i] = i; - assert ( ring->iobufs[i] == NULL ); - } - ring->id_prod = 0; - ring->id_cons = 0; - - return 0; -} - -/** - * Destroy descriptor ring - * - * @v netvsc NetVSC device - * @v ring Descriptor ring - * @v discard Method used to discard outstanding buffer, or NULL - */ -static void netvsc_destroy_ring ( struct netvsc_device *netvsc, - struct netvsc_ring *ring, - void ( * discard ) ( struct netvsc_device *, - struct io_buffer *, - unsigned int ) ) { - struct io_buffer *iobuf; - unsigned int i; - - /* Flush any outstanding buffers */ - for ( i = 0 ; i < ring->count ; i++ ) { - iobuf = ring->iobufs[i]; - if ( ! iobuf ) - continue; - ring->iobufs[i] = NULL; - ring->ids[ ( ring->id_cons++ ) & ( ring->count - 1 ) ] = i; - if ( discard ) - discard ( netvsc, iobuf, i ); - } - - /* Sanity check */ - assert ( netvsc_ring_is_empty ( ring ) ); -} - -/** - * Copy data from data buffer - * - * @v pages Transfer page set - * @v data Data buffer - * @v offset Offset within page set - * @v len Length within page set - * @ret rc Return status code - */ -static int netvsc_buffer_copy ( struct vmbus_xfer_pages *pages, void *data, - size_t offset, size_t len ) { - struct netvsc_buffer *buffer = - container_of ( pages, struct netvsc_buffer, pages ); - - /* Sanity check */ - if ( ( offset > buffer->len ) || ( len > ( buffer->len - offset ) ) ) - return -ERANGE; - - /* Copy data from buffer */ - copy_from_user ( data, buffer->data, offset, len ); - - return 0; -} - -/** Transfer page set operations */ -static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations = { - .copy = netvsc_buffer_copy, -}; - -/** - * Create data buffer - * - * @v netvsc NetVSC device - * @v buffer Data buffer - * @ret rc Return status code - */ -static int netvsc_create_buffer ( struct netvsc_device *netvsc, - struct netvsc_buffer *buffer ) { - struct vmbus_device *vmdev = netvsc->vmdev; - int gpadl; - int rc; - - /* Allocate receive buffer */ - buffer->data = umalloc ( buffer->len ); - if ( ! buffer->data ) { - DBGC ( netvsc, "NETVSC %s could not allocate %zd-byte buffer\n", - netvsc->name, buffer->len ); - rc = -ENOMEM; - goto err_alloc; - } - - /* Establish GPA descriptor list */ - gpadl = vmbus_establish_gpadl ( vmdev, buffer->data, buffer->len ); - if ( gpadl < 0 ) { - rc = gpadl; - DBGC ( netvsc, "NETVSC %s could not establish GPADL: %s\n", - netvsc->name, strerror ( rc ) ); - goto err_establish_gpadl; - } - buffer->gpadl = gpadl; - - /* Register transfer page set */ - if ( ( rc = vmbus_register_pages ( vmdev, &buffer->pages ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not register transfer pages: " - "%s\n", netvsc->name, strerror ( rc ) ); - goto err_register_pages; - } - - return 0; - - vmbus_unregister_pages ( vmdev, &buffer->pages ); - err_register_pages: - vmbus_gpadl_teardown ( vmdev, gpadl ); - err_establish_gpadl: - ufree ( buffer->data ); - err_alloc: - return rc; -} - -/** - * Destroy data buffer - * - * @v netvsc NetVSC device - * @v buffer Data buffer - */ -static void netvsc_destroy_buffer ( struct netvsc_device *netvsc, - struct netvsc_buffer *buffer ) { - struct vmbus_device *vmdev = netvsc->vmdev; - int rc; - - /* Unregister transfer pages */ - vmbus_unregister_pages ( vmdev, &buffer->pages ); - - /* Tear down GPA descriptor list */ - if ( ( rc = vmbus_gpadl_teardown ( vmdev, buffer->gpadl ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not tear down GPADL: %s\n", - netvsc->name, strerror ( rc ) ); - /* Death is imminent. The host may well continue to - * write to the data buffer. The best we can do is - * leak memory for now and hope that the host doesn't - * write to this region after we load an OS. - */ - return; - } - - /* Free buffer */ - ufree ( buffer->data ); -} - -/** - * Open device - * - * @v rndis RNDIS device - * @ret rc Return status code - */ -static int netvsc_open ( struct rndis_device *rndis ) { - struct netvsc_device *netvsc = rndis->priv; - int rc; - - /* Initialise receive buffer */ - if ( ( rc = netvsc_create_buffer ( netvsc, &netvsc->rx ) ) != 0 ) - goto err_create_rx; - - /* Open channel */ - if ( ( rc = vmbus_open ( netvsc->vmdev, &netvsc_channel_operations, - PAGE_SIZE, PAGE_SIZE, NETVSC_MTU ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not open VMBus: %s\n", - netvsc->name, strerror ( rc ) ); - goto err_vmbus_open; - } - - /* Initialise communication with NetVSP */ - if ( ( rc = netvsc_initialise ( netvsc ) ) != 0 ) - goto err_initialise; - if ( ( rc = netvsc_ndis_version ( netvsc ) ) != 0 ) - goto err_ndis_version; - - /* Initialise transmit ring */ - if ( ( rc = netvsc_create_ring ( netvsc, &netvsc->tx ) ) != 0 ) - goto err_create_tx; - - /* Establish receive buffer */ - if ( ( rc = netvsc_establish_buffer ( netvsc, &netvsc->rx ) ) != 0 ) - goto err_establish_rx; - - return 0; - - netvsc_revoke_buffer ( netvsc, &netvsc->rx ); - err_establish_rx: - netvsc_destroy_ring ( netvsc, &netvsc->tx, NULL ); - err_create_tx: - err_ndis_version: - err_initialise: - vmbus_close ( netvsc->vmdev ); - err_vmbus_open: - netvsc_destroy_buffer ( netvsc, &netvsc->rx ); - err_create_rx: - return rc; -} - -/** - * Close device - * - * @v rndis RNDIS device - */ -static void netvsc_close ( struct rndis_device *rndis ) { - struct netvsc_device *netvsc = rndis->priv; - - /* Revoke receive buffer */ - netvsc_revoke_buffer ( netvsc, &netvsc->rx ); - - /* Destroy transmit ring */ - netvsc_destroy_ring ( netvsc, &netvsc->tx, netvsc_cancel_transmit ); - - /* Close channel */ - vmbus_close ( netvsc->vmdev ); - - /* Destroy receive buffer */ - netvsc_destroy_buffer ( netvsc, &netvsc->rx ); -} - -/** RNDIS operations */ -static struct rndis_operations netvsc_operations = { - .open = netvsc_open, - .close = netvsc_close, - .transmit = netvsc_transmit, - .poll = netvsc_poll, -}; - -/** - * Probe device - * - * @v vmdev VMBus device - * @ret rc Return status code - */ -static int netvsc_probe ( struct vmbus_device *vmdev ) { - struct netvsc_device *netvsc; - struct rndis_device *rndis; - int rc; - - /* Allocate and initialise structure */ - rndis = alloc_rndis ( sizeof ( *netvsc ) ); - if ( ! rndis ) { - rc = -ENOMEM; - goto err_alloc; - } - rndis_init ( rndis, &netvsc_operations ); - rndis->netdev->dev = &vmdev->dev; - netvsc = rndis->priv; - netvsc->vmdev = vmdev; - netvsc->rndis = rndis; - netvsc->name = vmdev->dev.name; - netvsc_init_ring ( &netvsc->tx, NETVSC_TX_NUM_DESC, - netvsc->tx_iobufs, netvsc->tx_ids ); - netvsc_init_buffer ( &netvsc->rx, NETVSC_RX_BUF_PAGESET, - &netvsc_xfer_pages_operations, - NETVSC_RX_ESTABLISH_MSG, NETVSC_RX_ESTABLISH_XRID, - NETVSC_RX_REVOKE_MSG, NETVSC_RX_REVOKE_XRID, - NETVSC_RX_BUF_LEN ); - vmbus_set_drvdata ( vmdev, rndis ); - - /* Register RNDIS device */ - if ( ( rc = register_rndis ( rndis ) ) != 0 ) { - DBGC ( netvsc, "NETVSC %s could not register: %s\n", - netvsc->name, strerror ( rc ) ); - goto err_register; - } - - return 0; - - unregister_rndis ( rndis ); - err_register: - free_rndis ( rndis ); - err_alloc: - return rc; -} - -/** - * Remove device - * - * @v vmdev VMBus device - */ -static void netvsc_remove ( struct vmbus_device *vmdev ) { - struct rndis_device *rndis = vmbus_get_drvdata ( vmdev ); - - /* Unregister RNDIS device */ - unregister_rndis ( rndis ); - - /* Free RNDIS device */ - free_rndis ( rndis ); -} - -/** NetVSC driver */ -struct vmbus_driver netvsc_driver __vmbus_driver = { - .name = "netvsc", - .type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f, - 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ), - .probe = netvsc_probe, - .remove = netvsc_remove, -}; -- cgit 1.2.3-korg