iPXE
vxge_main.c
Go to the documentation of this file.
00001 /*
00002  * vxge-main.c: iPXE driver for Neterion Inc's X3100 Series 10GbE
00003  *              PCIe I/O Virtualized Server Adapter.
00004  *
00005  * Copyright(c) 2002-2010 Neterion Inc.
00006  *
00007  * This software may be used and distributed according to the terms of
00008  * the GNU General Public License (GPL), incorporated herein by
00009  * reference.  Drivers based on or derived from this code fall under
00010  * the GPL and must retain the authorship, copyright and license
00011  * notice.
00012  *
00013  */
00014 
00015 FILE_LICENCE(GPL2_ONLY);
00016 
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <ipxe/io.h>
00021 #include <errno.h>
00022 #include <byteswap.h>
00023 #include <ipxe/pci.h>
00024 #include <ipxe/malloc.h>
00025 #include <ipxe/if_ether.h>
00026 #include <ipxe/ethernet.h>
00027 #include <ipxe/iobuf.h>
00028 #include <ipxe/netdevice.h>
00029 #include <ipxe/timer.h>
00030 #include <nic.h>
00031 
00032 #include "vxge_main.h"
00033 #include "vxge_reg.h"
00034 
00035 /* function modes strings */
00036 static char *vxge_func_mode_names[] = {
00037         "Single Function - 1 func, 17 vpath",
00038         "Multi Function 8 - 8 func, 2 vpath per func",
00039         "SRIOV 17 - 17 VF, 1 vpath per VF",
00040         "WLPEX/SharedIO 17 - 17 VH, 1 vpath/func/hierarchy",
00041         "WLPEX/SharedIO 8 - 8 VH, 2 vpath/func/hierarchy",
00042         "Multi Function 17 - 17 func, 1 vpath per func",
00043         "SRIOV 8 - 1 PF, 7 VF, 2 vpath per VF",
00044         "SRIOV 4 - 1 PF, 3 VF, 4 vpath per VF",
00045         "Multi Function 2 - 2 func, 8 vpath per func",
00046         "Multi Function 4 - 4 func, 4 vpath per func",
00047         "WLPEX/SharedIO 4 - 17 func, 1 vpath per func (PCIe ARI)",
00048         "Multi Function 8 - For ESX DirectIO - 8 func, 2 vpath per func",
00049 };
00050 
00051 static inline int is_vxge_card_up(struct vxgedev *vdev)
00052 {
00053         return test_bit(__VXGE_STATE_CARD_UP, vdev->state);
00054 }
00055 
00056 /*
00057  * vxge_xmit_compl
00058  *
00059  * If an interrupt was raised to indicate DMA complete of the Tx packet,
00060  * this function is called. It identifies the last TxD whose buffer was
00061  * freed and frees all skbs whose data have already DMA'ed into the NICs
00062  * internal memory.
00063  */
00064 enum vxge_hw_status
00065 vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw,
00066                 struct vxge_hw_fifo_txd *txdp, enum vxge_hw_fifo_tcode tcode)
00067 {
00068         struct net_device *netdev;
00069         struct io_buffer *tx_iob = NULL;
00070 
00071         vxge_trace();
00072 
00073         netdev = fifo_hw->vpathh->hldev->ndev;
00074 
00075         tx_iob = (struct io_buffer *)(intptr_t)txdp->host_control;
00076 
00077         if (tcode == VXGE_HW_FIFO_T_CODE_OK) {
00078                 netdev_tx_complete(netdev, tx_iob);
00079         } else {
00080                 netdev_tx_complete_err(netdev, tx_iob, -EINVAL);
00081                 vxge_debug(VXGE_ERR, "%s: transmit failed, tcode %d\n",
00082                                 netdev->name, tcode);
00083         }
00084 
00085         memset(txdp, 0, sizeof(struct vxge_hw_fifo_txd));
00086 
00087         return VXGE_HW_OK;
00088 }
00089 
00090 /* reset vpaths */
00091 enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
00092 {
00093         enum vxge_hw_status status = VXGE_HW_OK;
00094         struct __vxge_hw_virtualpath *vpath;
00095 
00096         vxge_trace();
00097 
00098         vpath = vdev->vpath.vpathh;
00099 
00100         if (vpath) {
00101                 if ((status = vxge_hw_vpath_reset(vpath)) == VXGE_HW_OK) {
00102                         if (is_vxge_card_up(vdev) &&
00103                                 (status = vxge_hw_vpath_recover_from_reset(
00104                                         vpath)) != VXGE_HW_OK) {
00105                                 vxge_debug(VXGE_ERR, "vxge_hw_vpath_recover_"
00106                                         "from_reset failed\n");
00107                                 return status;
00108                         } else {
00109                                 status = __vxge_hw_vpath_reset_check(vpath);
00110                                 if (status != VXGE_HW_OK) {
00111                                         vxge_debug(VXGE_ERR,
00112                                         "__vxge_hw_vpath_reset_check error\n");
00113                                         return status;
00114                                 }
00115                         }
00116                 } else {
00117                         vxge_debug(VXGE_ERR, "vxge_hw_vpath_reset failed\n");
00118                         return status;
00119                 }
00120         }
00121         return status;
00122 }
00123 
00124 /* close vpaths */
00125 void vxge_close_vpaths(struct vxgedev *vdev)
00126 {
00127 
00128         if (vdev->vpath.vpathh && vdev->vpath.is_open)
00129                 vxge_hw_vpath_close(vdev->vpath.vpathh);
00130 
00131         vdev->vpath.is_open = 0;
00132         vdev->vpath.vpathh = NULL;
00133 }
00134 
00135 /* open vpaths */
00136 int vxge_open_vpaths(struct vxgedev *vdev)
00137 {
00138         enum vxge_hw_status status;
00139         struct __vxge_hw_device *hldev;
00140 
00141         hldev = (struct __vxge_hw_device  *)pci_get_drvdata(vdev->pdev);
00142 
00143         vdev->vpath.vpathh = &hldev->virtual_path;
00144         vdev->vpath.fifo.ndev = vdev->ndev;
00145         vdev->vpath.fifo.pdev = vdev->pdev;
00146         vdev->vpath.fifo.fifoh = &hldev->virtual_path.fifoh;
00147         vdev->vpath.ring.ndev = vdev->ndev;
00148         vdev->vpath.ring.pdev = vdev->pdev;
00149         vdev->vpath.ring.ringh = &hldev->virtual_path.ringh;
00150 
00151         status = vxge_hw_vpath_open(vdev->devh, &vdev->vpath);
00152         if (status == VXGE_HW_OK) {
00153                 vdev->vpath.is_open = 1;
00154         } else {
00155                 vxge_debug(VXGE_ERR,
00156                         "%s: vpath: %d failed to open "
00157                         "with status: %d\n",
00158                         vdev->ndev->name, vdev->vpath.device_id,
00159                         status);
00160                 vxge_close_vpaths(vdev);
00161                 return status;
00162         }
00163 
00164         hldev->vpaths_deployed |= vxge_mBIT(vdev->vpath.vpathh->vp_id);
00165 
00166         return VXGE_HW_OK;
00167 }
00168 
00169 /** Functions that implement the iPXE driver API **/
00170 
00171 /**
00172  * vxge_xmit
00173  * @skb : the socket buffer containing the Tx data.
00174  * @dev : device pointer.
00175  *
00176  * This function is the Tx entry point of the driver. Neterion NIC supports
00177  * certain protocol assist features on Tx side, namely  CSO, S/G, LSO.
00178  */
00179 static int
00180 vxge_xmit(struct net_device *dev, struct io_buffer *iobuf)
00181 {
00182         struct vxge_fifo *fifo = NULL;
00183         struct vxgedev *vdev = NULL;
00184         struct __vxge_hw_fifo *fifoh;
00185         struct vxge_hw_fifo_txd *txdp;
00186 
00187         vxge_trace();
00188 
00189         vdev = (struct vxgedev *)netdev_priv(dev);
00190 
00191         if (!is_vxge_card_up(vdev)) {
00192                 vxge_debug(VXGE_ERR,
00193                         "%s: vdev not initialized\n", dev->name);
00194                 return -EIO;
00195         }
00196 
00197         if (!netdev_link_ok(dev)) {
00198                 vxge_debug(VXGE_ERR,
00199                         "%s: Link down, transmit failed\n", dev->name);
00200                 return -ENETDOWN;
00201         }
00202 
00203         fifo = &vdev->vpath.fifo;
00204         fifoh = fifo->fifoh;
00205 
00206         txdp = vxge_hw_fifo_free_txdl_get(fifoh);
00207         if (!txdp) {
00208                 vxge_debug(VXGE_ERR,
00209                         "%s: Out of tx descriptors\n", dev->name);
00210                 return -ENOBUFS;
00211         }
00212 
00213         vxge_debug(VXGE_XMIT, "%s: %s:%d fifoh offset= %d\n",
00214                 dev->name, __func__, __LINE__, fifoh->sw_offset);
00215 
00216         vxge_hw_fifo_txdl_buffer_set(fifoh, txdp, iobuf);
00217 
00218         vxge_hw_fifo_txdl_post(fifoh, txdp);
00219 
00220         return 0;
00221 }
00222 
00223 /*
00224  *  vxge_poll
00225  *  @ndev: net device pointer
00226  *
00227  *  This function acks the interrupt. It polls for rx packets
00228  *  and send to upper layer. It also checks for tx completion
00229  *  and frees iobs.
00230  */
00231 static void vxge_poll(struct net_device *ndev)
00232 {
00233         struct __vxge_hw_device  *hldev;
00234         struct vxgedev *vdev;
00235 
00236         vxge_debug(VXGE_POLL, "%s:%d \n", __func__, __LINE__);
00237 
00238         vdev = (struct vxgedev *)netdev_priv(ndev);
00239         hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
00240 
00241         if (!is_vxge_card_up(vdev))
00242                 return;
00243 
00244         /* process alarm and acknowledge the interrupts */
00245         vxge_hw_device_begin_irq(hldev);
00246 
00247         vxge_hw_vpath_poll_tx(&hldev->virtual_path.fifoh);
00248 
00249         vxge_hw_vpath_poll_rx(&hldev->virtual_path.ringh);
00250 }
00251 
00252 /*
00253  * vxge_irq - enable or Disable interrupts
00254  *
00255  * @netdev   netdevice structure reference
00256  * @action   requested interrupt action
00257  */
00258 static void vxge_irq(struct net_device *netdev __unused, int action)
00259 {
00260         struct __vxge_hw_device  *hldev;
00261         struct vxgedev *vdev;
00262 
00263         vxge_debug(VXGE_INFO,
00264                 "%s:%d action(%d)\n", __func__, __LINE__, action);
00265 
00266         vdev = (struct vxgedev *)netdev_priv(netdev);
00267         hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
00268 
00269         switch (action) {
00270         case DISABLE:
00271                 vxge_hw_device_mask_all(hldev);
00272                 break;
00273         default:
00274                 vxge_hw_device_unmask_all(hldev);
00275                 break;
00276         }
00277 }
00278 
00279 /**
00280  * vxge_open
00281  * @dev: pointer to the device structure.
00282  *
00283  * This function is the open entry point of the driver. It mainly calls a
00284  * function to allocate Rx buffers and inserts them into the buffer
00285  * descriptors and then enables the Rx part of the NIC.
00286  * Return value: '0' on success and an appropriate (-)ve integer as
00287  * defined in errno.h file on failure.
00288  */
00289 int
00290 vxge_open(struct net_device *dev)
00291 {
00292         enum vxge_hw_status status;
00293         struct vxgedev *vdev;
00294         struct __vxge_hw_device *hldev;
00295         int ret = 0;
00296 
00297         vxge_debug(VXGE_INFO, "%s: %s:%d\n",
00298                         VXGE_DRIVER_NAME, __func__, __LINE__);
00299 
00300         vdev = (struct vxgedev *)netdev_priv(dev);
00301         hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
00302 
00303         /* make sure you have link off by default every time Nic is
00304          * initialized */
00305         netdev_link_down(dev);
00306 
00307         /* Open VPATHs */
00308         status = vxge_open_vpaths(vdev);
00309         if (status != VXGE_HW_OK) {
00310                 vxge_debug(VXGE_ERR, "%s: fatal: Vpath open failed\n",
00311                                 VXGE_DRIVER_NAME);
00312                 ret = -EPERM;
00313                 goto out0;
00314         }
00315 
00316         vdev->mtu = VXGE_HW_DEFAULT_MTU;
00317         /* set initial mtu before enabling the device */
00318         status = vxge_hw_vpath_mtu_set(vdev->vpath.vpathh, vdev->mtu);
00319         if (status != VXGE_HW_OK) {
00320                 vxge_debug(VXGE_ERR,
00321                         "%s: fatal: can not set new MTU\n", dev->name);
00322                 ret = -EPERM;
00323                 goto out2;
00324         }
00325         vxge_debug(VXGE_INFO,
00326                 "%s: MTU is %d\n", vdev->ndev->name, vdev->mtu);
00327 
00328         set_bit(__VXGE_STATE_CARD_UP, vdev->state);
00329 
00330         wmb();
00331 
00332         if (vxge_hw_device_link_state_get(vdev->devh) == VXGE_HW_LINK_UP) {
00333                 netdev_link_up(vdev->ndev);
00334                 vxge_debug(VXGE_INFO, "%s: Link Up\n", vdev->ndev->name);
00335         }
00336 
00337         vxge_hw_device_intr_enable(hldev);
00338 
00339         vxge_hw_vpath_enable(vdev->vpath.vpathh);
00340         wmb();
00341         vxge_hw_vpath_rx_doorbell_init(vdev->vpath.vpathh);
00342 
00343         goto out0;
00344 
00345 out2:
00346         vxge_close_vpaths(vdev);
00347 out0:
00348         vxge_debug(VXGE_INFO, "%s: %s:%d  Exiting...\n",
00349                                 dev->name, __func__, __LINE__);
00350         return ret;
00351 }
00352 
00353 /**
00354  * vxge_close
00355  * @dev: device pointer.
00356  *
00357  * This is the stop entry point of the driver. It needs to undo exactly
00358  * whatever was done by the open entry point, thus it's usually referred to
00359  * as the close function.Among other things this function mainly stops the
00360  * Rx side of the NIC and frees all the Rx buffers in the Rx rings.
00361  * Return value: '0' on success and an appropriate (-)ve integer as
00362  * defined in errno.h file on failure.
00363  */
00364 static void vxge_close(struct net_device *dev)
00365 {
00366         struct vxgedev *vdev;
00367         struct __vxge_hw_device *hldev;
00368 
00369         vxge_debug(VXGE_INFO, "%s: %s:%d\n",
00370                 dev->name, __func__, __LINE__);
00371 
00372         vdev = (struct vxgedev *)netdev_priv(dev);
00373         hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
00374 
00375         if (!is_vxge_card_up(vdev))
00376                 return;
00377 
00378         clear_bit(__VXGE_STATE_CARD_UP, vdev->state);
00379 
00380         vxge_hw_vpath_set_zero_rx_frm_len(hldev);
00381 
00382         netdev_link_down(vdev->ndev);
00383         vxge_debug(VXGE_INFO, "%s: Link Down\n", vdev->ndev->name);
00384 
00385         /* Note that at this point xmit() is stopped by upper layer */
00386         vxge_hw_device_intr_disable(hldev);
00387 
00388         /* Multi function shares INTA, hence we should
00389          * leave it in enabled state
00390          */
00391         if (is_mf(hldev->hw_info.function_mode))
00392                 vxge_hw_device_unmask_all(hldev);
00393 
00394         vxge_reset_all_vpaths(vdev);
00395 
00396         vxge_close_vpaths(vdev);
00397 
00398         vxge_debug(VXGE_INFO,
00399                 "%s: %s:%d  Exiting...\n", dev->name, __func__, __LINE__);
00400 }
00401 
00402 static struct net_device_operations vxge_operations;
00403 
00404 int vxge_device_register(struct __vxge_hw_device *hldev,
00405                                 struct vxgedev **vdev_out)
00406 {
00407         struct net_device *ndev;
00408         struct vxgedev *vdev;
00409         int ret = 0;
00410 
00411         *vdev_out = NULL;
00412 
00413         ndev = alloc_etherdev(sizeof(struct vxgedev));
00414         if (ndev == NULL) {
00415                 vxge_debug(VXGE_ERR, "%s : device allocation failed\n",
00416                                 __func__);
00417                 ret = -ENODEV;
00418                 goto _out0;
00419         }
00420 
00421         vxge_debug(VXGE_INFO, "%s:%d  netdev registering\n",
00422                 __func__, __LINE__);
00423         vdev = netdev_priv(ndev);
00424         memset(vdev, 0, sizeof(struct vxgedev));
00425 
00426         vdev->ndev = ndev;
00427         vdev->devh = hldev;
00428         vdev->pdev = hldev->pdev;
00429 
00430         ndev->dev = &vdev->pdev->dev;
00431         /* Associate vxge-specific network operations operations with
00432          * generic network device layer */
00433         netdev_init(ndev, &vxge_operations);
00434 
00435         memcpy(ndev->hw_addr,
00436                 (u8 *)hldev->hw_info.mac_addrs[hldev->first_vp_id], ETH_ALEN);
00437 
00438         if (register_netdev(ndev)) {
00439                 vxge_debug(VXGE_ERR, "%s : device registration failed!\n",
00440                         __func__);
00441                 ret = -ENODEV;
00442                 goto _out2;
00443         }
00444 
00445         /* Leave link state as off at this point, when the link change
00446          * interrupt comes the state will be automatically changed to
00447          * the right state.
00448          */
00449 
00450         vxge_debug(VXGE_INFO, "%s: Ethernet device registered\n",
00451                 VXGE_DRIVER_NAME);
00452 
00453         *vdev_out = vdev;
00454 
00455         return ret;
00456 _out2:
00457         netdev_put(ndev);
00458 _out0:
00459         return ret;
00460 }
00461 
00462 /*
00463  * vxge_device_unregister
00464  *
00465  * This function will unregister and free network device
00466  */
00467 void
00468 vxge_device_unregister(struct __vxge_hw_device *hldev)
00469 {
00470         struct net_device *ndev;
00471 
00472         ndev = hldev->ndev;
00473 
00474         unregister_netdev(ndev);
00475         netdev_nullify(ndev);
00476         netdev_put(ndev);
00477 
00478         vxge_debug(VXGE_INFO, "%s: ethernet device unregistered\n",
00479                                 VXGE_DRIVER_NAME);
00480 }
00481 
00482 /**
00483  * vxge_probe
00484  * @pdev : structure containing the PCI related information of the device.
00485  * @id: List of PCI devices supported by the driver listed in vxge_id_table.
00486  * Description:
00487  * This function is called when a new PCI device gets detected and initializes
00488  * it.
00489  * Return value:
00490  * returns 0 on success and negative on failure.
00491  *
00492  */
00493 static int
00494 vxge_probe(struct pci_device *pdev)
00495 {
00496         struct __vxge_hw_device  *hldev;
00497         enum vxge_hw_status status;
00498         int ret = 0;
00499         u64 vpath_mask = 0;
00500         struct vxgedev *vdev;
00501         int i;
00502         u8 revision, titan1;
00503         u32 function_mode;
00504         unsigned long mmio_start, mmio_len;
00505         void *bar0;
00506         struct vxge_hw_device_hw_info hw_info;
00507         struct vxge_hw_device_version *fw_version;
00508 
00509         vxge_debug(VXGE_INFO, "vxge_probe for device " PCI_FMT "\n",
00510                         PCI_ARGS(pdev));
00511 
00512         pci_read_config_byte(pdev, PCI_REVISION, &revision);
00513         titan1 = is_titan1(pdev->device, revision);
00514 
00515         mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
00516         mmio_len   = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
00517         vxge_debug(VXGE_INFO, "mmio_start: %#08lx, mmio_len: %#08lx\n",
00518                         mmio_start, mmio_len);
00519 
00520         /* sets the bus master */
00521         adjust_pci_device(pdev);
00522 
00523         bar0 = ioremap(mmio_start, mmio_len);
00524         if (!bar0) {
00525                 vxge_debug(VXGE_ERR,
00526                         "%s : cannot remap io memory bar0\n", __func__);
00527                 ret = -ENODEV;
00528                 goto _exit0;
00529         }
00530 
00531         status = vxge_hw_device_hw_info_get(pdev, bar0, &hw_info);
00532         if (status != VXGE_HW_OK) {
00533                 vxge_debug(VXGE_ERR,
00534                         "%s: Reading of hardware info failed.\n",
00535                         VXGE_DRIVER_NAME);
00536                 ret = -EINVAL;
00537                 goto _exit1;
00538         }
00539 
00540         if (hw_info.func_id != 0) {
00541                 /* Non zero function, So do not load the driver */
00542                 iounmap(bar0);
00543                 pci_set_drvdata(pdev, NULL);
00544                 return -EINVAL;
00545         }
00546 
00547 
00548         vpath_mask = hw_info.vpath_mask;
00549         if (vpath_mask == 0) {
00550                 vxge_debug(VXGE_ERR,
00551                         "%s: No vpaths available in device\n",
00552                         VXGE_DRIVER_NAME);
00553                 ret = -EINVAL;
00554                 goto _exit1;
00555         }
00556         vxge_debug(VXGE_INFO,
00557                 "%s:%d  Vpath mask = %llx\n", __func__, __LINE__,
00558                 (unsigned long long)vpath_mask);
00559 
00560         fw_version = &hw_info.fw_version;
00561         /* fail the driver loading if firmware is incompatible */
00562         if ((fw_version->major != VXGE_CERT_FW_VER_MAJOR) ||
00563                 (fw_version->minor < VXGE_CERT_FW_VER_MINOR)) {
00564                 printf("%s: Adapter's current firmware version: %d.%d.%d\n",
00565                         VXGE_DRIVER_NAME, fw_version->major,
00566                         fw_version->minor, fw_version->build);
00567 
00568                 printf("%s: Upgrade firmware to version %d.%d.%d\n",
00569                         VXGE_DRIVER_NAME, VXGE_CERT_FW_VER_MAJOR,
00570                         VXGE_CERT_FW_VER_MINOR, VXGE_CERT_FW_VER_BUILD);
00571 
00572                 ret = -EACCES;
00573                 goto _exit1;
00574         }
00575 
00576         status = vxge_hw_device_initialize(&hldev, bar0, pdev, titan1);
00577         if (status != VXGE_HW_OK) {
00578                 vxge_debug(VXGE_ERR,
00579                         "Failed to initialize device (%d)\n", status);
00580                         ret = -EINVAL;
00581                         goto _exit1;
00582         }
00583         memcpy(&hldev->hw_info, &hw_info,
00584                 sizeof(struct vxge_hw_device_hw_info));
00585 
00586         /* find the vpath id of the first available one */
00587         for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++)
00588                 if (vpath_mask & vxge_mBIT(i)) {
00589                         hldev->first_vp_id = i;
00590                         break;
00591                 }
00592         /* if FCS stripping is not disabled in MAC fail driver load */
00593         if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) {
00594                 vxge_debug(VXGE_ERR,
00595                         "%s: FCS stripping is not disabled in MAC"
00596                         " failing driver load\n", VXGE_DRIVER_NAME);
00597                 ret = -EINVAL;
00598                 goto _exit2;
00599         }
00600 
00601         /* Read function mode */
00602         status = vxge_hw_get_func_mode(hldev, &function_mode);
00603         if (status != VXGE_HW_OK)
00604                 goto _exit2;
00605 
00606         hldev->hw_info.function_mode = function_mode;
00607 
00608         /* set private device info */
00609         pci_set_drvdata(pdev, hldev);
00610 
00611         if (vxge_device_register(hldev, &vdev)) {
00612                 ret = -EINVAL;
00613                 goto _exit2;
00614         }
00615 
00616         /* set private HW device info */
00617         hldev->ndev = vdev->ndev;
00618         hldev->vdev = vdev;
00619         hldev->pdev = pdev;
00620         vdev->mtu = VXGE_HW_DEFAULT_MTU;
00621         vdev->bar0 = bar0;
00622         vdev->titan1 = titan1;
00623         /* Virtual Path count */
00624         vdev->vpath.device_id = hldev->first_vp_id;
00625         vdev->vpath.vdev = vdev;
00626         memcpy((u8 *)vdev->vpath.macaddr,
00627                         (u8 *)hldev->hw_info.mac_addrs[hldev->first_vp_id],
00628                         ETH_ALEN);
00629 
00630         hldev->hw_info.serial_number[VXGE_HW_INFO_LEN - 1] = '\0';
00631         hldev->hw_info.product_desc[VXGE_HW_INFO_LEN - 1] = '\0';
00632         hldev->hw_info.part_number[VXGE_HW_INFO_LEN - 1] = '\0';
00633 
00634         vxge_debug(VXGE_INFO, "%s: Neterion %s Server Adapter\n",
00635                 VXGE_DRIVER_NAME, hldev->hw_info.product_desc);
00636         vxge_debug(VXGE_INFO, "%s: SERIAL NUMBER: %s\n",
00637                 VXGE_DRIVER_NAME, hldev->hw_info.serial_number);
00638         vxge_debug(VXGE_INFO, "%s: PART NUMBER: %s\n",
00639                 VXGE_DRIVER_NAME, hldev->hw_info.part_number);
00640         vxge_debug(VXGE_INFO, "%s: MAC ADDR: %s\n",
00641                 VXGE_DRIVER_NAME, eth_ntoa(vdev->vpath.macaddr));
00642         vxge_debug(VXGE_INFO,
00643                 "%s: Firmware version : %s Date : %s\n", VXGE_DRIVER_NAME,
00644                 hldev->hw_info.fw_version.version,
00645                 hldev->hw_info.fw_date.date);
00646         vxge_debug(VXGE_INFO, "%s: %s Enabled\n",
00647                         VXGE_DRIVER_NAME, vxge_func_mode_names[function_mode]);
00648 
00649         vxge_debug(VXGE_INFO, "%s: %s:%d  Probe Exiting...\n",
00650                 VXGE_DRIVER_NAME, __func__, __LINE__);
00651 
00652         return 0;
00653 
00654 _exit2:
00655         vxge_hw_device_terminate(hldev);
00656 _exit1:
00657         iounmap(bar0);
00658 _exit0:
00659         pci_set_drvdata(pdev, NULL);
00660         printf("%s: WARNING!! Driver loading failed!!\n",
00661                 VXGE_DRIVER_NAME);
00662 
00663         return ret;
00664 }
00665 
00666 /**
00667  * vxge_remove - Free the PCI device
00668  * @pdev: structure containing the PCI related information of the device.
00669  * Description: This function is called by the Pci subsystem to release a
00670  * PCI device and free up all resource held up by the device.
00671  */
00672 static void
00673 vxge_remove(struct pci_device *pdev)
00674 {
00675         struct __vxge_hw_device  *hldev;
00676         struct vxgedev *vdev = NULL;
00677         struct net_device *ndev;
00678 
00679         vxge_debug(VXGE_INFO,
00680                 "%s:%d\n", __func__, __LINE__);
00681         hldev = (struct __vxge_hw_device  *) pci_get_drvdata(pdev);
00682         if (hldev == NULL)
00683                 return;
00684 
00685         ndev = hldev->ndev;
00686         vdev = netdev_priv(ndev);
00687 
00688         iounmap(vdev->bar0);
00689 
00690         vxge_device_unregister(hldev);
00691 
00692         vxge_debug(VXGE_INFO,
00693                 "%s:%d  Device unregistered\n", __func__, __LINE__);
00694 
00695         vxge_hw_device_terminate(hldev);
00696         pci_set_drvdata(pdev, NULL);
00697 }
00698 
00699 /* vxge net device operations */
00700 static struct net_device_operations vxge_operations = {
00701         .open           = vxge_open,
00702         .close          = vxge_close,
00703         .transmit       = vxge_xmit,
00704         .poll           = vxge_poll,
00705         .irq            = vxge_irq,
00706 };
00707 
00708 static struct pci_device_id vxge_main_nics[] = {
00709         /* If you change this, also adjust vxge_nics[] in vxge.c */
00710         PCI_ID(0x17d5, 0x5833, "vxge-x3100", "Neterion X3100 Series", 0),
00711 };
00712 
00713 struct pci_driver vxge_driver __pci_driver = {
00714         .ids = vxge_main_nics,
00715         .id_count = (sizeof(vxge_main_nics) / sizeof(vxge_main_nics[0])),
00716         .probe = vxge_probe,
00717         .remove = vxge_remove,
00718 };