iPXE
netvsc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /** @file
00027  *
00028  * Hyper-V network virtual service client
00029  *
00030  * The network virtual service client (NetVSC) connects to the network
00031  * virtual service provider (NetVSP) via the Hyper-V virtual machine
00032  * bus (VMBus).  It provides a transport layer for RNDIS packets.
00033  */
00034 
00035 #include <errno.h>
00036 #include <unistd.h>
00037 #include <byteswap.h>
00038 #include <ipxe/umalloc.h>
00039 #include <ipxe/rndis.h>
00040 #include <ipxe/vmbus.h>
00041 #include "netvsc.h"
00042 
00043 /**
00044  * Send control message and wait for completion
00045  *
00046  * @v netvsc            NetVSC device
00047  * @v xrid              Relative transaction ID
00048  * @v data              Data
00049  * @v len               Length of data
00050  * @ret rc              Return status code
00051  */
00052 static int netvsc_control ( struct netvsc_device *netvsc, unsigned int xrid,
00053                             const void *data, size_t len ) {
00054         uint64_t xid = ( NETVSC_BASE_XID + xrid );
00055         unsigned int i;
00056         int rc;
00057 
00058         /* Send control message */
00059         if ( ( rc = vmbus_send_control ( netvsc->vmdev, xid, data, len ) ) !=0){
00060                 DBGC ( netvsc, "NETVSC %s could not send control message: %s\n",
00061                        netvsc->name, strerror ( rc ) );
00062                 return rc;
00063         }
00064 
00065         /* Record transaction ID */
00066         netvsc->wait_xrid = xrid;
00067 
00068         /* Wait for operation to complete */
00069         for ( i = 0 ; i < NETVSC_MAX_WAIT_MS ; i++ ) {
00070 
00071                 /* Check for completion */
00072                 if ( ! netvsc->wait_xrid )
00073                         return netvsc->wait_rc;
00074 
00075                 /* Poll VMBus device */
00076                 vmbus_poll ( netvsc->vmdev );
00077 
00078                 /* Delay for 1ms */
00079                 mdelay ( 1 );
00080         }
00081 
00082         DBGC ( netvsc, "NETVSC %s timed out waiting for XRID %d\n",
00083                netvsc->name, xrid );
00084         vmbus_dump_channel ( netvsc->vmdev );
00085         return -ETIMEDOUT;
00086 }
00087 
00088 /**
00089  * Handle generic completion
00090  *
00091  * @v netvsc            NetVSC device
00092  * @v data              Data
00093  * @v len               Length of data
00094  * @ret rc              Return status code
00095  */
00096 static int netvsc_completed ( struct netvsc_device *netvsc __unused,
00097                               const void *data __unused, size_t len __unused ) {
00098         return 0;
00099 }
00100 
00101 /**
00102  * Initialise communication
00103  *
00104  * @v netvsc            NetVSC device
00105  * @ret rc              Return status code
00106  */
00107 static int netvsc_initialise ( struct netvsc_device *netvsc ) {
00108         struct netvsc_init_message msg;
00109         int rc;
00110 
00111         /* Construct message */
00112         memset ( &msg, 0, sizeof ( msg ) );
00113         msg.header.type = cpu_to_le32 ( NETVSC_INIT_MSG );
00114         msg.min = cpu_to_le32 ( NETVSC_VERSION_1 );
00115         msg.max = cpu_to_le32 ( NETVSC_VERSION_1 );
00116 
00117         /* Send message and wait for completion */
00118         if ( ( rc = netvsc_control ( netvsc, NETVSC_INIT_XRID, &msg,
00119                                      sizeof ( msg ) ) ) != 0 ) {
00120                 DBGC ( netvsc, "NETVSC %s could not initialise: %s\n",
00121                        netvsc->name, strerror ( rc ) );
00122                 return rc;
00123         }
00124 
00125         return 0;
00126 }
00127 
00128 /**
00129  * Handle initialisation completion
00130  *
00131  * @v netvsc            NetVSC device
00132  * @v data              Data
00133  * @v len               Length of data
00134  * @ret rc              Return status code
00135  */
00136 static int
00137 netvsc_initialised ( struct netvsc_device *netvsc, const void *data,
00138                      size_t len ) {
00139         const struct netvsc_init_completion *cmplt = data;
00140 
00141         /* Check completion */
00142         if ( len < sizeof ( *cmplt ) ) {
00143                 DBGC ( netvsc, "NETVSC %s underlength initialisation "
00144                        "completion (%zd bytes)\n", netvsc->name, len );
00145                 return -EINVAL;
00146         }
00147         if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
00148                 DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
00149                        "type %d\n", netvsc->name,
00150                        le32_to_cpu ( cmplt->header.type ) );
00151                 return -EPROTO;
00152         }
00153         if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
00154                 DBGC ( netvsc, "NETVSC %s initialisation failure status %d\n",
00155                        netvsc->name, le32_to_cpu ( cmplt->status ) );
00156                 return -EPROTO;
00157         }
00158 
00159         return 0;
00160 }
00161 
00162 /**
00163  * Set NDIS version
00164  *
00165  * @v netvsc            NetVSC device
00166  * @ret rc              Return status code
00167  */
00168 static int netvsc_ndis_version ( struct netvsc_device *netvsc ) {
00169         struct netvsc_ndis_version_message msg;
00170         int rc;
00171 
00172         /* Construct message */
00173         memset ( &msg, 0, sizeof ( msg ) );
00174         msg.header.type = cpu_to_le32 ( NETVSC_NDIS_VERSION_MSG );
00175         msg.major = cpu_to_le32 ( NETVSC_NDIS_MAJOR );
00176         msg.minor = cpu_to_le32 ( NETVSC_NDIS_MINOR );
00177 
00178         /* Send message and wait for completion */
00179         if ( ( rc = netvsc_control ( netvsc, NETVSC_NDIS_VERSION_XRID,
00180                                      &msg, sizeof ( msg ) ) ) != 0 ) {
00181                 DBGC ( netvsc, "NETVSC %s could not set NDIS version: %s\n",
00182                        netvsc->name, strerror ( rc ) );
00183                 return rc;
00184         }
00185 
00186         return 0;
00187 }
00188 
00189 /**
00190  * Establish data buffer
00191  *
00192  * @v netvsc            NetVSC device
00193  * @v buffer            Data buffer
00194  * @ret rc              Return status code
00195  */
00196 static int netvsc_establish_buffer ( struct netvsc_device *netvsc,
00197                                      struct netvsc_buffer *buffer ) {
00198         struct netvsc_establish_buffer_message msg;
00199         int rc;
00200 
00201         /* Construct message */
00202         memset ( &msg, 0, sizeof ( msg ) );
00203         msg.header.type = cpu_to_le32 ( buffer->establish_type );
00204         msg.gpadl = cpu_to_le32 ( buffer->gpadl );
00205         msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
00206 
00207         /* Send message and wait for completion */
00208         if ( ( rc = netvsc_control ( netvsc, buffer->establish_xrid, &msg,
00209                                      sizeof ( msg ) ) ) != 0 ) {
00210                 DBGC ( netvsc, "NETVSC %s could not establish buffer: %s\n",
00211                        netvsc->name, strerror ( rc ) );
00212                 return rc;
00213         }
00214 
00215         return 0;
00216 }
00217 
00218 /**
00219  * Handle establish receive data buffer completion
00220  *
00221  * @v netvsc            NetVSC device
00222  * @v data              Data
00223  * @v len               Length of data
00224  * @ret rc              Return status code
00225  */
00226 static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
00227                                           const void *data, size_t len ) {
00228         const struct netvsc_rx_establish_buffer_completion *cmplt = data;
00229 
00230         /* Check completion */
00231         if ( len < sizeof ( *cmplt ) ) {
00232                 DBGC ( netvsc, "NETVSC %s underlength buffer completion (%zd "
00233                        "bytes)\n", netvsc->name, len );
00234                 return -EINVAL;
00235         }
00236         if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
00237                 DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
00238                        "%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
00239                 return -EPROTO;
00240         }
00241         if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
00242                 DBGC ( netvsc, "NETVSC %s buffer failure status %d\n",
00243                        netvsc->name, le32_to_cpu ( cmplt->status ) );
00244                 return -EPROTO;
00245         }
00246 
00247         return 0;
00248 }
00249 
00250 /**
00251  * Revoke data buffer
00252  *
00253  * @v netvsc            NetVSC device
00254  * @v buffer            Data buffer
00255  * @ret rc              Return status code
00256  */
00257 static int netvsc_revoke_buffer ( struct netvsc_device *netvsc,
00258                                   struct netvsc_buffer *buffer ) {
00259         struct netvsc_revoke_buffer_message msg;
00260         int rc;
00261 
00262         /* If the buffer's GPADL is obsolete (i.e. was created before
00263          * the most recent Hyper-V reset), then we will never receive
00264          * a response to the revoke message.  Since the GPADL is
00265          * already destroyed as far as the hypervisor is concerned, no
00266          * further action is required.
00267          */
00268         if ( netvsc_is_obsolete ( netvsc ) )
00269                 return 0;
00270 
00271         /* Construct message */
00272         memset ( &msg, 0, sizeof ( msg ) );
00273         msg.header.type = cpu_to_le32 ( buffer->revoke_type );
00274         msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
00275 
00276         /* Send message and wait for completion */
00277         if ( ( rc = netvsc_control ( netvsc, buffer->revoke_xrid,
00278                                      &msg, sizeof ( msg ) ) ) != 0 ) {
00279                 DBGC ( netvsc, "NETVSC %s could not revoke buffer: %s\n",
00280                        netvsc->name, strerror ( rc ) );
00281                 return rc;
00282         }
00283 
00284         return 0;
00285 }
00286 
00287 /**
00288  * Handle received control packet
00289  *
00290  * @v vmdev             VMBus device
00291  * @v xid               Transaction ID
00292  * @v data              Data
00293  * @v len               Length of data
00294  * @ret rc              Return status code
00295  */
00296 static int netvsc_recv_control ( struct vmbus_device *vmdev, uint64_t xid,
00297                                  const void *data, size_t len ) {
00298         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00299         struct netvsc_device *netvsc = rndis->priv;
00300 
00301         DBGC ( netvsc, "NETVSC %s received unsupported control packet "
00302                "(%08llx):\n", netvsc->name, xid );
00303         DBGC_HDA ( netvsc, 0, data, len );
00304         return -ENOTSUP;
00305 }
00306 
00307 /**
00308  * Handle received data packet
00309  *
00310  * @v vmdev             VMBus device
00311  * @v xid               Transaction ID
00312  * @v data              Data
00313  * @v len               Length of data
00314  * @v list              List of I/O buffers
00315  * @ret rc              Return status code
00316  */
00317 static int netvsc_recv_data ( struct vmbus_device *vmdev, uint64_t xid,
00318                               const void *data, size_t len,
00319                               struct list_head *list ) {
00320         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00321         struct netvsc_device *netvsc = rndis->priv;
00322         const struct netvsc_rndis_message *msg = data;
00323         struct io_buffer *iobuf;
00324         struct io_buffer *tmp;
00325         int rc;
00326 
00327         /* Sanity check */
00328         if ( len < sizeof ( *msg ) ) {
00329                 DBGC ( netvsc, "NETVSC %s received underlength RNDIS packet "
00330                        "(%zd bytes)\n", netvsc->name, len );
00331                 rc = -EINVAL;
00332                 goto err_sanity;
00333         }
00334         if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
00335                 DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
00336                        "type %d\n", netvsc->name,
00337                        le32_to_cpu ( msg->header.type ) );
00338                 rc = -EINVAL;
00339                 goto err_sanity;
00340         }
00341 
00342         /* Send completion back to host */
00343         if ( ( rc = vmbus_send_completion ( vmdev, xid, NULL, 0 ) ) != 0 ) {
00344                 DBGC ( netvsc, "NETVSC %s could not send completion: %s\n",
00345                        netvsc->name, strerror ( rc ) );
00346                 goto err_completion;
00347         }
00348 
00349         /* Hand off to RNDIS */
00350         list_for_each_entry_safe ( iobuf, tmp, list, list ) {
00351                 list_del ( &iobuf->list );
00352                 rndis_rx ( rndis, iob_disown ( iobuf ) );
00353         }
00354 
00355         return 0;
00356 
00357  err_completion:
00358  err_sanity:
00359         list_for_each_entry_safe ( iobuf, tmp, list, list ) {
00360                 list_del ( &iobuf->list );
00361                 free_iob ( iobuf );
00362         }
00363         return rc;
00364 }
00365 
00366 /**
00367  * Handle received completion packet
00368  *
00369  * @v vmdev             VMBus device
00370  * @v xid               Transaction ID
00371  * @v data              Data
00372  * @v len               Length of data
00373  * @ret rc              Return status code
00374  */
00375 static int netvsc_recv_completion ( struct vmbus_device *vmdev, uint64_t xid,
00376                                     const void *data, size_t len ) {
00377         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00378         struct netvsc_device *netvsc = rndis->priv;
00379         struct io_buffer *iobuf;
00380         int ( * completion ) ( struct netvsc_device *netvsc,
00381                                const void *data, size_t len );
00382         unsigned int xrid = ( xid - NETVSC_BASE_XID );
00383         unsigned int tx_id;
00384         int rc;
00385 
00386         /* Handle transmit completion, if applicable */
00387         tx_id = ( xrid - NETVSC_TX_BASE_XRID );
00388         if ( ( tx_id < NETVSC_TX_NUM_DESC ) &&
00389              ( ( iobuf = netvsc->tx.iobufs[tx_id] ) != NULL ) ) {
00390 
00391                 /* Free buffer ID */
00392                 netvsc->tx.iobufs[tx_id] = NULL;
00393                 netvsc->tx.ids[ ( netvsc->tx.id_cons++ ) &
00394                                 ( netvsc->tx.count - 1 ) ] = tx_id;
00395 
00396                 /* Hand back to RNDIS */
00397                 rndis_tx_complete ( rndis, iobuf );
00398                 return 0;
00399         }
00400 
00401         /* Otherwise determine completion handler */
00402         if ( xrid == NETVSC_INIT_XRID ) {
00403                 completion = netvsc_initialised;
00404         } else if ( xrid == NETVSC_RX_ESTABLISH_XRID ) {
00405                 completion = netvsc_rx_established_buffer;
00406         } else if ( ( netvsc->wait_xrid != 0 ) &&
00407                     ( xrid == netvsc->wait_xrid ) ) {
00408                 completion = netvsc_completed;
00409         } else {
00410                 DBGC ( netvsc, "NETVSC %s received unexpected completion "
00411                        "(%08llx)\n", netvsc->name, xid );
00412                 return -EPIPE;
00413         }
00414 
00415         /* Hand off to completion handler */
00416         rc = completion ( netvsc, data, len );
00417 
00418         /* Record completion handler result if applicable */
00419         if ( xrid == netvsc->wait_xrid ) {
00420                 netvsc->wait_xrid = 0;
00421                 netvsc->wait_rc = rc;
00422         }
00423 
00424         return rc;
00425 }
00426 
00427 /**
00428  * Handle received cancellation packet
00429  *
00430  * @v vmdev             VMBus device
00431  * @v xid               Transaction ID
00432  * @ret rc              Return status code
00433  */
00434 static int netvsc_recv_cancellation ( struct vmbus_device *vmdev,
00435                                       uint64_t xid ) {
00436         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00437         struct netvsc_device *netvsc = rndis->priv;
00438 
00439         DBGC ( netvsc, "NETVSC %s received unsupported cancellation packet "
00440                "(%08llx):\n", netvsc->name, xid );
00441         return -ENOTSUP;
00442 }
00443 
00444 /** VMBus channel operations */
00445 static struct vmbus_channel_operations netvsc_channel_operations = {
00446         .recv_control = netvsc_recv_control,
00447         .recv_data = netvsc_recv_data,
00448         .recv_completion = netvsc_recv_completion,
00449         .recv_cancellation = netvsc_recv_cancellation,
00450 };
00451 
00452 /**
00453  * Poll for completed and received packets
00454  *
00455  * @v rndis             RNDIS device
00456  */
00457 static void netvsc_poll ( struct rndis_device *rndis ) {
00458         struct netvsc_device *netvsc = rndis->priv;
00459         struct vmbus_device *vmdev = netvsc->vmdev;
00460 
00461         /* Poll VMBus device */
00462         while ( vmbus_has_data ( vmdev ) )
00463                 vmbus_poll ( vmdev );
00464 }
00465 
00466 /**
00467  * Transmit packet
00468  *
00469  * @v rndis             RNDIS device
00470  * @v iobuf             I/O buffer
00471  * @ret rc              Return status code
00472  *
00473  * If this method returns success then the RNDIS device must
00474  * eventually report completion via rndis_tx_complete().
00475  */
00476 static int netvsc_transmit ( struct rndis_device *rndis,
00477                              struct io_buffer *iobuf ) {
00478         struct netvsc_device *netvsc = rndis->priv;
00479         struct rndis_header *header = iobuf->data;
00480         struct netvsc_rndis_message msg;
00481         unsigned int tx_id;
00482         unsigned int xrid;
00483         uint64_t xid;
00484         int rc;
00485 
00486         /* If the device is obsolete (i.e. was opened before the most
00487          * recent Hyper-V reset), then we will never receive transmit
00488          * completions.  Fail transmissions immediately to minimise
00489          * the delay in closing and reopening the device.
00490          */
00491         if ( netvsc_is_obsolete ( netvsc ) )
00492                 return -EPIPE;
00493 
00494         /* Sanity check */
00495         assert ( iob_len ( iobuf ) >= sizeof ( *header ) );
00496         assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) );
00497 
00498         /* Check that we have space in the transmit ring */
00499         if ( netvsc_ring_is_full ( &netvsc->tx ) )
00500                 return rndis_tx_defer ( rndis, iobuf );
00501 
00502         /* Allocate buffer ID and calculate transaction ID */
00503         tx_id = netvsc->tx.ids[ netvsc->tx.id_prod & ( netvsc->tx.count - 1 ) ];
00504         assert ( netvsc->tx.iobufs[tx_id] == NULL );
00505         xrid = ( NETVSC_TX_BASE_XRID + tx_id );
00506         xid = ( NETVSC_BASE_XID + xrid );
00507 
00508         /* Construct message */
00509         memset ( &msg, 0, sizeof ( msg ) );
00510         msg.header.type = cpu_to_le32 ( NETVSC_RNDIS_MSG );
00511         msg.channel = ( ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) ?
00512                         NETVSC_RNDIS_DATA : NETVSC_RNDIS_CONTROL );
00513         msg.buffer = cpu_to_le32 ( NETVSC_RNDIS_NO_BUFFER );
00514 
00515         /* Send message */
00516         if ( ( rc = vmbus_send_data ( netvsc->vmdev, xid, &msg, sizeof ( msg ),
00517                                       iobuf ) ) != 0 ) {
00518                 DBGC ( netvsc, "NETVSC %s could not send RNDIS message: %s\n",
00519                        netvsc->name, strerror ( rc ) );
00520                 return rc;
00521         }
00522 
00523         /* Store I/O buffer and consume buffer ID */
00524         netvsc->tx.iobufs[tx_id] = iobuf;
00525         netvsc->tx.id_prod++;
00526 
00527         return 0;
00528 }
00529 
00530 /**
00531  * Cancel transmission
00532  *
00533  * @v netvsc            NetVSC device
00534  * @v iobuf             I/O buffer
00535  * @v tx_id             Transmission ID
00536  */
00537 static void netvsc_cancel_transmit ( struct netvsc_device *netvsc,
00538                                      struct io_buffer *iobuf,
00539                                      unsigned int tx_id ) {
00540         unsigned int xrid;
00541         uint64_t xid;
00542 
00543         /* Send cancellation */
00544         xrid = ( NETVSC_TX_BASE_XRID + tx_id );
00545         xid = ( NETVSC_BASE_XID + xrid );
00546         DBGC ( netvsc, "NETVSC %s cancelling transmission %#x\n",
00547                netvsc->name, tx_id );
00548         vmbus_send_cancellation ( netvsc->vmdev, xid );
00549 
00550         /* Report back to RNDIS */
00551         rndis_tx_complete_err ( netvsc->rndis, iobuf, -ECANCELED );
00552 }
00553 
00554 /**
00555  * Create descriptor ring
00556  *
00557  * @v netvsc            NetVSC device
00558  * @v ring              Descriptor ring
00559  * @ret rc              Return status code
00560  */
00561 static int netvsc_create_ring ( struct netvsc_device *netvsc __unused,
00562                                 struct netvsc_ring *ring ) {
00563         unsigned int i;
00564 
00565         /* Initialise buffer ID ring */
00566         for ( i = 0 ; i < ring->count ; i++ ) {
00567                 ring->ids[i] = i;
00568                 assert ( ring->iobufs[i] == NULL );
00569         }
00570         ring->id_prod = 0;
00571         ring->id_cons = 0;
00572 
00573         return 0;
00574 }
00575 
00576 /**
00577  * Destroy descriptor ring
00578  *
00579  * @v netvsc            NetVSC device
00580  * @v ring              Descriptor ring
00581  * @v discard           Method used to discard outstanding buffer, or NULL
00582  */
00583 static void netvsc_destroy_ring ( struct netvsc_device *netvsc,
00584                                   struct netvsc_ring *ring,
00585                                   void ( * discard ) ( struct netvsc_device *,
00586                                                        struct io_buffer *,
00587                                                        unsigned int ) ) {
00588         struct io_buffer *iobuf;
00589         unsigned int i;
00590 
00591         /* Flush any outstanding buffers */
00592         for ( i = 0 ; i < ring->count ; i++ ) {
00593                 iobuf = ring->iobufs[i];
00594                 if ( ! iobuf )
00595                         continue;
00596                 ring->iobufs[i] = NULL;
00597                 ring->ids[ ( ring->id_cons++ ) & ( ring->count - 1 ) ] = i;
00598                 if ( discard )
00599                         discard ( netvsc, iobuf, i );
00600         }
00601 
00602         /* Sanity check */
00603         assert ( netvsc_ring_is_empty ( ring ) );
00604 }
00605 
00606 /**
00607  * Copy data from data buffer
00608  *
00609  * @v pages             Transfer page set
00610  * @v data              Data buffer
00611  * @v offset            Offset within page set
00612  * @v len               Length within page set
00613  * @ret rc              Return status code
00614  */
00615 static int netvsc_buffer_copy ( struct vmbus_xfer_pages *pages, void *data,
00616                                 size_t offset, size_t len ) {
00617         struct netvsc_buffer *buffer =
00618                 container_of ( pages, struct netvsc_buffer, pages );
00619 
00620         /* Sanity check */
00621         if ( ( offset > buffer->len ) || ( len > ( buffer->len - offset ) ) )
00622                 return -ERANGE;
00623 
00624         /* Copy data from buffer */
00625         copy_from_user ( data, buffer->data, offset, len );
00626 
00627         return 0;
00628 }
00629 
00630 /** Transfer page set operations */
00631 static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations = {
00632         .copy = netvsc_buffer_copy,
00633 };
00634 
00635 /**
00636  * Create data buffer
00637  *
00638  * @v netvsc            NetVSC device
00639  * @v buffer            Data buffer
00640  * @ret rc              Return status code
00641  */
00642 static int netvsc_create_buffer ( struct netvsc_device *netvsc,
00643                                   struct netvsc_buffer *buffer ) {
00644         struct vmbus_device *vmdev = netvsc->vmdev;
00645         int gpadl;
00646         int rc;
00647 
00648         /* Allocate receive buffer */
00649         buffer->data = umalloc ( buffer->len );
00650         if ( ! buffer->data ) {
00651                 DBGC ( netvsc, "NETVSC %s could not allocate %zd-byte buffer\n",
00652                        netvsc->name, buffer->len );
00653                 rc = -ENOMEM;
00654                 goto err_alloc;
00655         }
00656 
00657         /* Establish GPA descriptor list */
00658         gpadl = vmbus_establish_gpadl ( vmdev, buffer->data, buffer->len );
00659         if ( gpadl < 0 ) {
00660                 rc = gpadl;
00661                 DBGC ( netvsc, "NETVSC %s could not establish GPADL: %s\n",
00662                        netvsc->name, strerror ( rc ) );
00663                 goto err_establish_gpadl;
00664         }
00665         buffer->gpadl = gpadl;
00666 
00667         /* Register transfer page set */
00668         if ( ( rc = vmbus_register_pages ( vmdev, &buffer->pages ) ) != 0 ) {
00669                 DBGC ( netvsc, "NETVSC %s could not register transfer pages: "
00670                        "%s\n", netvsc->name, strerror ( rc ) );
00671                 goto err_register_pages;
00672         }
00673 
00674         return 0;
00675 
00676         vmbus_unregister_pages ( vmdev, &buffer->pages );
00677  err_register_pages:
00678         vmbus_gpadl_teardown ( vmdev, gpadl );
00679  err_establish_gpadl:
00680         ufree ( buffer->data );
00681  err_alloc:
00682         return rc;
00683 }
00684 
00685 /**
00686  * Destroy data buffer
00687  *
00688  * @v netvsc            NetVSC device
00689  * @v buffer            Data buffer
00690  */
00691 static void netvsc_destroy_buffer ( struct netvsc_device *netvsc,
00692                                     struct netvsc_buffer *buffer ) {
00693         struct vmbus_device *vmdev = netvsc->vmdev;
00694         int rc;
00695 
00696         /* Unregister transfer pages */
00697         vmbus_unregister_pages ( vmdev, &buffer->pages );
00698 
00699         /* Tear down GPA descriptor list */
00700         if ( ( rc = vmbus_gpadl_teardown ( vmdev, buffer->gpadl ) ) != 0 ) {
00701                 DBGC ( netvsc, "NETVSC %s could not tear down GPADL: %s\n",
00702                        netvsc->name, strerror ( rc ) );
00703                 /* Death is imminent.  The host may well continue to
00704                  * write to the data buffer.  The best we can do is
00705                  * leak memory for now and hope that the host doesn't
00706                  * write to this region after we load an OS.
00707                  */
00708                 return;
00709         }
00710 
00711         /* Free buffer */
00712         ufree ( buffer->data );
00713 }
00714 
00715 /**
00716  * Open device
00717  *
00718  * @v rndis             RNDIS device
00719  * @ret rc              Return status code
00720  */
00721 static int netvsc_open ( struct rndis_device *rndis ) {
00722         struct netvsc_device *netvsc = rndis->priv;
00723         int rc;
00724 
00725         /* Initialise receive buffer */
00726         if ( ( rc = netvsc_create_buffer ( netvsc, &netvsc->rx ) ) != 0 )
00727                 goto err_create_rx;
00728 
00729         /* Open channel */
00730         if ( ( rc = vmbus_open ( netvsc->vmdev, &netvsc_channel_operations,
00731                                  PAGE_SIZE, PAGE_SIZE, NETVSC_MTU ) ) != 0 ) {
00732                 DBGC ( netvsc, "NETVSC %s could not open VMBus: %s\n",
00733                        netvsc->name, strerror ( rc ) );
00734                 goto err_vmbus_open;
00735         }
00736 
00737         /* Initialise communication with NetVSP */
00738         if ( ( rc = netvsc_initialise ( netvsc ) ) != 0 )
00739                 goto err_initialise;
00740         if ( ( rc = netvsc_ndis_version ( netvsc ) ) != 0 )
00741                 goto err_ndis_version;
00742 
00743         /* Initialise transmit ring */
00744         if ( ( rc = netvsc_create_ring ( netvsc, &netvsc->tx ) ) != 0 )
00745                 goto err_create_tx;
00746 
00747         /* Establish receive buffer */
00748         if ( ( rc = netvsc_establish_buffer ( netvsc, &netvsc->rx ) ) != 0 )
00749                 goto err_establish_rx;
00750 
00751         return 0;
00752 
00753         netvsc_revoke_buffer ( netvsc, &netvsc->rx );
00754  err_establish_rx:
00755         netvsc_destroy_ring ( netvsc, &netvsc->tx, NULL );
00756  err_create_tx:
00757  err_ndis_version:
00758  err_initialise:
00759         vmbus_close ( netvsc->vmdev );
00760  err_vmbus_open:
00761         netvsc_destroy_buffer ( netvsc, &netvsc->rx );
00762  err_create_rx:
00763         return rc;
00764 }
00765 
00766 /**
00767  * Close device
00768  *
00769  * @v rndis             RNDIS device
00770  */
00771 static void netvsc_close ( struct rndis_device *rndis ) {
00772         struct netvsc_device *netvsc = rndis->priv;
00773 
00774         /* Revoke receive buffer */
00775         netvsc_revoke_buffer ( netvsc, &netvsc->rx );
00776 
00777         /* Destroy transmit ring */
00778         netvsc_destroy_ring ( netvsc, &netvsc->tx, netvsc_cancel_transmit );
00779 
00780         /* Close channel */
00781         vmbus_close ( netvsc->vmdev );
00782 
00783         /* Destroy receive buffer */
00784         netvsc_destroy_buffer ( netvsc, &netvsc->rx );
00785 }
00786 
00787 /** RNDIS operations */
00788 static struct rndis_operations netvsc_operations = {
00789         .open = netvsc_open,
00790         .close = netvsc_close,
00791         .transmit = netvsc_transmit,
00792         .poll = netvsc_poll,
00793 };
00794 
00795 /**
00796  * Probe device
00797  *
00798  * @v vmdev             VMBus device
00799  * @ret rc              Return status code
00800  */
00801 static int netvsc_probe ( struct vmbus_device *vmdev ) {
00802         struct netvsc_device *netvsc;
00803         struct rndis_device *rndis;
00804         int rc;
00805 
00806         /* Allocate and initialise structure */
00807         rndis = alloc_rndis ( sizeof ( *netvsc ) );
00808         if ( ! rndis ) {
00809                 rc = -ENOMEM;
00810                 goto err_alloc;
00811         }
00812         rndis_init ( rndis, &netvsc_operations );
00813         rndis->netdev->dev = &vmdev->dev;
00814         netvsc = rndis->priv;
00815         netvsc->vmdev = vmdev;
00816         netvsc->rndis = rndis;
00817         netvsc->name = vmdev->dev.name;
00818         netvsc_init_ring ( &netvsc->tx, NETVSC_TX_NUM_DESC,
00819                            netvsc->tx_iobufs, netvsc->tx_ids );
00820         netvsc_init_buffer ( &netvsc->rx, NETVSC_RX_BUF_PAGESET,
00821                              &netvsc_xfer_pages_operations,
00822                              NETVSC_RX_ESTABLISH_MSG, NETVSC_RX_ESTABLISH_XRID,
00823                              NETVSC_RX_REVOKE_MSG, NETVSC_RX_REVOKE_XRID,
00824                              NETVSC_RX_BUF_LEN );
00825         vmbus_set_drvdata ( vmdev, rndis );
00826 
00827         /* Register RNDIS device */
00828         if ( ( rc = register_rndis ( rndis ) ) != 0 ) {
00829                 DBGC ( netvsc, "NETVSC %s could not register: %s\n",
00830                        netvsc->name, strerror ( rc ) );
00831                 goto err_register;
00832         }
00833 
00834         return 0;
00835 
00836         unregister_rndis ( rndis );
00837  err_register:
00838         free_rndis ( rndis );
00839  err_alloc:
00840         return rc;
00841 }
00842 
00843 /**
00844  * Reset device
00845  *
00846  * @v vmdev             VMBus device
00847  * @ret rc              Return status code
00848  */
00849 static int netvsc_reset ( struct vmbus_device *vmdev ) {
00850         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00851         struct netvsc_device *netvsc = rndis->priv;
00852         struct net_device *netdev = rndis->netdev;
00853         int rc;
00854 
00855         /* A closed device holds no NetVSC (or RNDIS) state, so there
00856          * is nothing to reset.
00857          */
00858         if ( ! netdev_is_open ( netdev ) )
00859                 return 0;
00860 
00861         /* Close and reopen device to reset any stale state */
00862         netdev_close ( netdev );
00863         if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
00864                 DBGC ( netvsc, "NETVSC %s could not reopen: %s\n",
00865                        netvsc->name, strerror ( rc ) );
00866                 return rc;
00867         }
00868 
00869         return 0;
00870 }
00871 
00872 /**
00873  * Remove device
00874  *
00875  * @v vmdev             VMBus device
00876  */
00877 static void netvsc_remove ( struct vmbus_device *vmdev ) {
00878         struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
00879 
00880         /* Unregister RNDIS device */
00881         unregister_rndis ( rndis );
00882 
00883         /* Free RNDIS device */
00884         free_rndis ( rndis );
00885 }
00886 
00887 /** NetVSC driver */
00888 struct vmbus_driver netvsc_driver __vmbus_driver = {
00889         .name = "netvsc",
00890         .type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f,
00891                              0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ),
00892         .probe = netvsc_probe,
00893         .reset = netvsc_reset,
00894         .remove = netvsc_remove,
00895 };