xref: /openbmc/linux/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c (revision b97d6790d03b763eca08847a9a5869a4291b9f9a)
13ce7547eSJiawen Wu // SPDX-License-Identifier: GPL-2.0
23ce7547eSJiawen Wu /* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */
33ce7547eSJiawen Wu 
43ce7547eSJiawen Wu #include <linux/types.h>
53ce7547eSJiawen Wu #include <linux/module.h>
63ce7547eSJiawen Wu #include <linux/pci.h>
73ce7547eSJiawen Wu #include <linux/netdevice.h>
83ce7547eSJiawen Wu #include <linux/string.h>
93ce7547eSJiawen Wu #include <linux/etherdevice.h>
1008f08f93SJiawen Wu #include <linux/phylink.h>
11d21d2c7fSJiawen Wu #include <net/ip.h>
1281dc0741SMengyuan Lou #include <linux/if_vlan.h>
133ce7547eSJiawen Wu 
14a34b3e6eSJiawen Wu #include "../libwx/wx_type.h"
155d3ac705SJiawen Wu #include "../libwx/wx_lib.h"
16a34b3e6eSJiawen Wu #include "../libwx/wx_hw.h"
17b0801256SJiawen Wu #include "txgbe_type.h"
18b0801256SJiawen Wu #include "txgbe_hw.h"
19c3e382adSJiawen Wu #include "txgbe_phy.h"
201b8d1c50SMengyuan Lou #include "txgbe_ethtool.h"
213ce7547eSJiawen Wu 
223ce7547eSJiawen Wu char txgbe_driver_name[] = "txgbe";
233ce7547eSJiawen Wu 
243ce7547eSJiawen Wu /* txgbe_pci_tbl - PCI Device ID Table
253ce7547eSJiawen Wu  *
263ce7547eSJiawen Wu  * Wildcard entries (PCI_ANY_ID) should come last
273ce7547eSJiawen Wu  * Last entry must be all 0s
283ce7547eSJiawen Wu  *
293ce7547eSJiawen Wu  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
303ce7547eSJiawen Wu  *   Class, Class Mask, private data (not used) }
313ce7547eSJiawen Wu  */
323ce7547eSJiawen Wu static const struct pci_device_id txgbe_pci_tbl[] = {
333ce7547eSJiawen Wu 	{ PCI_VDEVICE(WANGXUN, TXGBE_DEV_ID_SP1000), 0},
343ce7547eSJiawen Wu 	{ PCI_VDEVICE(WANGXUN, TXGBE_DEV_ID_WX1820), 0},
353ce7547eSJiawen Wu 	/* required last entry */
363ce7547eSJiawen Wu 	{ .device = 0 }
373ce7547eSJiawen Wu };
383ce7547eSJiawen Wu 
393ce7547eSJiawen Wu #define DEFAULT_DEBUG_LEVEL_SHIFT 3
403ce7547eSJiawen Wu 
txgbe_check_minimum_link(struct wx * wx)41270a71e6SJiawen Wu static void txgbe_check_minimum_link(struct wx *wx)
42a34b3e6eSJiawen Wu {
43a34b3e6eSJiawen Wu 	struct pci_dev *pdev;
44a34b3e6eSJiawen Wu 
45270a71e6SJiawen Wu 	pdev = wx->pdev;
46a34b3e6eSJiawen Wu 	pcie_print_link_status(pdev);
47a34b3e6eSJiawen Wu }
48a34b3e6eSJiawen Wu 
49a34b3e6eSJiawen Wu /**
50a34b3e6eSJiawen Wu  * txgbe_enumerate_functions - Get the number of ports this device has
51270a71e6SJiawen Wu  * @wx: wx structure
52a34b3e6eSJiawen Wu  *
53a34b3e6eSJiawen Wu  * This function enumerates the phsyical functions co-located on a single slot,
54a34b3e6eSJiawen Wu  * in order to determine how many ports a device has. This is most useful in
55a34b3e6eSJiawen Wu  * determining the required GT/s of PCIe bandwidth necessary for optimal
56a34b3e6eSJiawen Wu  * performance.
57a34b3e6eSJiawen Wu  **/
txgbe_enumerate_functions(struct wx * wx)58270a71e6SJiawen Wu static int txgbe_enumerate_functions(struct wx *wx)
59a34b3e6eSJiawen Wu {
60270a71e6SJiawen Wu 	struct pci_dev *entry, *pdev = wx->pdev;
61a34b3e6eSJiawen Wu 	int physfns = 0;
62a34b3e6eSJiawen Wu 
63a34b3e6eSJiawen Wu 	list_for_each_entry(entry, &pdev->bus->devices, bus_list) {
64a34b3e6eSJiawen Wu 		/* When the devices on the bus don't all match our device ID,
65a34b3e6eSJiawen Wu 		 * we can't reliably determine the correct number of
66a34b3e6eSJiawen Wu 		 * functions. This can occur if a function has been direct
67a34b3e6eSJiawen Wu 		 * attached to a virtual machine using VT-d.
68a34b3e6eSJiawen Wu 		 */
69a34b3e6eSJiawen Wu 		if (entry->vendor != pdev->vendor ||
70a34b3e6eSJiawen Wu 		    entry->device != pdev->device)
71a34b3e6eSJiawen Wu 			return -EINVAL;
72a34b3e6eSJiawen Wu 
73a34b3e6eSJiawen Wu 		physfns++;
74a34b3e6eSJiawen Wu 	}
75a34b3e6eSJiawen Wu 
76a34b3e6eSJiawen Wu 	return physfns;
77a34b3e6eSJiawen Wu }
78a34b3e6eSJiawen Wu 
795d3ac705SJiawen Wu /**
805d3ac705SJiawen Wu  * txgbe_irq_enable - Enable default interrupt generation settings
815d3ac705SJiawen Wu  * @wx: pointer to private structure
825d3ac705SJiawen Wu  * @queues: enable irqs for queues
835d3ac705SJiawen Wu  **/
txgbe_irq_enable(struct wx * wx,bool queues)845d3ac705SJiawen Wu static void txgbe_irq_enable(struct wx *wx, bool queues)
855d3ac705SJiawen Wu {
86b83c3731SJiawen Wu 	wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
87b83c3731SJiawen Wu 
885d3ac705SJiawen Wu 	/* unmask interrupt */
895d3ac705SJiawen Wu 	wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
905d3ac705SJiawen Wu 	if (queues)
915d3ac705SJiawen Wu 		wx_intr_enable(wx, TXGBE_INTR_QALL(wx));
925d3ac705SJiawen Wu }
935d3ac705SJiawen Wu 
945d3ac705SJiawen Wu /**
955d3ac705SJiawen Wu  * txgbe_intr - msi/legacy mode Interrupt Handler
965d3ac705SJiawen Wu  * @irq: interrupt number
975d3ac705SJiawen Wu  * @data: pointer to a network interface device structure
985d3ac705SJiawen Wu  **/
txgbe_intr(int __always_unused irq,void * data)995d3ac705SJiawen Wu static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
1005d3ac705SJiawen Wu {
1015d3ac705SJiawen Wu 	struct wx_q_vector *q_vector;
1025d3ac705SJiawen Wu 	struct wx *wx  = data;
1035d3ac705SJiawen Wu 	struct pci_dev *pdev;
1045d3ac705SJiawen Wu 	u32 eicr;
1055d3ac705SJiawen Wu 
1065d3ac705SJiawen Wu 	q_vector = wx->q_vector[0];
1075d3ac705SJiawen Wu 	pdev = wx->pdev;
1085d3ac705SJiawen Wu 
1095d3ac705SJiawen Wu 	eicr = wx_misc_isb(wx, WX_ISB_VEC0);
1105d3ac705SJiawen Wu 	if (!eicr) {
1115d3ac705SJiawen Wu 		/* shared interrupt alert!
1125d3ac705SJiawen Wu 		 * the interrupt that we masked before the ICR read.
1135d3ac705SJiawen Wu 		 */
1145d3ac705SJiawen Wu 		if (netif_running(wx->netdev))
1155d3ac705SJiawen Wu 			txgbe_irq_enable(wx, true);
1165d3ac705SJiawen Wu 		return IRQ_NONE;        /* Not our interrupt */
1175d3ac705SJiawen Wu 	}
1185d3ac705SJiawen Wu 	wx->isb_mem[WX_ISB_VEC0] = 0;
1195d3ac705SJiawen Wu 	if (!(pdev->msi_enabled))
1205d3ac705SJiawen Wu 		wr32(wx, WX_PX_INTA, 1);
1215d3ac705SJiawen Wu 
1225d3ac705SJiawen Wu 	wx->isb_mem[WX_ISB_MISC] = 0;
1235d3ac705SJiawen Wu 	/* would disable interrupts here but it is auto disabled */
1245d3ac705SJiawen Wu 	napi_schedule_irqoff(&q_vector->napi);
1255d3ac705SJiawen Wu 
1265d3ac705SJiawen Wu 	/* re-enable link(maybe) and non-queue interrupts, no flush.
1275d3ac705SJiawen Wu 	 * txgbe_poll will re-enable the queue interrupts
1285d3ac705SJiawen Wu 	 */
1295d3ac705SJiawen Wu 	if (netif_running(wx->netdev))
1305d3ac705SJiawen Wu 		txgbe_irq_enable(wx, false);
1315d3ac705SJiawen Wu 
1325d3ac705SJiawen Wu 	return IRQ_HANDLED;
1335d3ac705SJiawen Wu }
1345d3ac705SJiawen Wu 
1355d3ac705SJiawen Wu /**
1365d3ac705SJiawen Wu  * txgbe_request_msix_irqs - Initialize MSI-X interrupts
1375d3ac705SJiawen Wu  * @wx: board private structure
1385d3ac705SJiawen Wu  *
1395d3ac705SJiawen Wu  * Allocate MSI-X vectors and request interrupts from the kernel.
1405d3ac705SJiawen Wu  **/
txgbe_request_msix_irqs(struct wx * wx)1415d3ac705SJiawen Wu static int txgbe_request_msix_irqs(struct wx *wx)
1425d3ac705SJiawen Wu {
1435d3ac705SJiawen Wu 	struct net_device *netdev = wx->netdev;
1445d3ac705SJiawen Wu 	int vector, err;
1455d3ac705SJiawen Wu 
1465d3ac705SJiawen Wu 	for (vector = 0; vector < wx->num_q_vectors; vector++) {
1475d3ac705SJiawen Wu 		struct wx_q_vector *q_vector = wx->q_vector[vector];
1485d3ac705SJiawen Wu 		struct msix_entry *entry = &wx->msix_entries[vector];
1495d3ac705SJiawen Wu 
1505d3ac705SJiawen Wu 		if (q_vector->tx.ring && q_vector->rx.ring)
1515d3ac705SJiawen Wu 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
1525d3ac705SJiawen Wu 				 "%s-TxRx-%d", netdev->name, entry->entry);
1535d3ac705SJiawen Wu 		else
1545d3ac705SJiawen Wu 			/* skip this unused q_vector */
1555d3ac705SJiawen Wu 			continue;
1565d3ac705SJiawen Wu 
1575d3ac705SJiawen Wu 		err = request_irq(entry->vector, wx_msix_clean_rings, 0,
1585d3ac705SJiawen Wu 				  q_vector->name, q_vector);
1595d3ac705SJiawen Wu 		if (err) {
1605d3ac705SJiawen Wu 			wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",
1615d3ac705SJiawen Wu 			       q_vector->name, err);
1625d3ac705SJiawen Wu 			goto free_queue_irqs;
1635d3ac705SJiawen Wu 		}
1645d3ac705SJiawen Wu 	}
1655d3ac705SJiawen Wu 
1665d3ac705SJiawen Wu 	return 0;
1675d3ac705SJiawen Wu 
1685d3ac705SJiawen Wu free_queue_irqs:
1695d3ac705SJiawen Wu 	while (vector) {
1705d3ac705SJiawen Wu 		vector--;
1715d3ac705SJiawen Wu 		free_irq(wx->msix_entries[vector].vector,
1725d3ac705SJiawen Wu 			 wx->q_vector[vector]);
1735d3ac705SJiawen Wu 	}
1745d3ac705SJiawen Wu 	wx_reset_interrupt_capability(wx);
1755d3ac705SJiawen Wu 	return err;
1765d3ac705SJiawen Wu }
1775d3ac705SJiawen Wu 
1785d3ac705SJiawen Wu /**
1795d3ac705SJiawen Wu  * txgbe_request_irq - initialize interrupts
1805d3ac705SJiawen Wu  * @wx: board private structure
1815d3ac705SJiawen Wu  *
1825d3ac705SJiawen Wu  * Attempt to configure interrupts using the best available
1835d3ac705SJiawen Wu  * capabilities of the hardware and kernel.
1845d3ac705SJiawen Wu  **/
txgbe_request_irq(struct wx * wx)1855d3ac705SJiawen Wu static int txgbe_request_irq(struct wx *wx)
1865d3ac705SJiawen Wu {
1875d3ac705SJiawen Wu 	struct net_device *netdev = wx->netdev;
1885d3ac705SJiawen Wu 	struct pci_dev *pdev = wx->pdev;
1895d3ac705SJiawen Wu 	int err;
1905d3ac705SJiawen Wu 
1915d3ac705SJiawen Wu 	if (pdev->msix_enabled)
1925d3ac705SJiawen Wu 		err = txgbe_request_msix_irqs(wx);
1935d3ac705SJiawen Wu 	else if (pdev->msi_enabled)
1945d3ac705SJiawen Wu 		err = request_irq(wx->pdev->irq, &txgbe_intr, 0,
1955d3ac705SJiawen Wu 				  netdev->name, wx);
1965d3ac705SJiawen Wu 	else
1975d3ac705SJiawen Wu 		err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED,
1985d3ac705SJiawen Wu 				  netdev->name, wx);
1995d3ac705SJiawen Wu 
2005d3ac705SJiawen Wu 	if (err)
2015d3ac705SJiawen Wu 		wx_err(wx, "request_irq failed, Error %d\n", err);
2025d3ac705SJiawen Wu 
2035d3ac705SJiawen Wu 	return err;
2045d3ac705SJiawen Wu }
2055d3ac705SJiawen Wu 
txgbe_up_complete(struct wx * wx)206270a71e6SJiawen Wu static void txgbe_up_complete(struct wx *wx)
207049fe536SJiawen Wu {
20808f08f93SJiawen Wu 	struct net_device *netdev = wx->netdev;
20908f08f93SJiawen Wu 	struct txgbe *txgbe;
2100ef7e159SJiawen Wu 
2119607a3e6SJiawen Wu 	wx_control_hw(wx, true);
2125d3ac705SJiawen Wu 	wx_configure_vectors(wx);
2135d3ac705SJiawen Wu 
2140d22be52SJiawen Wu 	/* make sure to complete pre-operations */
2150d22be52SJiawen Wu 	smp_mb__before_atomic();
2160d22be52SJiawen Wu 	wx_napi_enable_all(wx);
2170d22be52SJiawen Wu 
21808f08f93SJiawen Wu 	txgbe = netdev_to_txgbe(netdev);
21908f08f93SJiawen Wu 	phylink_start(txgbe->phylink);
22008f08f93SJiawen Wu 
2215d3ac705SJiawen Wu 	/* clear any pending interrupts, may auto mask */
22259513714SJiawen Wu 	rd32(wx, WX_PX_IC(0));
22359513714SJiawen Wu 	rd32(wx, WX_PX_IC(1));
2245d3ac705SJiawen Wu 	rd32(wx, WX_PX_MISC_IC);
2255d3ac705SJiawen Wu 	txgbe_irq_enable(wx, true);
2260ef7e159SJiawen Wu 
2270d22be52SJiawen Wu 	/* enable transmits */
22808f08f93SJiawen Wu 	netif_tx_start_all_queues(netdev);
229049fe536SJiawen Wu }
230049fe536SJiawen Wu 
txgbe_reset(struct wx * wx)231270a71e6SJiawen Wu static void txgbe_reset(struct wx *wx)
232d21d2c7fSJiawen Wu {
233270a71e6SJiawen Wu 	struct net_device *netdev = wx->netdev;
234d21d2c7fSJiawen Wu 	u8 old_addr[ETH_ALEN];
235d21d2c7fSJiawen Wu 	int err;
236d21d2c7fSJiawen Wu 
237270a71e6SJiawen Wu 	err = txgbe_reset_hw(wx);
238d21d2c7fSJiawen Wu 	if (err != 0)
239270a71e6SJiawen Wu 		wx_err(wx, "Hardware Error: %d\n", err);
240d21d2c7fSJiawen Wu 
2417df4af51SMengyuan Lou 	wx_start_hw(wx);
242d21d2c7fSJiawen Wu 	/* do not flush user set addresses */
2439607a3e6SJiawen Wu 	memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len);
2449607a3e6SJiawen Wu 	wx_flush_sw_mac_table(wx);
2459607a3e6SJiawen Wu 	wx_mac_set_default_filter(wx, old_addr);
246d21d2c7fSJiawen Wu }
247d21d2c7fSJiawen Wu 
txgbe_disable_device(struct wx * wx)248270a71e6SJiawen Wu static void txgbe_disable_device(struct wx *wx)
249d21d2c7fSJiawen Wu {
250270a71e6SJiawen Wu 	struct net_device *netdev = wx->netdev;
2510ef7e159SJiawen Wu 	u32 i;
252d21d2c7fSJiawen Wu 
2539607a3e6SJiawen Wu 	wx_disable_pcie_master(wx);
254d21d2c7fSJiawen Wu 	/* disable receives */
2559607a3e6SJiawen Wu 	wx_disable_rx(wx);
256d21d2c7fSJiawen Wu 
2570ef7e159SJiawen Wu 	/* disable all enabled rx queues */
2580ef7e159SJiawen Wu 	for (i = 0; i < wx->num_rx_queues; i++)
2590ef7e159SJiawen Wu 		/* this call also flushes the previous write */
2600ef7e159SJiawen Wu 		wx_disable_rx_queue(wx, wx->rx_ring[i]);
2610ef7e159SJiawen Wu 
2620d22be52SJiawen Wu 	netif_tx_stop_all_queues(netdev);
263d21d2c7fSJiawen Wu 	netif_tx_disable(netdev);
264d21d2c7fSJiawen Wu 
2655d3ac705SJiawen Wu 	wx_irq_disable(wx);
2660d22be52SJiawen Wu 	wx_napi_disable_all(wx);
2675d3ac705SJiawen Wu 
2689607a3e6SJiawen Wu 	if (wx->bus.func < 2)
2699607a3e6SJiawen Wu 		wr32m(wx, TXGBE_MIS_PRB_CTL, TXGBE_MIS_PRB_CTL_LAN_UP(wx->bus.func), 0);
270d21d2c7fSJiawen Wu 	else
271270a71e6SJiawen Wu 		wx_err(wx, "%s: invalid bus lan id %d\n",
2729607a3e6SJiawen Wu 		       __func__, wx->bus.func);
273d21d2c7fSJiawen Wu 
2749607a3e6SJiawen Wu 	if (!(((wx->subsystem_device_id & WX_NCSI_MASK) == WX_NCSI_SUP) ||
2759607a3e6SJiawen Wu 	      ((wx->subsystem_device_id & WX_WOL_MASK) == WX_WOL_SUP))) {
276d21d2c7fSJiawen Wu 		/* disable mac transmiter */
2779607a3e6SJiawen Wu 		wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
278d21d2c7fSJiawen Wu 	}
279d21d2c7fSJiawen Wu 
2800ef7e159SJiawen Wu 	/* disable transmits in the hardware now that interrupts are off */
2810ef7e159SJiawen Wu 	for (i = 0; i < wx->num_tx_queues; i++) {
2820ef7e159SJiawen Wu 		u8 reg_idx = wx->tx_ring[i]->reg_idx;
2830ef7e159SJiawen Wu 
2840ef7e159SJiawen Wu 		wr32(wx, WX_PX_TR_CFG(reg_idx), WX_PX_TR_CFG_SWFLSH);
2850ef7e159SJiawen Wu 	}
2860ef7e159SJiawen Wu 
287d21d2c7fSJiawen Wu 	/* Disable the Tx DMA engine */
2889607a3e6SJiawen Wu 	wr32m(wx, WX_TDM_CTL, WX_TDM_CTL_TE, 0);
289d21d2c7fSJiawen Wu }
290d21d2c7fSJiawen Wu 
txgbe_down(struct wx * wx)291270a71e6SJiawen Wu static void txgbe_down(struct wx *wx)
292d21d2c7fSJiawen Wu {
29308f08f93SJiawen Wu 	struct txgbe *txgbe = netdev_to_txgbe(wx->netdev);
29408f08f93SJiawen Wu 
295270a71e6SJiawen Wu 	txgbe_disable_device(wx);
296270a71e6SJiawen Wu 	txgbe_reset(wx);
29708f08f93SJiawen Wu 	phylink_stop(txgbe->phylink);
2980d22be52SJiawen Wu 
2990d22be52SJiawen Wu 	wx_clean_all_tx_rings(wx);
3000d22be52SJiawen Wu 	wx_clean_all_rx_rings(wx);
301d21d2c7fSJiawen Wu }
302d21d2c7fSJiawen Wu 
303a34b3e6eSJiawen Wu /**
30402b2a6f9SJiawen Wu  *  txgbe_init_type_code - Initialize the shared code
30502b2a6f9SJiawen Wu  *  @wx: pointer to hardware structure
30602b2a6f9SJiawen Wu  **/
txgbe_init_type_code(struct wx * wx)30702b2a6f9SJiawen Wu static void txgbe_init_type_code(struct wx *wx)
30802b2a6f9SJiawen Wu {
30902b2a6f9SJiawen Wu 	u8 device_type = wx->subsystem_device_id & 0xF0;
31002b2a6f9SJiawen Wu 
31102b2a6f9SJiawen Wu 	switch (wx->device_id) {
31202b2a6f9SJiawen Wu 	case TXGBE_DEV_ID_SP1000:
31302b2a6f9SJiawen Wu 	case TXGBE_DEV_ID_WX1820:
31402b2a6f9SJiawen Wu 		wx->mac.type = wx_mac_sp;
31502b2a6f9SJiawen Wu 		break;
31602b2a6f9SJiawen Wu 	default:
31702b2a6f9SJiawen Wu 		wx->mac.type = wx_mac_unknown;
31802b2a6f9SJiawen Wu 		break;
31902b2a6f9SJiawen Wu 	}
32002b2a6f9SJiawen Wu 
32102b2a6f9SJiawen Wu 	switch (device_type) {
32202b2a6f9SJiawen Wu 	case TXGBE_ID_SFP:
32302b2a6f9SJiawen Wu 		wx->media_type = sp_media_fiber;
32402b2a6f9SJiawen Wu 		break;
32502b2a6f9SJiawen Wu 	case TXGBE_ID_XAUI:
32602b2a6f9SJiawen Wu 	case TXGBE_ID_SGMII:
32702b2a6f9SJiawen Wu 		wx->media_type = sp_media_copper;
32802b2a6f9SJiawen Wu 		break;
32902b2a6f9SJiawen Wu 	case TXGBE_ID_KR_KX_KX4:
33002b2a6f9SJiawen Wu 	case TXGBE_ID_MAC_XAUI:
33102b2a6f9SJiawen Wu 	case TXGBE_ID_MAC_SGMII:
33202b2a6f9SJiawen Wu 		wx->media_type = sp_media_backplane;
33302b2a6f9SJiawen Wu 		break;
33402b2a6f9SJiawen Wu 	case TXGBE_ID_SFI_XAUI:
33502b2a6f9SJiawen Wu 		if (wx->bus.func == 0)
33602b2a6f9SJiawen Wu 			wx->media_type = sp_media_fiber;
33702b2a6f9SJiawen Wu 		else
33802b2a6f9SJiawen Wu 			wx->media_type = sp_media_copper;
33902b2a6f9SJiawen Wu 		break;
34002b2a6f9SJiawen Wu 	default:
34102b2a6f9SJiawen Wu 		wx->media_type = sp_media_unknown;
34202b2a6f9SJiawen Wu 		break;
34302b2a6f9SJiawen Wu 	}
34402b2a6f9SJiawen Wu }
34502b2a6f9SJiawen Wu 
34602b2a6f9SJiawen Wu /**
347270a71e6SJiawen Wu  * txgbe_sw_init - Initialize general software structures (struct wx)
348270a71e6SJiawen Wu  * @wx: board private structure to initialize
349a34b3e6eSJiawen Wu  **/
txgbe_sw_init(struct wx * wx)350270a71e6SJiawen Wu static int txgbe_sw_init(struct wx *wx)
351a34b3e6eSJiawen Wu {
3525d3ac705SJiawen Wu 	u16 msix_count = 0;
353a34b3e6eSJiawen Wu 	int err;
354a34b3e6eSJiawen Wu 
3559607a3e6SJiawen Wu 	wx->mac.num_rar_entries = TXGBE_SP_RAR_ENTRIES;
3569607a3e6SJiawen Wu 	wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES;
3579607a3e6SJiawen Wu 	wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES;
3589607a3e6SJiawen Wu 	wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE;
3597df4af51SMengyuan Lou 	wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE;
3600ef7e159SJiawen Wu 	wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE;
3610ef7e159SJiawen Wu 	wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ;
36279625f45SJiawen Wu 
363a34b3e6eSJiawen Wu 	/* PCI config space info */
3649607a3e6SJiawen Wu 	err = wx_sw_init(wx);
365*61a55071SJiawen Wu 	if (err < 0)
366a34b3e6eSJiawen Wu 		return err;
367a34b3e6eSJiawen Wu 
36802b2a6f9SJiawen Wu 	txgbe_init_type_code(wx);
369b0801256SJiawen Wu 
3705d3ac705SJiawen Wu 	/* Set common capability flags and settings */
3715d3ac705SJiawen Wu 	wx->max_q_vectors = TXGBE_MAX_MSIX_VECTORS;
3725d3ac705SJiawen Wu 	err = wx_get_pcie_msix_counts(wx, &msix_count, TXGBE_MAX_MSIX_VECTORS);
3735d3ac705SJiawen Wu 	if (err)
3745d3ac705SJiawen Wu 		wx_err(wx, "Do not support MSI-X\n");
3755d3ac705SJiawen Wu 	wx->mac.max_msix_vectors = msix_count;
3765d3ac705SJiawen Wu 
3775d3ac705SJiawen Wu 	/* enable itr by default in dynamic mode */
3785d3ac705SJiawen Wu 	wx->rx_itr_setting = 1;
3795d3ac705SJiawen Wu 	wx->tx_itr_setting = 1;
3805d3ac705SJiawen Wu 
3815d3ac705SJiawen Wu 	/* set default ring sizes */
3825d3ac705SJiawen Wu 	wx->tx_ring_count = TXGBE_DEFAULT_TXD;
3835d3ac705SJiawen Wu 	wx->rx_ring_count = TXGBE_DEFAULT_RXD;
3845d3ac705SJiawen Wu 
3855d3ac705SJiawen Wu 	/* set default work limits */
3865d3ac705SJiawen Wu 	wx->tx_work_limit = TXGBE_DEFAULT_TX_WORK;
3875d3ac705SJiawen Wu 	wx->rx_work_limit = TXGBE_DEFAULT_RX_WORK;
3885d3ac705SJiawen Wu 
389d21d2c7fSJiawen Wu 	return 0;
390d21d2c7fSJiawen Wu }
391d21d2c7fSJiawen Wu 
392d21d2c7fSJiawen Wu /**
393d21d2c7fSJiawen Wu  * txgbe_open - Called when a network interface is made active
394d21d2c7fSJiawen Wu  * @netdev: network interface device structure
395d21d2c7fSJiawen Wu  *
396d21d2c7fSJiawen Wu  * Returns 0 on success, negative value on failure
397d21d2c7fSJiawen Wu  *
398d21d2c7fSJiawen Wu  * The open entry point is called when a network interface is made
399d21d2c7fSJiawen Wu  * active by the system (IFF_UP).
400d21d2c7fSJiawen Wu  **/
txgbe_open(struct net_device * netdev)401d21d2c7fSJiawen Wu static int txgbe_open(struct net_device *netdev)
402d21d2c7fSJiawen Wu {
403270a71e6SJiawen Wu 	struct wx *wx = netdev_priv(netdev);
4045d3ac705SJiawen Wu 	int err;
4055d3ac705SJiawen Wu 
4060ef7e159SJiawen Wu 	err = wx_setup_resources(wx);
4075d3ac705SJiawen Wu 	if (err)
4085d3ac705SJiawen Wu 		goto err_reset;
4095d3ac705SJiawen Wu 
4105d3ac705SJiawen Wu 	wx_configure(wx);
4115d3ac705SJiawen Wu 
4125d3ac705SJiawen Wu 	err = txgbe_request_irq(wx);
4135d3ac705SJiawen Wu 	if (err)
4145d3ac705SJiawen Wu 		goto err_free_isb;
415049fe536SJiawen Wu 
4160d22be52SJiawen Wu 	/* Notify the stack of the actual queue counts. */
4170d22be52SJiawen Wu 	err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues);
4180d22be52SJiawen Wu 	if (err)
4190d22be52SJiawen Wu 		goto err_free_irq;
4200d22be52SJiawen Wu 
4210d22be52SJiawen Wu 	err = netif_set_real_num_rx_queues(netdev, wx->num_rx_queues);
4220d22be52SJiawen Wu 	if (err)
4230d22be52SJiawen Wu 		goto err_free_irq;
4240d22be52SJiawen Wu 
425270a71e6SJiawen Wu 	txgbe_up_complete(wx);
426049fe536SJiawen Wu 
427d21d2c7fSJiawen Wu 	return 0;
4285d3ac705SJiawen Wu 
4290d22be52SJiawen Wu err_free_irq:
4300d22be52SJiawen Wu 	wx_free_irq(wx);
4315d3ac705SJiawen Wu err_free_isb:
4325d3ac705SJiawen Wu 	wx_free_isb_resources(wx);
4335d3ac705SJiawen Wu err_reset:
4345d3ac705SJiawen Wu 	txgbe_reset(wx);
4355d3ac705SJiawen Wu 
4365d3ac705SJiawen Wu 	return err;
437d21d2c7fSJiawen Wu }
438d21d2c7fSJiawen Wu 
439d21d2c7fSJiawen Wu /**
440d21d2c7fSJiawen Wu  * txgbe_close_suspend - actions necessary to both suspend and close flows
441270a71e6SJiawen Wu  * @wx: the private wx struct
442d21d2c7fSJiawen Wu  *
443d21d2c7fSJiawen Wu  * This function should contain the necessary work common to both suspending
444d21d2c7fSJiawen Wu  * and closing of the device.
445d21d2c7fSJiawen Wu  */
txgbe_close_suspend(struct wx * wx)446270a71e6SJiawen Wu static void txgbe_close_suspend(struct wx *wx)
447d21d2c7fSJiawen Wu {
448270a71e6SJiawen Wu 	txgbe_disable_device(wx);
4490ef7e159SJiawen Wu 	wx_free_resources(wx);
450d21d2c7fSJiawen Wu }
451d21d2c7fSJiawen Wu 
452d21d2c7fSJiawen Wu /**
453d21d2c7fSJiawen Wu  * txgbe_close - Disables a network interface
454d21d2c7fSJiawen Wu  * @netdev: network interface device structure
455d21d2c7fSJiawen Wu  *
456d21d2c7fSJiawen Wu  * Returns 0, this is not allowed to fail
457d21d2c7fSJiawen Wu  *
458d21d2c7fSJiawen Wu  * The close entry point is called when an interface is de-activated
459d21d2c7fSJiawen Wu  * by the OS.  The hardware is still under the drivers control, but
460d21d2c7fSJiawen Wu  * needs to be disabled.  A global MAC reset is issued to stop the
461d21d2c7fSJiawen Wu  * hardware, and all transmit and receive resources are freed.
462d21d2c7fSJiawen Wu  **/
txgbe_close(struct net_device * netdev)463d21d2c7fSJiawen Wu static int txgbe_close(struct net_device *netdev)
464d21d2c7fSJiawen Wu {
465270a71e6SJiawen Wu 	struct wx *wx = netdev_priv(netdev);
466d21d2c7fSJiawen Wu 
467270a71e6SJiawen Wu 	txgbe_down(wx);
4685d3ac705SJiawen Wu 	wx_free_irq(wx);
4690ef7e159SJiawen Wu 	wx_free_resources(wx);
470270a71e6SJiawen Wu 	wx_control_hw(wx, false);
471b0801256SJiawen Wu 
472a34b3e6eSJiawen Wu 	return 0;
473a34b3e6eSJiawen Wu }
474a34b3e6eSJiawen Wu 
txgbe_dev_shutdown(struct pci_dev * pdev)475e7214663SSimon Horman static void txgbe_dev_shutdown(struct pci_dev *pdev)
4763ce7547eSJiawen Wu {
477270a71e6SJiawen Wu 	struct wx *wx = pci_get_drvdata(pdev);
478270a71e6SJiawen Wu 	struct net_device *netdev;
4793ce7547eSJiawen Wu 
480270a71e6SJiawen Wu 	netdev = wx->netdev;
4813ce7547eSJiawen Wu 	netif_device_detach(netdev);
4823ce7547eSJiawen Wu 
483d21d2c7fSJiawen Wu 	rtnl_lock();
484d21d2c7fSJiawen Wu 	if (netif_running(netdev))
485270a71e6SJiawen Wu 		txgbe_close_suspend(wx);
486d21d2c7fSJiawen Wu 	rtnl_unlock();
487d21d2c7fSJiawen Wu 
4889607a3e6SJiawen Wu 	wx_control_hw(wx, false);
489049fe536SJiawen Wu 
4903ce7547eSJiawen Wu 	pci_disable_device(pdev);
4913ce7547eSJiawen Wu }
4923ce7547eSJiawen Wu 
txgbe_shutdown(struct pci_dev * pdev)4933ce7547eSJiawen Wu static void txgbe_shutdown(struct pci_dev *pdev)
4943ce7547eSJiawen Wu {
495e7214663SSimon Horman 	txgbe_dev_shutdown(pdev);
4963ce7547eSJiawen Wu 
4973ce7547eSJiawen Wu 	if (system_state == SYSTEM_POWER_OFF) {
498e7214663SSimon Horman 		pci_wake_from_d3(pdev, false);
4993ce7547eSJiawen Wu 		pci_set_power_state(pdev, PCI_D3hot);
5003ce7547eSJiawen Wu 	}
5013ce7547eSJiawen Wu }
5023ce7547eSJiawen Wu 
503d21d2c7fSJiawen Wu static const struct net_device_ops txgbe_netdev_ops = {
504d21d2c7fSJiawen Wu 	.ndo_open               = txgbe_open,
505d21d2c7fSJiawen Wu 	.ndo_stop               = txgbe_close,
50681dc0741SMengyuan Lou 	.ndo_change_mtu         = wx_change_mtu,
5070d22be52SJiawen Wu 	.ndo_start_xmit         = wx_xmit_frame,
5080ef7e159SJiawen Wu 	.ndo_set_rx_mode        = wx_set_rx_mode,
5096670f1ecSMengyuan Lou 	.ndo_set_features       = wx_set_features,
510d21d2c7fSJiawen Wu 	.ndo_validate_addr      = eth_validate_addr,
51179625f45SJiawen Wu 	.ndo_set_mac_address    = wx_set_mac,
5120d22be52SJiawen Wu 	.ndo_get_stats64        = wx_get_stats64,
5137df4af51SMengyuan Lou 	.ndo_vlan_rx_add_vid    = wx_vlan_rx_add_vid,
5147df4af51SMengyuan Lou 	.ndo_vlan_rx_kill_vid   = wx_vlan_rx_kill_vid,
515d21d2c7fSJiawen Wu };
516d21d2c7fSJiawen Wu 
5173ce7547eSJiawen Wu /**
5183ce7547eSJiawen Wu  * txgbe_probe - Device Initialization Routine
5193ce7547eSJiawen Wu  * @pdev: PCI device information struct
5203ce7547eSJiawen Wu  * @ent: entry in txgbe_pci_tbl
5213ce7547eSJiawen Wu  *
5223ce7547eSJiawen Wu  * Returns 0 on success, negative on failure
5233ce7547eSJiawen Wu  *
5243ce7547eSJiawen Wu  * txgbe_probe initializes an adapter identified by a pci_dev structure.
525270a71e6SJiawen Wu  * The OS initialization, configuring of the wx private structure,
5263ce7547eSJiawen Wu  * and a hardware reset occur.
5273ce7547eSJiawen Wu  **/
txgbe_probe(struct pci_dev * pdev,const struct pci_device_id __always_unused * ent)5283ce7547eSJiawen Wu static int txgbe_probe(struct pci_dev *pdev,
5293ce7547eSJiawen Wu 		       const struct pci_device_id __always_unused *ent)
5303ce7547eSJiawen Wu {
5313ce7547eSJiawen Wu 	struct net_device *netdev;
532a34b3e6eSJiawen Wu 	int err, expected_gts;
533270a71e6SJiawen Wu 	struct wx *wx = NULL;
534c3e382adSJiawen Wu 	struct txgbe *txgbe;
5353ce7547eSJiawen Wu 
536049fe536SJiawen Wu 	u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0;
537049fe536SJiawen Wu 	u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0;
538049fe536SJiawen Wu 	u16 build = 0, major = 0, patch = 0;
539049fe536SJiawen Wu 	u8 part_str[TXGBE_PBANUM_LENGTH];
540049fe536SJiawen Wu 	u32 etrack_id = 0;
541049fe536SJiawen Wu 
5423ce7547eSJiawen Wu 	err = pci_enable_device_mem(pdev);
5433ce7547eSJiawen Wu 	if (err)
5443ce7547eSJiawen Wu 		return err;
5453ce7547eSJiawen Wu 
5463ce7547eSJiawen Wu 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
5473ce7547eSJiawen Wu 	if (err) {
5483ce7547eSJiawen Wu 		dev_err(&pdev->dev,
5493ce7547eSJiawen Wu 			"No usable DMA configuration, aborting\n");
5503ce7547eSJiawen Wu 		goto err_pci_disable_dev;
5513ce7547eSJiawen Wu 	}
5523ce7547eSJiawen Wu 
5533ce7547eSJiawen Wu 	err = pci_request_selected_regions(pdev,
5543ce7547eSJiawen Wu 					   pci_select_bars(pdev, IORESOURCE_MEM),
5553ce7547eSJiawen Wu 					   txgbe_driver_name);
5563ce7547eSJiawen Wu 	if (err) {
5573ce7547eSJiawen Wu 		dev_err(&pdev->dev,
5583ce7547eSJiawen Wu 			"pci_request_selected_regions failed 0x%x\n", err);
5593ce7547eSJiawen Wu 		goto err_pci_disable_dev;
5603ce7547eSJiawen Wu 	}
5613ce7547eSJiawen Wu 
5623ce7547eSJiawen Wu 	pci_set_master(pdev);
5633ce7547eSJiawen Wu 
5643ce7547eSJiawen Wu 	netdev = devm_alloc_etherdev_mqs(&pdev->dev,
565270a71e6SJiawen Wu 					 sizeof(struct wx),
5663ce7547eSJiawen Wu 					 TXGBE_MAX_TX_QUEUES,
5673ce7547eSJiawen Wu 					 TXGBE_MAX_RX_QUEUES);
5683ce7547eSJiawen Wu 	if (!netdev) {
5693ce7547eSJiawen Wu 		err = -ENOMEM;
5703ce7547eSJiawen Wu 		goto err_pci_release_regions;
5713ce7547eSJiawen Wu 	}
5723ce7547eSJiawen Wu 
5733ce7547eSJiawen Wu 	SET_NETDEV_DEV(netdev, &pdev->dev);
5743ce7547eSJiawen Wu 
575270a71e6SJiawen Wu 	wx = netdev_priv(netdev);
5769607a3e6SJiawen Wu 	wx->netdev = netdev;
577270a71e6SJiawen Wu 	wx->pdev = pdev;
5783ce7547eSJiawen Wu 
579270a71e6SJiawen Wu 	wx->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
580270a71e6SJiawen Wu 
581270a71e6SJiawen Wu 	wx->hw_addr = devm_ioremap(&pdev->dev,
5823ce7547eSJiawen Wu 				   pci_resource_start(pdev, 0),
5833ce7547eSJiawen Wu 				   pci_resource_len(pdev, 0));
584270a71e6SJiawen Wu 	if (!wx->hw_addr) {
5853ce7547eSJiawen Wu 		err = -EIO;
5863ce7547eSJiawen Wu 		goto err_pci_release_regions;
5873ce7547eSJiawen Wu 	}
5883ce7547eSJiawen Wu 
5891b8d1c50SMengyuan Lou 	wx->driver_name = txgbe_driver_name;
5901b8d1c50SMengyuan Lou 	txgbe_set_ethtool_ops(netdev);
591d21d2c7fSJiawen Wu 	netdev->netdev_ops = &txgbe_netdev_ops;
592a34b3e6eSJiawen Wu 
593a34b3e6eSJiawen Wu 	/* setup the private structure */
594270a71e6SJiawen Wu 	err = txgbe_sw_init(wx);
595a34b3e6eSJiawen Wu 	if (err)
596d21d2c7fSJiawen Wu 		goto err_free_mac_table;
597a34b3e6eSJiawen Wu 
598a34b3e6eSJiawen Wu 	/* check if flash load is done after hw power up */
5999607a3e6SJiawen Wu 	err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PERST);
600a34b3e6eSJiawen Wu 	if (err)
601d21d2c7fSJiawen Wu 		goto err_free_mac_table;
6029607a3e6SJiawen Wu 	err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PWRRST);
603a34b3e6eSJiawen Wu 	if (err)
604d21d2c7fSJiawen Wu 		goto err_free_mac_table;
605a34b3e6eSJiawen Wu 
6069607a3e6SJiawen Wu 	err = wx_mng_present(wx);
607049fe536SJiawen Wu 	if (err) {
608049fe536SJiawen Wu 		dev_err(&pdev->dev, "Management capability is not present\n");
609049fe536SJiawen Wu 		goto err_free_mac_table;
610049fe536SJiawen Wu 	}
611049fe536SJiawen Wu 
612270a71e6SJiawen Wu 	err = txgbe_reset_hw(wx);
613b0801256SJiawen Wu 	if (err) {
614b0801256SJiawen Wu 		dev_err(&pdev->dev, "HW Init failed: %d\n", err);
615d21d2c7fSJiawen Wu 		goto err_free_mac_table;
616b0801256SJiawen Wu 	}
617b0801256SJiawen Wu 
6186670f1ecSMengyuan Lou 	netdev->features = NETIF_F_SG |
6196670f1ecSMengyuan Lou 			   NETIF_F_TSO |
6206670f1ecSMengyuan Lou 			   NETIF_F_TSO6 |
6216670f1ecSMengyuan Lou 			   NETIF_F_RXHASH |
6226670f1ecSMengyuan Lou 			   NETIF_F_RXCSUM |
6236670f1ecSMengyuan Lou 			   NETIF_F_HW_CSUM;
6240ef7e159SJiawen Wu 
6256670f1ecSMengyuan Lou 	netdev->gso_partial_features =  NETIF_F_GSO_ENCAP_ALL;
6266670f1ecSMengyuan Lou 	netdev->features |= netdev->gso_partial_features;
6276670f1ecSMengyuan Lou 	netdev->features |= NETIF_F_SCTP_CRC;
6286670f1ecSMengyuan Lou 	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
6296670f1ecSMengyuan Lou 	netdev->hw_enc_features |= netdev->vlan_features;
6306670f1ecSMengyuan Lou 	netdev->features |= NETIF_F_VLAN_FEATURES;
6310ef7e159SJiawen Wu 	/* copy netdev features into list of user selectable features */
6320ef7e159SJiawen Wu 	netdev->hw_features |= netdev->features | NETIF_F_RXALL;
6336670f1ecSMengyuan Lou 	netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
6346670f1ecSMengyuan Lou 	netdev->features |= NETIF_F_HIGHDMA;
6356670f1ecSMengyuan Lou 	netdev->hw_features |= NETIF_F_GRO;
6366670f1ecSMengyuan Lou 	netdev->features |= NETIF_F_GRO;
6370ef7e159SJiawen Wu 
6380ef7e159SJiawen Wu 	netdev->priv_flags |= IFF_UNICAST_FLT;
6390ef7e159SJiawen Wu 	netdev->priv_flags |= IFF_SUPP_NOFCS;
6400ef7e159SJiawen Wu 
6410ef7e159SJiawen Wu 	netdev->min_mtu = ETH_MIN_MTU;
64281dc0741SMengyuan Lou 	netdev->max_mtu = WX_MAX_JUMBO_FRAME_SIZE -
64381dc0741SMengyuan Lou 			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
6443ce7547eSJiawen Wu 
645049fe536SJiawen Wu 	/* make sure the EEPROM is good */
6469607a3e6SJiawen Wu 	err = txgbe_validate_eeprom_checksum(wx, NULL);
647049fe536SJiawen Wu 	if (err != 0) {
648049fe536SJiawen Wu 		dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
6499607a3e6SJiawen Wu 		wr32(wx, WX_MIS_RST, WX_MIS_RST_SW_RST);
650049fe536SJiawen Wu 		err = -EIO;
651049fe536SJiawen Wu 		goto err_free_mac_table;
652049fe536SJiawen Wu 	}
653049fe536SJiawen Wu 
6549607a3e6SJiawen Wu 	eth_hw_addr_set(netdev, wx->mac.perm_addr);
6559607a3e6SJiawen Wu 	wx_mac_set_default_filter(wx, wx->mac.perm_addr);
656d21d2c7fSJiawen Wu 
6575d3ac705SJiawen Wu 	err = wx_init_interrupt_scheme(wx);
6585d3ac705SJiawen Wu 	if (err)
6595d3ac705SJiawen Wu 		goto err_free_mac_table;
6605d3ac705SJiawen Wu 
661049fe536SJiawen Wu 	/* Save off EEPROM version number and Option Rom version which
662049fe536SJiawen Wu 	 * together make a unique identify for the eeprom
663049fe536SJiawen Wu 	 */
6649607a3e6SJiawen Wu 	wx_read_ee_hostif(wx,
6659607a3e6SJiawen Wu 			  wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_H,
666049fe536SJiawen Wu 			  &eeprom_verh);
6679607a3e6SJiawen Wu 	wx_read_ee_hostif(wx,
6689607a3e6SJiawen Wu 			  wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_L,
669049fe536SJiawen Wu 			  &eeprom_verl);
670049fe536SJiawen Wu 	etrack_id = (eeprom_verh << 16) | eeprom_verl;
671049fe536SJiawen Wu 
6729607a3e6SJiawen Wu 	wx_read_ee_hostif(wx,
6739607a3e6SJiawen Wu 			  wx->eeprom.sw_region_offset + TXGBE_ISCSI_BOOT_CONFIG,
674049fe536SJiawen Wu 			  &offset);
675049fe536SJiawen Wu 
676049fe536SJiawen Wu 	/* Make sure offset to SCSI block is valid */
677049fe536SJiawen Wu 	if (!(offset == 0x0) && !(offset == 0xffff)) {
6789607a3e6SJiawen Wu 		wx_read_ee_hostif(wx, offset + 0x84, &eeprom_cfg_blkh);
6799607a3e6SJiawen Wu 		wx_read_ee_hostif(wx, offset + 0x83, &eeprom_cfg_blkl);
680049fe536SJiawen Wu 
681049fe536SJiawen Wu 		/* Only display Option Rom if exist */
682049fe536SJiawen Wu 		if (eeprom_cfg_blkl && eeprom_cfg_blkh) {
683049fe536SJiawen Wu 			major = eeprom_cfg_blkl >> 8;
684049fe536SJiawen Wu 			build = (eeprom_cfg_blkl << 8) | (eeprom_cfg_blkh >> 8);
685049fe536SJiawen Wu 			patch = eeprom_cfg_blkh & 0x00ff;
686049fe536SJiawen Wu 
687270a71e6SJiawen Wu 			snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),
688049fe536SJiawen Wu 				 "0x%08x, %d.%d.%d", etrack_id, major, build,
689049fe536SJiawen Wu 				 patch);
690049fe536SJiawen Wu 		} else {
691270a71e6SJiawen Wu 			snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),
692049fe536SJiawen Wu 				 "0x%08x", etrack_id);
693049fe536SJiawen Wu 		}
694049fe536SJiawen Wu 	} else {
695270a71e6SJiawen Wu 		snprintf(wx->eeprom_id, sizeof(wx->eeprom_id),
696049fe536SJiawen Wu 			 "0x%08x", etrack_id);
697049fe536SJiawen Wu 	}
698049fe536SJiawen Wu 
699ab928c24SJiawen Wu 	if (etrack_id < 0x20010)
700ab928c24SJiawen Wu 		dev_warn(&pdev->dev, "Please upgrade the firmware to 0x20010 or above.\n");
701ab928c24SJiawen Wu 
702c3e382adSJiawen Wu 	txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL);
703c3e382adSJiawen Wu 	if (!txgbe) {
704c3e382adSJiawen Wu 		err = -ENOMEM;
705c3e382adSJiawen Wu 		goto err_release_hw;
706c3e382adSJiawen Wu 	}
707c3e382adSJiawen Wu 
708c3e382adSJiawen Wu 	txgbe->wx = wx;
709c3e382adSJiawen Wu 	wx->priv = txgbe;
710c3e382adSJiawen Wu 
711c3e382adSJiawen Wu 	err = txgbe_init_phy(txgbe);
712d21d2c7fSJiawen Wu 	if (err)
713049fe536SJiawen Wu 		goto err_release_hw;
714d21d2c7fSJiawen Wu 
715c3e382adSJiawen Wu 	err = register_netdev(netdev);
716c3e382adSJiawen Wu 	if (err)
717c3e382adSJiawen Wu 		goto err_remove_phy;
718c3e382adSJiawen Wu 
719270a71e6SJiawen Wu 	pci_set_drvdata(pdev, wx);
7203ce7547eSJiawen Wu 
7210d22be52SJiawen Wu 	netif_tx_stop_all_queues(netdev);
7220d22be52SJiawen Wu 
723a34b3e6eSJiawen Wu 	/* calculate the expected PCIe bandwidth required for optimal
724a34b3e6eSJiawen Wu 	 * performance. Note that some older parts will never have enough
725a34b3e6eSJiawen Wu 	 * bandwidth due to being older generation PCIe parts. We clamp these
726a34b3e6eSJiawen Wu 	 * parts to ensure that no warning is displayed, as this could confuse
727a34b3e6eSJiawen Wu 	 * users otherwise.
728a34b3e6eSJiawen Wu 	 */
729270a71e6SJiawen Wu 	expected_gts = txgbe_enumerate_functions(wx) * 10;
730a34b3e6eSJiawen Wu 
731a34b3e6eSJiawen Wu 	/* don't check link if we failed to enumerate functions */
732a34b3e6eSJiawen Wu 	if (expected_gts > 0)
733270a71e6SJiawen Wu 		txgbe_check_minimum_link(wx);
734a34b3e6eSJiawen Wu 	else
735a34b3e6eSJiawen Wu 		dev_warn(&pdev->dev, "Failed to enumerate PF devices.\n");
736a34b3e6eSJiawen Wu 
737049fe536SJiawen Wu 	/* First try to read PBA as a string */
7389607a3e6SJiawen Wu 	err = txgbe_read_pba_string(wx, part_str, TXGBE_PBANUM_LENGTH);
739049fe536SJiawen Wu 	if (err)
740049fe536SJiawen Wu 		strncpy(part_str, "Unknown", TXGBE_PBANUM_LENGTH);
741049fe536SJiawen Wu 
742270a71e6SJiawen Wu 	netif_info(wx, probe, netdev, "%pM\n", netdev->dev_addr);
743d21d2c7fSJiawen Wu 
7443ce7547eSJiawen Wu 	return 0;
7453ce7547eSJiawen Wu 
746c3e382adSJiawen Wu err_remove_phy:
747c3e382adSJiawen Wu 	txgbe_remove_phy(txgbe);
748049fe536SJiawen Wu err_release_hw:
7495d3ac705SJiawen Wu 	wx_clear_interrupt_scheme(wx);
7509607a3e6SJiawen Wu 	wx_control_hw(wx, false);
751d21d2c7fSJiawen Wu err_free_mac_table:
7529607a3e6SJiawen Wu 	kfree(wx->mac_table);
7533ce7547eSJiawen Wu err_pci_release_regions:
7543ce7547eSJiawen Wu 	pci_release_selected_regions(pdev,
7553ce7547eSJiawen Wu 				     pci_select_bars(pdev, IORESOURCE_MEM));
7563ce7547eSJiawen Wu err_pci_disable_dev:
7573ce7547eSJiawen Wu 	pci_disable_device(pdev);
7583ce7547eSJiawen Wu 	return err;
7593ce7547eSJiawen Wu }
7603ce7547eSJiawen Wu 
7613ce7547eSJiawen Wu /**
7623ce7547eSJiawen Wu  * txgbe_remove - Device Removal Routine
7633ce7547eSJiawen Wu  * @pdev: PCI device information struct
7643ce7547eSJiawen Wu  *
7653ce7547eSJiawen Wu  * txgbe_remove is called by the PCI subsystem to alert the driver
7663ce7547eSJiawen Wu  * that it should release a PCI device.  The could be caused by a
7673ce7547eSJiawen Wu  * Hot-Plug event, or because the driver is going to be removed from
7683ce7547eSJiawen Wu  * memory.
7693ce7547eSJiawen Wu  **/
txgbe_remove(struct pci_dev * pdev)7703ce7547eSJiawen Wu static void txgbe_remove(struct pci_dev *pdev)
7713ce7547eSJiawen Wu {
772270a71e6SJiawen Wu 	struct wx *wx = pci_get_drvdata(pdev);
773c3e382adSJiawen Wu 	struct txgbe *txgbe = wx->priv;
774d21d2c7fSJiawen Wu 	struct net_device *netdev;
775d21d2c7fSJiawen Wu 
776270a71e6SJiawen Wu 	netdev = wx->netdev;
777d21d2c7fSJiawen Wu 	unregister_netdev(netdev);
778d21d2c7fSJiawen Wu 
779c3e382adSJiawen Wu 	txgbe_remove_phy(txgbe);
780c3e382adSJiawen Wu 
7813ce7547eSJiawen Wu 	pci_release_selected_regions(pdev,
7823ce7547eSJiawen Wu 				     pci_select_bars(pdev, IORESOURCE_MEM));
7833ce7547eSJiawen Wu 
784270a71e6SJiawen Wu 	kfree(wx->mac_table);
7855d3ac705SJiawen Wu 	wx_clear_interrupt_scheme(wx);
786d21d2c7fSJiawen Wu 
7873ce7547eSJiawen Wu 	pci_disable_device(pdev);
7883ce7547eSJiawen Wu }
7893ce7547eSJiawen Wu 
7903ce7547eSJiawen Wu static struct pci_driver txgbe_driver = {
7913ce7547eSJiawen Wu 	.name     = txgbe_driver_name,
7923ce7547eSJiawen Wu 	.id_table = txgbe_pci_tbl,
7933ce7547eSJiawen Wu 	.probe    = txgbe_probe,
7943ce7547eSJiawen Wu 	.remove   = txgbe_remove,
7953ce7547eSJiawen Wu 	.shutdown = txgbe_shutdown,
7963ce7547eSJiawen Wu };
7973ce7547eSJiawen Wu 
7983ce7547eSJiawen Wu module_pci_driver(txgbe_driver);
7993ce7547eSJiawen Wu 
8003ce7547eSJiawen Wu MODULE_DEVICE_TABLE(pci, txgbe_pci_tbl);
8013ce7547eSJiawen Wu MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@trustnetic.com>");
8023ce7547eSJiawen Wu MODULE_DESCRIPTION("WangXun(R) 10 Gigabit PCI Express Network Driver");
8033ce7547eSJiawen Wu MODULE_LICENSE("GPL");
804