brintos

brintos / linux-shallow public Read only

0
0
Text · 19.3 KiB · 53aeae2 Raw
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