iPXE
vmxnet3.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 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 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 #include <stdint.h>
00027 #include <errno.h>
00028 #include <assert.h>
00029 #include <byteswap.h>
00030 #include <ipxe/pci.h>
00031 #include <ipxe/io.h>
00032 #include <ipxe/malloc.h>
00033 #include <ipxe/profile.h>
00034 #include <ipxe/iobuf.h>
00035 #include <ipxe/netdevice.h>
00036 #include <ipxe/if_ether.h>
00037 #include <ipxe/ethernet.h>
00038 #include "vmxnet3.h"
00039 
00040 /**
00041  * @file
00042  *
00043  * VMware vmxnet3 virtual NIC driver
00044  *
00045  */
00046 
00047 /** VM command profiler */
00048 static struct profiler vmxnet3_vm_command_profiler __profiler =
00049         { .name = "vmxnet3.vm_command" };
00050 
00051 /** VM transmit profiler */
00052 static struct profiler vmxnet3_vm_tx_profiler __profiler =
00053         { .name = "vmxnet3.vm_tx" };
00054 
00055 /** VM receive refill profiler */
00056 static struct profiler vmxnet3_vm_refill_profiler __profiler =
00057         { .name = "vmxnet3.vm_refill" };
00058 
00059 /** VM event profiler */
00060 static struct profiler vmxnet3_vm_event_profiler __profiler =
00061         { .name = "vmxnet3.vm_event" };
00062 
00063 /**
00064  * Issue command
00065  *
00066  * @v vmxnet            vmxnet3 NIC
00067  * @v command           Command to issue
00068  * @ret result          Command result
00069  */
00070 static inline uint32_t vmxnet3_command ( struct vmxnet3_nic *vmxnet,
00071                                          uint32_t command ) {
00072         uint32_t result;
00073 
00074         /* Issue command */
00075         profile_start ( &vmxnet3_vm_command_profiler );
00076         writel ( command, ( vmxnet->vd + VMXNET3_VD_CMD ) );
00077         result = readl ( vmxnet->vd + VMXNET3_VD_CMD );
00078         profile_stop ( &vmxnet3_vm_command_profiler );
00079         profile_exclude ( &vmxnet3_vm_command_profiler );
00080 
00081         return result;
00082 }
00083 
00084 /**
00085  * Transmit packet
00086  *
00087  * @v netdev            Network device
00088  * @v iobuf             I/O buffer
00089  * @ret rc              Return status code
00090  */
00091 static int vmxnet3_transmit ( struct net_device *netdev,
00092                               struct io_buffer *iobuf ) {
00093         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00094         struct vmxnet3_tx_desc *tx_desc;
00095         unsigned int fill;
00096         unsigned int desc_idx;
00097         unsigned int generation;
00098 
00099         /* Check that we have a free transmit descriptor */
00100         fill = ( vmxnet->count.tx_prod - vmxnet->count.tx_cons );
00101         if ( fill >= VMXNET3_TX_FILL ) {
00102                 DBGC ( vmxnet, "VMXNET3 %p out of transmit descriptors\n",
00103                        vmxnet );
00104                 return -ENOBUFS;
00105         }
00106 
00107         /* Locate transmit descriptor */
00108         desc_idx = ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC );
00109         generation = ( ( vmxnet->count.tx_prod & VMXNET3_NUM_TX_DESC ) ?
00110                        0 : cpu_to_le32 ( VMXNET3_TXF_GEN ) );
00111         assert ( vmxnet->tx_iobuf[desc_idx] == NULL );
00112 
00113         /* Increment producer counter */
00114         vmxnet->count.tx_prod++;
00115 
00116         /* Store I/O buffer for later completion */
00117         vmxnet->tx_iobuf[desc_idx] = iobuf;
00118 
00119         /* Populate transmit descriptor */
00120         tx_desc = &vmxnet->dma->tx_desc[desc_idx];
00121         tx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
00122         tx_desc->flags[0] = ( generation | cpu_to_le32 ( iob_len ( iobuf ) ) );
00123         tx_desc->flags[1] = cpu_to_le32 ( VMXNET3_TXF_CQ | VMXNET3_TXF_EOP );
00124 
00125         /* Hand over descriptor to NIC */
00126         wmb();
00127         profile_start ( &vmxnet3_vm_tx_profiler );
00128         writel ( ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC ),
00129                  ( vmxnet->pt + VMXNET3_PT_TXPROD ) );
00130         profile_stop ( &vmxnet3_vm_tx_profiler );
00131         profile_exclude ( &vmxnet3_vm_tx_profiler );
00132 
00133         return 0;
00134 }
00135 
00136 /**
00137  * Poll for completed transmissions
00138  *
00139  * @v netdev            Network device
00140  */
00141 static void vmxnet3_poll_tx ( struct net_device *netdev ) {
00142         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00143         struct vmxnet3_tx_comp *tx_comp;
00144         struct io_buffer *iobuf;
00145         unsigned int comp_idx;
00146         unsigned int desc_idx;
00147         unsigned int generation;
00148 
00149         while ( 1 ) {
00150 
00151                 /* Look for completed descriptors */
00152                 comp_idx = ( vmxnet->count.tx_cons % VMXNET3_NUM_TX_COMP );
00153                 generation = ( ( vmxnet->count.tx_cons & VMXNET3_NUM_TX_COMP ) ?
00154                                0 : cpu_to_le32 ( VMXNET3_TXCF_GEN ) );
00155                 tx_comp = &vmxnet->dma->tx_comp[comp_idx];
00156                 if ( generation != ( tx_comp->flags &
00157                                      cpu_to_le32 ( VMXNET3_TXCF_GEN ) ) ) {
00158                         break;
00159                 }
00160 
00161                 /* Increment consumer counter */
00162                 vmxnet->count.tx_cons++;
00163 
00164                 /* Locate corresponding transmit descriptor */
00165                 desc_idx = ( le32_to_cpu ( tx_comp->index ) %
00166                              VMXNET3_NUM_TX_DESC );
00167                 iobuf = vmxnet->tx_iobuf[desc_idx];
00168                 if ( ! iobuf ) {
00169                         DBGC ( vmxnet, "VMXNET3 %p completed on empty transmit "
00170                                "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
00171                         netdev_tx_err ( netdev, NULL, -ENOTTY );
00172                         continue;
00173                 }
00174 
00175                 /* Remove I/O buffer from transmit queue */
00176                 vmxnet->tx_iobuf[desc_idx] = NULL;
00177 
00178                 /* Report transmission completion to network layer */
00179                 DBGC2 ( vmxnet, "VMXNET3 %p completed TX %#x/%#x (len %#zx)\n",
00180                         vmxnet, comp_idx, desc_idx, iob_len ( iobuf ) );
00181                 netdev_tx_complete ( netdev, iobuf );
00182         }
00183 }
00184 
00185 /**
00186  * Flush any uncompleted transmit buffers
00187  *
00188  * @v netdev            Network device
00189  */
00190 static void vmxnet3_flush_tx ( struct net_device *netdev ) {
00191         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00192         unsigned int i;
00193 
00194         for ( i = 0 ; i < VMXNET3_NUM_TX_DESC ; i++ ) {
00195                 if ( vmxnet->tx_iobuf[i] ) {
00196                         netdev_tx_complete_err ( netdev, vmxnet->tx_iobuf[i],
00197                                                  -ECANCELED );
00198                         vmxnet->tx_iobuf[i] = NULL;
00199                 }
00200         }
00201 }
00202 
00203 /**
00204  * Refill receive ring
00205  *
00206  * @v netdev            Network device
00207  */
00208 static void vmxnet3_refill_rx ( struct net_device *netdev ) {
00209         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00210         struct vmxnet3_rx_desc *rx_desc;
00211         struct io_buffer *iobuf;
00212         unsigned int orig_rx_prod = vmxnet->count.rx_prod;
00213         unsigned int desc_idx;
00214         unsigned int generation;
00215 
00216         /* Fill receive ring to specified fill level */
00217         while ( vmxnet->count.rx_fill < VMXNET3_RX_FILL ) {
00218 
00219                 /* Locate receive descriptor */
00220                 desc_idx = ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC );
00221                 generation = ( ( vmxnet->count.rx_prod & VMXNET3_NUM_RX_DESC ) ?
00222                                0 : cpu_to_le32 ( VMXNET3_RXF_GEN ) );
00223                 assert ( vmxnet->rx_iobuf[desc_idx] == NULL );
00224 
00225                 /* Allocate I/O buffer */
00226                 iobuf = alloc_iob ( VMXNET3_MTU + NET_IP_ALIGN );
00227                 if ( ! iobuf ) {
00228                         /* Non-fatal low memory condition */
00229                         break;
00230                 }
00231                 iob_reserve ( iobuf, NET_IP_ALIGN );
00232 
00233                 /* Increment producer counter and fill level */
00234                 vmxnet->count.rx_prod++;
00235                 vmxnet->count.rx_fill++;
00236 
00237                 /* Store I/O buffer for later completion */
00238                 vmxnet->rx_iobuf[desc_idx] = iobuf;
00239 
00240                 /* Populate receive descriptor */
00241                 rx_desc = &vmxnet->dma->rx_desc[desc_idx];
00242                 rx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
00243                 rx_desc->flags = ( generation | cpu_to_le32 ( VMXNET3_MTU ) );
00244 
00245         }
00246 
00247         /* Hand over any new descriptors to NIC */
00248         if ( vmxnet->count.rx_prod != orig_rx_prod ) {
00249                 wmb();
00250                 profile_start ( &vmxnet3_vm_refill_profiler );
00251                 writel ( ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC ),
00252                          ( vmxnet->pt + VMXNET3_PT_RXPROD ) );
00253                 profile_stop ( &vmxnet3_vm_refill_profiler );
00254                 profile_exclude ( &vmxnet3_vm_refill_profiler );
00255         }
00256 }
00257 
00258 /**
00259  * Poll for received packets
00260  *
00261  * @v netdev            Network device
00262  */
00263 static void vmxnet3_poll_rx ( struct net_device *netdev ) {
00264         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00265         struct vmxnet3_rx_comp *rx_comp;
00266         struct io_buffer *iobuf;
00267         unsigned int comp_idx;
00268         unsigned int desc_idx;
00269         unsigned int generation;
00270         size_t len;
00271 
00272         while ( 1 ) {
00273 
00274                 /* Look for completed descriptors */
00275                 comp_idx = ( vmxnet->count.rx_cons % VMXNET3_NUM_RX_COMP );
00276                 generation = ( ( vmxnet->count.rx_cons & VMXNET3_NUM_RX_COMP ) ?
00277                                0 : cpu_to_le32 ( VMXNET3_RXCF_GEN ) );
00278                 rx_comp = &vmxnet->dma->rx_comp[comp_idx];
00279                 if ( generation != ( rx_comp->flags &
00280                                      cpu_to_le32 ( VMXNET3_RXCF_GEN ) ) ) {
00281                         break;
00282                 }
00283 
00284                 /* Increment consumer counter */
00285                 vmxnet->count.rx_cons++;
00286 
00287                 /* Locate corresponding receive descriptor */
00288                 desc_idx = ( le32_to_cpu ( rx_comp->index ) %
00289                              VMXNET3_NUM_RX_DESC );
00290                 iobuf = vmxnet->rx_iobuf[desc_idx];
00291                 if ( ! iobuf ) {
00292                         DBGC ( vmxnet, "VMXNET3 %p completed on empty receive "
00293                                "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
00294                         netdev_rx_err ( netdev, NULL, -ENOTTY );
00295                         continue;
00296                 }
00297 
00298                 /* Remove I/O buffer from receive queue */
00299                 vmxnet->rx_iobuf[desc_idx] = NULL;
00300                 vmxnet->count.rx_fill--;
00301 
00302                 /* Deliver packet to network layer */
00303                 len = ( le32_to_cpu ( rx_comp->len ) &
00304                         ( VMXNET3_MAX_PACKET_LEN - 1 ) );
00305                 DBGC2 ( vmxnet, "VMXNET3 %p completed RX %#x/%#x (len %#zx)\n",
00306                         vmxnet, comp_idx, desc_idx, len );
00307                 iob_put ( iobuf, len );
00308                 netdev_rx ( netdev, iobuf );
00309         }
00310 }
00311 
00312 /**
00313  * Flush any uncompleted receive buffers
00314  *
00315  * @v netdev            Network device
00316  */
00317 static void vmxnet3_flush_rx ( struct net_device *netdev ) {
00318         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00319         struct io_buffer *iobuf;
00320         unsigned int i;
00321 
00322         for ( i = 0 ; i < VMXNET3_NUM_RX_DESC ; i++ ) {
00323                 if ( ( iobuf = vmxnet->rx_iobuf[i] ) != NULL ) {
00324                         netdev_rx_err ( netdev, iobuf, -ECANCELED );
00325                         vmxnet->rx_iobuf[i] = NULL;
00326                 }
00327         }
00328 }
00329 
00330 /**
00331  * Check link state
00332  *
00333  * @v netdev            Network device
00334  */
00335 static void vmxnet3_check_link ( struct net_device *netdev ) {
00336         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00337         uint32_t state;
00338         int link_up;
00339         unsigned int link_speed;
00340 
00341         /* Get link state */
00342         state = vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_LINK );
00343         link_up = ( state & 1 );
00344         link_speed = ( state >> 16 );
00345 
00346         /* Report link state to network device */
00347         if ( link_up ) {
00348                 DBGC ( vmxnet, "VMXNET3 %p link is up at %d Mbps\n",
00349                        vmxnet, link_speed );
00350                 netdev_link_up ( netdev );
00351         } else {
00352                 DBGC ( vmxnet, "VMXNET3 %p link is down\n", vmxnet );
00353                 netdev_link_down ( netdev );
00354         }
00355 }
00356 
00357 /**
00358  * Poll for events
00359  *
00360  * @v netdev            Network device
00361  */
00362 static void vmxnet3_poll_events ( struct net_device *netdev ) {
00363         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00364         uint32_t events;
00365 
00366         /* Do nothing unless there are events to process */
00367         if ( ! vmxnet->dma->shared.ecr )
00368                 return;
00369         events = le32_to_cpu ( vmxnet->dma->shared.ecr );
00370 
00371         /* Acknowledge these events */
00372         profile_start ( &vmxnet3_vm_event_profiler );
00373         writel ( events, ( vmxnet->vd + VMXNET3_VD_ECR ) );
00374         profile_stop ( &vmxnet3_vm_event_profiler );
00375         profile_exclude ( &vmxnet3_vm_event_profiler );
00376 
00377         /* Check for link state change */
00378         if ( events & VMXNET3_ECR_LINK ) {
00379                 vmxnet3_check_link ( netdev );
00380                 events &= ~VMXNET3_ECR_LINK;
00381         }
00382 
00383         /* Check for queue errors */
00384         if ( events & ( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR ) ) {
00385                 vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_QUEUE_STATUS );
00386                 DBGC ( vmxnet, "VMXNET3 %p queue error status (TX %08x, RX "
00387                        "%08x)\n", vmxnet,
00388                        le32_to_cpu ( vmxnet->dma->queues.tx.status.error ),
00389                        le32_to_cpu ( vmxnet->dma->queues.rx.status.error ) );
00390                 /* Report errors to allow for visibility via "ifstat" */
00391                 if ( events & VMXNET3_ECR_TQERR )
00392                         netdev_tx_err ( netdev, NULL, -EPIPE );
00393                 if ( events & VMXNET3_ECR_RQERR )
00394                         netdev_rx_err ( netdev, NULL, -EPIPE );
00395                 events &= ~( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR );
00396         }
00397 
00398         /* Check for unknown events */
00399         if ( events ) {
00400                 DBGC ( vmxnet, "VMXNET3 %p unknown events %08x\n",
00401                        vmxnet, events );
00402                 /* Report error to allow for visibility via "ifstat" */
00403                 netdev_rx_err ( netdev, NULL, -ENODEV );
00404         }
00405 }
00406 
00407 /**
00408  * Poll network device
00409  *
00410  * @v netdev            Network device
00411  */
00412 static void vmxnet3_poll ( struct net_device *netdev ) {
00413 
00414         vmxnet3_poll_events ( netdev );
00415         vmxnet3_poll_tx ( netdev );
00416         vmxnet3_poll_rx ( netdev );
00417         vmxnet3_refill_rx ( netdev );
00418 }
00419 
00420 /**
00421  * Enable/disable interrupts
00422  *
00423  * @v netdev            Network device
00424  * @v enable            Interrupts should be enabled
00425  */
00426 static void vmxnet3_irq ( struct net_device *netdev, int enable ) {
00427         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00428 
00429         DBGC ( vmxnet, "VMXNET3 %p %s IRQ not implemented\n",
00430                vmxnet, ( enable ? "enable" : "disable" ) );
00431 }
00432 
00433 /**
00434  * Set MAC address
00435  *
00436  * @v vmxnet            vmxnet3 NIC
00437  * @v ll_addr           Link-layer address to set
00438  */
00439 static void vmxnet3_set_ll_addr ( struct vmxnet3_nic *vmxnet,
00440                                   const void *ll_addr ) {
00441         struct {
00442                 uint32_t low;
00443                 uint32_t high;
00444         } __attribute__ (( packed )) mac;
00445 
00446         memset ( &mac, 0, sizeof ( mac ) );
00447         memcpy ( &mac, ll_addr, ETH_ALEN );
00448         writel ( cpu_to_le32 ( mac.low ), ( vmxnet->vd + VMXNET3_VD_MACL ) );
00449         writel ( cpu_to_le32 ( mac.high ), ( vmxnet->vd + VMXNET3_VD_MACH ) );
00450 }
00451 
00452 /**
00453  * Open NIC
00454  *
00455  * @v netdev            Network device
00456  * @ret rc              Return status code
00457  */
00458 static int vmxnet3_open ( struct net_device *netdev ) {
00459         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00460         struct vmxnet3_shared *shared;
00461         struct vmxnet3_queues *queues;
00462         uint64_t shared_bus;
00463         uint64_t queues_bus;
00464         uint32_t status;
00465         int rc;
00466 
00467         /* Allocate DMA areas */
00468         vmxnet->dma = malloc_dma ( sizeof ( *vmxnet->dma ), VMXNET3_DMA_ALIGN );
00469         if ( ! vmxnet->dma ) {
00470                 DBGC ( vmxnet, "VMXNET3 %p could not allocate DMA area\n",
00471                        vmxnet );
00472                 rc = -ENOMEM;
00473                 goto err_alloc_dma;
00474         }
00475         memset ( vmxnet->dma, 0, sizeof ( *vmxnet->dma ) );
00476 
00477         /* Populate queue descriptors */
00478         queues = &vmxnet->dma->queues;
00479         queues->tx.cfg.desc_address =
00480                 cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_desc ) );
00481         queues->tx.cfg.comp_address =
00482                 cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_comp ) );
00483         queues->tx.cfg.num_desc = cpu_to_le32 ( VMXNET3_NUM_TX_DESC );
00484         queues->tx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_TX_COMP );
00485         queues->rx.cfg.desc_address[0] =
00486                 cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_desc ) );
00487         queues->rx.cfg.comp_address =
00488                 cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_comp ) );
00489         queues->rx.cfg.num_desc[0] = cpu_to_le32 ( VMXNET3_NUM_RX_DESC );
00490         queues->rx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_RX_COMP );
00491         queues_bus = virt_to_bus ( queues );
00492         DBGC ( vmxnet, "VMXNET3 %p queue descriptors at %08llx+%zx\n",
00493                vmxnet, queues_bus, sizeof ( *queues ) );
00494 
00495         /* Populate shared area */
00496         shared = &vmxnet->dma->shared;
00497         shared->magic = cpu_to_le32 ( VMXNET3_SHARED_MAGIC );
00498         shared->misc.version = cpu_to_le32 ( VMXNET3_VERSION_MAGIC );
00499         shared->misc.version_support = cpu_to_le32 ( VMXNET3_VERSION_SELECT );
00500         shared->misc.upt_version_support =
00501                 cpu_to_le32 ( VMXNET3_UPT_VERSION_SELECT );
00502         shared->misc.queue_desc_address = cpu_to_le64 ( queues_bus );
00503         shared->misc.queue_desc_len = cpu_to_le32 ( sizeof ( *queues ) );
00504         shared->misc.mtu = cpu_to_le32 ( VMXNET3_MTU );
00505         shared->misc.num_tx_queues = 1;
00506         shared->misc.num_rx_queues = 1;
00507         shared->interrupt.num_intrs = 1;
00508         shared->interrupt.control = cpu_to_le32 ( VMXNET3_IC_DISABLE_ALL );
00509         shared->rx_filter.mode = cpu_to_le32 ( VMXNET3_RXM_UCAST |
00510                                                VMXNET3_RXM_BCAST |
00511                                                VMXNET3_RXM_ALL_MULTI );
00512         shared_bus = virt_to_bus ( shared );
00513         DBGC ( vmxnet, "VMXNET3 %p shared area at %08llx+%zx\n",
00514                vmxnet, shared_bus, sizeof ( *shared ) );
00515 
00516         /* Zero counters */
00517         memset ( &vmxnet->count, 0, sizeof ( vmxnet->count ) );
00518 
00519         /* Set MAC address */
00520         vmxnet3_set_ll_addr ( vmxnet, &netdev->ll_addr );
00521 
00522         /* Pass shared area to device */
00523         writel ( ( shared_bus >> 0 ), ( vmxnet->vd + VMXNET3_VD_DSAL ) );
00524         writel ( ( shared_bus >> 32 ), ( vmxnet->vd + VMXNET3_VD_DSAH ) );
00525 
00526         /* Activate device */
00527         if ( ( status = vmxnet3_command ( vmxnet,
00528                                           VMXNET3_CMD_ACTIVATE_DEV ) ) != 0 ) {
00529                 DBGC ( vmxnet, "VMXNET3 %p could not activate (status %#x)\n",
00530                        vmxnet, status );
00531                 rc = -EIO;
00532                 goto err_activate;
00533         }
00534 
00535         /* Fill receive ring */
00536         vmxnet3_refill_rx ( netdev );
00537 
00538         return 0;
00539 
00540         vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
00541         vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
00542  err_activate:
00543         vmxnet3_flush_tx ( netdev );
00544         vmxnet3_flush_rx ( netdev );
00545         free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
00546  err_alloc_dma:
00547         return rc;
00548 }
00549 
00550 /**
00551  * Close NIC
00552  *
00553  * @v netdev            Network device
00554  */
00555 static void vmxnet3_close ( struct net_device *netdev ) {
00556         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00557 
00558         vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
00559         vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
00560         vmxnet3_flush_tx ( netdev );
00561         vmxnet3_flush_rx ( netdev );
00562         free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
00563 }
00564 
00565 /** vmxnet3 net device operations */
00566 static struct net_device_operations vmxnet3_operations = {
00567         .open           = vmxnet3_open,
00568         .close          = vmxnet3_close,
00569         .transmit       = vmxnet3_transmit,
00570         .poll           = vmxnet3_poll,
00571         .irq            = vmxnet3_irq,
00572 };
00573 
00574 /**
00575  * Check version
00576  *
00577  * @v vmxnet            vmxnet3 NIC
00578  * @ret rc              Return status code
00579  */
00580 static int vmxnet3_check_version ( struct vmxnet3_nic *vmxnet ) {
00581         uint32_t version;
00582         uint32_t upt_version;
00583 
00584         /* Read version */
00585         version = readl ( vmxnet->vd + VMXNET3_VD_VRRS );
00586         upt_version = readl ( vmxnet->vd + VMXNET3_VD_UVRS );
00587         DBGC ( vmxnet, "VMXNET3 %p is version %d (UPT version %d)\n",
00588                vmxnet, version, upt_version );
00589 
00590         /* Inform NIC of driver version */
00591         writel ( VMXNET3_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_VRRS ) );
00592         writel ( VMXNET3_UPT_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_UVRS ) );
00593 
00594         return 0;
00595 }
00596 
00597 /**
00598  * Get permanent MAC address
00599  *
00600  * @v vmxnet            vmxnet3 NIC
00601  * @v hw_addr           Hardware address to fill in
00602  */
00603 static void vmxnet3_get_hw_addr ( struct vmxnet3_nic *vmxnet, void *hw_addr ) {
00604         struct {
00605                 uint32_t low;
00606                 uint32_t high;
00607         } __attribute__ (( packed )) mac;
00608 
00609         mac.low = le32_to_cpu ( vmxnet3_command ( vmxnet,
00610                                                VMXNET3_CMD_GET_PERM_MAC_LO ) );
00611         mac.high = le32_to_cpu ( vmxnet3_command ( vmxnet,
00612                                                VMXNET3_CMD_GET_PERM_MAC_HI ) );
00613         memcpy ( hw_addr, &mac, ETH_ALEN );
00614 }
00615 
00616 /**
00617  * Probe PCI device
00618  *
00619  * @v pci               PCI device
00620  * @v id                PCI ID
00621  * @ret rc              Return status code
00622  */
00623 static int vmxnet3_probe ( struct pci_device *pci ) {
00624         struct net_device *netdev;
00625         struct vmxnet3_nic *vmxnet;
00626         int rc;
00627 
00628         /* Allocate network device */
00629         netdev = alloc_etherdev ( sizeof ( *vmxnet ) );
00630         if ( ! netdev ) {
00631                 rc = -ENOMEM;
00632                 goto err_alloc_etherdev;
00633         }
00634         netdev_init ( netdev, &vmxnet3_operations );
00635         vmxnet = netdev_priv ( netdev );
00636         pci_set_drvdata ( pci, netdev );
00637         netdev->dev = &pci->dev;
00638         memset ( vmxnet, 0, sizeof ( *vmxnet ) );
00639 
00640         /* Fix up PCI device */
00641         adjust_pci_device ( pci );
00642 
00643         /* Map PCI BARs */
00644         vmxnet->pt = ioremap ( pci_bar_start ( pci, VMXNET3_PT_BAR ),
00645                                VMXNET3_PT_LEN );
00646         if ( ! vmxnet->pt ) {
00647                 rc = -ENODEV;
00648                 goto err_ioremap_pt;
00649         }
00650         vmxnet->vd = ioremap ( pci_bar_start ( pci, VMXNET3_VD_BAR ),
00651                                VMXNET3_VD_LEN );
00652         if ( ! vmxnet->vd ) {
00653                 rc = -ENODEV;
00654                 goto err_ioremap_vd;
00655         }
00656 
00657         /* Version check */
00658         if ( ( rc = vmxnet3_check_version ( vmxnet ) ) != 0 )
00659                 goto err_check_version;
00660 
00661         /* Reset device */
00662         if ( ( rc = vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV ) ) != 0 )
00663                 goto err_reset;
00664 
00665         /* Read initial MAC address */
00666         vmxnet3_get_hw_addr ( vmxnet, &netdev->hw_addr );
00667 
00668         /* Register network device */
00669         if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
00670                 DBGC ( vmxnet, "VMXNET3 %p could not register net device: "
00671                        "%s\n", vmxnet, strerror ( rc ) );
00672                 goto err_register_netdev;
00673         }
00674 
00675         /* Get initial link state */
00676         vmxnet3_check_link ( netdev );
00677 
00678         return 0;
00679 
00680         unregister_netdev ( netdev );
00681  err_register_netdev:
00682  err_reset:
00683  err_check_version:
00684         iounmap ( vmxnet->vd );
00685  err_ioremap_vd:
00686         iounmap ( vmxnet->pt );
00687  err_ioremap_pt:
00688         netdev_nullify ( netdev );
00689         netdev_put ( netdev );
00690  err_alloc_etherdev:
00691         return rc;
00692 }
00693 
00694 /**
00695  * Remove PCI device
00696  *
00697  * @v pci               PCI device
00698  */
00699 static void vmxnet3_remove ( struct pci_device *pci ) {
00700         struct net_device *netdev = pci_get_drvdata ( pci );
00701         struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
00702 
00703         unregister_netdev ( netdev );
00704         iounmap ( vmxnet->vd );
00705         iounmap ( vmxnet->pt );
00706         netdev_nullify ( netdev );
00707         netdev_put ( netdev );
00708 }
00709 
00710 /** vmxnet3 PCI IDs */
00711 static struct pci_device_id vmxnet3_nics[] = {
00712         PCI_ROM ( 0x15ad, 0x07b0, "vmxnet3", "vmxnet3 virtual NIC", 0 ),
00713 };
00714 
00715 /** vmxnet3 PCI driver */
00716 struct pci_driver vmxnet3_driver __pci_driver = {
00717         .ids = vmxnet3_nics,
00718         .id_count = ( sizeof ( vmxnet3_nics ) / sizeof ( vmxnet3_nics[0] ) ),
00719         .probe = vmxnet3_probe,
00720         .remove = vmxnet3_remove,
00721 };