iPXE
intelxl.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2018 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 #include <stdint.h>
00027 #include <string.h>
00028 #include <stdio.h>
00029 #include <unistd.h>
00030 #include <errno.h>
00031 #include <byteswap.h>
00032 #include <ipxe/netdevice.h>
00033 #include <ipxe/ethernet.h>
00034 #include <ipxe/if_ether.h>
00035 #include <ipxe/vlan.h>
00036 #include <ipxe/iobuf.h>
00037 #include <ipxe/malloc.h>
00038 #include <ipxe/pci.h>
00039 #include <ipxe/version.h>
00040 #include "intelxl.h"
00041 
00042 /** @file
00043  *
00044  * Intel 40 Gigabit Ethernet network card driver
00045  *
00046  */
00047 
00048 /******************************************************************************
00049  *
00050  * Device reset
00051  *
00052  ******************************************************************************
00053  */
00054 
00055 /**
00056  * Reset hardware
00057  *
00058  * @v intelxl           Intel device
00059  * @ret rc              Return status code
00060  */
00061 static int intelxl_reset ( struct intelxl_nic *intelxl ) {
00062         uint32_t pfgen_ctrl;
00063 
00064         /* Perform a global software reset */
00065         pfgen_ctrl = readl ( intelxl->regs + INTELXL_PFGEN_CTRL );
00066         writel ( ( pfgen_ctrl | INTELXL_PFGEN_CTRL_PFSWR ),
00067                  intelxl->regs + INTELXL_PFGEN_CTRL );
00068         mdelay ( INTELXL_RESET_DELAY_MS );
00069 
00070         return 0;
00071 }
00072 
00073 /******************************************************************************
00074  *
00075  * MAC address
00076  *
00077  ******************************************************************************
00078  */
00079 
00080 /**
00081  * Fetch initial MAC address and maximum frame size
00082  *
00083  * @v intelxl           Intel device
00084  * @v netdev            Network device
00085  * @ret rc              Return status code
00086  */
00087 static int intelxl_fetch_mac ( struct intelxl_nic *intelxl,
00088                                struct net_device *netdev ) {
00089         union intelxl_receive_address mac;
00090         uint32_t prtgl_sal;
00091         uint32_t prtgl_sah;
00092         size_t mfs;
00093 
00094         /* Read NVM-loaded address */
00095         prtgl_sal = readl ( intelxl->regs + INTELXL_PRTGL_SAL );
00096         prtgl_sah = readl ( intelxl->regs + INTELXL_PRTGL_SAH );
00097         mac.reg.low = cpu_to_le32 ( prtgl_sal );
00098         mac.reg.high = cpu_to_le32 ( prtgl_sah );
00099 
00100         /* Check that address is valid */
00101         if ( ! is_valid_ether_addr ( mac.raw ) ) {
00102                 DBGC ( intelxl, "INTELXL %p has invalid MAC address (%s)\n",
00103                        intelxl, eth_ntoa ( mac.raw ) );
00104                 return -ENOENT;
00105         }
00106 
00107         /* Copy MAC address */
00108         DBGC ( intelxl, "INTELXL %p has autoloaded MAC address %s\n",
00109                intelxl, eth_ntoa ( mac.raw ) );
00110         memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN );
00111 
00112         /* Get maximum frame size */
00113         mfs = INTELXL_PRTGL_SAH_MFS_GET ( prtgl_sah );
00114         netdev->max_pkt_len = ( mfs - 4 /* CRC */ );
00115 
00116         return 0;
00117 }
00118 
00119 /******************************************************************************
00120  *
00121  * MSI-X interrupts
00122  *
00123  ******************************************************************************
00124  */
00125 
00126 /**
00127  * Enable MSI-X dummy interrupt
00128  *
00129  * @v intelxl           Intel device
00130  * @v pci               PCI device
00131  * @ret rc              Return status code
00132  */
00133 int intelxl_msix_enable ( struct intelxl_nic *intelxl,
00134                           struct pci_device *pci ) {
00135         int rc;
00136 
00137         /* Enable MSI-X capability */
00138         if ( ( rc = pci_msix_enable ( pci, &intelxl->msix ) ) != 0 ) {
00139                 DBGC ( intelxl, "INTELXL %p could not enable MSI-X: %s\n",
00140                        intelxl, strerror ( rc ) );
00141                 return rc;
00142         }
00143 
00144         /* Configure interrupt zero to write to dummy location */
00145         pci_msix_map ( &intelxl->msix, 0, virt_to_bus ( &intelxl->msg ), 0 );
00146 
00147         /* Enable dummy interrupt zero */
00148         pci_msix_unmask ( &intelxl->msix, 0 );
00149 
00150         return 0;
00151 }
00152 
00153 /**
00154  * Disable MSI-X dummy interrupt
00155  *
00156  * @v intelxl           Intel device
00157  * @v pci               PCI device
00158  */
00159 void intelxl_msix_disable ( struct intelxl_nic *intelxl,
00160                             struct pci_device *pci ) {
00161 
00162         /* Disable dummy interrupt zero */
00163         pci_msix_mask ( &intelxl->msix, 0 );
00164 
00165         /* Disable MSI-X capability */
00166         pci_msix_disable ( pci, &intelxl->msix );
00167 }
00168 
00169 /******************************************************************************
00170  *
00171  * Admin queue
00172  *
00173  ******************************************************************************
00174  */
00175 
00176 /** Admin queue register offsets */
00177 static const struct intelxl_admin_offsets intelxl_admin_offsets = {
00178         .bal = INTELXL_ADMIN_BAL,
00179         .bah = INTELXL_ADMIN_BAH,
00180         .len = INTELXL_ADMIN_LEN,
00181         .head = INTELXL_ADMIN_HEAD,
00182         .tail = INTELXL_ADMIN_TAIL,
00183 };
00184 
00185 /**
00186  * Allocate admin queue
00187  *
00188  * @v intelxl           Intel device
00189  * @v admin             Admin queue
00190  * @ret rc              Return status code
00191  */
00192 static int intelxl_alloc_admin ( struct intelxl_nic *intelxl,
00193                                  struct intelxl_admin *admin ) {
00194         size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
00195         size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
00196 
00197         /* Allocate admin queue */
00198         admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
00199         if ( ! admin->buf )
00200                 return -ENOMEM;
00201         admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
00202 
00203         DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
00204                "[%08llx,%08llx)\n", intelxl,
00205                ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
00206                ( ( unsigned long long ) virt_to_bus ( admin->desc ) ),
00207                ( ( unsigned long long ) ( virt_to_bus ( admin->desc ) + len ) ),
00208                ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
00209                ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
00210                                           buf_len ) ) );
00211         return 0;
00212 }
00213 
00214 /**
00215  * Enable admin queue
00216  *
00217  * @v intelxl           Intel device
00218  * @v admin             Admin queue
00219  */
00220 static void intelxl_enable_admin ( struct intelxl_nic *intelxl,
00221                                    struct intelxl_admin *admin ) {
00222         size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
00223         const struct intelxl_admin_offsets *regs = admin->regs;
00224         void *admin_regs = ( intelxl->regs + admin->base );
00225         physaddr_t address;
00226 
00227         /* Initialise admin queue */
00228         memset ( admin->desc, 0, len );
00229 
00230         /* Reset head and tail registers */
00231         writel ( 0, admin_regs + regs->head );
00232         writel ( 0, admin_regs + regs->tail );
00233 
00234         /* Reset queue index */
00235         admin->index = 0;
00236 
00237         /* Program queue address */
00238         address = virt_to_bus ( admin->desc );
00239         writel ( ( address & 0xffffffffUL ), admin_regs + regs->bal );
00240         if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
00241                 writel ( ( ( ( uint64_t ) address ) >> 32 ),
00242                          admin_regs + regs->bah );
00243         } else {
00244                 writel ( 0, admin_regs + regs->bah );
00245         }
00246 
00247         /* Program queue length and enable queue */
00248         writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
00249                    INTELXL_ADMIN_LEN_ENABLE ),
00250                  admin_regs + regs->len );
00251 }
00252 
00253 /**
00254  * Disable admin queue
00255  *
00256  * @v intelxl           Intel device
00257  * @v admin             Admin queue
00258  */
00259 static void intelxl_disable_admin ( struct intelxl_nic *intelxl,
00260                                     struct intelxl_admin *admin ) {
00261         const struct intelxl_admin_offsets *regs = admin->regs;
00262         void *admin_regs = ( intelxl->regs + admin->base );
00263 
00264         /* Disable queue */
00265         writel ( 0, admin_regs + regs->len );
00266 }
00267 
00268 /**
00269  * Free admin queue
00270  *
00271  * @v intelxl           Intel device
00272  * @v admin             Admin queue
00273  */
00274 static void intelxl_free_admin ( struct intelxl_nic *intelxl __unused,
00275                                  struct intelxl_admin *admin ) {
00276         size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
00277         size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
00278 
00279         /* Free queue */
00280         free_dma ( admin->buf, ( buf_len + len ) );
00281 }
00282 
00283 /**
00284  * Get next admin command queue descriptor
00285  *
00286  * @v intelxl           Intel device
00287  * @ret cmd             Command descriptor
00288  */
00289 struct intelxl_admin_descriptor *
00290 intelxl_admin_command_descriptor ( struct intelxl_nic *intelxl ) {
00291         struct intelxl_admin *admin = &intelxl->command;
00292         struct intelxl_admin_descriptor *cmd;
00293 
00294         /* Get and initialise next descriptor */
00295         cmd = &admin->desc[ admin->index % INTELXL_ADMIN_NUM_DESC ];
00296         memset ( cmd, 0, sizeof ( *cmd ) );
00297         return cmd;
00298 }
00299 
00300 /**
00301  * Get next admin command queue data buffer
00302  *
00303  * @v intelxl           Intel device
00304  * @ret buf             Data buffer
00305  */
00306 union intelxl_admin_buffer *
00307 intelxl_admin_command_buffer ( struct intelxl_nic *intelxl ) {
00308         struct intelxl_admin *admin = &intelxl->command;
00309         union intelxl_admin_buffer *buf;
00310 
00311         /* Get next data buffer */
00312         buf = &admin->buf[ admin->index % INTELXL_ADMIN_NUM_DESC ];
00313         memset ( buf, 0, sizeof ( *buf ) );
00314         return buf;
00315 }
00316 
00317 /**
00318  * Initialise admin event queue descriptor
00319  *
00320  * @v intelxl           Intel device
00321  * @v index             Event queue index
00322  */
00323 static void intelxl_admin_event_init ( struct intelxl_nic *intelxl,
00324                                        unsigned int index ) {
00325         struct intelxl_admin *admin = &intelxl->event;
00326         struct intelxl_admin_descriptor *evt;
00327         union intelxl_admin_buffer *buf;
00328         uint64_t address;
00329 
00330         /* Initialise descriptor */
00331         evt = &admin->desc[ index % INTELXL_ADMIN_NUM_DESC ];
00332         buf = &admin->buf[ index % INTELXL_ADMIN_NUM_DESC ];
00333         address = virt_to_bus ( buf );
00334         evt->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
00335         evt->len = cpu_to_le16 ( sizeof ( *buf ) );
00336         evt->params.buffer.high = cpu_to_le32 ( address >> 32 );
00337         evt->params.buffer.low = cpu_to_le32 ( address & 0xffffffffUL );
00338 }
00339 
00340 /**
00341  * Issue admin queue command
00342  *
00343  * @v intelxl           Intel device
00344  * @ret rc              Return status code
00345  */
00346 int intelxl_admin_command ( struct intelxl_nic *intelxl ) {
00347         struct intelxl_admin *admin = &intelxl->command;
00348         const struct intelxl_admin_offsets *regs = admin->regs;
00349         void *admin_regs = ( intelxl->regs + admin->base );
00350         struct intelxl_admin_descriptor *cmd;
00351         union intelxl_admin_buffer *buf;
00352         uint64_t address;
00353         uint32_t cookie;
00354         unsigned int index;
00355         unsigned int tail;
00356         unsigned int i;
00357         int rc;
00358 
00359         /* Get next queue entry */
00360         index = admin->index++;
00361         tail = ( admin->index % INTELXL_ADMIN_NUM_DESC );
00362         cmd = &admin->desc[ index % INTELXL_ADMIN_NUM_DESC ];
00363         buf = &admin->buf[ index % INTELXL_ADMIN_NUM_DESC ];
00364         DBGC2 ( intelxl, "INTELXL %p admin command %#x opcode %#04x",
00365                 intelxl, index, le16_to_cpu ( cmd->opcode ) );
00366         if ( cmd->vopcode )
00367                 DBGC2 ( intelxl, "/%#08x", le32_to_cpu ( cmd->vopcode ) );
00368         DBGC2 ( intelxl, ":\n" );
00369 
00370         /* Sanity checks */
00371         assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_DD ) ) );
00372         assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_CMP ) ) );
00373         assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_ERR ) ) );
00374         assert ( cmd->ret == 0 );
00375 
00376         /* Populate data buffer address if applicable */
00377         if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
00378                 address = virt_to_bus ( buf );
00379                 cmd->params.buffer.high = cpu_to_le32 ( address >> 32 );
00380                 cmd->params.buffer.low = cpu_to_le32 ( address & 0xffffffffUL );
00381         }
00382 
00383         /* Populate cookie, if not being (ab)used for VF opcode */
00384         if ( ! cmd->vopcode )
00385                 cmd->cookie = cpu_to_le32 ( index );
00386 
00387         /* Record cookie */
00388         cookie = cmd->cookie;
00389 
00390         /* Post command descriptor */
00391         DBGC2_HDA ( intelxl, virt_to_phys ( cmd ), cmd, sizeof ( *cmd ) );
00392         if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
00393                 DBGC2_HDA ( intelxl, virt_to_phys ( buf ), buf,
00394                             le16_to_cpu ( cmd->len ) );
00395         }
00396         wmb();
00397         writel ( tail, admin_regs + regs->tail );
00398 
00399         /* Wait for completion */
00400         for ( i = 0 ; i < INTELXL_ADMIN_MAX_WAIT_MS ; i++ ) {
00401 
00402                 /* If response is not complete, delay 1ms and retry */
00403                 if ( ! ( cmd->flags & INTELXL_ADMIN_FL_DD ) ) {
00404                         mdelay ( 1 );
00405                         continue;
00406                 }
00407                 DBGC2 ( intelxl, "INTELXL %p admin command %#x response:\n",
00408                         intelxl, index );
00409                 DBGC2_HDA ( intelxl, virt_to_phys ( cmd ), cmd,
00410                             sizeof ( *cmd ) );
00411 
00412                 /* Check for cookie mismatch */
00413                 if ( cmd->cookie != cookie ) {
00414                         DBGC ( intelxl, "INTELXL %p admin command %#x bad "
00415                                "cookie %#x\n", intelxl, index,
00416                                le32_to_cpu ( cmd->cookie ) );
00417                         rc = -EPROTO;
00418                         goto err;
00419                 }
00420 
00421                 /* Check for errors */
00422                 if ( cmd->ret != 0 ) {
00423                         DBGC ( intelxl, "INTELXL %p admin command %#x error "
00424                                "%d\n", intelxl, index,
00425                                le16_to_cpu ( cmd->ret ) );
00426                         rc = -EIO;
00427                         goto err;
00428                 }
00429 
00430                 /* Success */
00431                 return 0;
00432         }
00433 
00434         rc = -ETIMEDOUT;
00435         DBGC ( intelxl, "INTELXL %p timed out waiting for admin command %#x:\n",
00436                intelxl, index );
00437  err:
00438         DBGC_HDA ( intelxl, virt_to_phys ( cmd ), cmd, sizeof ( *cmd ) );
00439         return rc;
00440 }
00441 
00442 /**
00443  * Get firmware version
00444  *
00445  * @v intelxl           Intel device
00446  * @ret rc              Return status code
00447  */
00448 static int intelxl_admin_version ( struct intelxl_nic *intelxl ) {
00449         struct intelxl_admin_descriptor *cmd;
00450         struct intelxl_admin_version_params *version;
00451         unsigned int api;
00452         int rc;
00453 
00454         /* Populate descriptor */
00455         cmd = intelxl_admin_command_descriptor ( intelxl );
00456         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_VERSION );
00457         version = &cmd->params.version;
00458 
00459         /* Issue command */
00460         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00461                 return rc;
00462         api = le16_to_cpu ( version->api.major );
00463         DBGC ( intelxl, "INTELXL %p firmware v%d.%d API v%d.%d\n",
00464                intelxl, le16_to_cpu ( version->firmware.major ),
00465                le16_to_cpu ( version->firmware.minor ),
00466                api, le16_to_cpu ( version->api.minor ) );
00467 
00468         /* Check for API compatibility */
00469         if ( api > INTELXL_ADMIN_API_MAJOR ) {
00470                 DBGC ( intelxl, "INTELXL %p unsupported API v%d\n",
00471                        intelxl, api );
00472                 return -ENOTSUP;
00473         }
00474 
00475         return 0;
00476 }
00477 
00478 /**
00479  * Report driver version
00480  *
00481  * @v intelxl           Intel device
00482  * @ret rc              Return status code
00483  */
00484 static int intelxl_admin_driver ( struct intelxl_nic *intelxl ) {
00485         struct intelxl_admin_descriptor *cmd;
00486         struct intelxl_admin_driver_params *driver;
00487         union intelxl_admin_buffer *buf;
00488         int rc;
00489 
00490         /* Populate descriptor */
00491         cmd = intelxl_admin_command_descriptor ( intelxl );
00492         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_DRIVER );
00493         cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
00494         cmd->len = cpu_to_le16 ( sizeof ( buf->driver ) );
00495         driver = &cmd->params.driver;
00496         driver->major = product_major_version;
00497         driver->minor = product_minor_version;
00498         buf = intelxl_admin_command_buffer ( intelxl );
00499         snprintf ( buf->driver.name, sizeof ( buf->driver.name ), "%s",
00500                    ( product_name[0] ? product_name : product_short_name ) );
00501 
00502         /* Issue command */
00503         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00504                 return rc;
00505 
00506         return 0;
00507 }
00508 
00509 /**
00510  * Shutdown admin queues
00511  *
00512  * @v intelxl           Intel device
00513  * @ret rc              Return status code
00514  */
00515 static int intelxl_admin_shutdown ( struct intelxl_nic *intelxl ) {
00516         struct intelxl_admin_descriptor *cmd;
00517         struct intelxl_admin_shutdown_params *shutdown;
00518         int rc;
00519 
00520         /* Populate descriptor */
00521         cmd = intelxl_admin_command_descriptor ( intelxl );
00522         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_SHUTDOWN );
00523         shutdown = &cmd->params.shutdown;
00524         shutdown->unloading = INTELXL_ADMIN_SHUTDOWN_UNLOADING;
00525 
00526         /* Issue command */
00527         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00528                 return rc;
00529 
00530         return 0;
00531 }
00532 
00533 /**
00534  * Clear PXE mode
00535  *
00536  * @v intelxl           Intel device
00537  * @ret rc              Return status code
00538  */
00539 static int intelxl_admin_clear_pxe ( struct intelxl_nic *intelxl ) {
00540         struct intelxl_admin_descriptor *cmd;
00541         struct intelxl_admin_clear_pxe_params *pxe;
00542         uint32_t gllan_rctl_0;
00543         int rc;
00544 
00545         /* Do nothing if device is already out of PXE mode */
00546         gllan_rctl_0 = readl ( intelxl->regs + INTELXL_GLLAN_RCTL_0 );
00547         if ( ! ( gllan_rctl_0 & INTELXL_GLLAN_RCTL_0_PXE_MODE ) ) {
00548                 DBGC2 ( intelxl, "INTELXL %p already in non-PXE mode\n",
00549                         intelxl );
00550                 return 0;
00551         }
00552 
00553         /* Populate descriptor */
00554         cmd = intelxl_admin_command_descriptor ( intelxl );
00555         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_CLEAR_PXE );
00556         pxe = &cmd->params.pxe;
00557         pxe->magic = INTELXL_ADMIN_CLEAR_PXE_MAGIC;
00558 
00559         /* Issue command */
00560         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00561                 return rc;
00562 
00563         return 0;
00564 }
00565 
00566 /**
00567  * Get switch configuration
00568  *
00569  * @v intelxl           Intel device
00570  * @ret rc              Return status code
00571  */
00572 static int intelxl_admin_switch ( struct intelxl_nic *intelxl ) {
00573         struct intelxl_admin_descriptor *cmd;
00574         struct intelxl_admin_switch_params *sw;
00575         union intelxl_admin_buffer *buf;
00576         int rc;
00577 
00578         /* Populate descriptor */
00579         cmd = intelxl_admin_command_descriptor ( intelxl );
00580         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_SWITCH );
00581         cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
00582         cmd->len = cpu_to_le16 ( sizeof ( buf->sw ) );
00583         sw = &cmd->params.sw;
00584         buf = intelxl_admin_command_buffer ( intelxl );
00585 
00586         /* Get each configuration in turn */
00587         do {
00588                 /* Issue command */
00589                 if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00590                         return rc;
00591 
00592                 /* Dump raw configuration */
00593                 DBGC2 ( intelxl, "INTELXL %p SEID %#04x:\n",
00594                         intelxl, le16_to_cpu ( buf->sw.cfg.seid ) );
00595                 DBGC2_HDA ( intelxl, 0, &buf->sw.cfg, sizeof ( buf->sw.cfg ) );
00596 
00597                 /* Parse response */
00598                 if ( buf->sw.cfg.type == INTELXL_ADMIN_SWITCH_TYPE_VSI ) {
00599                         intelxl->vsi = le16_to_cpu ( buf->sw.cfg.seid );
00600                         DBGC ( intelxl, "INTELXL %p VSI %#04x uplink %#04x "
00601                                "downlink %#04x conn %#02x\n", intelxl,
00602                                intelxl->vsi, le16_to_cpu ( buf->sw.cfg.uplink ),
00603                                le16_to_cpu ( buf->sw.cfg.downlink ),
00604                                buf->sw.cfg.connection );
00605                 }
00606 
00607         } while ( sw->next );
00608 
00609         /* Check that we found a VSI */
00610         if ( ! intelxl->vsi ) {
00611                 DBGC ( intelxl, "INTELXL %p has no VSI\n", intelxl );
00612                 return -ENOENT;
00613         }
00614 
00615         return 0;
00616 }
00617 
00618 /**
00619  * Get VSI parameters
00620  *
00621  * @v intelxl           Intel device
00622  * @ret rc              Return status code
00623  */
00624 static int intelxl_admin_vsi ( struct intelxl_nic *intelxl ) {
00625         struct intelxl_admin_descriptor *cmd;
00626         struct intelxl_admin_vsi_params *vsi;
00627         union intelxl_admin_buffer *buf;
00628         int rc;
00629 
00630         /* Populate descriptor */
00631         cmd = intelxl_admin_command_descriptor ( intelxl );
00632         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_VSI );
00633         cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
00634         cmd->len = cpu_to_le16 ( sizeof ( buf->vsi ) );
00635         vsi = &cmd->params.vsi;
00636         vsi->vsi = cpu_to_le16 ( intelxl->vsi );
00637         buf = intelxl_admin_command_buffer ( intelxl );
00638 
00639         /* Issue command */
00640         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00641                 return rc;
00642 
00643         /* Parse response */
00644         intelxl->queue = le16_to_cpu ( buf->vsi.queue[0] );
00645         intelxl->qset = le16_to_cpu ( buf->vsi.qset[0] );
00646         DBGC ( intelxl, "INTELXL %p VSI %#04x queue %#04x qset %#04x\n",
00647                intelxl, intelxl->vsi, intelxl->queue, intelxl->qset );
00648 
00649         return 0;
00650 }
00651 
00652 /**
00653  * Set VSI promiscuous modes
00654  *
00655  * @v intelxl           Intel device
00656  * @ret rc              Return status code
00657  */
00658 static int intelxl_admin_promisc ( struct intelxl_nic *intelxl ) {
00659         struct intelxl_admin_descriptor *cmd;
00660         struct intelxl_admin_promisc_params *promisc;
00661         uint16_t flags;
00662         int rc;
00663 
00664         /* Populate descriptor */
00665         cmd = intelxl_admin_command_descriptor ( intelxl );
00666         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_PROMISC );
00667         flags = ( INTELXL_ADMIN_PROMISC_FL_UNICAST |
00668                   INTELXL_ADMIN_PROMISC_FL_MULTICAST |
00669                   INTELXL_ADMIN_PROMISC_FL_BROADCAST |
00670                   INTELXL_ADMIN_PROMISC_FL_VLAN );
00671         promisc = &cmd->params.promisc;
00672         promisc->flags = cpu_to_le16 ( flags );
00673         promisc->valid = cpu_to_le16 ( flags );
00674         promisc->vsi = cpu_to_le16 ( intelxl->vsi );
00675 
00676         /* Issue command */
00677         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00678                 return rc;
00679 
00680         return 0;
00681 }
00682 
00683 /**
00684  * Restart autonegotiation
00685  *
00686  * @v intelxl           Intel device
00687  * @ret rc              Return status code
00688  */
00689 static int intelxl_admin_autoneg ( struct intelxl_nic *intelxl ) {
00690         struct intelxl_admin_descriptor *cmd;
00691         struct intelxl_admin_autoneg_params *autoneg;
00692         int rc;
00693 
00694         /* Populate descriptor */
00695         cmd = intelxl_admin_command_descriptor ( intelxl );
00696         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_AUTONEG );
00697         autoneg = &cmd->params.autoneg;
00698         autoneg->flags = ( INTELXL_ADMIN_AUTONEG_FL_RESTART |
00699                            INTELXL_ADMIN_AUTONEG_FL_ENABLE );
00700 
00701         /* Issue command */
00702         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00703                 return rc;
00704 
00705         return 0;
00706 }
00707 
00708 /**
00709  * Get link status
00710  *
00711  * @v netdev            Network device
00712  * @ret rc              Return status code
00713  */
00714 static int intelxl_admin_link ( struct net_device *netdev ) {
00715         struct intelxl_nic *intelxl = netdev->priv;
00716         struct intelxl_admin_descriptor *cmd;
00717         struct intelxl_admin_link_params *link;
00718         int rc;
00719 
00720         /* Populate descriptor */
00721         cmd = intelxl_admin_command_descriptor ( intelxl );
00722         cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_LINK );
00723         link = &cmd->params.link;
00724         link->notify = INTELXL_ADMIN_LINK_NOTIFY;
00725 
00726         /* Issue command */
00727         if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
00728                 return rc;
00729         DBGC ( intelxl, "INTELXL %p PHY %#02x speed %#02x status %#02x\n",
00730                intelxl, link->phy, link->speed, link->status );
00731 
00732         /* Update network device */
00733         if ( link->status & INTELXL_ADMIN_LINK_UP ) {
00734                 netdev_link_up ( netdev );
00735         } else {
00736                 netdev_link_down ( netdev );
00737         }
00738 
00739         return 0;
00740 }
00741 
00742 /**
00743  * Handle virtual function event (when VF driver is not present)
00744  *
00745  * @v netdev            Network device
00746  * @v evt               Admin queue event descriptor
00747  * @v buf               Admin queue event data buffer
00748  */
00749 __weak void
00750 intelxlvf_admin_event ( struct net_device *netdev __unused,
00751                         struct intelxl_admin_descriptor *evt __unused,
00752                         union intelxl_admin_buffer *buf __unused ) {
00753 
00754         /* Nothing to do */
00755 }
00756 
00757 /**
00758  * Refill admin event queue
00759  *
00760  * @v intelxl           Intel device
00761  */
00762 static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) {
00763         struct intelxl_admin *admin = &intelxl->event;
00764         const struct intelxl_admin_offsets *regs = admin->regs;
00765         void *admin_regs = ( intelxl->regs + admin->base );
00766         unsigned int tail;
00767 
00768         /* Update tail pointer */
00769         tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) %
00770                  INTELXL_ADMIN_NUM_DESC );
00771         wmb();
00772         writel ( tail, admin_regs + regs->tail );
00773 }
00774 
00775 /**
00776  * Poll admin event queue
00777  *
00778  * @v netdev            Network device
00779  */
00780 void intelxl_poll_admin ( struct net_device *netdev ) {
00781         struct intelxl_nic *intelxl = netdev->priv;
00782         struct intelxl_admin *admin = &intelxl->event;
00783         struct intelxl_admin_descriptor *evt;
00784         union intelxl_admin_buffer *buf;
00785 
00786         /* Check for events */
00787         while ( 1 ) {
00788 
00789                 /* Get next event descriptor and data buffer */
00790                 evt = &admin->desc[ admin->index % INTELXL_ADMIN_NUM_DESC ];
00791                 buf = &admin->buf[ admin->index % INTELXL_ADMIN_NUM_DESC ];
00792 
00793                 /* Stop if descriptor is not yet completed */
00794                 if ( ! ( evt->flags & INTELXL_ADMIN_FL_DD ) )
00795                         return;
00796                 DBGC2 ( intelxl, "INTELXL %p admin event %#x:\n",
00797                         intelxl, admin->index );
00798                 DBGC2_HDA ( intelxl, virt_to_phys ( evt ), evt,
00799                             sizeof ( *evt ) );
00800                 if ( evt->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
00801                         DBGC2_HDA ( intelxl, virt_to_phys ( buf ), buf,
00802                                     le16_to_cpu ( evt->len ) );
00803                 }
00804 
00805                 /* Handle event */
00806                 switch ( evt->opcode ) {
00807                 case cpu_to_le16 ( INTELXL_ADMIN_LINK ):
00808                         intelxl_admin_link ( netdev );
00809                         break;
00810                 case cpu_to_le16 ( INTELXL_ADMIN_SEND_TO_VF ):
00811                         intelxlvf_admin_event ( netdev, evt, buf );
00812                         break;
00813                 default:
00814                         DBGC ( intelxl, "INTELXL %p admin event %#x "
00815                                "unrecognised opcode %#04x\n", intelxl,
00816                                admin->index, le16_to_cpu ( evt->opcode ) );
00817                         break;
00818                 }
00819 
00820                 /* Reset descriptor and refill queue */
00821                 intelxl_admin_event_init ( intelxl, admin->index );
00822                 admin->index++;
00823                 intelxl_refill_admin ( intelxl );
00824         }
00825 }
00826 
00827 /**
00828  * Open admin queues
00829  *
00830  * @v intelxl           Intel device
00831  * @ret rc              Return status code
00832  */
00833 int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
00834         int rc;
00835 
00836         /* Allocate admin event queue */
00837         if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->event ) ) != 0 )
00838                 goto err_alloc_event;
00839 
00840         /* Allocate admin command queue */
00841         if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->command ) ) != 0 )
00842                 goto err_alloc_command;
00843 
00844         /* (Re)open admin queues */
00845         intelxl_reopen_admin ( intelxl );
00846 
00847         /* Get firmware version */
00848         if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
00849                 goto err_version;
00850 
00851         /* Report driver version */
00852         if ( ( rc = intelxl_admin_driver ( intelxl ) ) != 0 )
00853                 goto err_driver;
00854 
00855         return 0;
00856 
00857  err_driver:
00858  err_version:
00859         intelxl_disable_admin ( intelxl, &intelxl->command );
00860         intelxl_disable_admin ( intelxl, &intelxl->event );
00861         intelxl_free_admin ( intelxl, &intelxl->command );
00862  err_alloc_command:
00863         intelxl_free_admin ( intelxl, &intelxl->event );
00864  err_alloc_event:
00865         return rc;
00866 }
00867 
00868 /**
00869  * Reopen admin queues (after virtual function reset)
00870  *
00871  * @v intelxl           Intel device
00872  */
00873 void intelxl_reopen_admin ( struct intelxl_nic *intelxl ) {
00874         unsigned int i;
00875 
00876         /* Enable admin event queue */
00877         intelxl_enable_admin ( intelxl, &intelxl->event );
00878 
00879         /* Enable admin command queue */
00880         intelxl_enable_admin ( intelxl, &intelxl->command );
00881 
00882         /* Initialise all admin event queue descriptors */
00883         for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
00884                 intelxl_admin_event_init ( intelxl, i );
00885 
00886         /* Post all descriptors to event queue */
00887         intelxl_refill_admin ( intelxl );
00888 }
00889 
00890 /**
00891  * Close admin queues
00892  *
00893  * @v intelxl           Intel device
00894  */
00895 void intelxl_close_admin ( struct intelxl_nic *intelxl ) {
00896 
00897         /* Shut down admin queues */
00898         intelxl_admin_shutdown ( intelxl );
00899 
00900         /* Disable admin queues */
00901         intelxl_disable_admin ( intelxl, &intelxl->command );
00902         intelxl_disable_admin ( intelxl, &intelxl->event );
00903 
00904         /* Free admin queues */
00905         intelxl_free_admin ( intelxl, &intelxl->command );
00906         intelxl_free_admin ( intelxl, &intelxl->event );
00907 }
00908 
00909 /******************************************************************************
00910  *
00911  * Descriptor rings
00912  *
00913  ******************************************************************************
00914  */
00915 
00916 /**
00917  * Allocate descriptor ring
00918  *
00919  * @v intelxl           Intel device
00920  * @v ring              Descriptor ring
00921  * @ret rc              Return status code
00922  */
00923 int intelxl_alloc_ring ( struct intelxl_nic *intelxl,
00924                          struct intelxl_ring *ring ) {
00925         physaddr_t address;
00926         int rc;
00927 
00928         /* Allocate descriptor ring */
00929         ring->desc.raw = malloc_dma ( ring->len, INTELXL_ALIGN );
00930         if ( ! ring->desc.raw ) {
00931                 rc = -ENOMEM;
00932                 goto err_alloc;
00933         }
00934         address = virt_to_bus ( ring->desc.raw );
00935 
00936         /* Initialise descriptor ring */
00937         memset ( ring->desc.raw, 0, ring->len );
00938 
00939         /* Reset tail pointer */
00940         writel ( 0, ( intelxl->regs + ring->tail ) );
00941 
00942         /* Reset counters */
00943         ring->prod = 0;
00944         ring->cons = 0;
00945 
00946         DBGC ( intelxl, "INTELXL %p ring %06x is at [%08llx,%08llx)\n",
00947                intelxl, ( ring->reg + ring->tail ),
00948                ( ( unsigned long long ) address ),
00949                ( ( unsigned long long ) address + ring->len ) );
00950 
00951         return 0;
00952 
00953         free_dma ( ring->desc.raw, ring->len );
00954  err_alloc:
00955         return rc;
00956 }
00957 
00958 /**
00959  * Free descriptor ring
00960  *
00961  * @v intelxl           Intel device
00962  * @v ring              Descriptor ring
00963  */
00964 void intelxl_free_ring ( struct intelxl_nic *intelxl __unused,
00965                          struct intelxl_ring *ring ) {
00966 
00967         /* Free descriptor ring */
00968         free_dma ( ring->desc.raw, ring->len );
00969         ring->desc.raw = NULL;
00970 }
00971 
00972 /**
00973  * Dump queue context (for debugging)
00974  *
00975  * @v intelxl           Intel device
00976  * @v op                Context operation
00977  * @v len               Size of context
00978  */
00979 static __attribute__ (( unused )) void
00980 intelxl_context_dump ( struct intelxl_nic *intelxl, uint32_t op, size_t len ) {
00981         struct intelxl_context_line line;
00982         uint32_t pfcm_lanctxctl;
00983         uint32_t pfcm_lanctxstat;
00984         unsigned int queue;
00985         unsigned int index;
00986         unsigned int i;
00987 
00988         /* Do nothing unless debug output is enabled */
00989         if ( ! DBG_EXTRA )
00990                 return;
00991 
00992         /* Dump context */
00993         DBGC2 ( intelxl, "INTELXL %p context %#08x:\n", intelxl, op );
00994         for ( index = 0 ; ( sizeof ( line ) * index ) < len ; index++ ) {
00995 
00996                 /* Start context operation */
00997                 queue = ( intelxl->base + intelxl->queue );
00998                 pfcm_lanctxctl =
00999                         ( INTELXL_PFCM_LANCTXCTL_QUEUE_NUM ( queue ) |
01000                           INTELXL_PFCM_LANCTXCTL_SUB_LINE ( index ) |
01001                           INTELXL_PFCM_LANCTXCTL_OP_CODE_READ | op );
01002                 writel ( pfcm_lanctxctl,
01003                          intelxl->regs + INTELXL_PFCM_LANCTXCTL );
01004 
01005                 /* Wait for operation to complete */
01006                 for ( i = 0 ; i < INTELXL_CTX_MAX_WAIT_MS ; i++ ) {
01007 
01008                         /* Check if operation is complete */
01009                         pfcm_lanctxstat = readl ( intelxl->regs +
01010                                                   INTELXL_PFCM_LANCTXSTAT );
01011                         if ( pfcm_lanctxstat & INTELXL_PFCM_LANCTXSTAT_DONE )
01012                                 break;
01013 
01014                         /* Delay */
01015                         mdelay ( 1 );
01016                 }
01017 
01018                 /* Read context data */
01019                 for ( i = 0 ; i < ( sizeof ( line ) /
01020                                     sizeof ( line.raw[0] ) ) ; i++ ) {
01021                         line.raw[i] = readl ( intelxl->regs +
01022                                               INTELXL_PFCM_LANCTXDATA ( i ) );
01023                 }
01024                 DBGC2_HDA ( intelxl, ( sizeof ( line ) * index ),
01025                             &line, sizeof ( line ) );
01026         }
01027 }
01028 
01029 /**
01030  * Program queue context line
01031  *
01032  * @v intelxl           Intel device
01033  * @v line              Queue context line
01034  * @v index             Line number
01035  * @v op                Context operation
01036  * @ret rc              Return status code
01037  */
01038 static int intelxl_context_line ( struct intelxl_nic *intelxl,
01039                                   struct intelxl_context_line *line,
01040                                   unsigned int index, uint32_t op ) {
01041         uint32_t pfcm_lanctxctl;
01042         uint32_t pfcm_lanctxstat;
01043         unsigned int queue;
01044         unsigned int i;
01045 
01046         /* Write context data */
01047         for ( i = 0; i < ( sizeof ( *line ) / sizeof ( line->raw[0] ) ); i++ ) {
01048                 writel ( le32_to_cpu ( line->raw[i] ),
01049                          intelxl->regs + INTELXL_PFCM_LANCTXDATA ( i ) );
01050         }
01051 
01052         /* Start context operation */
01053         queue = ( intelxl->base + intelxl->queue );
01054         pfcm_lanctxctl = ( INTELXL_PFCM_LANCTXCTL_QUEUE_NUM ( queue ) |
01055                            INTELXL_PFCM_LANCTXCTL_SUB_LINE ( index ) |
01056                            INTELXL_PFCM_LANCTXCTL_OP_CODE_WRITE | op );
01057         writel ( pfcm_lanctxctl, intelxl->regs + INTELXL_PFCM_LANCTXCTL );
01058 
01059         /* Wait for operation to complete */
01060         for ( i = 0 ; i < INTELXL_CTX_MAX_WAIT_MS ; i++ ) {
01061 
01062                 /* Check if operation is complete */
01063                 pfcm_lanctxstat = readl ( intelxl->regs +
01064                                           INTELXL_PFCM_LANCTXSTAT );
01065                 if ( pfcm_lanctxstat & INTELXL_PFCM_LANCTXSTAT_DONE )
01066                         return 0;
01067 
01068                 /* Delay */
01069                 mdelay ( 1 );
01070         }
01071 
01072         DBGC ( intelxl, "INTELXL %p timed out waiting for context: %#08x\n",
01073                intelxl, pfcm_lanctxctl );
01074         return -ETIMEDOUT;
01075 }
01076 
01077 /**
01078  * Program queue context
01079  *
01080  * @v intelxl           Intel device
01081  * @v line              Queue context lines
01082  * @v len               Size of context
01083  * @v op                Context operation
01084  * @ret rc              Return status code
01085  */
01086 static int intelxl_context ( struct intelxl_nic *intelxl,
01087                              struct intelxl_context_line *line,
01088                              size_t len, uint32_t op ) {
01089         unsigned int index;
01090         int rc;
01091 
01092         DBGC2 ( intelxl, "INTELXL %p context %#08x len %#zx:\n",
01093                 intelxl, op, len );
01094         DBGC2_HDA ( intelxl, 0, line, len );
01095 
01096         /* Program one line at a time */
01097         for ( index = 0 ; ( sizeof ( *line ) * index ) < len ; index++ ) {
01098                 if ( ( rc = intelxl_context_line ( intelxl, line++, index,
01099                                                    op ) ) != 0 )
01100                         return rc;
01101         }
01102 
01103         return 0;
01104 }
01105 
01106 /**
01107  * Program transmit queue context
01108  *
01109  * @v intelxl           Intel device
01110  * @v address           Descriptor ring base address
01111  * @ret rc              Return status code
01112  */
01113 static int intelxl_context_tx ( struct intelxl_nic *intelxl,
01114                                 physaddr_t address ) {
01115         union {
01116                 struct intelxl_context_tx tx;
01117                 struct intelxl_context_line line;
01118         } ctx;
01119         int rc;
01120 
01121         /* Initialise context */
01122         memset ( &ctx, 0, sizeof ( ctx ) );
01123         ctx.tx.flags = cpu_to_le16 ( INTELXL_CTX_TX_FL_NEW );
01124         ctx.tx.base = cpu_to_le64 ( INTELXL_CTX_TX_BASE ( address ) );
01125         ctx.tx.count =
01126                 cpu_to_le16 ( INTELXL_CTX_TX_COUNT ( INTELXL_TX_NUM_DESC ) );
01127         ctx.tx.qset = INTELXL_CTX_TX_QSET ( intelxl->qset );
01128 
01129         /* Program context */
01130         if ( ( rc = intelxl_context ( intelxl, &ctx.line, sizeof ( ctx ),
01131                                       INTELXL_PFCM_LANCTXCTL_TYPE_TX ) ) != 0 )
01132                 return rc;
01133 
01134         return 0;
01135 }
01136 
01137 /**
01138  * Program receive queue context
01139  *
01140  * @v intelxl           Intel device
01141  * @v address           Descriptor ring base address
01142  * @ret rc              Return status code
01143  */
01144 static int intelxl_context_rx ( struct intelxl_nic *intelxl,
01145                                 physaddr_t address ) {
01146         union {
01147                 struct intelxl_context_rx rx;
01148                 struct intelxl_context_line line;
01149         } ctx;
01150         uint64_t base_count;
01151         int rc;
01152 
01153         /* Initialise context */
01154         memset ( &ctx, 0, sizeof ( ctx ) );
01155         base_count = INTELXL_CTX_RX_BASE_COUNT ( address, INTELXL_RX_NUM_DESC );
01156         ctx.rx.base_count = cpu_to_le64 ( base_count );
01157         ctx.rx.len = cpu_to_le16 ( INTELXL_CTX_RX_LEN ( intelxl->mfs ) );
01158         ctx.rx.flags = ( INTELXL_CTX_RX_FL_DSIZE | INTELXL_CTX_RX_FL_CRCSTRIP );
01159         ctx.rx.mfs = cpu_to_le16 ( INTELXL_CTX_RX_MFS ( intelxl->mfs ) );
01160 
01161         /* Program context */
01162         if ( ( rc = intelxl_context ( intelxl, &ctx.line, sizeof ( ctx ),
01163                                       INTELXL_PFCM_LANCTXCTL_TYPE_RX ) ) != 0 )
01164                 return rc;
01165 
01166         return 0;
01167 }
01168 
01169 /**
01170  * Enable descriptor ring
01171  *
01172  * @v intelxl           Intel device
01173  * @v ring              Descriptor ring
01174  * @ret rc              Return status code
01175  */
01176 static int intelxl_enable_ring ( struct intelxl_nic *intelxl,
01177                                  struct intelxl_ring *ring ) {
01178         void *ring_regs = ( intelxl->regs + ring->reg );
01179         uint32_t qxx_ena;
01180 
01181         /* Enable ring */
01182         writel ( INTELXL_QXX_ENA_REQ, ( ring_regs + INTELXL_QXX_ENA ) );
01183         udelay ( INTELXL_QUEUE_ENABLE_DELAY_US );
01184         qxx_ena = readl ( ring_regs + INTELXL_QXX_ENA );
01185         if ( ! ( qxx_ena & INTELXL_QXX_ENA_STAT ) ) {
01186                 DBGC ( intelxl, "INTELXL %p ring %06x failed to enable: "
01187                        "%#08x\n", intelxl, ring->reg, qxx_ena );
01188                 return -EIO;
01189         }
01190 
01191         return 0;
01192 }
01193 
01194 /**
01195  * Disable descriptor ring
01196  *
01197  * @v intelxl           Intel device
01198  * @v ring              Descriptor ring
01199  * @ret rc              Return status code
01200  */
01201 static int intelxl_disable_ring ( struct intelxl_nic *intelxl,
01202                                   struct intelxl_ring *ring ) {
01203         void *ring_regs = ( intelxl->regs + ring->reg );
01204         uint32_t qxx_ena;
01205         unsigned int i;
01206 
01207         /* Disable ring */
01208         writel ( 0, ( ring_regs + INTELXL_QXX_ENA ) );
01209 
01210         /* Wait for ring to be disabled */
01211         for ( i = 0 ; i < INTELXL_QUEUE_DISABLE_MAX_WAIT_MS ; i++ ) {
01212 
01213                 /* Check if ring is disabled */
01214                 qxx_ena = readl ( ring_regs + INTELXL_QXX_ENA );
01215                 if ( ! ( qxx_ena & INTELXL_QXX_ENA_STAT ) )
01216                         return 0;
01217 
01218                 /* Delay */
01219                 mdelay ( 1 );
01220         }
01221 
01222         DBGC ( intelxl, "INTELXL %p ring %06x timed out waiting for disable: "
01223                "%#08x\n", intelxl, ring->reg, qxx_ena );
01224         return -ETIMEDOUT;
01225 }
01226 
01227 /**
01228  * Create descriptor ring
01229  *
01230  * @v intelxl           Intel device
01231  * @v ring              Descriptor ring
01232  * @ret rc              Return status code
01233  */
01234 static int intelxl_create_ring ( struct intelxl_nic *intelxl,
01235                                  struct intelxl_ring *ring ) {
01236         physaddr_t address;
01237         int rc;
01238 
01239         /* Allocate descriptor ring */
01240         if ( ( rc = intelxl_alloc_ring ( intelxl, ring ) ) != 0 )
01241                 goto err_alloc;
01242 
01243         /* Program queue context */
01244         address = virt_to_bus ( ring->desc.raw );
01245         if ( ( rc = ring->context ( intelxl, address ) ) != 0 )
01246                 goto err_context;
01247 
01248         /* Enable ring */
01249         if ( ( rc = intelxl_enable_ring ( intelxl, ring ) ) != 0 )
01250                 goto err_enable;
01251 
01252         return 0;
01253 
01254         intelxl_disable_ring ( intelxl, ring );
01255  err_enable:
01256  err_context:
01257         intelxl_free_ring ( intelxl, ring );
01258  err_alloc:
01259         return rc;
01260 }
01261 
01262 /**
01263  * Destroy descriptor ring
01264  *
01265  * @v intelxl           Intel device
01266  * @v ring              Descriptor ring
01267  */
01268 static void intelxl_destroy_ring ( struct intelxl_nic *intelxl,
01269                                    struct intelxl_ring *ring ) {
01270         int rc;
01271 
01272         /* Disable ring */
01273         if ( ( rc = intelxl_disable_ring ( intelxl, ring ) ) != 0 ) {
01274                 /* Leak memory; there's nothing else we can do */
01275                 return;
01276         }
01277 
01278         /* Free descriptor ring */
01279         intelxl_free_ring ( intelxl, ring );
01280 }
01281 
01282 /**
01283  * Refill receive descriptor ring
01284  *
01285  * @v intelxl           Intel device
01286  */
01287 static void intelxl_refill_rx ( struct intelxl_nic *intelxl ) {
01288         struct intelxl_rx_data_descriptor *rx;
01289         struct io_buffer *iobuf;
01290         unsigned int rx_idx;
01291         unsigned int rx_tail;
01292         physaddr_t address;
01293         unsigned int refilled = 0;
01294 
01295         /* Refill ring */
01296         while ( ( intelxl->rx.prod - intelxl->rx.cons ) < INTELXL_RX_FILL ) {
01297 
01298                 /* Allocate I/O buffer */
01299                 iobuf = alloc_iob ( intelxl->mfs );
01300                 if ( ! iobuf ) {
01301                         /* Wait for next refill */
01302                         break;
01303                 }
01304 
01305                 /* Get next receive descriptor */
01306                 rx_idx = ( intelxl->rx.prod++ % INTELXL_RX_NUM_DESC );
01307                 rx = &intelxl->rx.desc.rx[rx_idx].data;
01308 
01309                 /* Populate receive descriptor */
01310                 address = virt_to_bus ( iobuf->data );
01311                 rx->address = cpu_to_le64 ( address );
01312                 rx->flags = 0;
01313 
01314                 /* Record I/O buffer */
01315                 assert ( intelxl->rx_iobuf[rx_idx] == NULL );
01316                 intelxl->rx_iobuf[rx_idx] = iobuf;
01317 
01318                 DBGC2 ( intelxl, "INTELXL %p RX %d is [%llx,%llx)\n", intelxl,
01319                         rx_idx, ( ( unsigned long long ) address ),
01320                         ( ( unsigned long long ) address + intelxl->mfs ) );
01321                 refilled++;
01322         }
01323 
01324         /* Push descriptors to card, if applicable */
01325         if ( refilled ) {
01326                 wmb();
01327                 rx_tail = ( intelxl->rx.prod % INTELXL_RX_NUM_DESC );
01328                 writel ( rx_tail, ( intelxl->regs + intelxl->rx.tail ) );
01329         }
01330 }
01331 
01332 /**
01333  * Discard unused receive I/O buffers
01334  *
01335  * @v intelxl           Intel device
01336  */
01337 void intelxl_empty_rx ( struct intelxl_nic *intelxl ) {
01338         unsigned int i;
01339 
01340         /* Discard any unused receive buffers */
01341         for ( i = 0 ; i < INTELXL_RX_NUM_DESC ; i++ ) {
01342                 if ( intelxl->rx_iobuf[i] )
01343                         free_iob ( intelxl->rx_iobuf[i] );
01344                 intelxl->rx_iobuf[i] = NULL;
01345         }
01346 }
01347 
01348 /******************************************************************************
01349  *
01350  * Network device interface
01351  *
01352  ******************************************************************************
01353  */
01354 
01355 /**
01356  * Open network device
01357  *
01358  * @v netdev            Network device
01359  * @ret rc              Return status code
01360  */
01361 static int intelxl_open ( struct net_device *netdev ) {
01362         struct intelxl_nic *intelxl = netdev->priv;
01363         union intelxl_receive_address mac;
01364         unsigned int queue;
01365         uint32_t prtgl_sal;
01366         uint32_t prtgl_sah;
01367         int rc;
01368 
01369         /* Calculate maximum frame size */
01370         intelxl->mfs = ( ( ETH_HLEN + netdev->mtu + 4 /* CRC */ +
01371                            INTELXL_ALIGN - 1 ) & ~( INTELXL_ALIGN - 1 ) );
01372 
01373         /* Program MAC address and maximum frame size */
01374         memset ( &mac, 0, sizeof ( mac ) );
01375         memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) );
01376         prtgl_sal = le32_to_cpu ( mac.reg.low );
01377         prtgl_sah = ( le32_to_cpu ( mac.reg.high ) |
01378                       INTELXL_PRTGL_SAH_MFS_SET ( intelxl->mfs ) );
01379         writel ( prtgl_sal, intelxl->regs + INTELXL_PRTGL_SAL );
01380         writel ( prtgl_sah, intelxl->regs + INTELXL_PRTGL_SAH );
01381 
01382         /* Associate transmit queue to PF */
01383         writel ( ( INTELXL_QXX_CTL_PFVF_Q_PF |
01384                    INTELXL_QXX_CTL_PFVF_PF_INDX ( intelxl->pf ) ),
01385                  ( intelxl->regs + intelxl->tx.reg + INTELXL_QXX_CTL ) );
01386 
01387         /* Clear transmit pre queue disable */
01388         queue = ( intelxl->base + intelxl->queue );
01389         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_CLEAR_QDIS |
01390                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01391                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01392 
01393         /* Reset transmit queue head */
01394         writel ( 0, ( intelxl->regs + INTELXL_QTX_HEAD ( intelxl->queue ) ) );
01395 
01396         /* Create receive descriptor ring */
01397         if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->rx ) ) != 0 )
01398                 goto err_create_rx;
01399 
01400         /* Create transmit descriptor ring */
01401         if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->tx ) ) != 0 )
01402                 goto err_create_tx;
01403 
01404         /* Fill receive ring */
01405         intelxl_refill_rx ( intelxl );
01406 
01407         /* Restart autonegotiation */
01408         intelxl_admin_autoneg ( intelxl );
01409 
01410         /* Update link state */
01411         intelxl_admin_link ( netdev );
01412 
01413         return 0;
01414 
01415         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_SET_QDIS |
01416                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01417                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01418         udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
01419         intelxl_destroy_ring ( intelxl, &intelxl->tx );
01420  err_create_tx:
01421         intelxl_destroy_ring ( intelxl, &intelxl->rx );
01422  err_create_rx:
01423         return rc;
01424 }
01425 
01426 /**
01427  * Close network device
01428  *
01429  * @v netdev            Network device
01430  */
01431 static void intelxl_close ( struct net_device *netdev ) {
01432         struct intelxl_nic *intelxl = netdev->priv;
01433         unsigned int queue;
01434 
01435         /* Dump contexts (for debugging) */
01436         intelxl_context_dump ( intelxl, INTELXL_PFCM_LANCTXCTL_TYPE_TX,
01437                                sizeof ( struct intelxl_context_tx ) );
01438         intelxl_context_dump ( intelxl, INTELXL_PFCM_LANCTXCTL_TYPE_RX,
01439                                sizeof ( struct intelxl_context_rx ) );
01440 
01441         /* Pre-disable transmit queue */
01442         queue = ( intelxl->base + intelxl->queue );
01443         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_SET_QDIS |
01444                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01445                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01446         udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
01447 
01448         /* Destroy transmit descriptor ring */
01449         intelxl_destroy_ring ( intelxl, &intelxl->tx );
01450 
01451         /* Destroy receive descriptor ring */
01452         intelxl_destroy_ring ( intelxl, &intelxl->rx );
01453 
01454         /* Discard any unused receive buffers */
01455         intelxl_empty_rx ( intelxl );
01456 }
01457 
01458 /**
01459  * Transmit packet
01460  *
01461  * @v netdev            Network device
01462  * @v iobuf             I/O buffer
01463  * @ret rc              Return status code
01464  */
01465 int intelxl_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
01466         struct intelxl_nic *intelxl = netdev->priv;
01467         struct intelxl_tx_data_descriptor *tx;
01468         unsigned int tx_idx;
01469         unsigned int tx_tail;
01470         physaddr_t address;
01471         size_t len;
01472 
01473         /* Get next transmit descriptor */
01474         if ( ( intelxl->tx.prod - intelxl->tx.cons ) >= INTELXL_TX_FILL ) {
01475                 DBGC ( intelxl, "INTELXL %p out of transmit descriptors\n",
01476                        intelxl );
01477                 return -ENOBUFS;
01478         }
01479         tx_idx = ( intelxl->tx.prod++ % INTELXL_TX_NUM_DESC );
01480         tx_tail = ( intelxl->tx.prod % INTELXL_TX_NUM_DESC );
01481         tx = &intelxl->tx.desc.tx[tx_idx].data;
01482 
01483         /* Populate transmit descriptor */
01484         address = virt_to_bus ( iobuf->data );
01485         len = iob_len ( iobuf );
01486         tx->address = cpu_to_le64 ( address );
01487         tx->len = cpu_to_le32 ( INTELXL_TX_DATA_LEN ( len ) );
01488         tx->flags = cpu_to_le32 ( INTELXL_TX_DATA_DTYP | INTELXL_TX_DATA_EOP |
01489                                   INTELXL_TX_DATA_RS | INTELXL_TX_DATA_JFDI );
01490         wmb();
01491 
01492         /* Notify card that there are packets ready to transmit */
01493         writel ( tx_tail, ( intelxl->regs + intelxl->tx.tail ) );
01494 
01495         DBGC2 ( intelxl, "INTELXL %p TX %d is [%llx,%llx)\n", intelxl, tx_idx,
01496                 ( ( unsigned long long ) address ),
01497                 ( ( unsigned long long ) address + len ) );
01498         return 0;
01499 }
01500 
01501 /**
01502  * Poll for completed packets
01503  *
01504  * @v netdev            Network device
01505  */
01506 static void intelxl_poll_tx ( struct net_device *netdev ) {
01507         struct intelxl_nic *intelxl = netdev->priv;
01508         struct intelxl_tx_writeback_descriptor *tx_wb;
01509         unsigned int tx_idx;
01510 
01511         /* Check for completed packets */
01512         while ( intelxl->tx.cons != intelxl->tx.prod ) {
01513 
01514                 /* Get next transmit descriptor */
01515                 tx_idx = ( intelxl->tx.cons % INTELXL_TX_NUM_DESC );
01516                 tx_wb = &intelxl->tx.desc.tx[tx_idx].wb;
01517 
01518                 /* Stop if descriptor is still in use */
01519                 if ( ! ( tx_wb->flags & INTELXL_TX_WB_FL_DD ) )
01520                         return;
01521                 DBGC2 ( intelxl, "INTELXL %p TX %d complete\n",
01522                         intelxl, tx_idx );
01523 
01524                 /* Complete TX descriptor */
01525                 netdev_tx_complete_next ( netdev );
01526                 intelxl->tx.cons++;
01527         }
01528 }
01529 
01530 /**
01531  * Poll for received packets
01532  *
01533  * @v netdev            Network device
01534  */
01535 static void intelxl_poll_rx ( struct net_device *netdev ) {
01536         struct intelxl_nic *intelxl = netdev->priv;
01537         struct intelxl_rx_writeback_descriptor *rx_wb;
01538         struct io_buffer *iobuf;
01539         unsigned int rx_idx;
01540         unsigned int tag;
01541         size_t len;
01542 
01543         /* Check for received packets */
01544         while ( intelxl->rx.cons != intelxl->rx.prod ) {
01545 
01546                 /* Get next receive descriptor */
01547                 rx_idx = ( intelxl->rx.cons % INTELXL_RX_NUM_DESC );
01548                 rx_wb = &intelxl->rx.desc.rx[rx_idx].wb;
01549 
01550                 /* Stop if descriptor is still in use */
01551                 if ( ! ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_DD ) ) )
01552                         return;
01553 
01554                 /* Populate I/O buffer */
01555                 iobuf = intelxl->rx_iobuf[rx_idx];
01556                 intelxl->rx_iobuf[rx_idx] = NULL;
01557                 len = INTELXL_RX_WB_LEN ( le32_to_cpu ( rx_wb->len ) );
01558                 iob_put ( iobuf, len );
01559 
01560                 /* Find VLAN device, if applicable */
01561                 if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_VLAN ) ) {
01562                         tag = VLAN_TAG ( le16_to_cpu ( rx_wb->vlan ) );
01563                 } else {
01564                         tag = 0;
01565                 }
01566 
01567                 /* Hand off to network stack */
01568                 if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_RXE ) ) {
01569                         DBGC ( intelxl, "INTELXL %p RX %d error (length %zd, "
01570                                "flags %08x)\n", intelxl, rx_idx, len,
01571                                le32_to_cpu ( rx_wb->flags ) );
01572                         vlan_netdev_rx_err ( netdev, tag, iobuf, -EIO );
01573                 } else {
01574                         DBGC2 ( intelxl, "INTELXL %p RX %d complete (length "
01575                                 "%zd)\n", intelxl, rx_idx, len );
01576                         vlan_netdev_rx ( netdev, tag, iobuf );
01577                 }
01578                 intelxl->rx.cons++;
01579         }
01580 }
01581 
01582 /**
01583  * Poll for completed and received packets
01584  *
01585  * @v netdev            Network device
01586  */
01587 void intelxl_poll ( struct net_device *netdev ) {
01588         struct intelxl_nic *intelxl = netdev->priv;
01589 
01590         /* Poll for completed packets */
01591         intelxl_poll_tx ( netdev );
01592 
01593         /* Poll for received packets */
01594         intelxl_poll_rx ( netdev );
01595 
01596         /* Poll for admin events */
01597         intelxl_poll_admin ( netdev );
01598 
01599         /* Refill RX ring */
01600         intelxl_refill_rx ( intelxl );
01601 
01602         /* Rearm interrupt, since otherwise receive descriptors will
01603          * be written back only after a complete cacheline (four
01604          * packets) have been received.
01605          *
01606          * There is unfortunately no efficient way to determine
01607          * whether or not rearming the interrupt is necessary.  If we
01608          * are running inside a hypervisor (e.g. using a VF or PF as a
01609          * passed-through PCI device), then the MSI-X write is
01610          * redirected by the hypervisor to the real host APIC and the
01611          * host ISR then raises an interrupt within the guest.  We
01612          * therefore cannot poll the nominal MSI-X target location to
01613          * watch for the value being written.  We could read from the
01614          * INT_DYN_CTL register, but this is even less efficient than
01615          * just unconditionally rearming the interrupt.
01616          */
01617         writel ( INTELXL_INT_DYN_CTL_INTENA, intelxl->regs + intelxl->intr );
01618 }
01619 
01620 /** Network device operations */
01621 static struct net_device_operations intelxl_operations = {
01622         .open           = intelxl_open,
01623         .close          = intelxl_close,
01624         .transmit       = intelxl_transmit,
01625         .poll           = intelxl_poll,
01626 };
01627 
01628 /******************************************************************************
01629  *
01630  * PCI interface
01631  *
01632  ******************************************************************************
01633  */
01634 
01635 /**
01636  * Probe PCI device
01637  *
01638  * @v pci               PCI device
01639  * @ret rc              Return status code
01640  */
01641 static int intelxl_probe ( struct pci_device *pci ) {
01642         struct net_device *netdev;
01643         struct intelxl_nic *intelxl;
01644         uint32_t pfgen_portnum;
01645         uint32_t pflan_qalloc;
01646         int rc;
01647 
01648         /* Allocate and initialise net device */
01649         netdev = alloc_etherdev ( sizeof ( *intelxl ) );
01650         if ( ! netdev ) {
01651                 rc = -ENOMEM;
01652                 goto err_alloc;
01653         }
01654         netdev_init ( netdev, &intelxl_operations );
01655         intelxl = netdev->priv;
01656         pci_set_drvdata ( pci, netdev );
01657         netdev->dev = &pci->dev;
01658         memset ( intelxl, 0, sizeof ( *intelxl ) );
01659         intelxl->pf = PCI_FUNC ( pci->busdevfn );
01660         intelxl->intr = INTELXL_PFINT_DYN_CTL0;
01661         intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD,
01662                              &intelxl_admin_offsets );
01663         intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT,
01664                              &intelxl_admin_offsets );
01665         intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC,
01666                             sizeof ( intelxl->tx.desc.tx[0] ),
01667                             intelxl_context_tx );
01668         intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC,
01669                             sizeof ( intelxl->rx.desc.rx[0] ),
01670                             intelxl_context_rx );
01671 
01672         /* Fix up PCI device */
01673         adjust_pci_device ( pci );
01674 
01675         /* Map registers */
01676         intelxl->regs = ioremap ( pci->membase, INTELXL_BAR_SIZE );
01677         if ( ! intelxl->regs ) {
01678                 rc = -ENODEV;
01679                 goto err_ioremap;
01680         }
01681 
01682         /* Reset the NIC */
01683         if ( ( rc = intelxl_reset ( intelxl ) ) != 0 )
01684                 goto err_reset;
01685 
01686         /* Get port number and base queue number */
01687         pfgen_portnum = readl ( intelxl->regs + INTELXL_PFGEN_PORTNUM );
01688         intelxl->port = INTELXL_PFGEN_PORTNUM_PORT_NUM ( pfgen_portnum );
01689         pflan_qalloc = readl ( intelxl->regs + INTELXL_PFLAN_QALLOC );
01690         intelxl->base = INTELXL_PFLAN_QALLOC_FIRSTQ ( pflan_qalloc );
01691         DBGC ( intelxl, "INTELXL %p PF %d using port %d queues [%#04x-%#04x]\n",
01692                intelxl, intelxl->pf, intelxl->port, intelxl->base,
01693                INTELXL_PFLAN_QALLOC_LASTQ ( pflan_qalloc ) );
01694 
01695         /* Fetch MAC address and maximum frame size */
01696         if ( ( rc = intelxl_fetch_mac ( intelxl, netdev ) ) != 0 )
01697                 goto err_fetch_mac;
01698 
01699         /* Enable MSI-X dummy interrupt */
01700         if ( ( rc = intelxl_msix_enable ( intelxl, pci ) ) != 0 )
01701                 goto err_msix;
01702 
01703         /* Open admin queues */
01704         if ( ( rc = intelxl_open_admin ( intelxl ) ) != 0 )
01705                 goto err_open_admin;
01706 
01707         /* Clear PXE mode */
01708         if ( ( rc = intelxl_admin_clear_pxe ( intelxl ) ) != 0 )
01709                 goto err_admin_clear_pxe;
01710 
01711         /* Get switch configuration */
01712         if ( ( rc = intelxl_admin_switch ( intelxl ) ) != 0 )
01713                 goto err_admin_switch;
01714 
01715         /* Get VSI configuration */
01716         if ( ( rc = intelxl_admin_vsi ( intelxl ) ) != 0 )
01717                 goto err_admin_vsi;
01718 
01719         /* Configure switch for promiscuous mode */
01720         if ( ( rc = intelxl_admin_promisc ( intelxl ) ) != 0 )
01721                 goto err_admin_promisc;
01722 
01723         /* Configure queue register addresses */
01724         intelxl->tx.reg = INTELXL_QTX ( intelxl->queue );
01725         intelxl->tx.tail = ( intelxl->tx.reg + INTELXL_QXX_TAIL );
01726         intelxl->rx.reg = INTELXL_QRX ( intelxl->queue );
01727         intelxl->rx.tail = ( intelxl->rx.reg + INTELXL_QXX_TAIL );
01728 
01729         /* Configure interrupt causes */
01730         writel ( ( INTELXL_QINT_TQCTL_NEXTQ_INDX_NONE |
01731                    INTELXL_QINT_TQCTL_CAUSE_ENA ),
01732                  intelxl->regs + INTELXL_QINT_TQCTL ( intelxl->queue ) );
01733         writel ( ( INTELXL_QINT_RQCTL_NEXTQ_INDX ( intelxl->queue ) |
01734                    INTELXL_QINT_RQCTL_NEXTQ_TYPE_TX |
01735                    INTELXL_QINT_RQCTL_CAUSE_ENA ),
01736                  intelxl->regs + INTELXL_QINT_RQCTL ( intelxl->queue ) );
01737         writel ( ( INTELXL_PFINT_LNKLST0_FIRSTQ_INDX ( intelxl->queue ) |
01738                    INTELXL_PFINT_LNKLST0_FIRSTQ_TYPE_RX ),
01739                  intelxl->regs + INTELXL_PFINT_LNKLST0 );
01740         writel ( INTELXL_PFINT_ICR0_ENA_ADMINQ,
01741                  intelxl->regs + INTELXL_PFINT_ICR0_ENA );
01742 
01743         /* Register network device */
01744         if ( ( rc = register_netdev ( netdev ) ) != 0 )
01745                 goto err_register_netdev;
01746 
01747         /* Set initial link state */
01748         intelxl_admin_link ( netdev );
01749 
01750         return 0;
01751 
01752         unregister_netdev ( netdev );
01753  err_register_netdev:
01754  err_admin_promisc:
01755  err_admin_vsi:
01756  err_admin_switch:
01757  err_admin_clear_pxe:
01758         intelxl_close_admin ( intelxl );
01759  err_open_admin:
01760         intelxl_msix_disable ( intelxl, pci );
01761  err_msix:
01762  err_fetch_mac:
01763         intelxl_reset ( intelxl );
01764  err_reset:
01765         iounmap ( intelxl->regs );
01766  err_ioremap:
01767         netdev_nullify ( netdev );
01768         netdev_put ( netdev );
01769  err_alloc:
01770         return rc;
01771 }
01772 
01773 /**
01774  * Remove PCI device
01775  *
01776  * @v pci               PCI device
01777  */
01778 static void intelxl_remove ( struct pci_device *pci ) {
01779         struct net_device *netdev = pci_get_drvdata ( pci );
01780         struct intelxl_nic *intelxl = netdev->priv;
01781 
01782         /* Unregister network device */
01783         unregister_netdev ( netdev );
01784 
01785         /* Close admin queues */
01786         intelxl_close_admin ( intelxl );
01787 
01788         /* Disable MSI-X dummy interrupt */
01789         intelxl_msix_disable ( intelxl, pci );
01790 
01791         /* Reset the NIC */
01792         intelxl_reset ( intelxl );
01793 
01794         /* Free network device */
01795         iounmap ( intelxl->regs );
01796         netdev_nullify ( netdev );
01797         netdev_put ( netdev );
01798 }
01799 
01800 /** PCI device IDs */
01801 static struct pci_device_id intelxl_nics[] = {
01802         PCI_ROM ( 0x8086, 0x1572, "x710-sfp", "X710 10GbE SFP+", 0 ),
01803         PCI_ROM ( 0x8086, 0x1574, "xl710-qemu", "Virtual XL710", 0 ),
01804         PCI_ROM ( 0x8086, 0x1580, "xl710-kx-b", "XL710 40GbE backplane", 0 ),
01805         PCI_ROM ( 0x8086, 0x1581, "xl710-kx-c", "XL710 10GbE backplane", 0 ),
01806         PCI_ROM ( 0x8086, 0x1583, "xl710-qda2", "XL710 40GbE QSFP+", 0 ),
01807         PCI_ROM ( 0x8086, 0x1584, "xl710-qda1", "XL710 40GbE QSFP+", 0 ),
01808         PCI_ROM ( 0x8086, 0x1585, "x710-qsfp", "X710 10GbE QSFP+", 0 ),
01809         PCI_ROM ( 0x8086, 0x1586, "x710-10gt", "X710 10GBASE-T", 0 ),
01810         PCI_ROM ( 0x8086, 0x1587, "x710-kr2", "XL710 20GbE backplane", 0 ),
01811         PCI_ROM ( 0x8086, 0x1588, "x710-kr2-a", "XL710 20GbE backplane", 0 ),
01812         PCI_ROM ( 0x8086, 0x1589, "x710-10gt4", "X710 10GBASE-T4", 0 ),
01813         PCI_ROM ( 0x8086, 0x158a, "xxv710", "XXV710 25GbE backplane", 0 ),
01814         PCI_ROM ( 0x8086, 0x158b, "xxv710-sfp28", "XXV710 25GbE SFP28", 0 ),
01815         PCI_ROM ( 0x8086, 0x37ce, "x722-kx", "X722 10GbE backplane", 0 ),
01816         PCI_ROM ( 0x8086, 0x37cf, "x722-qsfp", "X722 10GbE QSFP+", 0 ),
01817         PCI_ROM ( 0x8086, 0x37d0, "x722-sfp", "X722 10GbE SFP+", 0 ),
01818         PCI_ROM ( 0x8086, 0x37d1, "x722-1gt", "X722 1GBASE-T", 0 ),
01819         PCI_ROM ( 0x8086, 0x37d2, "x722-10gt", "X722 10GBASE-T", 0 ),
01820         PCI_ROM ( 0x8086, 0x37d3, "x722-sfp-i", "X722 10GbE SFP+", 0 ),
01821 };
01822 
01823 /** PCI driver */
01824 struct pci_driver intelxl_driver __pci_driver = {
01825         .ids = intelxl_nics,
01826         .id_count = ( sizeof ( intelxl_nics ) / sizeof ( intelxl_nics[0] ) ),
01827         .probe = intelxl_probe,
01828         .remove = intelxl_remove,
01829 };