795 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2019 - 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 <net/ip.h>11#include <linux/phy.h>12#include <linux/if_vlan.h>13 14#include "../libwx/wx_type.h"15#include "../libwx/wx_hw.h"16#include "../libwx/wx_lib.h"17#include "ngbe_type.h"18#include "ngbe_mdio.h"19#include "ngbe_hw.h"20#include "ngbe_ethtool.h"21 22char ngbe_driver_name[] = "ngbe";23 24/* ngbe_pci_tbl - PCI Device ID Table25 *26 * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,27 * Class, Class Mask, private data (not used) }28 */29static const struct pci_device_id ngbe_pci_tbl[] = {30 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W), 0},31 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2), 0},32 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2S), 0},33 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4), 0},34 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4S), 0},35 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2), 0},36 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S), 0},37 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4), 0},38 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S), 0},39 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860LC), 0},40 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1), 0},41 { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1L), 0},42 /* required last entry */43 { .device = 0 }44};45 46/**47 * ngbe_init_type_code - Initialize the shared code48 * @wx: pointer to hardware structure49 **/50static void ngbe_init_type_code(struct wx *wx)51{52 int wol_mask = 0, ncsi_mask = 0;53 u16 type_mask = 0, val;54 55 wx->mac.type = wx_mac_em;56 type_mask = (u16)(wx->subsystem_device_id & NGBE_OEM_MASK);57 ncsi_mask = wx->subsystem_device_id & NGBE_NCSI_MASK;58 wol_mask = wx->subsystem_device_id & NGBE_WOL_MASK;59 60 val = rd32(wx, WX_CFG_PORT_ST);61 wx->mac_type = (val & BIT(7)) >> 7 ?62 em_mac_type_rgmii :63 em_mac_type_mdi;64 65 wx->wol_hw_supported = (wol_mask == NGBE_WOL_SUP) ? 1 : 0;66 wx->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK ||67 type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;68 69 switch (type_mask) {70 case NGBE_SUBID_LY_YT8521S_SFP:71 case NGBE_SUBID_LY_M88E1512_SFP:72 case NGBE_SUBID_YT8521S_SFP_GPIO:73 case NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO:74 wx->gpio_ctrl = 1;75 break;76 default:77 wx->gpio_ctrl = 0;78 break;79 }80}81 82/**83 * ngbe_sw_init - Initialize general software structures84 * @wx: board private structure to initialize85 **/86static int ngbe_sw_init(struct wx *wx)87{88 struct pci_dev *pdev = wx->pdev;89 u16 msix_count = 0;90 int err = 0;91 92 wx->mac.num_rar_entries = NGBE_RAR_ENTRIES;93 wx->mac.max_rx_queues = NGBE_MAX_RX_QUEUES;94 wx->mac.max_tx_queues = NGBE_MAX_TX_QUEUES;95 wx->mac.mcft_size = NGBE_MC_TBL_SIZE;96 wx->mac.vft_size = NGBE_SP_VFT_TBL_SIZE;97 wx->mac.rx_pb_size = NGBE_RX_PB_SIZE;98 wx->mac.tx_pb_size = NGBE_TDB_PB_SZ;99 100 /* PCI config space info */101 err = wx_sw_init(wx);102 if (err < 0)103 return err;104 105 /* mac type, phy type , oem type */106 ngbe_init_type_code(wx);107 108 /* Set common capability flags and settings */109 wx->max_q_vectors = NGBE_MAX_MSIX_VECTORS;110 err = wx_get_pcie_msix_counts(wx, &msix_count, NGBE_MAX_MSIX_VECTORS);111 if (err)112 dev_err(&pdev->dev, "Do not support MSI-X\n");113 wx->mac.max_msix_vectors = msix_count;114 115 wx->ring_feature[RING_F_RSS].limit = min_t(int, NGBE_MAX_RSS_INDICES,116 num_online_cpus());117 wx->rss_enabled = true;118 119 /* enable itr by default in dynamic mode */120 wx->rx_itr_setting = 1;121 wx->tx_itr_setting = 1;122 123 /* set default ring sizes */124 wx->tx_ring_count = NGBE_DEFAULT_TXD;125 wx->rx_ring_count = NGBE_DEFAULT_RXD;126 127 /* set default work limits */128 wx->tx_work_limit = NGBE_DEFAULT_TX_WORK;129 wx->rx_work_limit = NGBE_DEFAULT_RX_WORK;130 131 return 0;132}133 134/**135 * ngbe_irq_enable - Enable default interrupt generation settings136 * @wx: board private structure137 * @queues: enable all queues interrupts138 **/139static void ngbe_irq_enable(struct wx *wx, bool queues)140{141 u32 mask;142 143 /* enable misc interrupt */144 mask = NGBE_PX_MISC_IEN_MASK;145 146 wr32(wx, WX_GPIO_DDR, WX_GPIO_DDR_0);147 wr32(wx, WX_GPIO_INTEN, WX_GPIO_INTEN_0 | WX_GPIO_INTEN_1);148 wr32(wx, WX_GPIO_INTTYPE_LEVEL, 0x0);149 wr32(wx, WX_GPIO_POLARITY, wx->gpio_ctrl ? 0 : 0x3);150 151 wr32(wx, WX_PX_MISC_IEN, mask);152 153 /* mask interrupt */154 if (queues)155 wx_intr_enable(wx, NGBE_INTR_ALL);156 else157 wx_intr_enable(wx, NGBE_INTR_MISC);158}159 160/**161 * ngbe_intr - msi/legacy mode Interrupt Handler162 * @irq: interrupt number163 * @data: pointer to a network interface device structure164 **/165static irqreturn_t ngbe_intr(int __always_unused irq, void *data)166{167 struct wx_q_vector *q_vector;168 struct wx *wx = data;169 struct pci_dev *pdev;170 u32 eicr;171 172 q_vector = wx->q_vector[0];173 pdev = wx->pdev;174 175 eicr = wx_misc_isb(wx, WX_ISB_VEC0);176 if (!eicr) {177 /* shared interrupt alert!178 * the interrupt that we masked before the EICR read.179 */180 if (netif_running(wx->netdev))181 ngbe_irq_enable(wx, true);182 return IRQ_NONE; /* Not our interrupt */183 }184 wx->isb_mem[WX_ISB_VEC0] = 0;185 if (!(pdev->msi_enabled))186 wr32(wx, WX_PX_INTA, 1);187 188 wx->isb_mem[WX_ISB_MISC] = 0;189 /* would disable interrupts here but it is auto disabled */190 napi_schedule_irqoff(&q_vector->napi);191 192 if (netif_running(wx->netdev))193 ngbe_irq_enable(wx, false);194 195 return IRQ_HANDLED;196}197 198static irqreturn_t ngbe_msix_other(int __always_unused irq, void *data)199{200 struct wx *wx = data;201 202 /* re-enable the original interrupt state, no lsc, no queues */203 if (netif_running(wx->netdev))204 ngbe_irq_enable(wx, false);205 206 return IRQ_HANDLED;207}208 209/**210 * ngbe_request_msix_irqs - Initialize MSI-X interrupts211 * @wx: board private structure212 *213 * ngbe_request_msix_irqs allocates MSI-X vectors and requests214 * interrupts from the kernel.215 **/216static int ngbe_request_msix_irqs(struct wx *wx)217{218 struct net_device *netdev = wx->netdev;219 int vector, err;220 221 for (vector = 0; vector < wx->num_q_vectors; vector++) {222 struct wx_q_vector *q_vector = wx->q_vector[vector];223 struct msix_entry *entry = &wx->msix_q_entries[vector];224 225 if (q_vector->tx.ring && q_vector->rx.ring)226 snprintf(q_vector->name, sizeof(q_vector->name) - 1,227 "%s-TxRx-%d", netdev->name, entry->entry);228 else229 /* skip this unused q_vector */230 continue;231 232 err = request_irq(entry->vector, wx_msix_clean_rings, 0,233 q_vector->name, q_vector);234 if (err) {235 wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",236 q_vector->name, err);237 goto free_queue_irqs;238 }239 }240 241 err = request_irq(wx->msix_entry->vector,242 ngbe_msix_other, 0, netdev->name, wx);243 244 if (err) {245 wx_err(wx, "request_irq for msix_other failed: %d\n", err);246 goto free_queue_irqs;247 }248 249 return 0;250 251free_queue_irqs:252 while (vector) {253 vector--;254 free_irq(wx->msix_q_entries[vector].vector,255 wx->q_vector[vector]);256 }257 wx_reset_interrupt_capability(wx);258 return err;259}260 261/**262 * ngbe_request_irq - initialize interrupts263 * @wx: board private structure264 *265 * Attempts to configure interrupts using the best available266 * capabilities of the hardware and kernel.267 **/268static int ngbe_request_irq(struct wx *wx)269{270 struct net_device *netdev = wx->netdev;271 struct pci_dev *pdev = wx->pdev;272 int err;273 274 if (pdev->msix_enabled)275 err = ngbe_request_msix_irqs(wx);276 else if (pdev->msi_enabled)277 err = request_irq(pdev->irq, ngbe_intr, 0,278 netdev->name, wx);279 else280 err = request_irq(pdev->irq, ngbe_intr, IRQF_SHARED,281 netdev->name, wx);282 283 if (err)284 wx_err(wx, "request_irq failed, Error %d\n", err);285 286 return err;287}288 289static void ngbe_disable_device(struct wx *wx)290{291 struct net_device *netdev = wx->netdev;292 u32 i;293 294 /* disable all enabled rx queues */295 for (i = 0; i < wx->num_rx_queues; i++)296 /* this call also flushes the previous write */297 wx_disable_rx_queue(wx, wx->rx_ring[i]);298 /* disable receives */299 wx_disable_rx(wx);300 wx_napi_disable_all(wx);301 netif_tx_stop_all_queues(netdev);302 netif_tx_disable(netdev);303 if (wx->gpio_ctrl)304 ngbe_sfp_modules_txrx_powerctl(wx, false);305 wx_irq_disable(wx);306 /* disable transmits in the hardware now that interrupts are off */307 for (i = 0; i < wx->num_tx_queues; i++) {308 u8 reg_idx = wx->tx_ring[i]->reg_idx;309 310 wr32(wx, WX_PX_TR_CFG(reg_idx), WX_PX_TR_CFG_SWFLSH);311 }312 313 wx_update_stats(wx);314}315 316void ngbe_down(struct wx *wx)317{318 phylink_stop(wx->phylink);319 ngbe_disable_device(wx);320 wx_clean_all_tx_rings(wx);321 wx_clean_all_rx_rings(wx);322}323 324void ngbe_up(struct wx *wx)325{326 wx_configure_vectors(wx);327 328 /* make sure to complete pre-operations */329 smp_mb__before_atomic();330 wx_napi_enable_all(wx);331 /* enable transmits */332 netif_tx_start_all_queues(wx->netdev);333 334 /* clear any pending interrupts, may auto mask */335 rd32(wx, WX_PX_IC(0));336 rd32(wx, WX_PX_MISC_IC);337 ngbe_irq_enable(wx, true);338 if (wx->gpio_ctrl)339 ngbe_sfp_modules_txrx_powerctl(wx, true);340 341 phylink_start(wx->phylink);342}343 344/**345 * ngbe_open - Called when a network interface is made active346 * @netdev: network interface device structure347 *348 * Returns 0 on success, negative value on failure349 *350 * The open entry point is called when a network interface is made351 * active by the system (IFF_UP).352 **/353static int ngbe_open(struct net_device *netdev)354{355 struct wx *wx = netdev_priv(netdev);356 int err;357 358 wx_control_hw(wx, true);359 360 err = wx_setup_resources(wx);361 if (err)362 return err;363 364 wx_configure(wx);365 366 err = ngbe_request_irq(wx);367 if (err)368 goto err_free_resources;369 370 err = phylink_connect_phy(wx->phylink, wx->phydev);371 if (err)372 goto err_free_irq;373 374 err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues);375 if (err)376 goto err_dis_phy;377 378 err = netif_set_real_num_rx_queues(netdev, wx->num_rx_queues);379 if (err)380 goto err_dis_phy;381 382 ngbe_up(wx);383 384 return 0;385err_dis_phy:386 phylink_disconnect_phy(wx->phylink);387err_free_irq:388 wx_free_irq(wx);389err_free_resources:390 wx_free_isb_resources(wx);391 wx_free_resources(wx);392 return err;393}394 395/**396 * ngbe_close - Disables a network interface397 * @netdev: network interface device structure398 *399 * Returns 0, this is not allowed to fail400 *401 * The close entry point is called when an interface is de-activated402 * by the OS. The hardware is still under the drivers control, but403 * needs to be disabled. A global MAC reset is issued to stop the404 * hardware, and all transmit and receive resources are freed.405 **/406static int ngbe_close(struct net_device *netdev)407{408 struct wx *wx = netdev_priv(netdev);409 410 ngbe_down(wx);411 wx_free_irq(wx);412 wx_free_isb_resources(wx);413 wx_free_resources(wx);414 phylink_disconnect_phy(wx->phylink);415 wx_control_hw(wx, false);416 417 return 0;418}419 420static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)421{422 struct wx *wx = pci_get_drvdata(pdev);423 struct net_device *netdev;424 u32 wufc = wx->wol;425 426 netdev = wx->netdev;427 rtnl_lock();428 netif_device_detach(netdev);429 430 if (netif_running(netdev))431 ngbe_close(netdev);432 wx_clear_interrupt_scheme(wx);433 rtnl_unlock();434 435 if (wufc) {436 wx_set_rx_mode(netdev);437 wx_configure_rx(wx);438 wr32(wx, NGBE_PSR_WKUP_CTL, wufc);439 } else {440 wr32(wx, NGBE_PSR_WKUP_CTL, 0);441 }442 pci_wake_from_d3(pdev, !!wufc);443 *enable_wake = !!wufc;444 wx_control_hw(wx, false);445 446 pci_disable_device(pdev);447}448 449static void ngbe_shutdown(struct pci_dev *pdev)450{451 struct wx *wx = pci_get_drvdata(pdev);452 bool wake;453 454 wake = !!wx->wol;455 456 ngbe_dev_shutdown(pdev, &wake);457 458 if (system_state == SYSTEM_POWER_OFF) {459 pci_wake_from_d3(pdev, wake);460 pci_set_power_state(pdev, PCI_D3hot);461 }462}463 464/**465 * ngbe_setup_tc - routine to configure net_device for multiple traffic466 * classes.467 *468 * @dev: net device to configure469 * @tc: number of traffic classes to enable470 */471int ngbe_setup_tc(struct net_device *dev, u8 tc)472{473 struct wx *wx = netdev_priv(dev);474 475 /* Hardware has to reinitialize queues and interrupts to476 * match packet buffer alignment. Unfortunately, the477 * hardware is not flexible enough to do this dynamically.478 */479 if (netif_running(dev))480 ngbe_close(dev);481 482 wx_clear_interrupt_scheme(wx);483 484 if (tc)485 netdev_set_num_tc(dev, tc);486 else487 netdev_reset_tc(dev);488 489 wx_init_interrupt_scheme(wx);490 491 if (netif_running(dev))492 ngbe_open(dev);493 494 return 0;495}496 497static const struct net_device_ops ngbe_netdev_ops = {498 .ndo_open = ngbe_open,499 .ndo_stop = ngbe_close,500 .ndo_change_mtu = wx_change_mtu,501 .ndo_start_xmit = wx_xmit_frame,502 .ndo_set_rx_mode = wx_set_rx_mode,503 .ndo_set_features = wx_set_features,504 .ndo_fix_features = wx_fix_features,505 .ndo_validate_addr = eth_validate_addr,506 .ndo_set_mac_address = wx_set_mac,507 .ndo_get_stats64 = wx_get_stats64,508 .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,509 .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,510};511 512/**513 * ngbe_probe - Device Initialization Routine514 * @pdev: PCI device information struct515 * @ent: entry in ngbe_pci_tbl516 *517 * Returns 0 on success, negative on failure518 *519 * ngbe_probe initializes an wx identified by a pci_dev structure.520 * The OS initialization, configuring of the wx private structure,521 * and a hardware reset occur.522 **/523static int ngbe_probe(struct pci_dev *pdev,524 const struct pci_device_id __always_unused *ent)525{526 struct net_device *netdev;527 u32 e2rom_cksum_cap = 0;528 struct wx *wx = NULL;529 static int func_nums;530 u16 e2rom_ver = 0;531 u32 etrack_id = 0;532 u32 saved_ver = 0;533 int err;534 535 err = pci_enable_device_mem(pdev);536 if (err)537 return err;538 539 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));540 if (err) {541 dev_err(&pdev->dev,542 "No usable DMA configuration, aborting\n");543 goto err_pci_disable_dev;544 }545 546 err = pci_request_selected_regions(pdev,547 pci_select_bars(pdev, IORESOURCE_MEM),548 ngbe_driver_name);549 if (err) {550 dev_err(&pdev->dev,551 "pci_request_selected_regions failed %d\n", err);552 goto err_pci_disable_dev;553 }554 555 pci_set_master(pdev);556 557 netdev = devm_alloc_etherdev_mqs(&pdev->dev,558 sizeof(struct wx),559 NGBE_MAX_TX_QUEUES,560 NGBE_MAX_RX_QUEUES);561 if (!netdev) {562 err = -ENOMEM;563 goto err_pci_release_regions;564 }565 566 SET_NETDEV_DEV(netdev, &pdev->dev);567 568 wx = netdev_priv(netdev);569 wx->netdev = netdev;570 wx->pdev = pdev;571 wx->msg_enable = BIT(3) - 1;572 573 wx->hw_addr = devm_ioremap(&pdev->dev,574 pci_resource_start(pdev, 0),575 pci_resource_len(pdev, 0));576 if (!wx->hw_addr) {577 err = -EIO;578 goto err_pci_release_regions;579 }580 581 wx->driver_name = ngbe_driver_name;582 ngbe_set_ethtool_ops(netdev);583 netdev->netdev_ops = &ngbe_netdev_ops;584 585 netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM |586 NETIF_F_TSO | NETIF_F_TSO6 |587 NETIF_F_RXHASH | NETIF_F_RXCSUM;588 netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_TSO_MANGLEID;589 netdev->vlan_features |= netdev->features;590 netdev->features |= NETIF_F_IPV6_CSUM | NETIF_F_VLAN_FEATURES;591 /* copy netdev features into list of user selectable features */592 netdev->hw_features |= netdev->features | NETIF_F_RXALL;593 netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;594 netdev->features |= NETIF_F_HIGHDMA;595 netdev->hw_features |= NETIF_F_GRO;596 netdev->features |= NETIF_F_GRO;597 598 netdev->priv_flags |= IFF_UNICAST_FLT;599 netdev->priv_flags |= IFF_SUPP_NOFCS;600 netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;601 602 netdev->min_mtu = ETH_MIN_MTU;603 netdev->max_mtu = WX_MAX_JUMBO_FRAME_SIZE -604 (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);605 606 wx->bd_number = func_nums;607 /* setup the private structure */608 err = ngbe_sw_init(wx);609 if (err)610 goto err_free_mac_table;611 612 /* check if flash load is done after hw power up */613 err = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PERST);614 if (err)615 goto err_free_mac_table;616 err = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PWRRST);617 if (err)618 goto err_free_mac_table;619 620 err = wx_mng_present(wx);621 if (err) {622 dev_err(&pdev->dev, "Management capability is not present\n");623 goto err_free_mac_table;624 }625 626 err = ngbe_reset_hw(wx);627 if (err) {628 dev_err(&pdev->dev, "HW Init failed: %d\n", err);629 goto err_free_mac_table;630 }631 632 if (wx->bus.func == 0) {633 wr32(wx, NGBE_CALSUM_CAP_STATUS, 0x0);634 wr32(wx, NGBE_EEPROM_VERSION_STORE_REG, 0x0);635 } else {636 e2rom_cksum_cap = rd32(wx, NGBE_CALSUM_CAP_STATUS);637 saved_ver = rd32(wx, NGBE_EEPROM_VERSION_STORE_REG);638 }639 640 wx_init_eeprom_params(wx);641 if (wx->bus.func == 0 || e2rom_cksum_cap == 0) {642 /* make sure the EEPROM is ready */643 err = ngbe_eeprom_chksum_hostif(wx);644 if (err) {645 dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");646 err = -EIO;647 goto err_free_mac_table;648 }649 }650 651 wx->wol = 0;652 if (wx->wol_hw_supported)653 wx->wol = NGBE_PSR_WKUP_CTL_MAG;654 655 netdev->ethtool->wol_enabled = !!(wx->wol);656 wr32(wx, NGBE_PSR_WKUP_CTL, wx->wol);657 device_set_wakeup_enable(&pdev->dev, wx->wol);658 659 /* Save off EEPROM version number and Option Rom version which660 * together make a unique identify for the eeprom661 */662 if (saved_ver) {663 etrack_id = saved_ver;664 } else {665 wx_read_ee_hostif(wx,666 wx->eeprom.sw_region_offset + NGBE_EEPROM_VERSION_H,667 &e2rom_ver);668 etrack_id = e2rom_ver << 16;669 wx_read_ee_hostif(wx,670 wx->eeprom.sw_region_offset + NGBE_EEPROM_VERSION_L,671 &e2rom_ver);672 etrack_id |= e2rom_ver;673 wr32(wx, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);674 }675 snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),676 "0x%08x", etrack_id);677 678 eth_hw_addr_set(netdev, wx->mac.perm_addr);679 wx_mac_set_default_filter(wx, wx->mac.perm_addr);680 681 err = wx_init_interrupt_scheme(wx);682 if (err)683 goto err_free_mac_table;684 685 /* phy Interface Configuration */686 err = ngbe_mdio_init(wx);687 if (err)688 goto err_clear_interrupt_scheme;689 690 err = register_netdev(netdev);691 if (err)692 goto err_register;693 694 pci_set_drvdata(pdev, wx);695 696 return 0;697 698err_register:699 phylink_destroy(wx->phylink);700 wx_control_hw(wx, false);701err_clear_interrupt_scheme:702 wx_clear_interrupt_scheme(wx);703err_free_mac_table:704 kfree(wx->mac_table);705err_pci_release_regions:706 pci_release_selected_regions(pdev,707 pci_select_bars(pdev, IORESOURCE_MEM));708err_pci_disable_dev:709 pci_disable_device(pdev);710 return err;711}712 713/**714 * ngbe_remove - Device Removal Routine715 * @pdev: PCI device information struct716 *717 * ngbe_remove is called by the PCI subsystem to alert the driver718 * that it should release a PCI device. The could be caused by a719 * Hot-Plug event, or because the driver is going to be removed from720 * memory.721 **/722static void ngbe_remove(struct pci_dev *pdev)723{724 struct wx *wx = pci_get_drvdata(pdev);725 struct net_device *netdev;726 727 netdev = wx->netdev;728 unregister_netdev(netdev);729 phylink_destroy(wx->phylink);730 pci_release_selected_regions(pdev,731 pci_select_bars(pdev, IORESOURCE_MEM));732 733 kfree(wx->rss_key);734 kfree(wx->mac_table);735 wx_clear_interrupt_scheme(wx);736 737 pci_disable_device(pdev);738}739 740static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state)741{742 bool wake;743 744 ngbe_dev_shutdown(pdev, &wake);745 device_set_wakeup_enable(&pdev->dev, wake);746 747 return 0;748}749 750static int ngbe_resume(struct pci_dev *pdev)751{752 struct net_device *netdev;753 struct wx *wx;754 u32 err;755 756 wx = pci_get_drvdata(pdev);757 netdev = wx->netdev;758 759 err = pci_enable_device_mem(pdev);760 if (err) {761 wx_err(wx, "Cannot enable PCI device from suspend\n");762 return err;763 }764 pci_set_master(pdev);765 device_wakeup_disable(&pdev->dev);766 767 ngbe_reset_hw(wx);768 rtnl_lock();769 err = wx_init_interrupt_scheme(wx);770 if (!err && netif_running(netdev))771 err = ngbe_open(netdev);772 if (!err)773 netif_device_attach(netdev);774 rtnl_unlock();775 776 return 0;777}778 779static struct pci_driver ngbe_driver = {780 .name = ngbe_driver_name,781 .id_table = ngbe_pci_tbl,782 .probe = ngbe_probe,783 .remove = ngbe_remove,784 .suspend = ngbe_suspend,785 .resume = ngbe_resume,786 .shutdown = ngbe_shutdown,787};788 789module_pci_driver(ngbe_driver);790 791MODULE_DEVICE_TABLE(pci, ngbe_pci_tbl);792MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@net-swift.com>");793MODULE_DESCRIPTION("WangXun(R) Gigabit PCI Express Network Driver");794MODULE_LICENSE("GPL");795