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