776 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */3 4#include <linux/types.h>5#include <linux/module.h>6#include <linux/pci.h>7#include <linux/netdevice.h>8#include <linux/string.h>9#include <linux/etherdevice.h>10#include <linux/phylink.h>11#include <net/ip.h>12#include <linux/if_vlan.h>13 14#include "../libwx/wx_type.h"15#include "../libwx/wx_lib.h"16#include "../libwx/wx_hw.h"17#include "txgbe_type.h"18#include "txgbe_hw.h"19#include "txgbe_phy.h"20#include "txgbe_irq.h"21#include "txgbe_fdir.h"22#include "txgbe_ethtool.h"23 24char txgbe_driver_name[] = "txgbe";25 26/* txgbe_pci_tbl - PCI Device ID Table27 *28 * Wildcard entries (PCI_ANY_ID) should come last29 * Last entry must be all 0s30 *31 * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,32 * Class, Class Mask, private data (not used) }33 */34static const struct pci_device_id txgbe_pci_tbl[] = {35 { PCI_VDEVICE(WANGXUN, TXGBE_DEV_ID_SP1000), 0},36 { PCI_VDEVICE(WANGXUN, TXGBE_DEV_ID_WX1820), 0},37 /* required last entry */38 { .device = 0 }39};40 41#define DEFAULT_DEBUG_LEVEL_SHIFT 342 43static void txgbe_check_minimum_link(struct wx *wx)44{45 struct pci_dev *pdev;46 47 pdev = wx->pdev;48 pcie_print_link_status(pdev);49}50 51/**52 * txgbe_enumerate_functions - Get the number of ports this device has53 * @wx: wx structure54 *55 * This function enumerates the phsyical functions co-located on a single slot,56 * in order to determine how many ports a device has. This is most useful in57 * determining the required GT/s of PCIe bandwidth necessary for optimal58 * performance.59 **/60static int txgbe_enumerate_functions(struct wx *wx)61{62 struct pci_dev *entry, *pdev = wx->pdev;63 int physfns = 0;64 65 list_for_each_entry(entry, &pdev->bus->devices, bus_list) {66 /* When the devices on the bus don't all match our device ID,67 * we can't reliably determine the correct number of68 * functions. This can occur if a function has been direct69 * attached to a virtual machine using VT-d.70 */71 if (entry->vendor != pdev->vendor ||72 entry->device != pdev->device)73 return -EINVAL;74 75 physfns++;76 }77 78 return physfns;79}80 81static void txgbe_up_complete(struct wx *wx)82{83 struct net_device *netdev = wx->netdev;84 85 txgbe_reinit_gpio_intr(wx);86 wx_control_hw(wx, true);87 wx_configure_vectors(wx);88 89 /* make sure to complete pre-operations */90 smp_mb__before_atomic();91 wx_napi_enable_all(wx);92 93 phylink_start(wx->phylink);94 95 /* clear any pending interrupts, may auto mask */96 rd32(wx, WX_PX_IC(0));97 rd32(wx, WX_PX_IC(1));98 rd32(wx, WX_PX_MISC_IC);99 txgbe_irq_enable(wx, true);100 101 /* enable transmits */102 netif_tx_start_all_queues(netdev);103}104 105static void txgbe_reset(struct wx *wx)106{107 struct net_device *netdev = wx->netdev;108 u8 old_addr[ETH_ALEN];109 int err;110 111 err = txgbe_reset_hw(wx);112 if (err != 0)113 wx_err(wx, "Hardware Error: %d\n", err);114 115 wx_start_hw(wx);116 /* do not flush user set addresses */117 memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len);118 wx_flush_sw_mac_table(wx);119 wx_mac_set_default_filter(wx, old_addr);120}121 122static void txgbe_disable_device(struct wx *wx)123{124 struct net_device *netdev = wx->netdev;125 u32 i;126 127 wx_disable_pcie_master(wx);128 /* disable receives */129 wx_disable_rx(wx);130 131 /* disable all enabled rx queues */132 for (i = 0; i < wx->num_rx_queues; i++)133 /* this call also flushes the previous write */134 wx_disable_rx_queue(wx, wx->rx_ring[i]);135 136 netif_tx_stop_all_queues(netdev);137 netif_tx_disable(netdev);138 139 wx_irq_disable(wx);140 wx_napi_disable_all(wx);141 142 if (wx->bus.func < 2)143 wr32m(wx, TXGBE_MIS_PRB_CTL, TXGBE_MIS_PRB_CTL_LAN_UP(wx->bus.func), 0);144 else145 wx_err(wx, "%s: invalid bus lan id %d\n",146 __func__, wx->bus.func);147 148 if (!(((wx->subsystem_device_id & WX_NCSI_MASK) == WX_NCSI_SUP) ||149 ((wx->subsystem_device_id & WX_WOL_MASK) == WX_WOL_SUP))) {150 /* disable mac transmiter */151 wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);152 }153 154 /* disable transmits in the hardware now that interrupts are off */155 for (i = 0; i < wx->num_tx_queues; i++) {156 u8 reg_idx = wx->tx_ring[i]->reg_idx;157 158 wr32(wx, WX_PX_TR_CFG(reg_idx), WX_PX_TR_CFG_SWFLSH);159 }160 161 /* Disable the Tx DMA engine */162 wr32m(wx, WX_TDM_CTL, WX_TDM_CTL_TE, 0);163 164 wx_update_stats(wx);165}166 167void txgbe_down(struct wx *wx)168{169 txgbe_disable_device(wx);170 txgbe_reset(wx);171 phylink_stop(wx->phylink);172 173 wx_clean_all_tx_rings(wx);174 wx_clean_all_rx_rings(wx);175}176 177void txgbe_up(struct wx *wx)178{179 wx_configure(wx);180 txgbe_up_complete(wx);181}182 183/**184 * txgbe_init_type_code - Initialize the shared code185 * @wx: pointer to hardware structure186 **/187static void txgbe_init_type_code(struct wx *wx)188{189 u8 device_type = wx->subsystem_device_id & 0xF0;190 191 switch (wx->device_id) {192 case TXGBE_DEV_ID_SP1000:193 case TXGBE_DEV_ID_WX1820:194 wx->mac.type = wx_mac_sp;195 break;196 default:197 wx->mac.type = wx_mac_unknown;198 break;199 }200 201 switch (device_type) {202 case TXGBE_ID_SFP:203 wx->media_type = sp_media_fiber;204 break;205 case TXGBE_ID_XAUI:206 case TXGBE_ID_SGMII:207 wx->media_type = sp_media_copper;208 break;209 case TXGBE_ID_KR_KX_KX4:210 case TXGBE_ID_MAC_XAUI:211 case TXGBE_ID_MAC_SGMII:212 wx->media_type = sp_media_backplane;213 break;214 case TXGBE_ID_SFI_XAUI:215 if (wx->bus.func == 0)216 wx->media_type = sp_media_fiber;217 else218 wx->media_type = sp_media_copper;219 break;220 default:221 wx->media_type = sp_media_unknown;222 break;223 }224}225 226/**227 * txgbe_sw_init - Initialize general software structures (struct wx)228 * @wx: board private structure to initialize229 **/230static int txgbe_sw_init(struct wx *wx)231{232 u16 msix_count = 0;233 int err;234 235 wx->mac.num_rar_entries = TXGBE_SP_RAR_ENTRIES;236 wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES;237 wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES;238 wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE;239 wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE;240 wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE;241 wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ;242 243 /* PCI config space info */244 err = wx_sw_init(wx);245 if (err < 0)246 return err;247 248 txgbe_init_type_code(wx);249 250 /* Set common capability flags and settings */251 wx->max_q_vectors = TXGBE_MAX_MSIX_VECTORS;252 err = wx_get_pcie_msix_counts(wx, &msix_count, TXGBE_MAX_MSIX_VECTORS);253 if (err)254 wx_err(wx, "Do not support MSI-X\n");255 wx->mac.max_msix_vectors = msix_count;256 257 wx->ring_feature[RING_F_RSS].limit = min_t(int, TXGBE_MAX_RSS_INDICES,258 num_online_cpus());259 wx->rss_enabled = true;260 261 wx->ring_feature[RING_F_FDIR].limit = min_t(int, TXGBE_MAX_FDIR_INDICES,262 num_online_cpus());263 set_bit(WX_FLAG_FDIR_CAPABLE, wx->flags);264 set_bit(WX_FLAG_FDIR_HASH, wx->flags);265 wx->atr_sample_rate = TXGBE_DEFAULT_ATR_SAMPLE_RATE;266 wx->atr = txgbe_atr;267 wx->configure_fdir = txgbe_configure_fdir;268 269 /* enable itr by default in dynamic mode */270 wx->rx_itr_setting = 1;271 wx->tx_itr_setting = 1;272 273 /* set default ring sizes */274 wx->tx_ring_count = TXGBE_DEFAULT_TXD;275 wx->rx_ring_count = TXGBE_DEFAULT_RXD;276 277 /* set default work limits */278 wx->tx_work_limit = TXGBE_DEFAULT_TX_WORK;279 wx->rx_work_limit = TXGBE_DEFAULT_RX_WORK;280 281 wx->do_reset = txgbe_do_reset;282 283 return 0;284}285 286static void txgbe_init_fdir(struct txgbe *txgbe)287{288 txgbe->fdir_filter_count = 0;289 spin_lock_init(&txgbe->fdir_perfect_lock);290}291 292/**293 * txgbe_open - Called when a network interface is made active294 * @netdev: network interface device structure295 *296 * Returns 0 on success, negative value on failure297 *298 * The open entry point is called when a network interface is made299 * active by the system (IFF_UP).300 **/301static int txgbe_open(struct net_device *netdev)302{303 struct wx *wx = netdev_priv(netdev);304 int err;305 306 err = wx_setup_resources(wx);307 if (err)308 goto err_reset;309 310 wx_configure(wx);311 312 err = txgbe_request_queue_irqs(wx);313 if (err)314 goto err_free_resources;315 316 /* Notify the stack of the actual queue counts. */317 err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues);318 if (err)319 goto err_free_irq;320 321 err = netif_set_real_num_rx_queues(netdev, wx->num_rx_queues);322 if (err)323 goto err_free_irq;324 325 txgbe_up_complete(wx);326 327 return 0;328 329err_free_irq:330 wx_free_irq(wx);331err_free_resources:332 wx_free_resources(wx);333err_reset:334 txgbe_reset(wx);335 336 return err;337}338 339/**340 * txgbe_close_suspend - actions necessary to both suspend and close flows341 * @wx: the private wx struct342 *343 * This function should contain the necessary work common to both suspending344 * and closing of the device.345 */346static void txgbe_close_suspend(struct wx *wx)347{348 txgbe_disable_device(wx);349 wx_free_resources(wx);350}351 352/**353 * txgbe_close - Disables a network interface354 * @netdev: network interface device structure355 *356 * Returns 0, this is not allowed to fail357 *358 * The close entry point is called when an interface is de-activated359 * by the OS. The hardware is still under the drivers control, but360 * needs to be disabled. A global MAC reset is issued to stop the361 * hardware, and all transmit and receive resources are freed.362 **/363static int txgbe_close(struct net_device *netdev)364{365 struct wx *wx = netdev_priv(netdev);366 367 txgbe_down(wx);368 wx_free_irq(wx);369 wx_free_resources(wx);370 txgbe_fdir_filter_exit(wx);371 wx_control_hw(wx, false);372 373 return 0;374}375 376static void txgbe_dev_shutdown(struct pci_dev *pdev)377{378 struct wx *wx = pci_get_drvdata(pdev);379 struct net_device *netdev;380 381 netdev = wx->netdev;382 netif_device_detach(netdev);383 384 rtnl_lock();385 if (netif_running(netdev))386 txgbe_close_suspend(wx);387 rtnl_unlock();388 389 wx_control_hw(wx, false);390 391 pci_disable_device(pdev);392}393 394static void txgbe_shutdown(struct pci_dev *pdev)395{396 txgbe_dev_shutdown(pdev);397 398 if (system_state == SYSTEM_POWER_OFF) {399 pci_wake_from_d3(pdev, false);400 pci_set_power_state(pdev, PCI_D3hot);401 }402}403 404/**405 * txgbe_setup_tc - routine to configure net_device for multiple traffic406 * classes.407 *408 * @dev: net device to configure409 * @tc: number of traffic classes to enable410 */411int txgbe_setup_tc(struct net_device *dev, u8 tc)412{413 struct wx *wx = netdev_priv(dev);414 struct txgbe *txgbe = wx->priv;415 416 /* Hardware has to reinitialize queues and interrupts to417 * match packet buffer alignment. Unfortunately, the418 * hardware is not flexible enough to do this dynamically.419 */420 if (netif_running(dev))421 txgbe_close(dev);422 else423 txgbe_reset(wx);424 425 txgbe_free_misc_irq(txgbe);426 wx_clear_interrupt_scheme(wx);427 428 if (tc)429 netdev_set_num_tc(dev, tc);430 else431 netdev_reset_tc(dev);432 433 wx_init_interrupt_scheme(wx);434 txgbe_setup_misc_irq(txgbe);435 436 if (netif_running(dev))437 txgbe_open(dev);438 439 return 0;440}441 442static void txgbe_reinit_locked(struct wx *wx)443{444 int err = 0;445 446 netif_trans_update(wx->netdev);447 448 err = wx_set_state_reset(wx);449 if (err) {450 wx_err(wx, "wait device reset timeout\n");451 return;452 }453 454 txgbe_down(wx);455 txgbe_up(wx);456 457 clear_bit(WX_STATE_RESETTING, wx->state);458}459 460void txgbe_do_reset(struct net_device *netdev)461{462 struct wx *wx = netdev_priv(netdev);463 464 if (netif_running(netdev))465 txgbe_reinit_locked(wx);466 else467 txgbe_reset(wx);468}469 470static const struct net_device_ops txgbe_netdev_ops = {471 .ndo_open = txgbe_open,472 .ndo_stop = txgbe_close,473 .ndo_change_mtu = wx_change_mtu,474 .ndo_start_xmit = wx_xmit_frame,475 .ndo_set_rx_mode = wx_set_rx_mode,476 .ndo_set_features = wx_set_features,477 .ndo_fix_features = wx_fix_features,478 .ndo_validate_addr = eth_validate_addr,479 .ndo_set_mac_address = wx_set_mac,480 .ndo_get_stats64 = wx_get_stats64,481 .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,482 .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,483};484 485/**486 * txgbe_probe - Device Initialization Routine487 * @pdev: PCI device information struct488 * @ent: entry in txgbe_pci_tbl489 *490 * Returns 0 on success, negative on failure491 *492 * txgbe_probe initializes an adapter identified by a pci_dev structure.493 * The OS initialization, configuring of the wx private structure,494 * and a hardware reset occur.495 **/496static int txgbe_probe(struct pci_dev *pdev,497 const struct pci_device_id __always_unused *ent)498{499 struct net_device *netdev;500 int err, expected_gts;501 struct wx *wx = NULL;502 struct txgbe *txgbe;503 504 u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0;505 u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0;506 u16 build = 0, major = 0, patch = 0;507 u32 etrack_id = 0;508 509 err = pci_enable_device_mem(pdev);510 if (err)511 return err;512 513 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));514 if (err) {515 dev_err(&pdev->dev,516 "No usable DMA configuration, aborting\n");517 goto err_pci_disable_dev;518 }519 520 err = pci_request_selected_regions(pdev,521 pci_select_bars(pdev, IORESOURCE_MEM),522 txgbe_driver_name);523 if (err) {524 dev_err(&pdev->dev,525 "pci_request_selected_regions failed 0x%x\n", err);526 goto err_pci_disable_dev;527 }528 529 pci_set_master(pdev);530 531 netdev = devm_alloc_etherdev_mqs(&pdev->dev,532 sizeof(struct wx),533 TXGBE_MAX_TX_QUEUES,534 TXGBE_MAX_RX_QUEUES);535 if (!netdev) {536 err = -ENOMEM;537 goto err_pci_release_regions;538 }539 540 SET_NETDEV_DEV(netdev, &pdev->dev);541 542 wx = netdev_priv(netdev);543 wx->netdev = netdev;544 wx->pdev = pdev;545 546 wx->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;547 548 wx->hw_addr = devm_ioremap(&pdev->dev,549 pci_resource_start(pdev, 0),550 pci_resource_len(pdev, 0));551 if (!wx->hw_addr) {552 err = -EIO;553 goto err_pci_release_regions;554 }555 556 wx->driver_name = txgbe_driver_name;557 txgbe_set_ethtool_ops(netdev);558 netdev->netdev_ops = &txgbe_netdev_ops;559 560 /* setup the private structure */561 err = txgbe_sw_init(wx);562 if (err)563 goto err_free_mac_table;564 565 /* check if flash load is done after hw power up */566 err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PERST);567 if (err)568 goto err_free_mac_table;569 err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PWRRST);570 if (err)571 goto err_free_mac_table;572 573 err = wx_mng_present(wx);574 if (err) {575 dev_err(&pdev->dev, "Management capability is not present\n");576 goto err_free_mac_table;577 }578 579 err = txgbe_reset_hw(wx);580 if (err) {581 dev_err(&pdev->dev, "HW Init failed: %d\n", err);582 goto err_free_mac_table;583 }584 585 netdev->features = NETIF_F_SG |586 NETIF_F_TSO |587 NETIF_F_TSO6 |588 NETIF_F_RXHASH |589 NETIF_F_RXCSUM |590 NETIF_F_HW_CSUM;591 592 netdev->gso_partial_features = NETIF_F_GSO_ENCAP_ALL;593 netdev->features |= netdev->gso_partial_features;594 netdev->features |= NETIF_F_SCTP_CRC;595 netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;596 netdev->hw_enc_features |= netdev->vlan_features;597 netdev->features |= NETIF_F_VLAN_FEATURES;598 /* copy netdev features into list of user selectable features */599 netdev->hw_features |= netdev->features | NETIF_F_RXALL;600 netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;601 netdev->features |= NETIF_F_HIGHDMA;602 netdev->hw_features |= NETIF_F_GRO;603 netdev->features |= NETIF_F_GRO;604 605 netdev->priv_flags |= IFF_UNICAST_FLT;606 netdev->priv_flags |= IFF_SUPP_NOFCS;607 netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;608 609 netdev->min_mtu = ETH_MIN_MTU;610 netdev->max_mtu = WX_MAX_JUMBO_FRAME_SIZE -611 (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);612 613 /* make sure the EEPROM is good */614 err = txgbe_validate_eeprom_checksum(wx, NULL);615 if (err != 0) {616 dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");617 wr32(wx, WX_MIS_RST, WX_MIS_RST_SW_RST);618 err = -EIO;619 goto err_free_mac_table;620 }621 622 eth_hw_addr_set(netdev, wx->mac.perm_addr);623 wx_mac_set_default_filter(wx, wx->mac.perm_addr);624 625 err = wx_init_interrupt_scheme(wx);626 if (err)627 goto err_free_mac_table;628 629 /* Save off EEPROM version number and Option Rom version which630 * together make a unique identify for the eeprom631 */632 wx_read_ee_hostif(wx,633 wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_H,634 &eeprom_verh);635 wx_read_ee_hostif(wx,636 wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_L,637 &eeprom_verl);638 etrack_id = (eeprom_verh << 16) | eeprom_verl;639 640 wx_read_ee_hostif(wx,641 wx->eeprom.sw_region_offset + TXGBE_ISCSI_BOOT_CONFIG,642 &offset);643 644 /* Make sure offset to SCSI block is valid */645 if (!(offset == 0x0) && !(offset == 0xffff)) {646 wx_read_ee_hostif(wx, offset + 0x84, &eeprom_cfg_blkh);647 wx_read_ee_hostif(wx, offset + 0x83, &eeprom_cfg_blkl);648 649 /* Only display Option Rom if exist */650 if (eeprom_cfg_blkl && eeprom_cfg_blkh) {651 major = eeprom_cfg_blkl >> 8;652 build = (eeprom_cfg_blkl << 8) | (eeprom_cfg_blkh >> 8);653 patch = eeprom_cfg_blkh & 0x00ff;654 655 snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),656 "0x%08x, %d.%d.%d", etrack_id, major, build,657 patch);658 } else {659 snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),660 "0x%08x", etrack_id);661 }662 } else {663 snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),664 "0x%08x", etrack_id);665 }666 667 if (etrack_id < 0x20010)668 dev_warn(&pdev->dev, "Please upgrade the firmware to 0x20010 or above.\n");669 670 txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL);671 if (!txgbe) {672 err = -ENOMEM;673 goto err_release_hw;674 }675 676 txgbe->wx = wx;677 wx->priv = txgbe;678 679 txgbe_init_fdir(txgbe);680 681 err = txgbe_setup_misc_irq(txgbe);682 if (err)683 goto err_release_hw;684 685 err = txgbe_init_phy(txgbe);686 if (err)687 goto err_free_misc_irq;688 689 err = register_netdev(netdev);690 if (err)691 goto err_remove_phy;692 693 pci_set_drvdata(pdev, wx);694 695 netif_tx_stop_all_queues(netdev);696 697 /* calculate the expected PCIe bandwidth required for optimal698 * performance. Note that some older parts will never have enough699 * bandwidth due to being older generation PCIe parts. We clamp these700 * parts to ensure that no warning is displayed, as this could confuse701 * users otherwise.702 */703 expected_gts = txgbe_enumerate_functions(wx) * 10;704 705 /* don't check link if we failed to enumerate functions */706 if (expected_gts > 0)707 txgbe_check_minimum_link(wx);708 else709 dev_warn(&pdev->dev, "Failed to enumerate PF devices.\n");710 711 return 0;712 713err_remove_phy:714 txgbe_remove_phy(txgbe);715err_free_misc_irq:716 txgbe_free_misc_irq(txgbe);717err_release_hw:718 wx_clear_interrupt_scheme(wx);719 wx_control_hw(wx, false);720err_free_mac_table:721 kfree(wx->mac_table);722err_pci_release_regions:723 pci_release_selected_regions(pdev,724 pci_select_bars(pdev, IORESOURCE_MEM));725err_pci_disable_dev:726 pci_disable_device(pdev);727 return err;728}729 730/**731 * txgbe_remove - Device Removal Routine732 * @pdev: PCI device information struct733 *734 * txgbe_remove is called by the PCI subsystem to alert the driver735 * that it should release a PCI device. The could be caused by a736 * Hot-Plug event, or because the driver is going to be removed from737 * memory.738 **/739static void txgbe_remove(struct pci_dev *pdev)740{741 struct wx *wx = pci_get_drvdata(pdev);742 struct txgbe *txgbe = wx->priv;743 struct net_device *netdev;744 745 netdev = wx->netdev;746 unregister_netdev(netdev);747 748 txgbe_remove_phy(txgbe);749 txgbe_free_misc_irq(txgbe);750 wx_free_isb_resources(wx);751 752 pci_release_selected_regions(pdev,753 pci_select_bars(pdev, IORESOURCE_MEM));754 755 kfree(wx->rss_key);756 kfree(wx->mac_table);757 wx_clear_interrupt_scheme(wx);758 759 pci_disable_device(pdev);760}761 762static struct pci_driver txgbe_driver = {763 .name = txgbe_driver_name,764 .id_table = txgbe_pci_tbl,765 .probe = txgbe_probe,766 .remove = txgbe_remove,767 .shutdown = txgbe_shutdown,768};769 770module_pci_driver(txgbe_driver);771 772MODULE_DEVICE_TABLE(pci, txgbe_pci_tbl);773MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@trustnetic.com>");774MODULE_DESCRIPTION("WangXun(R) 10 Gigabit PCI Express Network Driver");775MODULE_LICENSE("GPL");776