125e992a4SHeiner Kallweit // SPDX-License-Identifier: GPL-2.0-only
225e992a4SHeiner Kallweit /*
325e992a4SHeiner Kallweit  * r8169.c: RealTek 8169/8168/8101 ethernet driver.
425e992a4SHeiner Kallweit  *
525e992a4SHeiner Kallweit  * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
625e992a4SHeiner Kallweit  * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
725e992a4SHeiner Kallweit  * Copyright (c) a lot of people too. Please respect their work.
825e992a4SHeiner Kallweit  *
925e992a4SHeiner Kallweit  * See MAINTAINERS file for support contact information.
1025e992a4SHeiner Kallweit  */
1125e992a4SHeiner Kallweit 
1225e992a4SHeiner Kallweit #include <linux/module.h>
1325e992a4SHeiner Kallweit #include <linux/pci.h>
1425e992a4SHeiner Kallweit #include <linux/netdevice.h>
1525e992a4SHeiner Kallweit #include <linux/etherdevice.h>
1625e992a4SHeiner Kallweit #include <linux/clk.h>
1725e992a4SHeiner Kallweit #include <linux/delay.h>
1825e992a4SHeiner Kallweit #include <linux/ethtool.h>
1925e992a4SHeiner Kallweit #include <linux/phy.h>
2025e992a4SHeiner Kallweit #include <linux/if_vlan.h>
2125e992a4SHeiner Kallweit #include <linux/in.h>
2225e992a4SHeiner Kallweit #include <linux/io.h>
2325e992a4SHeiner Kallweit #include <linux/ip.h>
2425e992a4SHeiner Kallweit #include <linux/tcp.h>
2525e992a4SHeiner Kallweit #include <linux/interrupt.h>
2625e992a4SHeiner Kallweit #include <linux/dma-mapping.h>
2725e992a4SHeiner Kallweit #include <linux/pm_runtime.h>
286cf96dd4SHeiner Kallweit #include <linux/bitfield.h>
2925e992a4SHeiner Kallweit #include <linux/prefetch.h>
3025e992a4SHeiner Kallweit #include <linux/ipv6.h>
31ae1e82c6SHeiner Kallweit #include <asm/unaligned.h>
3225e992a4SHeiner Kallweit #include <net/ip6_checksum.h>
338624e9bbSHeiner Kallweit #include <net/netdev_queues.h>
3425e992a4SHeiner Kallweit 
352992bdfaSHeiner Kallweit #include "r8169.h"
368197f9d2SHeiner Kallweit #include "r8169_firmware.h"
378197f9d2SHeiner Kallweit 
3825e992a4SHeiner Kallweit #define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
3925e992a4SHeiner Kallweit #define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
4025e992a4SHeiner Kallweit #define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
4125e992a4SHeiner Kallweit #define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
4225e992a4SHeiner Kallweit #define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
4325e992a4SHeiner Kallweit #define FIRMWARE_8168F_1	"rtl_nic/rtl8168f-1.fw"
4425e992a4SHeiner Kallweit #define FIRMWARE_8168F_2	"rtl_nic/rtl8168f-2.fw"
4525e992a4SHeiner Kallweit #define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
4625e992a4SHeiner Kallweit #define FIRMWARE_8402_1		"rtl_nic/rtl8402-1.fw"
4725e992a4SHeiner Kallweit #define FIRMWARE_8411_1		"rtl_nic/rtl8411-1.fw"
4825e992a4SHeiner Kallweit #define FIRMWARE_8411_2		"rtl_nic/rtl8411-2.fw"
4925e992a4SHeiner Kallweit #define FIRMWARE_8106E_1	"rtl_nic/rtl8106e-1.fw"
5025e992a4SHeiner Kallweit #define FIRMWARE_8106E_2	"rtl_nic/rtl8106e-2.fw"
5125e992a4SHeiner Kallweit #define FIRMWARE_8168G_2	"rtl_nic/rtl8168g-2.fw"
5225e992a4SHeiner Kallweit #define FIRMWARE_8168G_3	"rtl_nic/rtl8168g-3.fw"
5325e992a4SHeiner Kallweit #define FIRMWARE_8168H_2	"rtl_nic/rtl8168h-2.fw"
54229c1e0dSHeiner Kallweit #define FIRMWARE_8168FP_3	"rtl_nic/rtl8168fp-3.fw"
5525e992a4SHeiner Kallweit #define FIRMWARE_8107E_2	"rtl_nic/rtl8107e-2.fw"
5602bf642bSHeiner Kallweit #define FIRMWARE_8125A_3	"rtl_nic/rtl8125a-3.fw"
570439297bSHeiner Kallweit #define FIRMWARE_8125B_2	"rtl_nic/rtl8125b-2.fw"
5825e992a4SHeiner Kallweit 
5925e992a4SHeiner Kallweit /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
6025e992a4SHeiner Kallweit    The RTL chips use a 64 element hash table based on the Ethernet CRC. */
6181cd17a4SHeiner Kallweit #define	MC_FILTER_LIMIT	32
6225e992a4SHeiner Kallweit 
6325e992a4SHeiner Kallweit #define TX_DMA_BURST	7	/* Maximum PCI burst, '7' is unlimited */
6425e992a4SHeiner Kallweit #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
6525e992a4SHeiner Kallweit 
6625e992a4SHeiner Kallweit #define R8169_REGS_SIZE		256
6725e992a4SHeiner Kallweit #define R8169_RX_BUF_SIZE	(SZ_16K - 1)
68f06059c2SHeiner Kallweit #define NUM_TX_DESC	256	/* Number of Tx descriptor registers */
69ed22a8ffSHeiner Kallweit #define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
7025e992a4SHeiner Kallweit #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
7125e992a4SHeiner Kallweit #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
728624e9bbSHeiner Kallweit #define R8169_TX_STOP_THRS	(MAX_SKB_FRAGS + 1)
738624e9bbSHeiner Kallweit #define R8169_TX_START_THRS	(2 * R8169_TX_STOP_THRS)
7425e992a4SHeiner Kallweit 
750360c046SHeiner Kallweit #define OCP_STD_PHY_BASE	0xa400
760360c046SHeiner Kallweit 
77145a40e8SHeiner Kallweit #define RTL_CFG_NO_GBIT	1
78145a40e8SHeiner Kallweit 
7925e992a4SHeiner Kallweit /* write/read MMIO register */
8025e992a4SHeiner Kallweit #define RTL_W8(tp, reg, val8)	writeb((val8), tp->mmio_addr + (reg))
8125e992a4SHeiner Kallweit #define RTL_W16(tp, reg, val16)	writew((val16), tp->mmio_addr + (reg))
8225e992a4SHeiner Kallweit #define RTL_W32(tp, reg, val32)	writel((val32), tp->mmio_addr + (reg))
8325e992a4SHeiner Kallweit #define RTL_R8(tp, reg)		readb(tp->mmio_addr + (reg))
8425e992a4SHeiner Kallweit #define RTL_R16(tp, reg)		readw(tp->mmio_addr + (reg))
8525e992a4SHeiner Kallweit #define RTL_R32(tp, reg)		readl(tp->mmio_addr + (reg))
8625e992a4SHeiner Kallweit 
87b410439cSHeiner Kallweit #define JUMBO_4K	(4 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
88b410439cSHeiner Kallweit #define JUMBO_6K	(6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
89b410439cSHeiner Kallweit #define JUMBO_7K	(7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
90b410439cSHeiner Kallweit #define JUMBO_9K	(9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
9125e992a4SHeiner Kallweit 
9225e992a4SHeiner Kallweit static const struct {
9325e992a4SHeiner Kallweit 	const char *name;
9425e992a4SHeiner Kallweit 	const char *fw_name;
9525e992a4SHeiner Kallweit } rtl_chip_infos[] = {
9625e992a4SHeiner Kallweit 	/* PCI devices. */
9725e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_02] = {"RTL8169s"				},
9825e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_03] = {"RTL8110s"				},
9925e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_04] = {"RTL8169sb/8110sb"			},
10025e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_05] = {"RTL8169sc/8110sc"			},
10125e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_06] = {"RTL8169sc/8110sc"			},
10225e992a4SHeiner Kallweit 	/* PCI-E devices. */
10325e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_07] = {"RTL8102e"				},
10425e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_08] = {"RTL8102e"				},
1059e0773c3SHeiner Kallweit 	[RTL_GIGA_MAC_VER_09] = {"RTL8102e/RTL8103e"			},
106e66d6586SHeiner Kallweit 	[RTL_GIGA_MAC_VER_10] = {"RTL8101e/RTL8100e"			},
10725e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_11] = {"RTL8168b/8111b"			},
108cdafdc29SHeiner Kallweit 	[RTL_GIGA_MAC_VER_14] = {"RTL8401"				},
10925e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_17] = {"RTL8168b/8111b"			},
11025e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_18] = {"RTL8168cp/8111cp"			},
11125e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_19] = {"RTL8168c/8111c"			},
11225e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_20] = {"RTL8168c/8111c"			},
11325e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_21] = {"RTL8168c/8111c"			},
11425e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_22] = {"RTL8168c/8111c"			},
11525e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_23] = {"RTL8168cp/8111cp"			},
11625e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_24] = {"RTL8168cp/8111cp"			},
11725e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_25] = {"RTL8168d/8111d",	FIRMWARE_8168D_1},
11825e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_26] = {"RTL8168d/8111d",	FIRMWARE_8168D_2},
11925e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_28] = {"RTL8168dp/8111dp"			},
12025e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_29] = {"RTL8105e",		FIRMWARE_8105E_1},
12125e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_30] = {"RTL8105e",		FIRMWARE_8105E_1},
12225e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_31] = {"RTL8168dp/8111dp"			},
12325e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_32] = {"RTL8168e/8111e",	FIRMWARE_8168E_1},
12425e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_33] = {"RTL8168e/8111e",	FIRMWARE_8168E_2},
12525e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_34] = {"RTL8168evl/8111evl",	FIRMWARE_8168E_3},
12625e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_35] = {"RTL8168f/8111f",	FIRMWARE_8168F_1},
12725e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_36] = {"RTL8168f/8111f",	FIRMWARE_8168F_2},
12825e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_37] = {"RTL8402",		FIRMWARE_8402_1 },
12925e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_38] = {"RTL8411",		FIRMWARE_8411_1 },
13025e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_39] = {"RTL8106e",		FIRMWARE_8106E_1},
13125e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_40] = {"RTL8168g/8111g",	FIRMWARE_8168G_2},
1329e0773c3SHeiner Kallweit 	[RTL_GIGA_MAC_VER_42] = {"RTL8168gu/8111gu",	FIRMWARE_8168G_3},
1339e0773c3SHeiner Kallweit 	[RTL_GIGA_MAC_VER_43] = {"RTL8106eus",		FIRMWARE_8106E_2},
1349e0773c3SHeiner Kallweit 	[RTL_GIGA_MAC_VER_44] = {"RTL8411b",		FIRMWARE_8411_2 },
13525e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_46] = {"RTL8168h/8111h",	FIRMWARE_8168H_2},
13625e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_48] = {"RTL8107e",		FIRMWARE_8107E_2},
13725e992a4SHeiner Kallweit 	[RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep"			},
138229c1e0dSHeiner Kallweit 	[RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117",  FIRMWARE_8168FP_3},
139e6d6ca6eSKai-Heng Feng 	[RTL_GIGA_MAC_VER_53] = {"RTL8168fp/RTL8117",			},
1404640338cSHeiner Kallweit 	[RTL_GIGA_MAC_VER_61] = {"RTL8125A",		FIRMWARE_8125A_3},
1410439297bSHeiner Kallweit 	/* reserve 62 for CFG_METHOD_4 in the vendor driver */
1420439297bSHeiner Kallweit 	[RTL_GIGA_MAC_VER_63] = {"RTL8125B",		FIRMWARE_8125B_2},
14325e992a4SHeiner Kallweit };
14425e992a4SHeiner Kallweit 
14525e992a4SHeiner Kallweit static const struct pci_device_id rtl8169_pci_tbl[] = {
146145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x2502) },
147145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x2600) },
148145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8129) },
149145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8136), RTL_CFG_NO_GBIT },
150145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8161) },
15172f898caSJanghyub Seo 	{ PCI_VDEVICE(REALTEK,	0x8162) },
152145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8167) },
153145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8168) },
154145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(NCUBE,	0x8168) },
155145a40e8SHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8169) },
15625e992a4SHeiner Kallweit 	{ PCI_VENDOR_ID_DLINK,	0x4300,
157145a40e8SHeiner Kallweit 		PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0 },
1589d9f3fbaSHeiner Kallweit 	{ PCI_VDEVICE(DLINK,	0x4300) },
1599d9f3fbaSHeiner Kallweit 	{ PCI_VDEVICE(DLINK,	0x4302) },
1609d9f3fbaSHeiner Kallweit 	{ PCI_VDEVICE(AT,	0xc107) },
1619d9f3fbaSHeiner Kallweit 	{ PCI_VDEVICE(USR,	0x0116) },
1629d9f3fbaSHeiner Kallweit 	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
1639d9f3fbaSHeiner Kallweit 	{ 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
164f1bce4adSHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x8125) },
165f1bce4adSHeiner Kallweit 	{ PCI_VDEVICE(REALTEK,	0x3000) },
16625e992a4SHeiner Kallweit 	{}
16725e992a4SHeiner Kallweit };
16825e992a4SHeiner Kallweit 
16925e992a4SHeiner Kallweit MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
17025e992a4SHeiner Kallweit 
17125e992a4SHeiner Kallweit enum rtl_registers {
17225e992a4SHeiner Kallweit 	MAC0		= 0,	/* Ethernet hardware address. */
17325e992a4SHeiner Kallweit 	MAC4		= 4,
17425e992a4SHeiner Kallweit 	MAR0		= 8,	/* Multicast filter. */
17525e992a4SHeiner Kallweit 	CounterAddrLow		= 0x10,
17625e992a4SHeiner Kallweit 	CounterAddrHigh		= 0x14,
17725e992a4SHeiner Kallweit 	TxDescStartAddrLow	= 0x20,
17825e992a4SHeiner Kallweit 	TxDescStartAddrHigh	= 0x24,
17925e992a4SHeiner Kallweit 	TxHDescStartAddrLow	= 0x28,
18025e992a4SHeiner Kallweit 	TxHDescStartAddrHigh	= 0x2c,
18125e992a4SHeiner Kallweit 	FLASH		= 0x30,
18225e992a4SHeiner Kallweit 	ERSR		= 0x36,
18325e992a4SHeiner Kallweit 	ChipCmd		= 0x37,
18425e992a4SHeiner Kallweit 	TxPoll		= 0x38,
18525e992a4SHeiner Kallweit 	IntrMask	= 0x3c,
18625e992a4SHeiner Kallweit 	IntrStatus	= 0x3e,
18725e992a4SHeiner Kallweit 
18825e992a4SHeiner Kallweit 	TxConfig	= 0x40,
18925e992a4SHeiner Kallweit #define	TXCFG_AUTO_FIFO			(1 << 7)	/* 8111e-vl */
19025e992a4SHeiner Kallweit #define	TXCFG_EMPTY			(1 << 11)	/* 8111e-vl */
19125e992a4SHeiner Kallweit 
19225e992a4SHeiner Kallweit 	RxConfig	= 0x44,
19325e992a4SHeiner Kallweit #define	RX128_INT_EN			(1 << 15)	/* 8111c and later */
19425e992a4SHeiner Kallweit #define	RX_MULTI_EN			(1 << 14)	/* 8111c only */
19525e992a4SHeiner Kallweit #define	RXCFG_FIFO_SHIFT		13
19625e992a4SHeiner Kallweit 					/* No threshold before first PCI xfer */
19725e992a4SHeiner Kallweit #define	RX_FIFO_THRESH			(7 << RXCFG_FIFO_SHIFT)
19825e992a4SHeiner Kallweit #define	RX_EARLY_OFF			(1 << 11)
1992e04cfddSChunHao Lin #define	RX_PAUSE_SLOT_ON		(1 << 11)	/* 8125b and later */
20025e992a4SHeiner Kallweit #define	RXCFG_DMA_SHIFT			8
20125e992a4SHeiner Kallweit 					/* Unlimited maximum PCI burst. */
20225e992a4SHeiner Kallweit #define	RX_DMA_BURST			(7 << RXCFG_DMA_SHIFT)
20325e992a4SHeiner Kallweit 
20425e992a4SHeiner Kallweit 	Cfg9346		= 0x50,
20525e992a4SHeiner Kallweit 	Config0		= 0x51,
20625e992a4SHeiner Kallweit 	Config1		= 0x52,
20725e992a4SHeiner Kallweit 	Config2		= 0x53,
20825e992a4SHeiner Kallweit #define PME_SIGNAL			(1 << 5)	/* 8168c and later */
20925e992a4SHeiner Kallweit 
21025e992a4SHeiner Kallweit 	Config3		= 0x54,
21125e992a4SHeiner Kallweit 	Config4		= 0x55,
21225e992a4SHeiner Kallweit 	Config5		= 0x56,
21325e992a4SHeiner Kallweit 	PHYAR		= 0x60,
21425e992a4SHeiner Kallweit 	PHYstatus	= 0x6c,
21525e992a4SHeiner Kallweit 	RxMaxSize	= 0xda,
21625e992a4SHeiner Kallweit 	CPlusCmd	= 0xe0,
21725e992a4SHeiner Kallweit 	IntrMitigate	= 0xe2,
21825e992a4SHeiner Kallweit 
2196cf96dd4SHeiner Kallweit #define RTL_COALESCE_TX_USECS	GENMASK(15, 12)
2206cf96dd4SHeiner Kallweit #define RTL_COALESCE_TX_FRAMES	GENMASK(11, 8)
2216cf96dd4SHeiner Kallweit #define RTL_COALESCE_RX_USECS	GENMASK(7, 4)
2226cf96dd4SHeiner Kallweit #define RTL_COALESCE_RX_FRAMES	GENMASK(3, 0)
2236cf96dd4SHeiner Kallweit 
2242b3e48b6SHeiner Kallweit #define RTL_COALESCE_T_MAX	0x0fU
2252b3e48b6SHeiner Kallweit #define RTL_COALESCE_FRAME_MAX	(RTL_COALESCE_T_MAX * 4)
22625e992a4SHeiner Kallweit 
22725e992a4SHeiner Kallweit 	RxDescAddrLow	= 0xe4,
22825e992a4SHeiner Kallweit 	RxDescAddrHigh	= 0xe8,
22925e992a4SHeiner Kallweit 	EarlyTxThres	= 0xec,	/* 8169. Unit of 32 bytes. */
23025e992a4SHeiner Kallweit 
23125e992a4SHeiner Kallweit #define NoEarlyTx	0x3f	/* Max value : no early transmit. */
23225e992a4SHeiner Kallweit 
23325e992a4SHeiner Kallweit 	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
23425e992a4SHeiner Kallweit 
23525e992a4SHeiner Kallweit #define TxPacketMax	(8064 >> 7)
23625e992a4SHeiner Kallweit #define EarlySize	0x27
23725e992a4SHeiner Kallweit 
23825e992a4SHeiner Kallweit 	FuncEvent	= 0xf0,
23925e992a4SHeiner Kallweit 	FuncEventMask	= 0xf4,
24025e992a4SHeiner Kallweit 	FuncPresetState	= 0xf8,
24125e992a4SHeiner Kallweit 	IBCR0           = 0xf8,
24225e992a4SHeiner Kallweit 	IBCR2           = 0xf9,
24325e992a4SHeiner Kallweit 	IBIMR0          = 0xfa,
24425e992a4SHeiner Kallweit 	IBISR0          = 0xfb,
24525e992a4SHeiner Kallweit 	FuncForceEvent	= 0xfc,
24625e992a4SHeiner Kallweit };
24725e992a4SHeiner Kallweit 
24825e992a4SHeiner Kallweit enum rtl8168_8101_registers {
24925e992a4SHeiner Kallweit 	CSIDR			= 0x64,
25025e992a4SHeiner Kallweit 	CSIAR			= 0x68,
25125e992a4SHeiner Kallweit #define	CSIAR_FLAG			0x80000000
25225e992a4SHeiner Kallweit #define	CSIAR_WRITE_CMD			0x80000000
25325e992a4SHeiner Kallweit #define	CSIAR_BYTE_ENABLE		0x0000f000
25425e992a4SHeiner Kallweit #define	CSIAR_ADDR_MASK			0x00000fff
25525e992a4SHeiner Kallweit 	PMCH			= 0x6f,
256128735a1SHeiner Kallweit #define D3COLD_NO_PLL_DOWN		BIT(7)
257128735a1SHeiner Kallweit #define D3HOT_NO_PLL_DOWN		BIT(6)
258128735a1SHeiner Kallweit #define D3_NO_PLL_DOWN			(BIT(7) | BIT(6))
25925e992a4SHeiner Kallweit 	EPHYAR			= 0x80,
26025e992a4SHeiner Kallweit #define	EPHYAR_FLAG			0x80000000
26125e992a4SHeiner Kallweit #define	EPHYAR_WRITE_CMD		0x80000000
26225e992a4SHeiner Kallweit #define	EPHYAR_REG_MASK			0x1f
26325e992a4SHeiner Kallweit #define	EPHYAR_REG_SHIFT		16
26425e992a4SHeiner Kallweit #define	EPHYAR_DATA_MASK		0xffff
26525e992a4SHeiner Kallweit 	DLLPR			= 0xd0,
26625e992a4SHeiner Kallweit #define	PFM_EN				(1 << 6)
26725e992a4SHeiner Kallweit #define	TX_10M_PS_EN			(1 << 7)
26825e992a4SHeiner Kallweit 	DBG_REG			= 0xd1,
26925e992a4SHeiner Kallweit #define	FIX_NAK_1			(1 << 4)
27025e992a4SHeiner Kallweit #define	FIX_NAK_2			(1 << 3)
27125e992a4SHeiner Kallweit 	TWSI			= 0xd2,
27225e992a4SHeiner Kallweit 	MCU			= 0xd3,
27325e992a4SHeiner Kallweit #define	NOW_IS_OOB			(1 << 7)
27425e992a4SHeiner Kallweit #define	TX_EMPTY			(1 << 5)
27525e992a4SHeiner Kallweit #define	RX_EMPTY			(1 << 4)
27625e992a4SHeiner Kallweit #define	RXTX_EMPTY			(TX_EMPTY | RX_EMPTY)
27725e992a4SHeiner Kallweit #define	EN_NDP				(1 << 3)
27825e992a4SHeiner Kallweit #define	EN_OOB_RESET			(1 << 2)
27925e992a4SHeiner Kallweit #define	LINK_LIST_RDY			(1 << 1)
28025e992a4SHeiner Kallweit 	EFUSEAR			= 0xdc,
28125e992a4SHeiner Kallweit #define	EFUSEAR_FLAG			0x80000000
28225e992a4SHeiner Kallweit #define	EFUSEAR_WRITE_CMD		0x80000000
28325e992a4SHeiner Kallweit #define	EFUSEAR_READ_CMD		0x00000000
28425e992a4SHeiner Kallweit #define	EFUSEAR_REG_MASK		0x03ff
28525e992a4SHeiner Kallweit #define	EFUSEAR_REG_SHIFT		8
28625e992a4SHeiner Kallweit #define	EFUSEAR_DATA_MASK		0xff
28725e992a4SHeiner Kallweit 	MISC_1			= 0xf2,
28825e992a4SHeiner Kallweit #define	PFM_D3COLD_EN			(1 << 6)
28925e992a4SHeiner Kallweit };
29025e992a4SHeiner Kallweit 
29125e992a4SHeiner Kallweit enum rtl8168_registers {
29225e992a4SHeiner Kallweit 	LED_FREQ		= 0x1a,
29325e992a4SHeiner Kallweit 	EEE_LED			= 0x1b,
29425e992a4SHeiner Kallweit 	ERIDR			= 0x70,
29525e992a4SHeiner Kallweit 	ERIAR			= 0x74,
29625e992a4SHeiner Kallweit #define ERIAR_FLAG			0x80000000
29725e992a4SHeiner Kallweit #define ERIAR_WRITE_CMD			0x80000000
29825e992a4SHeiner Kallweit #define ERIAR_READ_CMD			0x00000000
29925e992a4SHeiner Kallweit #define ERIAR_ADDR_BYTE_ALIGN		4
30025e992a4SHeiner Kallweit #define ERIAR_TYPE_SHIFT		16
30125e992a4SHeiner Kallweit #define ERIAR_EXGMAC			(0x00 << ERIAR_TYPE_SHIFT)
30225e992a4SHeiner Kallweit #define ERIAR_MSIX			(0x01 << ERIAR_TYPE_SHIFT)
30325e992a4SHeiner Kallweit #define ERIAR_ASF			(0x02 << ERIAR_TYPE_SHIFT)
30425e992a4SHeiner Kallweit #define ERIAR_OOB			(0x02 << ERIAR_TYPE_SHIFT)
30525e992a4SHeiner Kallweit #define ERIAR_MASK_SHIFT		12
30625e992a4SHeiner Kallweit #define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
30725e992a4SHeiner Kallweit #define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
30825e992a4SHeiner Kallweit #define ERIAR_MASK_0100			(0x4 << ERIAR_MASK_SHIFT)
30925e992a4SHeiner Kallweit #define ERIAR_MASK_0101			(0x5 << ERIAR_MASK_SHIFT)
31025e992a4SHeiner Kallweit #define ERIAR_MASK_1111			(0xf << ERIAR_MASK_SHIFT)
31125e992a4SHeiner Kallweit 	EPHY_RXER_NUM		= 0x7c,
31225e992a4SHeiner Kallweit 	OCPDR			= 0xb0,	/* OCP GPHY access */
31325e992a4SHeiner Kallweit #define OCPDR_WRITE_CMD			0x80000000
31425e992a4SHeiner Kallweit #define OCPDR_READ_CMD			0x00000000
31525e992a4SHeiner Kallweit #define OCPDR_REG_MASK			0x7f
31625e992a4SHeiner Kallweit #define OCPDR_GPHY_REG_SHIFT		16
31725e992a4SHeiner Kallweit #define OCPDR_DATA_MASK			0xffff
31825e992a4SHeiner Kallweit 	OCPAR			= 0xb4,
31925e992a4SHeiner Kallweit #define OCPAR_FLAG			0x80000000
32025e992a4SHeiner Kallweit #define OCPAR_GPHY_WRITE_CMD		0x8000f060
32125e992a4SHeiner Kallweit #define OCPAR_GPHY_READ_CMD		0x0000f060
32225e992a4SHeiner Kallweit 	GPHY_OCP		= 0xb8,
32325e992a4SHeiner Kallweit 	RDSAR1			= 0xd0,	/* 8168c only. Undocumented on 8168dp */
32425e992a4SHeiner Kallweit 	MISC			= 0xf0,	/* 8168e only. */
32525e992a4SHeiner Kallweit #define TXPLA_RST			(1 << 29)
32625e992a4SHeiner Kallweit #define DISABLE_LAN_EN			(1 << 23) /* Enable GPIO pin */
32725e992a4SHeiner Kallweit #define PWM_EN				(1 << 22)
32825e992a4SHeiner Kallweit #define RXDV_GATED_EN			(1 << 19)
32925e992a4SHeiner Kallweit #define EARLY_TALLY_EN			(1 << 16)
33025e992a4SHeiner Kallweit };
33125e992a4SHeiner Kallweit 
332f1bce4adSHeiner Kallweit enum rtl8125_registers {
333f1bce4adSHeiner Kallweit 	IntrMask_8125		= 0x38,
334f1bce4adSHeiner Kallweit 	IntrStatus_8125		= 0x3c,
335f1bce4adSHeiner Kallweit 	TxPoll_8125		= 0x90,
336f1bce4adSHeiner Kallweit 	MAC0_BKP		= 0x19e0,
3370439297bSHeiner Kallweit 	EEE_TXIDLE_TIMER_8125	= 0x6048,
338f1bce4adSHeiner Kallweit };
339f1bce4adSHeiner Kallweit 
340f1bce4adSHeiner Kallweit #define RX_VLAN_INNER_8125	BIT(22)
341f1bce4adSHeiner Kallweit #define RX_VLAN_OUTER_8125	BIT(23)
342f1bce4adSHeiner Kallweit #define RX_VLAN_8125		(RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)
343f1bce4adSHeiner Kallweit 
344f1bce4adSHeiner Kallweit #define RX_FETCH_DFLT_8125	(8 << 27)
345f1bce4adSHeiner Kallweit 
34625e992a4SHeiner Kallweit enum rtl_register_content {
34725e992a4SHeiner Kallweit 	/* InterruptStatusBits */
34825e992a4SHeiner Kallweit 	SYSErr		= 0x8000,
34925e992a4SHeiner Kallweit 	PCSTimeout	= 0x4000,
35025e992a4SHeiner Kallweit 	SWInt		= 0x0100,
35125e992a4SHeiner Kallweit 	TxDescUnavail	= 0x0080,
35225e992a4SHeiner Kallweit 	RxFIFOOver	= 0x0040,
35325e992a4SHeiner Kallweit 	LinkChg		= 0x0020,
35425e992a4SHeiner Kallweit 	RxOverflow	= 0x0010,
35525e992a4SHeiner Kallweit 	TxErr		= 0x0008,
35625e992a4SHeiner Kallweit 	TxOK		= 0x0004,
35725e992a4SHeiner Kallweit 	RxErr		= 0x0002,
35825e992a4SHeiner Kallweit 	RxOK		= 0x0001,
35925e992a4SHeiner Kallweit 
36025e992a4SHeiner Kallweit 	/* RxStatusDesc */
36125e992a4SHeiner Kallweit 	RxRWT	= (1 << 22),
36225e992a4SHeiner Kallweit 	RxRES	= (1 << 21),
36325e992a4SHeiner Kallweit 	RxRUNT	= (1 << 20),
36425e992a4SHeiner Kallweit 	RxCRC	= (1 << 19),
36525e992a4SHeiner Kallweit 
36625e992a4SHeiner Kallweit 	/* ChipCmdBits */
36725e992a4SHeiner Kallweit 	StopReq		= 0x80,
36825e992a4SHeiner Kallweit 	CmdReset	= 0x10,
36925e992a4SHeiner Kallweit 	CmdRxEnb	= 0x08,
37025e992a4SHeiner Kallweit 	CmdTxEnb	= 0x04,
37125e992a4SHeiner Kallweit 	RxBufEmpty	= 0x01,
37225e992a4SHeiner Kallweit 
37325e992a4SHeiner Kallweit 	/* TXPoll register p.5 */
37425e992a4SHeiner Kallweit 	HPQ		= 0x80,		/* Poll cmd on the high prio queue */
37525e992a4SHeiner Kallweit 	NPQ		= 0x40,		/* Poll cmd on the low prio queue */
37625e992a4SHeiner Kallweit 	FSWInt		= 0x01,		/* Forced software interrupt */
37725e992a4SHeiner Kallweit 
37825e992a4SHeiner Kallweit 	/* Cfg9346Bits */
37925e992a4SHeiner Kallweit 	Cfg9346_Lock	= 0x00,
38025e992a4SHeiner Kallweit 	Cfg9346_Unlock	= 0xc0,
38125e992a4SHeiner Kallweit 
38225e992a4SHeiner Kallweit 	/* rx_mode_bits */
38325e992a4SHeiner Kallweit 	AcceptErr	= 0x20,
38425e992a4SHeiner Kallweit 	AcceptRunt	= 0x10,
38510478283SHeiner Kallweit #define RX_CONFIG_ACCEPT_ERR_MASK	0x30
38625e992a4SHeiner Kallweit 	AcceptBroadcast	= 0x08,
38725e992a4SHeiner Kallweit 	AcceptMulticast	= 0x04,
38825e992a4SHeiner Kallweit 	AcceptMyPhys	= 0x02,
38925e992a4SHeiner Kallweit 	AcceptAllPhys	= 0x01,
39010478283SHeiner Kallweit #define RX_CONFIG_ACCEPT_OK_MASK	0x0f
39125e992a4SHeiner Kallweit #define RX_CONFIG_ACCEPT_MASK		0x3f
39225e992a4SHeiner Kallweit 
39325e992a4SHeiner Kallweit 	/* TxConfigBits */
39425e992a4SHeiner Kallweit 	TxInterFrameGapShift = 24,
39525e992a4SHeiner Kallweit 	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
39625e992a4SHeiner Kallweit 
39725e992a4SHeiner Kallweit 	/* Config1 register p.24 */
39825e992a4SHeiner Kallweit 	LEDS1		= (1 << 7),
39925e992a4SHeiner Kallweit 	LEDS0		= (1 << 6),
40025e992a4SHeiner Kallweit 	Speed_down	= (1 << 4),
40125e992a4SHeiner Kallweit 	MEMMAP		= (1 << 3),
40225e992a4SHeiner Kallweit 	IOMAP		= (1 << 2),
40325e992a4SHeiner Kallweit 	VPD		= (1 << 1),
40425e992a4SHeiner Kallweit 	PMEnable	= (1 << 0),	/* Power Management Enable */
40525e992a4SHeiner Kallweit 
40625e992a4SHeiner Kallweit 	/* Config2 register p. 25 */
40725e992a4SHeiner Kallweit 	ClkReqEn	= (1 << 7),	/* Clock Request Enable */
40825e992a4SHeiner Kallweit 	MSIEnable	= (1 << 5),	/* 8169 only. Reserved in the 8168. */
40925e992a4SHeiner Kallweit 	PCI_Clock_66MHz = 0x01,
41025e992a4SHeiner Kallweit 	PCI_Clock_33MHz = 0x00,
41125e992a4SHeiner Kallweit 
41225e992a4SHeiner Kallweit 	/* Config3 register p.25 */
41325e992a4SHeiner Kallweit 	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
41425e992a4SHeiner Kallweit 	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
41525e992a4SHeiner Kallweit 	Jumbo_En0	= (1 << 2),	/* 8168 only. Reserved in the 8168b */
41625e992a4SHeiner Kallweit 	Rdy_to_L23	= (1 << 1),	/* L23 Enable */
41725e992a4SHeiner Kallweit 	Beacon_en	= (1 << 0),	/* 8168 only. Reserved in the 8168b */
41825e992a4SHeiner Kallweit 
41925e992a4SHeiner Kallweit 	/* Config4 register */
42025e992a4SHeiner Kallweit 	Jumbo_En1	= (1 << 1),	/* 8168 only. Reserved in the 8168b */
42125e992a4SHeiner Kallweit 
42225e992a4SHeiner Kallweit 	/* Config5 register p.27 */
42325e992a4SHeiner Kallweit 	BWF		= (1 << 6),	/* Accept Broadcast wakeup frame */
42425e992a4SHeiner Kallweit 	MWF		= (1 << 5),	/* Accept Multicast wakeup frame */
42525e992a4SHeiner Kallweit 	UWF		= (1 << 4),	/* Accept Unicast wakeup frame */
42625e992a4SHeiner Kallweit 	Spi_en		= (1 << 3),
42725e992a4SHeiner Kallweit 	LanWake		= (1 << 1),	/* LanWake enable/disable */
42825e992a4SHeiner Kallweit 	PMEStatus	= (1 << 0),	/* PME status can be reset by PCI RST# */
42925e992a4SHeiner Kallweit 	ASPM_en		= (1 << 0),	/* ASPM enable */
43025e992a4SHeiner Kallweit 
43125e992a4SHeiner Kallweit 	/* CPlusCmd p.31 */
43225e992a4SHeiner Kallweit 	EnableBist	= (1 << 15),	// 8168 8101
43325e992a4SHeiner Kallweit 	Mac_dbgo_oe	= (1 << 14),	// 8168 8101
43409e65335SHeiner Kallweit 	EnAnaPLL	= (1 << 14),	// 8169
43525e992a4SHeiner Kallweit 	Normal_mode	= (1 << 13),	// unused
43625e992a4SHeiner Kallweit 	Force_half_dup	= (1 << 12),	// 8168 8101
43725e992a4SHeiner Kallweit 	Force_rxflow_en	= (1 << 11),	// 8168 8101
43825e992a4SHeiner Kallweit 	Force_txflow_en	= (1 << 10),	// 8168 8101
43925e992a4SHeiner Kallweit 	Cxpl_dbg_sel	= (1 << 9),	// 8168 8101
44025e992a4SHeiner Kallweit 	ASF		= (1 << 8),	// 8168 8101
44125e992a4SHeiner Kallweit 	PktCntrDisable	= (1 << 7),	// 8168 8101
44225e992a4SHeiner Kallweit 	Mac_dbgo_sel	= 0x001c,	// 8168
44325e992a4SHeiner Kallweit 	RxVlan		= (1 << 6),
44425e992a4SHeiner Kallweit 	RxChkSum	= (1 << 5),
44525e992a4SHeiner Kallweit 	PCIDAC		= (1 << 4),
44625e992a4SHeiner Kallweit 	PCIMulRW	= (1 << 3),
44725e992a4SHeiner Kallweit #define INTT_MASK	GENMASK(1, 0)
448bc73241eSHeiner Kallweit #define CPCMD_MASK	(Normal_mode | RxVlan | RxChkSum | INTT_MASK)
44925e992a4SHeiner Kallweit 
45025e992a4SHeiner Kallweit 	/* rtl8169_PHYstatus */
45125e992a4SHeiner Kallweit 	TBI_Enable	= 0x80,
45225e992a4SHeiner Kallweit 	TxFlowCtrl	= 0x40,
45325e992a4SHeiner Kallweit 	RxFlowCtrl	= 0x20,
45425e992a4SHeiner Kallweit 	_1000bpsF	= 0x10,
45525e992a4SHeiner Kallweit 	_100bps		= 0x08,
45625e992a4SHeiner Kallweit 	_10bps		= 0x04,
45725e992a4SHeiner Kallweit 	LinkStatus	= 0x02,
45825e992a4SHeiner Kallweit 	FullDup		= 0x01,
45925e992a4SHeiner Kallweit 
46025e992a4SHeiner Kallweit 	/* ResetCounterCommand */
46125e992a4SHeiner Kallweit 	CounterReset	= 0x1,
46225e992a4SHeiner Kallweit 
46325e992a4SHeiner Kallweit 	/* DumpCounterCommand */
46425e992a4SHeiner Kallweit 	CounterDump	= 0x8,
46525e992a4SHeiner Kallweit 
46625e992a4SHeiner Kallweit 	/* magic enable v2 */
46725e992a4SHeiner Kallweit 	MagicPacket_v2	= (1 << 16),	/* Wake up when receives a Magic Packet */
46825e992a4SHeiner Kallweit };
46925e992a4SHeiner Kallweit 
47025e992a4SHeiner Kallweit enum rtl_desc_bit {
47125e992a4SHeiner Kallweit 	/* First doubleword. */
47225e992a4SHeiner Kallweit 	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
47325e992a4SHeiner Kallweit 	RingEnd		= (1 << 30), /* End of descriptor ring */
47425e992a4SHeiner Kallweit 	FirstFrag	= (1 << 29), /* First segment of a packet */
47525e992a4SHeiner Kallweit 	LastFrag	= (1 << 28), /* Final segment of a packet */
47625e992a4SHeiner Kallweit };
47725e992a4SHeiner Kallweit 
47825e992a4SHeiner Kallweit /* Generic case. */
47925e992a4SHeiner Kallweit enum rtl_tx_desc_bit {
48025e992a4SHeiner Kallweit 	/* First doubleword. */
48125e992a4SHeiner Kallweit 	TD_LSO		= (1 << 27),		/* Large Send Offload */
48225e992a4SHeiner Kallweit #define TD_MSS_MAX			0x07ffu	/* MSS value */
48325e992a4SHeiner Kallweit 
48425e992a4SHeiner Kallweit 	/* Second doubleword. */
48525e992a4SHeiner Kallweit 	TxVlanTag	= (1 << 17),		/* Add VLAN tag */
48625e992a4SHeiner Kallweit };
48725e992a4SHeiner Kallweit 
48825e992a4SHeiner Kallweit /* 8169, 8168b and 810x except 8102e. */
48925e992a4SHeiner Kallweit enum rtl_tx_desc_bit_0 {
49025e992a4SHeiner Kallweit 	/* First doubleword. */
49125e992a4SHeiner Kallweit #define TD0_MSS_SHIFT			16	/* MSS position (11 bits) */
49225e992a4SHeiner Kallweit 	TD0_TCP_CS	= (1 << 16),		/* Calculate TCP/IP checksum */
49325e992a4SHeiner Kallweit 	TD0_UDP_CS	= (1 << 17),		/* Calculate UDP/IP checksum */
49425e992a4SHeiner Kallweit 	TD0_IP_CS	= (1 << 18),		/* Calculate IP checksum */
49525e992a4SHeiner Kallweit };
49625e992a4SHeiner Kallweit 
49725e992a4SHeiner Kallweit /* 8102e, 8168c and beyond. */
49825e992a4SHeiner Kallweit enum rtl_tx_desc_bit_1 {
49925e992a4SHeiner Kallweit 	/* First doubleword. */
50025e992a4SHeiner Kallweit 	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
50125e992a4SHeiner Kallweit 	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
50225e992a4SHeiner Kallweit #define GTTCPHO_SHIFT			18
503e64e0c89SHeiner Kallweit #define GTTCPHO_MAX			0x7f
50425e992a4SHeiner Kallweit 
50525e992a4SHeiner Kallweit 	/* Second doubleword. */
50625e992a4SHeiner Kallweit #define TCPHO_SHIFT			18
507e64e0c89SHeiner Kallweit #define TCPHO_MAX			0x3ff
50825e992a4SHeiner Kallweit #define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
50925e992a4SHeiner Kallweit 	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
51025e992a4SHeiner Kallweit 	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
51125e992a4SHeiner Kallweit 	TD1_TCP_CS	= (1 << 30),		/* Calculate TCP/IP checksum */
51225e992a4SHeiner Kallweit 	TD1_UDP_CS	= (1 << 31),		/* Calculate UDP/IP checksum */
51325e992a4SHeiner Kallweit };
51425e992a4SHeiner Kallweit 
51525e992a4SHeiner Kallweit enum rtl_rx_desc_bit {
51625e992a4SHeiner Kallweit 	/* Rx private */
51725e992a4SHeiner Kallweit 	PID1		= (1 << 18), /* Protocol ID bit 1/2 */
51825e992a4SHeiner Kallweit 	PID0		= (1 << 17), /* Protocol ID bit 0/2 */
51925e992a4SHeiner Kallweit 
52025e992a4SHeiner Kallweit #define RxProtoUDP	(PID1)
52125e992a4SHeiner Kallweit #define RxProtoTCP	(PID0)
52225e992a4SHeiner Kallweit #define RxProtoIP	(PID1 | PID0)
52325e992a4SHeiner Kallweit #define RxProtoMask	RxProtoIP
52425e992a4SHeiner Kallweit 
52525e992a4SHeiner Kallweit 	IPFail		= (1 << 16), /* IP checksum failed */
52625e992a4SHeiner Kallweit 	UDPFail		= (1 << 15), /* UDP/IP checksum failed */
52725e992a4SHeiner Kallweit 	TCPFail		= (1 << 14), /* TCP/IP checksum failed */
528206a75e0SHeiner Kallweit 
529206a75e0SHeiner Kallweit #define RxCSFailMask	(IPFail | UDPFail | TCPFail)
530206a75e0SHeiner Kallweit 
53125e992a4SHeiner Kallweit 	RxVlanTag	= (1 << 16), /* VLAN tag available */
53225e992a4SHeiner Kallweit };
53325e992a4SHeiner Kallweit 
5340170d594SHeiner Kallweit #define RTL_GSO_MAX_SIZE_V1	32000
5350170d594SHeiner Kallweit #define RTL_GSO_MAX_SEGS_V1	24
5360170d594SHeiner Kallweit #define RTL_GSO_MAX_SIZE_V2	64000
5370170d594SHeiner Kallweit #define RTL_GSO_MAX_SEGS_V2	64
5380170d594SHeiner Kallweit 
53925e992a4SHeiner Kallweit struct TxDesc {
54025e992a4SHeiner Kallweit 	__le32 opts1;
54125e992a4SHeiner Kallweit 	__le32 opts2;
54225e992a4SHeiner Kallweit 	__le64 addr;
54325e992a4SHeiner Kallweit };
54425e992a4SHeiner Kallweit 
54525e992a4SHeiner Kallweit struct RxDesc {
54625e992a4SHeiner Kallweit 	__le32 opts1;
54725e992a4SHeiner Kallweit 	__le32 opts2;
54825e992a4SHeiner Kallweit 	__le64 addr;
54925e992a4SHeiner Kallweit };
55025e992a4SHeiner Kallweit 
55125e992a4SHeiner Kallweit struct ring_info {
55225e992a4SHeiner Kallweit 	struct sk_buff	*skb;
55325e992a4SHeiner Kallweit 	u32		len;
55425e992a4SHeiner Kallweit };
55525e992a4SHeiner Kallweit 
55625e992a4SHeiner Kallweit struct rtl8169_counters {
55725e992a4SHeiner Kallweit 	__le64	tx_packets;
55825e992a4SHeiner Kallweit 	__le64	rx_packets;
55925e992a4SHeiner Kallweit 	__le64	tx_errors;
56025e992a4SHeiner Kallweit 	__le32	rx_errors;
56125e992a4SHeiner Kallweit 	__le16	rx_missed;
56225e992a4SHeiner Kallweit 	__le16	align_errors;
56325e992a4SHeiner Kallweit 	__le32	tx_one_collision;
56425e992a4SHeiner Kallweit 	__le32	tx_multi_collision;
56525e992a4SHeiner Kallweit 	__le64	rx_unicast;
56625e992a4SHeiner Kallweit 	__le64	rx_broadcast;
56725e992a4SHeiner Kallweit 	__le32	rx_multicast;
56825e992a4SHeiner Kallweit 	__le16	tx_aborted;
56925e992a4SHeiner Kallweit 	__le16	tx_underun;
57025e992a4SHeiner Kallweit };
57125e992a4SHeiner Kallweit 
57225e992a4SHeiner Kallweit struct rtl8169_tc_offsets {
57325e992a4SHeiner Kallweit 	bool	inited;
57425e992a4SHeiner Kallweit 	__le64	tx_errors;
57525e992a4SHeiner Kallweit 	__le32	tx_multi_collision;
57625e992a4SHeiner Kallweit 	__le16	tx_aborted;
5770da3359aSHeiner Kallweit 	__le16	rx_missed;
57825e992a4SHeiner Kallweit };
57925e992a4SHeiner Kallweit 
58025e992a4SHeiner Kallweit enum rtl_flag {
58125e992a4SHeiner Kallweit 	RTL_FLAG_TASK_ENABLED = 0,
58225e992a4SHeiner Kallweit 	RTL_FLAG_TASK_RESET_PENDING,
583fbe43b7fSHeiner Kallweit 	RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE,
58480c0576eSHeiner Kallweit 	RTL_FLAG_TASK_TX_TIMEOUT,
58525e992a4SHeiner Kallweit 	RTL_FLAG_MAX
58625e992a4SHeiner Kallweit };
58725e992a4SHeiner Kallweit 
588e0d38b58SHeiner Kallweit enum rtl_dash_type {
589e0d38b58SHeiner Kallweit 	RTL_DASH_NONE,
590e0d38b58SHeiner Kallweit 	RTL_DASH_DP,
591e0d38b58SHeiner Kallweit 	RTL_DASH_EP,
592e0d38b58SHeiner Kallweit };
593e0d38b58SHeiner Kallweit 
59425e992a4SHeiner Kallweit struct rtl8169_private {
59525e992a4SHeiner Kallweit 	void __iomem *mmio_addr;	/* memory map physical address */
59625e992a4SHeiner Kallweit 	struct pci_dev *pci_dev;
59725e992a4SHeiner Kallweit 	struct net_device *dev;
59825e992a4SHeiner Kallweit 	struct phy_device *phydev;
59925e992a4SHeiner Kallweit 	struct napi_struct napi;
60025e992a4SHeiner Kallweit 	enum mac_version mac_version;
601e0d38b58SHeiner Kallweit 	enum rtl_dash_type dash_type;
60225e992a4SHeiner Kallweit 	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
60325e992a4SHeiner Kallweit 	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
60425e992a4SHeiner Kallweit 	u32 dirty_tx;
60525e992a4SHeiner Kallweit 	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
60625e992a4SHeiner Kallweit 	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
60725e992a4SHeiner Kallweit 	dma_addr_t TxPhyAddr;
60825e992a4SHeiner Kallweit 	dma_addr_t RxPhyAddr;
60932879f00SHeiner Kallweit 	struct page *Rx_databuff[NUM_RX_DESC];	/* Rx data buffers */
61025e992a4SHeiner Kallweit 	struct ring_info tx_skb[NUM_TX_DESC];	/* Tx data buffers */
61125e992a4SHeiner Kallweit 	u16 cp_cmd;
612c1d532d2SHeiner Kallweit 	u32 irq_mask;
6131bd32771SThomas Gleixner 	int irq;
61425e992a4SHeiner Kallweit 	struct clk *clk;
61525e992a4SHeiner Kallweit 
61625e992a4SHeiner Kallweit 	struct {
61725e992a4SHeiner Kallweit 		DECLARE_BITMAP(flags, RTL_FLAG_MAX);
61825e992a4SHeiner Kallweit 		struct work_struct work;
61925e992a4SHeiner Kallweit 	} wk;
62025e992a4SHeiner Kallweit 
621d6c36cbcSSebastian Andrzej Siewior 	raw_spinlock_t config25_lock;
622d6c36cbcSSebastian Andrzej Siewior 	raw_spinlock_t mac_ocp_lock;
62391c86435SHeiner Kallweit 
624d6c36cbcSSebastian Andrzej Siewior 	raw_spinlock_t cfg9346_usage_lock;
62559ee97c0SHeiner Kallweit 	int cfg9346_usage_count;
62659ee97c0SHeiner Kallweit 
62725e992a4SHeiner Kallweit 	unsigned supports_gmii:1;
628cf2ffdeaSHeiner Kallweit 	unsigned aspm_manageable:1;
629c61d525fSChunHao Lin 	unsigned dash_enabled:1;
63025e992a4SHeiner Kallweit 	dma_addr_t counters_phys_addr;
63125e992a4SHeiner Kallweit 	struct rtl8169_counters *counters;
63225e992a4SHeiner Kallweit 	struct rtl8169_tc_offsets tc_offset;
63325e992a4SHeiner Kallweit 	u32 saved_wolopts;
6347ec3f872SHeiner Kallweit 	int eee_adv;
63525e992a4SHeiner Kallweit 
63625e992a4SHeiner Kallweit 	const char *fw_name;
6378197f9d2SHeiner Kallweit 	struct rtl_fw *rtl_fw;
63825e992a4SHeiner Kallweit 
63925e992a4SHeiner Kallweit 	u32 ocp_base;
64025e992a4SHeiner Kallweit };
64125e992a4SHeiner Kallweit 
64225e992a4SHeiner Kallweit typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);
64325e992a4SHeiner Kallweit 
64425e992a4SHeiner Kallweit MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
64525e992a4SHeiner Kallweit MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
64625e992a4SHeiner Kallweit MODULE_SOFTDEP("pre: realtek");
64725e992a4SHeiner Kallweit MODULE_LICENSE("GPL");
64825e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168D_1);
64925e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168D_2);
65025e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168E_1);
65125e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168E_2);
65225e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168E_3);
65325e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8105E_1);
65425e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168F_1);
65525e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168F_2);
65625e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8402_1);
65725e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8411_1);
65825e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8411_2);
65925e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8106E_1);
66025e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8106E_2);
66125e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168G_2);
66225e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168G_3);
66325e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168H_2);
664229c1e0dSHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8168FP_3);
66525e992a4SHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8107E_2);
66602bf642bSHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8125A_3);
6670439297bSHeiner Kallweit MODULE_FIRMWARE(FIRMWARE_8125B_2);
66825e992a4SHeiner Kallweit 
tp_to_dev(struct rtl8169_private * tp)66925e992a4SHeiner Kallweit static inline struct device *tp_to_dev(struct rtl8169_private *tp)
67025e992a4SHeiner Kallweit {
67125e992a4SHeiner Kallweit 	return &tp->pci_dev->dev;
67225e992a4SHeiner Kallweit }
67325e992a4SHeiner Kallweit 
rtl_lock_config_regs(struct rtl8169_private * tp)67425e992a4SHeiner Kallweit static void rtl_lock_config_regs(struct rtl8169_private *tp)
67525e992a4SHeiner Kallweit {
67659ee97c0SHeiner Kallweit 	unsigned long flags;
67759ee97c0SHeiner Kallweit 
678d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
67959ee97c0SHeiner Kallweit 	if (!--tp->cfg9346_usage_count)
68025e992a4SHeiner Kallweit 		RTL_W8(tp, Cfg9346, Cfg9346_Lock);
681d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
68225e992a4SHeiner Kallweit }
68325e992a4SHeiner Kallweit 
rtl_unlock_config_regs(struct rtl8169_private * tp)68425e992a4SHeiner Kallweit static void rtl_unlock_config_regs(struct rtl8169_private *tp)
68525e992a4SHeiner Kallweit {
68659ee97c0SHeiner Kallweit 	unsigned long flags;
68759ee97c0SHeiner Kallweit 
688d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
68959ee97c0SHeiner Kallweit 	if (!tp->cfg9346_usage_count++)
69025e992a4SHeiner Kallweit 		RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
691d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
69225e992a4SHeiner Kallweit }
69325e992a4SHeiner Kallweit 
rtl_pci_commit(struct rtl8169_private * tp)694711463f8SHeiner Kallweit static void rtl_pci_commit(struct rtl8169_private *tp)
695711463f8SHeiner Kallweit {
696711463f8SHeiner Kallweit 	/* Read an arbitrary register to commit a preceding PCI write */
697711463f8SHeiner Kallweit 	RTL_R8(tp, ChipCmd);
698711463f8SHeiner Kallweit }
699711463f8SHeiner Kallweit 
rtl_mod_config2(struct rtl8169_private * tp,u8 clear,u8 set)7006bc6c4e6SHeiner Kallweit static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
7016bc6c4e6SHeiner Kallweit {
7026bc6c4e6SHeiner Kallweit 	unsigned long flags;
7036bc6c4e6SHeiner Kallweit 	u8 val;
7046bc6c4e6SHeiner Kallweit 
705d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->config25_lock, flags);
7066bc6c4e6SHeiner Kallweit 	val = RTL_R8(tp, Config2);
7076bc6c4e6SHeiner Kallweit 	RTL_W8(tp, Config2, (val & ~clear) | set);
708d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
7096bc6c4e6SHeiner Kallweit }
7106bc6c4e6SHeiner Kallweit 
rtl_mod_config5(struct rtl8169_private * tp,u8 clear,u8 set)7116bc6c4e6SHeiner Kallweit static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
7126bc6c4e6SHeiner Kallweit {
7136bc6c4e6SHeiner Kallweit 	unsigned long flags;
7146bc6c4e6SHeiner Kallweit 	u8 val;
7156bc6c4e6SHeiner Kallweit 
716d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->config25_lock, flags);
7176bc6c4e6SHeiner Kallweit 	val = RTL_R8(tp, Config5);
7186bc6c4e6SHeiner Kallweit 	RTL_W8(tp, Config5, (val & ~clear) | set);
719d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
7206bc6c4e6SHeiner Kallweit }
7216bc6c4e6SHeiner Kallweit 
rtl_is_8125(struct rtl8169_private * tp)722f1bce4adSHeiner Kallweit static bool rtl_is_8125(struct rtl8169_private *tp)
723f1bce4adSHeiner Kallweit {
724efc37109SHeiner Kallweit 	return tp->mac_version >= RTL_GIGA_MAC_VER_61;
725f1bce4adSHeiner Kallweit }
726f1bce4adSHeiner Kallweit 
rtl_is_8168evl_up(struct rtl8169_private * tp)7279e9f33baSHeiner Kallweit static bool rtl_is_8168evl_up(struct rtl8169_private *tp)
7289e9f33baSHeiner Kallweit {
7299e9f33baSHeiner Kallweit 	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
730c623305bSHeiner Kallweit 	       tp->mac_version != RTL_GIGA_MAC_VER_39 &&
731e6d6ca6eSKai-Heng Feng 	       tp->mac_version <= RTL_GIGA_MAC_VER_53;
7329e9f33baSHeiner Kallweit }
7339e9f33baSHeiner Kallweit 
rtl_supports_eee(struct rtl8169_private * tp)7342e779ddbSHeiner Kallweit static bool rtl_supports_eee(struct rtl8169_private *tp)
7352e779ddbSHeiner Kallweit {
7362e779ddbSHeiner Kallweit 	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
7372e779ddbSHeiner Kallweit 	       tp->mac_version != RTL_GIGA_MAC_VER_37 &&
7382e779ddbSHeiner Kallweit 	       tp->mac_version != RTL_GIGA_MAC_VER_39;
7392e779ddbSHeiner Kallweit }
7402e779ddbSHeiner Kallweit 
rtl_read_mac_from_reg(struct rtl8169_private * tp,u8 * mac,int reg)741ce37115eSHeiner Kallweit static void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg)
742ce37115eSHeiner Kallweit {
743ce37115eSHeiner Kallweit 	int i;
744ce37115eSHeiner Kallweit 
745ce37115eSHeiner Kallweit 	for (i = 0; i < ETH_ALEN; i++)
746ce37115eSHeiner Kallweit 		mac[i] = RTL_R8(tp, reg + i);
747ce37115eSHeiner Kallweit }
748ce37115eSHeiner Kallweit 
74925e992a4SHeiner Kallweit struct rtl_cond {
75025e992a4SHeiner Kallweit 	bool (*check)(struct rtl8169_private *);
75125e992a4SHeiner Kallweit 	const char *msg;
75225e992a4SHeiner Kallweit };
75325e992a4SHeiner Kallweit 
rtl_loop_wait(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long usecs,int n,bool high)75425e992a4SHeiner Kallweit static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
755d6836ef0SHeiner Kallweit 			  unsigned long usecs, int n, bool high)
75625e992a4SHeiner Kallweit {
75725e992a4SHeiner Kallweit 	int i;
75825e992a4SHeiner Kallweit 
75925e992a4SHeiner Kallweit 	for (i = 0; i < n; i++) {
76025e992a4SHeiner Kallweit 		if (c->check(tp) == high)
76125e992a4SHeiner Kallweit 			return true;
762d6836ef0SHeiner Kallweit 		fsleep(usecs);
76325e992a4SHeiner Kallweit 	}
76493882c6fSHeiner Kallweit 
76593882c6fSHeiner Kallweit 	if (net_ratelimit())
766d6836ef0SHeiner Kallweit 		netdev_err(tp->dev, "%s == %d (loop: %d, delay: %lu).\n",
767d6836ef0SHeiner Kallweit 			   c->msg, !high, n, usecs);
76825e992a4SHeiner Kallweit 	return false;
76925e992a4SHeiner Kallweit }
77025e992a4SHeiner Kallweit 
rtl_loop_wait_high(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long d,int n)771d6836ef0SHeiner Kallweit static bool rtl_loop_wait_high(struct rtl8169_private *tp,
77225e992a4SHeiner Kallweit 			       const struct rtl_cond *c,
773d6836ef0SHeiner Kallweit 			       unsigned long d, int n)
77425e992a4SHeiner Kallweit {
775d6836ef0SHeiner Kallweit 	return rtl_loop_wait(tp, c, d, n, true);
77625e992a4SHeiner Kallweit }
77725e992a4SHeiner Kallweit 
rtl_loop_wait_low(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long d,int n)778d6836ef0SHeiner Kallweit static bool rtl_loop_wait_low(struct rtl8169_private *tp,
77925e992a4SHeiner Kallweit 			      const struct rtl_cond *c,
780d6836ef0SHeiner Kallweit 			      unsigned long d, int n)
78125e992a4SHeiner Kallweit {
782d6836ef0SHeiner Kallweit 	return rtl_loop_wait(tp, c, d, n, false);
78325e992a4SHeiner Kallweit }
78425e992a4SHeiner Kallweit 
78525e992a4SHeiner Kallweit #define DECLARE_RTL_COND(name)				\
78625e992a4SHeiner Kallweit static bool name ## _check(struct rtl8169_private *);	\
78725e992a4SHeiner Kallweit 							\
78825e992a4SHeiner Kallweit static const struct rtl_cond name = {			\
78925e992a4SHeiner Kallweit 	.check	= name ## _check,			\
79025e992a4SHeiner Kallweit 	.msg	= #name					\
79125e992a4SHeiner Kallweit };							\
79225e992a4SHeiner Kallweit 							\
79325e992a4SHeiner Kallweit static bool name ## _check(struct rtl8169_private *tp)
79425e992a4SHeiner Kallweit 
r8168fp_adjust_ocp_cmd(struct rtl8169_private * tp,u32 * cmd,int type)795c6cff9dfSHeiner Kallweit static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
796c6cff9dfSHeiner Kallweit {
797c6cff9dfSHeiner Kallweit 	/* based on RTL8168FP_OOBMAC_BASE in vendor driver */
798e6d6ca6eSKai-Heng Feng 	if (type == ERIAR_OOB &&
799e6d6ca6eSKai-Heng Feng 	    (tp->mac_version == RTL_GIGA_MAC_VER_52 ||
800e6d6ca6eSKai-Heng Feng 	     tp->mac_version == RTL_GIGA_MAC_VER_53))
801abbf9a0eSHayes Wang 		*cmd |= 0xf70 << 18;
802c6cff9dfSHeiner Kallweit }
803c6cff9dfSHeiner Kallweit 
DECLARE_RTL_COND(rtl_eriar_cond)804c6cff9dfSHeiner Kallweit DECLARE_RTL_COND(rtl_eriar_cond)
805c6cff9dfSHeiner Kallweit {
806c6cff9dfSHeiner Kallweit 	return RTL_R32(tp, ERIAR) & ERIAR_FLAG;
807c6cff9dfSHeiner Kallweit }
808c6cff9dfSHeiner Kallweit 
_rtl_eri_write(struct rtl8169_private * tp,int addr,u32 mask,u32 val,int type)809c6cff9dfSHeiner Kallweit static void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
810c6cff9dfSHeiner Kallweit 			   u32 val, int type)
811c6cff9dfSHeiner Kallweit {
812c6cff9dfSHeiner Kallweit 	u32 cmd = ERIAR_WRITE_CMD | type | mask | addr;
813c6cff9dfSHeiner Kallweit 
8145f1e1224SHeiner Kallweit 	if (WARN(addr & 3 || !mask, "addr: 0x%x, mask: 0x%08x\n", addr, mask))
8155f1e1224SHeiner Kallweit 		return;
8165f1e1224SHeiner Kallweit 
817c6cff9dfSHeiner Kallweit 	RTL_W32(tp, ERIDR, val);
818c6cff9dfSHeiner Kallweit 	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
819c6cff9dfSHeiner Kallweit 	RTL_W32(tp, ERIAR, cmd);
820c6cff9dfSHeiner Kallweit 
821c6cff9dfSHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
822c6cff9dfSHeiner Kallweit }
823c6cff9dfSHeiner Kallweit 
rtl_eri_write(struct rtl8169_private * tp,int addr,u32 mask,u32 val)824c6cff9dfSHeiner Kallweit static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
825c6cff9dfSHeiner Kallweit 			  u32 val)
826c6cff9dfSHeiner Kallweit {
827c6cff9dfSHeiner Kallweit 	_rtl_eri_write(tp, addr, mask, val, ERIAR_EXGMAC);
828c6cff9dfSHeiner Kallweit }
829c6cff9dfSHeiner Kallweit 
_rtl_eri_read(struct rtl8169_private * tp,int addr,int type)830c6cff9dfSHeiner Kallweit static u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
831c6cff9dfSHeiner Kallweit {
832c6cff9dfSHeiner Kallweit 	u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr;
833c6cff9dfSHeiner Kallweit 
834c6cff9dfSHeiner Kallweit 	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
835c6cff9dfSHeiner Kallweit 	RTL_W32(tp, ERIAR, cmd);
836c6cff9dfSHeiner Kallweit 
837c6cff9dfSHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
838c6cff9dfSHeiner Kallweit 		RTL_R32(tp, ERIDR) : ~0;
839c6cff9dfSHeiner Kallweit }
840c6cff9dfSHeiner Kallweit 
rtl_eri_read(struct rtl8169_private * tp,int addr)841c6cff9dfSHeiner Kallweit static u32 rtl_eri_read(struct rtl8169_private *tp, int addr)
842c6cff9dfSHeiner Kallweit {
843c6cff9dfSHeiner Kallweit 	return _rtl_eri_read(tp, addr, ERIAR_EXGMAC);
844c6cff9dfSHeiner Kallweit }
845c6cff9dfSHeiner Kallweit 
rtl_w0w1_eri(struct rtl8169_private * tp,int addr,u32 p,u32 m)846c6cff9dfSHeiner Kallweit static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 p, u32 m)
847c6cff9dfSHeiner Kallweit {
848c6cff9dfSHeiner Kallweit 	u32 val = rtl_eri_read(tp, addr);
849c6cff9dfSHeiner Kallweit 
850c6cff9dfSHeiner Kallweit 	rtl_eri_write(tp, addr, ERIAR_MASK_1111, (val & ~m) | p);
851c6cff9dfSHeiner Kallweit }
852c6cff9dfSHeiner Kallweit 
rtl_eri_set_bits(struct rtl8169_private * tp,int addr,u32 p)853c6cff9dfSHeiner Kallweit static void rtl_eri_set_bits(struct rtl8169_private *tp, int addr, u32 p)
854c6cff9dfSHeiner Kallweit {
855c6cff9dfSHeiner Kallweit 	rtl_w0w1_eri(tp, addr, p, 0);
856c6cff9dfSHeiner Kallweit }
857c6cff9dfSHeiner Kallweit 
rtl_eri_clear_bits(struct rtl8169_private * tp,int addr,u32 m)858c6cff9dfSHeiner Kallweit static void rtl_eri_clear_bits(struct rtl8169_private *tp, int addr, u32 m)
859c6cff9dfSHeiner Kallweit {
860c6cff9dfSHeiner Kallweit 	rtl_w0w1_eri(tp, addr, 0, m);
861c6cff9dfSHeiner Kallweit }
862c6cff9dfSHeiner Kallweit 
rtl_ocp_reg_failure(u32 reg)863a46604d7SHeiner Kallweit static bool rtl_ocp_reg_failure(u32 reg)
86425e992a4SHeiner Kallweit {
865a46604d7SHeiner Kallweit 	return WARN_ONCE(reg & 0xffff0001, "Invalid ocp reg %x!\n", reg);
86625e992a4SHeiner Kallweit }
86725e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_ocp_gphy_cond)86825e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_ocp_gphy_cond)
86925e992a4SHeiner Kallweit {
87025e992a4SHeiner Kallweit 	return RTL_R32(tp, GPHY_OCP) & OCPAR_FLAG;
87125e992a4SHeiner Kallweit }
87225e992a4SHeiner Kallweit 
r8168_phy_ocp_write(struct rtl8169_private * tp,u32 reg,u32 data)87325e992a4SHeiner Kallweit static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
87425e992a4SHeiner Kallweit {
875a46604d7SHeiner Kallweit 	if (rtl_ocp_reg_failure(reg))
87625e992a4SHeiner Kallweit 		return;
87725e992a4SHeiner Kallweit 
87825e992a4SHeiner Kallweit 	RTL_W32(tp, GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
87925e992a4SHeiner Kallweit 
880d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
88125e992a4SHeiner Kallweit }
88225e992a4SHeiner Kallweit 
r8168_phy_ocp_read(struct rtl8169_private * tp,u32 reg)8839b994b4aSHeiner Kallweit static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
88425e992a4SHeiner Kallweit {
885a46604d7SHeiner Kallweit 	if (rtl_ocp_reg_failure(reg))
88625e992a4SHeiner Kallweit 		return 0;
88725e992a4SHeiner Kallweit 
88825e992a4SHeiner Kallweit 	RTL_W32(tp, GPHY_OCP, reg << 15);
88925e992a4SHeiner Kallweit 
890d6836ef0SHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
8919b994b4aSHeiner Kallweit 		(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
89225e992a4SHeiner Kallweit }
89325e992a4SHeiner Kallweit 
__r8168_mac_ocp_write(struct rtl8169_private * tp,u32 reg,u32 data)89491c86435SHeiner Kallweit static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
89525e992a4SHeiner Kallweit {
896a46604d7SHeiner Kallweit 	if (rtl_ocp_reg_failure(reg))
89725e992a4SHeiner Kallweit 		return;
89825e992a4SHeiner Kallweit 
89925e992a4SHeiner Kallweit 	RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
90025e992a4SHeiner Kallweit }
90125e992a4SHeiner Kallweit 
r8168_mac_ocp_write(struct rtl8169_private * tp,u32 reg,u32 data)90291c86435SHeiner Kallweit static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
90391c86435SHeiner Kallweit {
90491c86435SHeiner Kallweit 	unsigned long flags;
90591c86435SHeiner Kallweit 
906d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
90791c86435SHeiner Kallweit 	__r8168_mac_ocp_write(tp, reg, data);
908d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
90991c86435SHeiner Kallweit }
91091c86435SHeiner Kallweit 
__r8168_mac_ocp_read(struct rtl8169_private * tp,u32 reg)91191c86435SHeiner Kallweit static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
91225e992a4SHeiner Kallweit {
913a46604d7SHeiner Kallweit 	if (rtl_ocp_reg_failure(reg))
91425e992a4SHeiner Kallweit 		return 0;
91525e992a4SHeiner Kallweit 
91625e992a4SHeiner Kallweit 	RTL_W32(tp, OCPDR, reg << 15);
91725e992a4SHeiner Kallweit 
91825e992a4SHeiner Kallweit 	return RTL_R32(tp, OCPDR);
91925e992a4SHeiner Kallweit }
92025e992a4SHeiner Kallweit 
r8168_mac_ocp_read(struct rtl8169_private * tp,u32 reg)92191c86435SHeiner Kallweit static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
92291c86435SHeiner Kallweit {
92391c86435SHeiner Kallweit 	unsigned long flags;
92491c86435SHeiner Kallweit 	u16 val;
92591c86435SHeiner Kallweit 
926d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
92791c86435SHeiner Kallweit 	val = __r8168_mac_ocp_read(tp, reg);
928d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
92991c86435SHeiner Kallweit 
93091c86435SHeiner Kallweit 	return val;
93191c86435SHeiner Kallweit }
93291c86435SHeiner Kallweit 
r8168_mac_ocp_modify(struct rtl8169_private * tp,u32 reg,u16 mask,u16 set)933ef712edeSHeiner Kallweit static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
934ef712edeSHeiner Kallweit 				 u16 set)
935ef712edeSHeiner Kallweit {
93691c86435SHeiner Kallweit 	unsigned long flags;
93791c86435SHeiner Kallweit 	u16 data;
938ef712edeSHeiner Kallweit 
939d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
94091c86435SHeiner Kallweit 	data = __r8168_mac_ocp_read(tp, reg);
94191c86435SHeiner Kallweit 	__r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
942d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
943ef712edeSHeiner Kallweit }
944ef712edeSHeiner Kallweit 
945acb58657SHeiner Kallweit /* Work around a hw issue with RTL8168g PHY, the quirk disables
946acb58657SHeiner Kallweit  * PHY MCU interrupts before PHY power-down.
947acb58657SHeiner Kallweit  */
rtl8168g_phy_suspend_quirk(struct rtl8169_private * tp,int value)948acb58657SHeiner Kallweit static void rtl8168g_phy_suspend_quirk(struct rtl8169_private *tp, int value)
949acb58657SHeiner Kallweit {
950acb58657SHeiner Kallweit 	switch (tp->mac_version) {
951acb58657SHeiner Kallweit 	case RTL_GIGA_MAC_VER_40:
952acb58657SHeiner Kallweit 		if (value & BMCR_RESET || !(value & BMCR_PDOWN))
953acb58657SHeiner Kallweit 			rtl_eri_set_bits(tp, 0x1a8, 0xfc000000);
954acb58657SHeiner Kallweit 		else
955acb58657SHeiner Kallweit 			rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000);
956acb58657SHeiner Kallweit 		break;
957acb58657SHeiner Kallweit 	default:
958acb58657SHeiner Kallweit 		break;
959acb58657SHeiner Kallweit 	}
960acb58657SHeiner Kallweit };
961acb58657SHeiner Kallweit 
r8168g_mdio_write(struct rtl8169_private * tp,int reg,int value)96225e992a4SHeiner Kallweit static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
96325e992a4SHeiner Kallweit {
96425e992a4SHeiner Kallweit 	if (reg == 0x1f) {
96525e992a4SHeiner Kallweit 		tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
96625e992a4SHeiner Kallweit 		return;
96725e992a4SHeiner Kallweit 	}
96825e992a4SHeiner Kallweit 
96925e992a4SHeiner Kallweit 	if (tp->ocp_base != OCP_STD_PHY_BASE)
97025e992a4SHeiner Kallweit 		reg -= 0x10;
97125e992a4SHeiner Kallweit 
972acb58657SHeiner Kallweit 	if (tp->ocp_base == OCP_STD_PHY_BASE && reg == MII_BMCR)
973acb58657SHeiner Kallweit 		rtl8168g_phy_suspend_quirk(tp, value);
974acb58657SHeiner Kallweit 
97525e992a4SHeiner Kallweit 	r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
97625e992a4SHeiner Kallweit }
97725e992a4SHeiner Kallweit 
r8168g_mdio_read(struct rtl8169_private * tp,int reg)97825e992a4SHeiner Kallweit static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
97925e992a4SHeiner Kallweit {
9809c6850feSHeiner Kallweit 	if (reg == 0x1f)
9819c6850feSHeiner Kallweit 		return tp->ocp_base == OCP_STD_PHY_BASE ? 0 : tp->ocp_base >> 4;
9829c6850feSHeiner Kallweit 
98325e992a4SHeiner Kallweit 	if (tp->ocp_base != OCP_STD_PHY_BASE)
98425e992a4SHeiner Kallweit 		reg -= 0x10;
98525e992a4SHeiner Kallweit 
98625e992a4SHeiner Kallweit 	return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
98725e992a4SHeiner Kallweit }
98825e992a4SHeiner Kallweit 
mac_mcu_write(struct rtl8169_private * tp,int reg,int value)98925e992a4SHeiner Kallweit static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
99025e992a4SHeiner Kallweit {
99125e992a4SHeiner Kallweit 	if (reg == 0x1f) {
99225e992a4SHeiner Kallweit 		tp->ocp_base = value << 4;
99325e992a4SHeiner Kallweit 		return;
99425e992a4SHeiner Kallweit 	}
99525e992a4SHeiner Kallweit 
99625e992a4SHeiner Kallweit 	r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
99725e992a4SHeiner Kallweit }
99825e992a4SHeiner Kallweit 
mac_mcu_read(struct rtl8169_private * tp,int reg)99925e992a4SHeiner Kallweit static int mac_mcu_read(struct rtl8169_private *tp, int reg)
100025e992a4SHeiner Kallweit {
100125e992a4SHeiner Kallweit 	return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
100225e992a4SHeiner Kallweit }
100325e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_phyar_cond)100425e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_phyar_cond)
100525e992a4SHeiner Kallweit {
100625e992a4SHeiner Kallweit 	return RTL_R32(tp, PHYAR) & 0x80000000;
100725e992a4SHeiner Kallweit }
100825e992a4SHeiner Kallweit 
r8169_mdio_write(struct rtl8169_private * tp,int reg,int value)100925e992a4SHeiner Kallweit static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
101025e992a4SHeiner Kallweit {
101125e992a4SHeiner Kallweit 	RTL_W32(tp, PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
101225e992a4SHeiner Kallweit 
1013d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
101425e992a4SHeiner Kallweit 	/*
101525e992a4SHeiner Kallweit 	 * According to hardware specs a 20us delay is required after write
101625e992a4SHeiner Kallweit 	 * complete indication, but before sending next command.
101725e992a4SHeiner Kallweit 	 */
101825e992a4SHeiner Kallweit 	udelay(20);
101925e992a4SHeiner Kallweit }
102025e992a4SHeiner Kallweit 
r8169_mdio_read(struct rtl8169_private * tp,int reg)102125e992a4SHeiner Kallweit static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
102225e992a4SHeiner Kallweit {
102325e992a4SHeiner Kallweit 	int value;
102425e992a4SHeiner Kallweit 
102525e992a4SHeiner Kallweit 	RTL_W32(tp, PHYAR, 0x0 | (reg & 0x1f) << 16);
102625e992a4SHeiner Kallweit 
1027d6836ef0SHeiner Kallweit 	value = rtl_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
10289b994b4aSHeiner Kallweit 		RTL_R32(tp, PHYAR) & 0xffff : -ETIMEDOUT;
102925e992a4SHeiner Kallweit 
103025e992a4SHeiner Kallweit 	/*
103125e992a4SHeiner Kallweit 	 * According to hardware specs a 20us delay is required after read
103225e992a4SHeiner Kallweit 	 * complete indication, but before sending next command.
103325e992a4SHeiner Kallweit 	 */
103425e992a4SHeiner Kallweit 	udelay(20);
103525e992a4SHeiner Kallweit 
103625e992a4SHeiner Kallweit 	return value;
103725e992a4SHeiner Kallweit }
103825e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_ocpar_cond)103925e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_ocpar_cond)
104025e992a4SHeiner Kallweit {
104125e992a4SHeiner Kallweit 	return RTL_R32(tp, OCPAR) & OCPAR_FLAG;
104225e992a4SHeiner Kallweit }
104325e992a4SHeiner Kallweit 
104425e992a4SHeiner Kallweit #define R8168DP_1_MDIO_ACCESS_BIT	0x00020000
104525e992a4SHeiner Kallweit 
r8168dp_2_mdio_start(struct rtl8169_private * tp)104625e992a4SHeiner Kallweit static void r8168dp_2_mdio_start(struct rtl8169_private *tp)
104725e992a4SHeiner Kallweit {
104825e992a4SHeiner Kallweit 	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
104925e992a4SHeiner Kallweit }
105025e992a4SHeiner Kallweit 
r8168dp_2_mdio_stop(struct rtl8169_private * tp)105125e992a4SHeiner Kallweit static void r8168dp_2_mdio_stop(struct rtl8169_private *tp)
105225e992a4SHeiner Kallweit {
105325e992a4SHeiner Kallweit 	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
105425e992a4SHeiner Kallweit }
105525e992a4SHeiner Kallweit 
r8168dp_2_mdio_write(struct rtl8169_private * tp,int reg,int value)105625e992a4SHeiner Kallweit static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
105725e992a4SHeiner Kallweit {
105825e992a4SHeiner Kallweit 	r8168dp_2_mdio_start(tp);
105925e992a4SHeiner Kallweit 
106025e992a4SHeiner Kallweit 	r8169_mdio_write(tp, reg, value);
106125e992a4SHeiner Kallweit 
106225e992a4SHeiner Kallweit 	r8168dp_2_mdio_stop(tp);
106325e992a4SHeiner Kallweit }
106425e992a4SHeiner Kallweit 
r8168dp_2_mdio_read(struct rtl8169_private * tp,int reg)106525e992a4SHeiner Kallweit static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
106625e992a4SHeiner Kallweit {
106725e992a4SHeiner Kallweit 	int value;
106825e992a4SHeiner Kallweit 
106962bdc8fdSHeiner Kallweit 	/* Work around issue with chip reporting wrong PHY ID */
107062bdc8fdSHeiner Kallweit 	if (reg == MII_PHYSID2)
107162bdc8fdSHeiner Kallweit 		return 0xc912;
107262bdc8fdSHeiner Kallweit 
107325e992a4SHeiner Kallweit 	r8168dp_2_mdio_start(tp);
107425e992a4SHeiner Kallweit 
107525e992a4SHeiner Kallweit 	value = r8169_mdio_read(tp, reg);
107625e992a4SHeiner Kallweit 
107725e992a4SHeiner Kallweit 	r8168dp_2_mdio_stop(tp);
107825e992a4SHeiner Kallweit 
107925e992a4SHeiner Kallweit 	return value;
108025e992a4SHeiner Kallweit }
108125e992a4SHeiner Kallweit 
rtl_writephy(struct rtl8169_private * tp,int location,int val)108225e992a4SHeiner Kallweit static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
108325e992a4SHeiner Kallweit {
108425e992a4SHeiner Kallweit 	switch (tp->mac_version) {
108525e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_28:
108625e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_31:
108725e992a4SHeiner Kallweit 		r8168dp_2_mdio_write(tp, location, val);
108825e992a4SHeiner Kallweit 		break;
10890439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
109025e992a4SHeiner Kallweit 		r8168g_mdio_write(tp, location, val);
109125e992a4SHeiner Kallweit 		break;
109225e992a4SHeiner Kallweit 	default:
109325e992a4SHeiner Kallweit 		r8169_mdio_write(tp, location, val);
109425e992a4SHeiner Kallweit 		break;
109525e992a4SHeiner Kallweit 	}
109625e992a4SHeiner Kallweit }
109725e992a4SHeiner Kallweit 
rtl_readphy(struct rtl8169_private * tp,int location)109825e992a4SHeiner Kallweit static int rtl_readphy(struct rtl8169_private *tp, int location)
109925e992a4SHeiner Kallweit {
110025e992a4SHeiner Kallweit 	switch (tp->mac_version) {
110125e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_28:
110225e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_31:
110325e992a4SHeiner Kallweit 		return r8168dp_2_mdio_read(tp, location);
11040439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
110525e992a4SHeiner Kallweit 		return r8168g_mdio_read(tp, location);
110625e992a4SHeiner Kallweit 	default:
110725e992a4SHeiner Kallweit 		return r8169_mdio_read(tp, location);
110825e992a4SHeiner Kallweit 	}
110925e992a4SHeiner Kallweit }
111025e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_ephyar_cond)111125e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_ephyar_cond)
111225e992a4SHeiner Kallweit {
111325e992a4SHeiner Kallweit 	return RTL_R32(tp, EPHYAR) & EPHYAR_FLAG;
111425e992a4SHeiner Kallweit }
111525e992a4SHeiner Kallweit 
rtl_ephy_write(struct rtl8169_private * tp,int reg_addr,int value)111625e992a4SHeiner Kallweit static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
111725e992a4SHeiner Kallweit {
111825e992a4SHeiner Kallweit 	RTL_W32(tp, EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
111925e992a4SHeiner Kallweit 		(reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
112025e992a4SHeiner Kallweit 
1121d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
112225e992a4SHeiner Kallweit 
112325e992a4SHeiner Kallweit 	udelay(10);
112425e992a4SHeiner Kallweit }
112525e992a4SHeiner Kallweit 
rtl_ephy_read(struct rtl8169_private * tp,int reg_addr)112625e992a4SHeiner Kallweit static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
112725e992a4SHeiner Kallweit {
112825e992a4SHeiner Kallweit 	RTL_W32(tp, EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
112925e992a4SHeiner Kallweit 
1130d6836ef0SHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
113125e992a4SHeiner Kallweit 		RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0;
113225e992a4SHeiner Kallweit }
113325e992a4SHeiner Kallweit 
r8168dp_ocp_read(struct rtl8169_private * tp,u16 reg)1134a15aaa03SHeiner Kallweit static u32 r8168dp_ocp_read(struct rtl8169_private *tp, u16 reg)
113525e992a4SHeiner Kallweit {
1136a15aaa03SHeiner Kallweit 	RTL_W32(tp, OCPAR, 0x0fu << 12 | (reg & 0x0fff));
1137d6836ef0SHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
113825e992a4SHeiner Kallweit 		RTL_R32(tp, OCPDR) : ~0;
113925e992a4SHeiner Kallweit }
114025e992a4SHeiner Kallweit 
r8168ep_ocp_read(struct rtl8169_private * tp,u16 reg)1141787c0c04SHeiner Kallweit static u32 r8168ep_ocp_read(struct rtl8169_private *tp, u16 reg)
114225e992a4SHeiner Kallweit {
114325e992a4SHeiner Kallweit 	return _rtl_eri_read(tp, reg, ERIAR_OOB);
114425e992a4SHeiner Kallweit }
114525e992a4SHeiner Kallweit 
r8168dp_ocp_write(struct rtl8169_private * tp,u8 mask,u16 reg,u32 data)114625e992a4SHeiner Kallweit static void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
114725e992a4SHeiner Kallweit 			      u32 data)
114825e992a4SHeiner Kallweit {
114925e992a4SHeiner Kallweit 	RTL_W32(tp, OCPDR, data);
115025e992a4SHeiner Kallweit 	RTL_W32(tp, OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
1151d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
115225e992a4SHeiner Kallweit }
115325e992a4SHeiner Kallweit 
r8168ep_ocp_write(struct rtl8169_private * tp,u8 mask,u16 reg,u32 data)115425e992a4SHeiner Kallweit static void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
115525e992a4SHeiner Kallweit 			      u32 data)
115625e992a4SHeiner Kallweit {
115725e992a4SHeiner Kallweit 	_rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
115825e992a4SHeiner Kallweit 		       data, ERIAR_OOB);
115925e992a4SHeiner Kallweit }
116025e992a4SHeiner Kallweit 
r8168dp_oob_notify(struct rtl8169_private * tp,u8 cmd)116125e992a4SHeiner Kallweit static void r8168dp_oob_notify(struct rtl8169_private *tp, u8 cmd)
116225e992a4SHeiner Kallweit {
116325e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd);
116425e992a4SHeiner Kallweit 
116525e992a4SHeiner Kallweit 	r8168dp_ocp_write(tp, 0x1, 0x30, 0x00000001);
116625e992a4SHeiner Kallweit }
116725e992a4SHeiner Kallweit 
116825e992a4SHeiner Kallweit #define OOB_CMD_RESET		0x00
116925e992a4SHeiner Kallweit #define OOB_CMD_DRIVER_START	0x05
117025e992a4SHeiner Kallweit #define OOB_CMD_DRIVER_STOP	0x06
117125e992a4SHeiner Kallweit 
rtl8168_get_ocp_reg(struct rtl8169_private * tp)117225e992a4SHeiner Kallweit static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
117325e992a4SHeiner Kallweit {
117425e992a4SHeiner Kallweit 	return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
117525e992a4SHeiner Kallweit }
117625e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_dp_ocp_read_cond)117725e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_dp_ocp_read_cond)
117825e992a4SHeiner Kallweit {
117925e992a4SHeiner Kallweit 	u16 reg;
118025e992a4SHeiner Kallweit 
118125e992a4SHeiner Kallweit 	reg = rtl8168_get_ocp_reg(tp);
118225e992a4SHeiner Kallweit 
1183a15aaa03SHeiner Kallweit 	return r8168dp_ocp_read(tp, reg) & 0x00000800;
118425e992a4SHeiner Kallweit }
118525e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_ep_ocp_read_cond)118625e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_ep_ocp_read_cond)
118725e992a4SHeiner Kallweit {
1188787c0c04SHeiner Kallweit 	return r8168ep_ocp_read(tp, 0x124) & 0x00000001;
118925e992a4SHeiner Kallweit }
119025e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_ocp_tx_cond)119125e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_ocp_tx_cond)
119225e992a4SHeiner Kallweit {
119325e992a4SHeiner Kallweit 	return RTL_R8(tp, IBISR0) & 0x20;
119425e992a4SHeiner Kallweit }
119525e992a4SHeiner Kallweit 
rtl8168ep_stop_cmac(struct rtl8169_private * tp)119625e992a4SHeiner Kallweit static void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
119725e992a4SHeiner Kallweit {
119825e992a4SHeiner Kallweit 	RTL_W8(tp, IBCR2, RTL_R8(tp, IBCR2) & ~0x01);
1199d6836ef0SHeiner Kallweit 	rtl_loop_wait_high(tp, &rtl_ocp_tx_cond, 50000, 2000);
120025e992a4SHeiner Kallweit 	RTL_W8(tp, IBISR0, RTL_R8(tp, IBISR0) | 0x20);
120125e992a4SHeiner Kallweit 	RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
120225e992a4SHeiner Kallweit }
120325e992a4SHeiner Kallweit 
rtl_dash_loop_wait(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long usecs,int n,bool high)1204a5eae74fSAtlas Yu static void rtl_dash_loop_wait(struct rtl8169_private *tp,
1205a5eae74fSAtlas Yu 			       const struct rtl_cond *c,
1206a5eae74fSAtlas Yu 			       unsigned long usecs, int n, bool high)
1207a5eae74fSAtlas Yu {
1208a5eae74fSAtlas Yu 	if (!tp->dash_enabled)
1209a5eae74fSAtlas Yu 		return;
1210a5eae74fSAtlas Yu 	rtl_loop_wait(tp, c, usecs, n, high);
1211a5eae74fSAtlas Yu }
1212a5eae74fSAtlas Yu 
rtl_dash_loop_wait_high(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long d,int n)1213a5eae74fSAtlas Yu static void rtl_dash_loop_wait_high(struct rtl8169_private *tp,
1214a5eae74fSAtlas Yu 				    const struct rtl_cond *c,
1215a5eae74fSAtlas Yu 				    unsigned long d, int n)
1216a5eae74fSAtlas Yu {
1217a5eae74fSAtlas Yu 	rtl_dash_loop_wait(tp, c, d, n, true);
1218a5eae74fSAtlas Yu }
1219a5eae74fSAtlas Yu 
rtl_dash_loop_wait_low(struct rtl8169_private * tp,const struct rtl_cond * c,unsigned long d,int n)1220a5eae74fSAtlas Yu static void rtl_dash_loop_wait_low(struct rtl8169_private *tp,
1221a5eae74fSAtlas Yu 				   const struct rtl_cond *c,
1222a5eae74fSAtlas Yu 				   unsigned long d, int n)
1223a5eae74fSAtlas Yu {
1224a5eae74fSAtlas Yu 	rtl_dash_loop_wait(tp, c, d, n, false);
1225a5eae74fSAtlas Yu }
1226a5eae74fSAtlas Yu 
rtl8168dp_driver_start(struct rtl8169_private * tp)122725e992a4SHeiner Kallweit static void rtl8168dp_driver_start(struct rtl8169_private *tp)
122825e992a4SHeiner Kallweit {
122925e992a4SHeiner Kallweit 	r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
1230a5eae74fSAtlas Yu 	rtl_dash_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
123125e992a4SHeiner Kallweit }
123225e992a4SHeiner Kallweit 
rtl8168ep_driver_start(struct rtl8169_private * tp)123325e992a4SHeiner Kallweit static void rtl8168ep_driver_start(struct rtl8169_private *tp)
123425e992a4SHeiner Kallweit {
123525e992a4SHeiner Kallweit 	r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
1236787c0c04SHeiner Kallweit 	r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
1237a5eae74fSAtlas Yu 	rtl_dash_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
123825e992a4SHeiner Kallweit }
123925e992a4SHeiner Kallweit 
rtl8168_driver_start(struct rtl8169_private * tp)124025e992a4SHeiner Kallweit static void rtl8168_driver_start(struct rtl8169_private *tp)
124125e992a4SHeiner Kallweit {
1242e0d38b58SHeiner Kallweit 	if (tp->dash_type == RTL_DASH_DP)
124325e992a4SHeiner Kallweit 		rtl8168dp_driver_start(tp);
1244e0d38b58SHeiner Kallweit 	else
124525e992a4SHeiner Kallweit 		rtl8168ep_driver_start(tp);
124625e992a4SHeiner Kallweit }
124725e992a4SHeiner Kallweit 
rtl8168dp_driver_stop(struct rtl8169_private * tp)124825e992a4SHeiner Kallweit static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
124925e992a4SHeiner Kallweit {
125025e992a4SHeiner Kallweit 	r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
1251a5eae74fSAtlas Yu 	rtl_dash_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
125225e992a4SHeiner Kallweit }
125325e992a4SHeiner Kallweit 
rtl8168ep_driver_stop(struct rtl8169_private * tp)125425e992a4SHeiner Kallweit static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
125525e992a4SHeiner Kallweit {
125625e992a4SHeiner Kallweit 	rtl8168ep_stop_cmac(tp);
125725e992a4SHeiner Kallweit 	r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
1258787c0c04SHeiner Kallweit 	r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
1259a5eae74fSAtlas Yu 	rtl_dash_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
126025e992a4SHeiner Kallweit }
126125e992a4SHeiner Kallweit 
rtl8168_driver_stop(struct rtl8169_private * tp)126225e992a4SHeiner Kallweit static void rtl8168_driver_stop(struct rtl8169_private *tp)
126325e992a4SHeiner Kallweit {
1264e0d38b58SHeiner Kallweit 	if (tp->dash_type == RTL_DASH_DP)
126525e992a4SHeiner Kallweit 		rtl8168dp_driver_stop(tp);
1266e0d38b58SHeiner Kallweit 	else
126725e992a4SHeiner Kallweit 		rtl8168ep_driver_stop(tp);
126825e992a4SHeiner Kallweit }
126925e992a4SHeiner Kallweit 
r8168dp_check_dash(struct rtl8169_private * tp)127025e992a4SHeiner Kallweit static bool r8168dp_check_dash(struct rtl8169_private *tp)
127125e992a4SHeiner Kallweit {
127225e992a4SHeiner Kallweit 	u16 reg = rtl8168_get_ocp_reg(tp);
127325e992a4SHeiner Kallweit 
1274e0d38b58SHeiner Kallweit 	return r8168dp_ocp_read(tp, reg) & BIT(15);
127525e992a4SHeiner Kallweit }
127625e992a4SHeiner Kallweit 
r8168ep_check_dash(struct rtl8169_private * tp)127725e992a4SHeiner Kallweit static bool r8168ep_check_dash(struct rtl8169_private *tp)
127825e992a4SHeiner Kallweit {
1279e0d38b58SHeiner Kallweit 	return r8168ep_ocp_read(tp, 0x128) & BIT(0);
128025e992a4SHeiner Kallweit }
128125e992a4SHeiner Kallweit 
rtl_dash_is_enabled(struct rtl8169_private * tp)1282c61d525fSChunHao Lin static bool rtl_dash_is_enabled(struct rtl8169_private *tp)
1283c61d525fSChunHao Lin {
1284c61d525fSChunHao Lin 	switch (tp->dash_type) {
1285c61d525fSChunHao Lin 	case RTL_DASH_DP:
1286c61d525fSChunHao Lin 		return r8168dp_check_dash(tp);
1287c61d525fSChunHao Lin 	case RTL_DASH_EP:
1288c61d525fSChunHao Lin 		return r8168ep_check_dash(tp);
1289c61d525fSChunHao Lin 	default:
1290c61d525fSChunHao Lin 		return false;
1291c61d525fSChunHao Lin 	}
1292c61d525fSChunHao Lin }
1293c61d525fSChunHao Lin 
rtl_get_dash_type(struct rtl8169_private * tp)1294c61d525fSChunHao Lin static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
129525e992a4SHeiner Kallweit {
129625e992a4SHeiner Kallweit 	switch (tp->mac_version) {
129725e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_28:
129825e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_31:
1299c61d525fSChunHao Lin 		return RTL_DASH_DP;
1300133706a9SHeiner Kallweit 	case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
1301c61d525fSChunHao Lin 		return RTL_DASH_EP;
130225e992a4SHeiner Kallweit 	default:
1303e0d38b58SHeiner Kallweit 		return RTL_DASH_NONE;
130425e992a4SHeiner Kallweit 	}
130525e992a4SHeiner Kallweit }
130625e992a4SHeiner Kallweit 
rtl_set_d3_pll_down(struct rtl8169_private * tp,bool enable)1307128735a1SHeiner Kallweit static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)
1308128735a1SHeiner Kallweit {
1309128735a1SHeiner Kallweit 	switch (tp->mac_version) {
1310128735a1SHeiner Kallweit 	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
1311d2a04370SHeiner Kallweit 	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
1312128735a1SHeiner Kallweit 	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37:
1313128735a1SHeiner Kallweit 	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
1314128735a1SHeiner Kallweit 		if (enable)
1315128735a1SHeiner Kallweit 			RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN);
1316128735a1SHeiner Kallweit 		else
1317128735a1SHeiner Kallweit 			RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | D3_NO_PLL_DOWN);
1318128735a1SHeiner Kallweit 		break;
1319128735a1SHeiner Kallweit 	default:
1320128735a1SHeiner Kallweit 		break;
1321128735a1SHeiner Kallweit 	}
1322128735a1SHeiner Kallweit }
1323128735a1SHeiner Kallweit 
rtl_reset_packet_filter(struct rtl8169_private * tp)132425e992a4SHeiner Kallweit static void rtl_reset_packet_filter(struct rtl8169_private *tp)
132525e992a4SHeiner Kallweit {
132654113dedSHeiner Kallweit 	rtl_eri_clear_bits(tp, 0xdc, BIT(0));
132754113dedSHeiner Kallweit 	rtl_eri_set_bits(tp, 0xdc, BIT(0));
132825e992a4SHeiner Kallweit }
132925e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_efusear_cond)133025e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_efusear_cond)
133125e992a4SHeiner Kallweit {
133225e992a4SHeiner Kallweit 	return RTL_R32(tp, EFUSEAR) & EFUSEAR_FLAG;
133325e992a4SHeiner Kallweit }
133425e992a4SHeiner Kallweit 
rtl8168d_efuse_read(struct rtl8169_private * tp,int reg_addr)13352992bdfaSHeiner Kallweit u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
133625e992a4SHeiner Kallweit {
133725e992a4SHeiner Kallweit 	RTL_W32(tp, EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
133825e992a4SHeiner Kallweit 
1339d6836ef0SHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
134025e992a4SHeiner Kallweit 		RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
134125e992a4SHeiner Kallweit }
134225e992a4SHeiner Kallweit 
rtl_get_events(struct rtl8169_private * tp)1343c1d532d2SHeiner Kallweit static u32 rtl_get_events(struct rtl8169_private *tp)
1344c1d532d2SHeiner Kallweit {
1345f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1346f1bce4adSHeiner Kallweit 		return RTL_R32(tp, IntrStatus_8125);
1347f1bce4adSHeiner Kallweit 	else
1348c1d532d2SHeiner Kallweit 		return RTL_R16(tp, IntrStatus);
1349c1d532d2SHeiner Kallweit }
1350c1d532d2SHeiner Kallweit 
rtl_ack_events(struct rtl8169_private * tp,u32 bits)1351c1d532d2SHeiner Kallweit static void rtl_ack_events(struct rtl8169_private *tp, u32 bits)
135225e992a4SHeiner Kallweit {
1353f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1354f1bce4adSHeiner Kallweit 		RTL_W32(tp, IntrStatus_8125, bits);
1355f1bce4adSHeiner Kallweit 	else
135625e992a4SHeiner Kallweit 		RTL_W16(tp, IntrStatus, bits);
135725e992a4SHeiner Kallweit }
135825e992a4SHeiner Kallweit 
rtl_irq_disable(struct rtl8169_private * tp)135925e992a4SHeiner Kallweit static void rtl_irq_disable(struct rtl8169_private *tp)
136025e992a4SHeiner Kallweit {
1361f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1362f1bce4adSHeiner Kallweit 		RTL_W32(tp, IntrMask_8125, 0);
1363f1bce4adSHeiner Kallweit 	else
136425e992a4SHeiner Kallweit 		RTL_W16(tp, IntrMask, 0);
136525e992a4SHeiner Kallweit }
136625e992a4SHeiner Kallweit 
rtl_irq_enable(struct rtl8169_private * tp)136725e992a4SHeiner Kallweit static void rtl_irq_enable(struct rtl8169_private *tp)
136825e992a4SHeiner Kallweit {
1369f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1370f1bce4adSHeiner Kallweit 		RTL_W32(tp, IntrMask_8125, tp->irq_mask);
1371f1bce4adSHeiner Kallweit 	else
137225e992a4SHeiner Kallweit 		RTL_W16(tp, IntrMask, tp->irq_mask);
137325e992a4SHeiner Kallweit }
137425e992a4SHeiner Kallweit 
rtl8169_irq_mask_and_ack(struct rtl8169_private * tp)137525e992a4SHeiner Kallweit static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
137625e992a4SHeiner Kallweit {
137725e992a4SHeiner Kallweit 	rtl_irq_disable(tp);
1378c1d532d2SHeiner Kallweit 	rtl_ack_events(tp, 0xffffffff);
1379711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
138025e992a4SHeiner Kallweit }
138125e992a4SHeiner Kallweit 
rtl_link_chg_patch(struct rtl8169_private * tp)138225e992a4SHeiner Kallweit static void rtl_link_chg_patch(struct rtl8169_private *tp)
138325e992a4SHeiner Kallweit {
138425e992a4SHeiner Kallweit 	struct phy_device *phydev = tp->phydev;
138525e992a4SHeiner Kallweit 
138625e992a4SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
138725e992a4SHeiner Kallweit 	    tp->mac_version == RTL_GIGA_MAC_VER_38) {
138825e992a4SHeiner Kallweit 		if (phydev->speed == SPEED_1000) {
138925e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
139025e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
139125e992a4SHeiner Kallweit 		} else if (phydev->speed == SPEED_100) {
139225e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
139325e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
139425e992a4SHeiner Kallweit 		} else {
139525e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
139625e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
139725e992a4SHeiner Kallweit 		}
139825e992a4SHeiner Kallweit 		rtl_reset_packet_filter(tp);
139925e992a4SHeiner Kallweit 	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
140025e992a4SHeiner Kallweit 		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
140125e992a4SHeiner Kallweit 		if (phydev->speed == SPEED_1000) {
140225e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
140325e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
140425e992a4SHeiner Kallweit 		} else {
140525e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
140625e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
140725e992a4SHeiner Kallweit 		}
140825e992a4SHeiner Kallweit 	} else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
140925e992a4SHeiner Kallweit 		if (phydev->speed == SPEED_10) {
141025e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);
141125e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);
141225e992a4SHeiner Kallweit 		} else {
141325e992a4SHeiner Kallweit 			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
141425e992a4SHeiner Kallweit 		}
141525e992a4SHeiner Kallweit 	}
141625e992a4SHeiner Kallweit }
141725e992a4SHeiner Kallweit 
141825e992a4SHeiner Kallweit #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
141925e992a4SHeiner Kallweit 
rtl8169_get_wol(struct net_device * dev,struct ethtool_wolinfo * wol)142025e992a4SHeiner Kallweit static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
142125e992a4SHeiner Kallweit {
142225e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
142325e992a4SHeiner Kallweit 
142425e992a4SHeiner Kallweit 	wol->supported = WAKE_ANY;
142525e992a4SHeiner Kallweit 	wol->wolopts = tp->saved_wolopts;
142625e992a4SHeiner Kallweit }
142725e992a4SHeiner Kallweit 
__rtl8169_set_wol(struct rtl8169_private * tp,u32 wolopts)142825e992a4SHeiner Kallweit static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
142925e992a4SHeiner Kallweit {
143025e992a4SHeiner Kallweit 	static const struct {
143125e992a4SHeiner Kallweit 		u32 opt;
143225e992a4SHeiner Kallweit 		u16 reg;
143325e992a4SHeiner Kallweit 		u8  mask;
143425e992a4SHeiner Kallweit 	} cfg[] = {
143525e992a4SHeiner Kallweit 		{ WAKE_PHY,   Config3, LinkUp },
143625e992a4SHeiner Kallweit 		{ WAKE_UCAST, Config5, UWF },
143725e992a4SHeiner Kallweit 		{ WAKE_BCAST, Config5, BWF },
143825e992a4SHeiner Kallweit 		{ WAKE_MCAST, Config5, MWF },
143925e992a4SHeiner Kallweit 		{ WAKE_ANY,   Config5, LanWake },
144025e992a4SHeiner Kallweit 		{ WAKE_MAGIC, Config3, MagicPacket }
144125e992a4SHeiner Kallweit 	};
1442f1bce4adSHeiner Kallweit 	unsigned int i, tmp = ARRAY_SIZE(cfg);
14436bc6c4e6SHeiner Kallweit 	unsigned long flags;
144425e992a4SHeiner Kallweit 	u8 options;
144525e992a4SHeiner Kallweit 
144625e992a4SHeiner Kallweit 	rtl_unlock_config_regs(tp);
144725e992a4SHeiner Kallweit 
14489e9f33baSHeiner Kallweit 	if (rtl_is_8168evl_up(tp)) {
1449f1bce4adSHeiner Kallweit 		tmp--;
145025e992a4SHeiner Kallweit 		if (wolopts & WAKE_MAGIC)
145154113dedSHeiner Kallweit 			rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2);
145225e992a4SHeiner Kallweit 		else
145354113dedSHeiner Kallweit 			rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2);
1454f1bce4adSHeiner Kallweit 	} else if (rtl_is_8125(tp)) {
1455f1bce4adSHeiner Kallweit 		tmp--;
1456f1bce4adSHeiner Kallweit 		if (wolopts & WAKE_MAGIC)
1457f1bce4adSHeiner Kallweit 			r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0));
1458f1bce4adSHeiner Kallweit 		else
1459f1bce4adSHeiner Kallweit 			r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
146025e992a4SHeiner Kallweit 	}
146125e992a4SHeiner Kallweit 
1462d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_irqsave(&tp->config25_lock, flags);
146325e992a4SHeiner Kallweit 	for (i = 0; i < tmp; i++) {
146425e992a4SHeiner Kallweit 		options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
146525e992a4SHeiner Kallweit 		if (wolopts & cfg[i].opt)
146625e992a4SHeiner Kallweit 			options |= cfg[i].mask;
146725e992a4SHeiner Kallweit 		RTL_W8(tp, cfg[i].reg, options);
146825e992a4SHeiner Kallweit 	}
1469d6c36cbcSSebastian Andrzej Siewior 	raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
147025e992a4SHeiner Kallweit 
147125e992a4SHeiner Kallweit 	switch (tp->mac_version) {
1472edcde3eeSHeiner Kallweit 	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
147325e992a4SHeiner Kallweit 		options = RTL_R8(tp, Config1) & ~PMEnable;
147425e992a4SHeiner Kallweit 		if (wolopts)
147525e992a4SHeiner Kallweit 			options |= PMEnable;
147625e992a4SHeiner Kallweit 		RTL_W8(tp, Config1, options);
147725e992a4SHeiner Kallweit 		break;
1478edcde3eeSHeiner Kallweit 	case RTL_GIGA_MAC_VER_34:
1479edcde3eeSHeiner Kallweit 	case RTL_GIGA_MAC_VER_37:
14800439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
148125e992a4SHeiner Kallweit 		if (wolopts)
14826bc6c4e6SHeiner Kallweit 			rtl_mod_config2(tp, 0, PME_SIGNAL);
14836bc6c4e6SHeiner Kallweit 		else
14846bc6c4e6SHeiner Kallweit 			rtl_mod_config2(tp, PME_SIGNAL, 0);
148525e992a4SHeiner Kallweit 		break;
1486edcde3eeSHeiner Kallweit 	default:
1487edcde3eeSHeiner Kallweit 		break;
148825e992a4SHeiner Kallweit 	}
148925e992a4SHeiner Kallweit 
149025e992a4SHeiner Kallweit 	rtl_lock_config_regs(tp);
149125e992a4SHeiner Kallweit 
149225e992a4SHeiner Kallweit 	device_set_wakeup_enable(tp_to_dev(tp), wolopts);
149354744510SHeiner Kallweit 
1494c61d525fSChunHao Lin 	if (!tp->dash_enabled) {
1495128735a1SHeiner Kallweit 		rtl_set_d3_pll_down(tp, !wolopts);
1496398fd408SHeiner Kallweit 		tp->dev->wol_enabled = wolopts ? 1 : 0;
149725e992a4SHeiner Kallweit 	}
149854744510SHeiner Kallweit }
149925e992a4SHeiner Kallweit 
rtl8169_set_wol(struct net_device * dev,struct ethtool_wolinfo * wol)150025e992a4SHeiner Kallweit static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
150125e992a4SHeiner Kallweit {
150225e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
150325e992a4SHeiner Kallweit 
150425e992a4SHeiner Kallweit 	if (wol->wolopts & ~WAKE_ANY)
150525e992a4SHeiner Kallweit 		return -EINVAL;
150625e992a4SHeiner Kallweit 
150725e992a4SHeiner Kallweit 	tp->saved_wolopts = wol->wolopts;
150825e992a4SHeiner Kallweit 	__rtl8169_set_wol(tp, tp->saved_wolopts);
150925e992a4SHeiner Kallweit 
151025e992a4SHeiner Kallweit 	return 0;
151125e992a4SHeiner Kallweit }
151225e992a4SHeiner Kallweit 
rtl8169_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)151325e992a4SHeiner Kallweit static void rtl8169_get_drvinfo(struct net_device *dev,
151425e992a4SHeiner Kallweit 				struct ethtool_drvinfo *info)
151525e992a4SHeiner Kallweit {
151625e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
151725e992a4SHeiner Kallweit 	struct rtl_fw *rtl_fw = tp->rtl_fw;
151825e992a4SHeiner Kallweit 
1519f029c781SWolfram Sang 	strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
1520f029c781SWolfram Sang 	strscpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
152125e992a4SHeiner Kallweit 	BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
152225e992a4SHeiner Kallweit 	if (rtl_fw)
1523f029c781SWolfram Sang 		strscpy(info->fw_version, rtl_fw->version,
152425e992a4SHeiner Kallweit 			sizeof(info->fw_version));
152525e992a4SHeiner Kallweit }
152625e992a4SHeiner Kallweit 
rtl8169_get_regs_len(struct net_device * dev)152725e992a4SHeiner Kallweit static int rtl8169_get_regs_len(struct net_device *dev)
152825e992a4SHeiner Kallweit {
152925e992a4SHeiner Kallweit 	return R8169_REGS_SIZE;
153025e992a4SHeiner Kallweit }
153125e992a4SHeiner Kallweit 
rtl8169_fix_features(struct net_device * dev,netdev_features_t features)153225e992a4SHeiner Kallweit static netdev_features_t rtl8169_fix_features(struct net_device *dev,
153325e992a4SHeiner Kallweit 	netdev_features_t features)
153425e992a4SHeiner Kallweit {
153525e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
153625e992a4SHeiner Kallweit 
153725e992a4SHeiner Kallweit 	if (dev->mtu > TD_MSS_MAX)
153825e992a4SHeiner Kallweit 		features &= ~NETIF_F_ALL_TSO;
153925e992a4SHeiner Kallweit 
1540a8ec173aSHeiner Kallweit 	if (dev->mtu > ETH_DATA_LEN &&
154125e992a4SHeiner Kallweit 	    tp->mac_version > RTL_GIGA_MAC_VER_06)
15427cb83b21SHeiner Kallweit 		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_ALL_TSO);
154325e992a4SHeiner Kallweit 
154425e992a4SHeiner Kallweit 	return features;
154525e992a4SHeiner Kallweit }
154625e992a4SHeiner Kallweit 
rtl_set_rx_config_features(struct rtl8169_private * tp,netdev_features_t features)154710478283SHeiner Kallweit static void rtl_set_rx_config_features(struct rtl8169_private *tp,
154825e992a4SHeiner Kallweit 				       netdev_features_t features)
154925e992a4SHeiner Kallweit {
155010478283SHeiner Kallweit 	u32 rx_config = RTL_R32(tp, RxConfig);
155125e992a4SHeiner Kallweit 
155225e992a4SHeiner Kallweit 	if (features & NETIF_F_RXALL)
155310478283SHeiner Kallweit 		rx_config |= RX_CONFIG_ACCEPT_ERR_MASK;
155425e992a4SHeiner Kallweit 	else
155510478283SHeiner Kallweit 		rx_config &= ~RX_CONFIG_ACCEPT_ERR_MASK;
155625e992a4SHeiner Kallweit 
1557f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp)) {
1558f1bce4adSHeiner Kallweit 		if (features & NETIF_F_HW_VLAN_CTAG_RX)
1559f1bce4adSHeiner Kallweit 			rx_config |= RX_VLAN_8125;
1560f1bce4adSHeiner Kallweit 		else
1561f1bce4adSHeiner Kallweit 			rx_config &= ~RX_VLAN_8125;
1562f1bce4adSHeiner Kallweit 	}
1563f1bce4adSHeiner Kallweit 
156425e992a4SHeiner Kallweit 	RTL_W32(tp, RxConfig, rx_config);
156510478283SHeiner Kallweit }
156610478283SHeiner Kallweit 
rtl8169_set_features(struct net_device * dev,netdev_features_t features)156710478283SHeiner Kallweit static int rtl8169_set_features(struct net_device *dev,
156810478283SHeiner Kallweit 				netdev_features_t features)
156910478283SHeiner Kallweit {
157010478283SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
157110478283SHeiner Kallweit 
157210478283SHeiner Kallweit 	rtl_set_rx_config_features(tp, features);
157325e992a4SHeiner Kallweit 
157425e992a4SHeiner Kallweit 	if (features & NETIF_F_RXCSUM)
157525e992a4SHeiner Kallweit 		tp->cp_cmd |= RxChkSum;
157625e992a4SHeiner Kallweit 	else
157725e992a4SHeiner Kallweit 		tp->cp_cmd &= ~RxChkSum;
157825e992a4SHeiner Kallweit 
1579f1bce4adSHeiner Kallweit 	if (!rtl_is_8125(tp)) {
158025e992a4SHeiner Kallweit 		if (features & NETIF_F_HW_VLAN_CTAG_RX)
158125e992a4SHeiner Kallweit 			tp->cp_cmd |= RxVlan;
158225e992a4SHeiner Kallweit 		else
158325e992a4SHeiner Kallweit 			tp->cp_cmd &= ~RxVlan;
1584f1bce4adSHeiner Kallweit 	}
158525e992a4SHeiner Kallweit 
158625e992a4SHeiner Kallweit 	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
1587711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
158825e992a4SHeiner Kallweit 
158925e992a4SHeiner Kallweit 	return 0;
159025e992a4SHeiner Kallweit }
159125e992a4SHeiner Kallweit 
rtl8169_tx_vlan_tag(struct sk_buff * skb)159225e992a4SHeiner Kallweit static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
159325e992a4SHeiner Kallweit {
159425e992a4SHeiner Kallweit 	return (skb_vlan_tag_present(skb)) ?
15957424edbbSHeiner Kallweit 		TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
159625e992a4SHeiner Kallweit }
159725e992a4SHeiner Kallweit 
rtl8169_rx_vlan_tag(struct RxDesc * desc,struct sk_buff * skb)159825e992a4SHeiner Kallweit static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
159925e992a4SHeiner Kallweit {
160025e992a4SHeiner Kallweit 	u32 opts2 = le32_to_cpu(desc->opts2);
160125e992a4SHeiner Kallweit 
160225e992a4SHeiner Kallweit 	if (opts2 & RxVlanTag)
16037424edbbSHeiner Kallweit 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff));
160425e992a4SHeiner Kallweit }
160525e992a4SHeiner Kallweit 
rtl8169_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * p)160625e992a4SHeiner Kallweit static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
160725e992a4SHeiner Kallweit 			     void *p)
160825e992a4SHeiner Kallweit {
160925e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
161025e992a4SHeiner Kallweit 	u32 __iomem *data = tp->mmio_addr;
161125e992a4SHeiner Kallweit 	u32 *dw = p;
161225e992a4SHeiner Kallweit 	int i;
161325e992a4SHeiner Kallweit 
161425e992a4SHeiner Kallweit 	for (i = 0; i < R8169_REGS_SIZE; i += 4)
161525e992a4SHeiner Kallweit 		memcpy_fromio(dw++, data++, 4);
161625e992a4SHeiner Kallweit }
161725e992a4SHeiner Kallweit 
161825e992a4SHeiner Kallweit static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
161925e992a4SHeiner Kallweit 	"tx_packets",
162025e992a4SHeiner Kallweit 	"rx_packets",
162125e992a4SHeiner Kallweit 	"tx_errors",
162225e992a4SHeiner Kallweit 	"rx_errors",
162325e992a4SHeiner Kallweit 	"rx_missed",
162425e992a4SHeiner Kallweit 	"align_errors",
162525e992a4SHeiner Kallweit 	"tx_single_collisions",
162625e992a4SHeiner Kallweit 	"tx_multi_collisions",
162725e992a4SHeiner Kallweit 	"unicast",
162825e992a4SHeiner Kallweit 	"broadcast",
162925e992a4SHeiner Kallweit 	"multicast",
163025e992a4SHeiner Kallweit 	"tx_aborted",
163125e992a4SHeiner Kallweit 	"tx_underrun",
163225e992a4SHeiner Kallweit };
163325e992a4SHeiner Kallweit 
rtl8169_get_sset_count(struct net_device * dev,int sset)163425e992a4SHeiner Kallweit static int rtl8169_get_sset_count(struct net_device *dev, int sset)
163525e992a4SHeiner Kallweit {
163625e992a4SHeiner Kallweit 	switch (sset) {
163725e992a4SHeiner Kallweit 	case ETH_SS_STATS:
163825e992a4SHeiner Kallweit 		return ARRAY_SIZE(rtl8169_gstrings);
163925e992a4SHeiner Kallweit 	default:
164025e992a4SHeiner Kallweit 		return -EOPNOTSUPP;
164125e992a4SHeiner Kallweit 	}
164225e992a4SHeiner Kallweit }
164325e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_counters_cond)164425e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_counters_cond)
164525e992a4SHeiner Kallweit {
164625e992a4SHeiner Kallweit 	return RTL_R32(tp, CounterAddrLow) & (CounterReset | CounterDump);
164725e992a4SHeiner Kallweit }
164825e992a4SHeiner Kallweit 
rtl8169_do_counters(struct rtl8169_private * tp,u32 counter_cmd)1649d56f58ceSHeiner Kallweit static void rtl8169_do_counters(struct rtl8169_private *tp, u32 counter_cmd)
165025e992a4SHeiner Kallweit {
1651b498ee3fSHeiner Kallweit 	u32 cmd = lower_32_bits(tp->counters_phys_addr);
165225e992a4SHeiner Kallweit 
1653b498ee3fSHeiner Kallweit 	RTL_W32(tp, CounterAddrHigh, upper_32_bits(tp->counters_phys_addr));
1654711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
165525e992a4SHeiner Kallweit 	RTL_W32(tp, CounterAddrLow, cmd);
165625e992a4SHeiner Kallweit 	RTL_W32(tp, CounterAddrLow, cmd | counter_cmd);
165725e992a4SHeiner Kallweit 
1658d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_counters_cond, 10, 1000);
165925e992a4SHeiner Kallweit }
166025e992a4SHeiner Kallweit 
rtl8169_update_counters(struct rtl8169_private * tp)1661d56f58ceSHeiner Kallweit static void rtl8169_update_counters(struct rtl8169_private *tp)
166225e992a4SHeiner Kallweit {
166325e992a4SHeiner Kallweit 	u8 val = RTL_R8(tp, ChipCmd);
166425e992a4SHeiner Kallweit 
166525e992a4SHeiner Kallweit 	/*
166625e992a4SHeiner Kallweit 	 * Some chips are unable to dump tally counters when the receiver
166725e992a4SHeiner Kallweit 	 * is disabled. If 0xff chip may be in a PCI power-save state.
166825e992a4SHeiner Kallweit 	 */
1669d56f58ceSHeiner Kallweit 	if (val & CmdRxEnb && val != 0xff)
1670d56f58ceSHeiner Kallweit 		rtl8169_do_counters(tp, CounterDump);
167125e992a4SHeiner Kallweit }
167225e992a4SHeiner Kallweit 
rtl8169_init_counter_offsets(struct rtl8169_private * tp)1673d56f58ceSHeiner Kallweit static void rtl8169_init_counter_offsets(struct rtl8169_private *tp)
167425e992a4SHeiner Kallweit {
167525e992a4SHeiner Kallweit 	struct rtl8169_counters *counters = tp->counters;
167625e992a4SHeiner Kallweit 
167725e992a4SHeiner Kallweit 	/*
167825e992a4SHeiner Kallweit 	 * rtl8169_init_counter_offsets is called from rtl_open.  On chip
167925e992a4SHeiner Kallweit 	 * versions prior to RTL_GIGA_MAC_VER_19 the tally counters are only
168025e992a4SHeiner Kallweit 	 * reset by a power cycle, while the counter values collected by the
168125e992a4SHeiner Kallweit 	 * driver are reset at every driver unload/load cycle.
168225e992a4SHeiner Kallweit 	 *
168325e992a4SHeiner Kallweit 	 * To make sure the HW values returned by @get_stats64 match the SW
168425e992a4SHeiner Kallweit 	 * values, we collect the initial values at first open(*) and use them
168525e992a4SHeiner Kallweit 	 * as offsets to normalize the values returned by @get_stats64.
168625e992a4SHeiner Kallweit 	 *
168725e992a4SHeiner Kallweit 	 * (*) We can't call rtl8169_init_counter_offsets from rtl_init_one
168825e992a4SHeiner Kallweit 	 * for the reason stated in rtl8169_update_counters; CmdRxEnb is only
168925e992a4SHeiner Kallweit 	 * set at open time by rtl_hw_start.
169025e992a4SHeiner Kallweit 	 */
169125e992a4SHeiner Kallweit 
169225e992a4SHeiner Kallweit 	if (tp->tc_offset.inited)
1693d56f58ceSHeiner Kallweit 		return;
169425e992a4SHeiner Kallweit 
16956b4f5031SHeiner Kallweit 	if (tp->mac_version >= RTL_GIGA_MAC_VER_19) {
16966b4f5031SHeiner Kallweit 		rtl8169_do_counters(tp, CounterReset);
16976b4f5031SHeiner Kallweit 	} else {
1698d56f58ceSHeiner Kallweit 		rtl8169_update_counters(tp);
169925e992a4SHeiner Kallweit 		tp->tc_offset.tx_errors = counters->tx_errors;
170025e992a4SHeiner Kallweit 		tp->tc_offset.tx_multi_collision = counters->tx_multi_collision;
170125e992a4SHeiner Kallweit 		tp->tc_offset.tx_aborted = counters->tx_aborted;
17020da3359aSHeiner Kallweit 		tp->tc_offset.rx_missed = counters->rx_missed;
17036b4f5031SHeiner Kallweit 	}
17046b4f5031SHeiner Kallweit 
170525e992a4SHeiner Kallweit 	tp->tc_offset.inited = true;
170625e992a4SHeiner Kallweit }
170725e992a4SHeiner Kallweit 
rtl8169_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)170825e992a4SHeiner Kallweit static void rtl8169_get_ethtool_stats(struct net_device *dev,
170925e992a4SHeiner Kallweit 				      struct ethtool_stats *stats, u64 *data)
171025e992a4SHeiner Kallweit {
171125e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
1712ec2f204bSHeiner Kallweit 	struct rtl8169_counters *counters;
171325e992a4SHeiner Kallweit 
1714ec2f204bSHeiner Kallweit 	counters = tp->counters;
171525e992a4SHeiner Kallweit 	rtl8169_update_counters(tp);
171625e992a4SHeiner Kallweit 
171725e992a4SHeiner Kallweit 	data[0] = le64_to_cpu(counters->tx_packets);
171825e992a4SHeiner Kallweit 	data[1] = le64_to_cpu(counters->rx_packets);
171925e992a4SHeiner Kallweit 	data[2] = le64_to_cpu(counters->tx_errors);
172025e992a4SHeiner Kallweit 	data[3] = le32_to_cpu(counters->rx_errors);
172125e992a4SHeiner Kallweit 	data[4] = le16_to_cpu(counters->rx_missed);
172225e992a4SHeiner Kallweit 	data[5] = le16_to_cpu(counters->align_errors);
172325e992a4SHeiner Kallweit 	data[6] = le32_to_cpu(counters->tx_one_collision);
172425e992a4SHeiner Kallweit 	data[7] = le32_to_cpu(counters->tx_multi_collision);
172525e992a4SHeiner Kallweit 	data[8] = le64_to_cpu(counters->rx_unicast);
172625e992a4SHeiner Kallweit 	data[9] = le64_to_cpu(counters->rx_broadcast);
172725e992a4SHeiner Kallweit 	data[10] = le32_to_cpu(counters->rx_multicast);
172825e992a4SHeiner Kallweit 	data[11] = le16_to_cpu(counters->tx_aborted);
172925e992a4SHeiner Kallweit 	data[12] = le16_to_cpu(counters->tx_underun);
173025e992a4SHeiner Kallweit }
173125e992a4SHeiner Kallweit 
rtl8169_get_strings(struct net_device * dev,u32 stringset,u8 * data)173225e992a4SHeiner Kallweit static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
173325e992a4SHeiner Kallweit {
173425e992a4SHeiner Kallweit 	switch(stringset) {
173525e992a4SHeiner Kallweit 	case ETH_SS_STATS:
1736da5ac772SKees Cook 		memcpy(data, rtl8169_gstrings, sizeof(rtl8169_gstrings));
173725e992a4SHeiner Kallweit 		break;
173825e992a4SHeiner Kallweit 	}
173925e992a4SHeiner Kallweit }
174025e992a4SHeiner Kallweit 
174125e992a4SHeiner Kallweit /*
174225e992a4SHeiner Kallweit  * Interrupt coalescing
174325e992a4SHeiner Kallweit  *
174425e992a4SHeiner Kallweit  * > 1 - the availability of the IntrMitigate (0xe2) register through the
174525e992a4SHeiner Kallweit  * >     8169, 8168 and 810x line of chipsets
174625e992a4SHeiner Kallweit  *
174725e992a4SHeiner Kallweit  * 8169, 8168, and 8136(810x) serial chipsets support it.
174825e992a4SHeiner Kallweit  *
174925e992a4SHeiner Kallweit  * > 2 - the Tx timer unit at gigabit speed
175025e992a4SHeiner Kallweit  *
175125e992a4SHeiner Kallweit  * The unit of the timer depends on both the speed and the setting of CPlusCmd
175225e992a4SHeiner Kallweit  * (0xe0) bit 1 and bit 0.
175325e992a4SHeiner Kallweit  *
175425e992a4SHeiner Kallweit  * For 8169
175525e992a4SHeiner Kallweit  * bit[1:0] \ speed        1000M           100M            10M
175625e992a4SHeiner Kallweit  * 0 0                     320ns           2.56us          40.96us
175725e992a4SHeiner Kallweit  * 0 1                     2.56us          20.48us         327.7us
175825e992a4SHeiner Kallweit  * 1 0                     5.12us          40.96us         655.4us
175925e992a4SHeiner Kallweit  * 1 1                     10.24us         81.92us         1.31ms
176025e992a4SHeiner Kallweit  *
176125e992a4SHeiner Kallweit  * For the other
176225e992a4SHeiner Kallweit  * bit[1:0] \ speed        1000M           100M            10M
176325e992a4SHeiner Kallweit  * 0 0                     5us             2.56us          40.96us
176425e992a4SHeiner Kallweit  * 0 1                     40us            20.48us         327.7us
176525e992a4SHeiner Kallweit  * 1 0                     80us            40.96us         655.4us
176625e992a4SHeiner Kallweit  * 1 1                     160us           81.92us         1.31ms
176725e992a4SHeiner Kallweit  */
176825e992a4SHeiner Kallweit 
176925e992a4SHeiner Kallweit /* rx/tx scale factors for all CPlusCmd[0:1] cases */
177025e992a4SHeiner Kallweit struct rtl_coalesce_info {
177125e992a4SHeiner Kallweit 	u32 speed;
17722815b305SHeiner Kallweit 	u32 scale_nsecs[4];
177325e992a4SHeiner Kallweit };
177425e992a4SHeiner Kallweit 
17752815b305SHeiner Kallweit /* produce array with base delay *1, *8, *8*2, *8*2*2 */
17762815b305SHeiner Kallweit #define COALESCE_DELAY(d) { (d), 8 * (d), 16 * (d), 32 * (d) }
17772815b305SHeiner Kallweit 
177825e992a4SHeiner Kallweit static const struct rtl_coalesce_info rtl_coalesce_info_8169[] = {
17792815b305SHeiner Kallweit 	{ SPEED_1000,	COALESCE_DELAY(320) },
178051f6291bSHeiner Kallweit 	{ SPEED_100,	COALESCE_DELAY(2560) },
178151f6291bSHeiner Kallweit 	{ SPEED_10,	COALESCE_DELAY(40960) },
178225e992a4SHeiner Kallweit 	{ 0 },
178325e992a4SHeiner Kallweit };
178425e992a4SHeiner Kallweit 
178525e992a4SHeiner Kallweit static const struct rtl_coalesce_info rtl_coalesce_info_8168_8136[] = {
17862815b305SHeiner Kallweit 	{ SPEED_1000,	COALESCE_DELAY(5000) },
178751f6291bSHeiner Kallweit 	{ SPEED_100,	COALESCE_DELAY(2560) },
178851f6291bSHeiner Kallweit 	{ SPEED_10,	COALESCE_DELAY(40960) },
178925e992a4SHeiner Kallweit 	{ 0 },
179025e992a4SHeiner Kallweit };
17912815b305SHeiner Kallweit #undef COALESCE_DELAY
179225e992a4SHeiner Kallweit 
179325e992a4SHeiner Kallweit /* get rx/tx scale vector corresponding to current speed */
1794ef2c0a78SHeiner Kallweit static const struct rtl_coalesce_info *
rtl_coalesce_info(struct rtl8169_private * tp)1795ef2c0a78SHeiner Kallweit rtl_coalesce_info(struct rtl8169_private *tp)
179625e992a4SHeiner Kallweit {
179725e992a4SHeiner Kallweit 	const struct rtl_coalesce_info *ci;
179825e992a4SHeiner Kallweit 
179920023d3eSHeiner Kallweit 	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
180020023d3eSHeiner Kallweit 		ci = rtl_coalesce_info_8169;
180120023d3eSHeiner Kallweit 	else
180220023d3eSHeiner Kallweit 		ci = rtl_coalesce_info_8168_8136;
180325e992a4SHeiner Kallweit 
180451f6291bSHeiner Kallweit 	/* if speed is unknown assume highest one */
180551f6291bSHeiner Kallweit 	if (tp->phydev->speed == SPEED_UNKNOWN)
180651f6291bSHeiner Kallweit 		return ci;
180751f6291bSHeiner Kallweit 
180820023d3eSHeiner Kallweit 	for (; ci->speed; ci++) {
180920023d3eSHeiner Kallweit 		if (tp->phydev->speed == ci->speed)
181025e992a4SHeiner Kallweit 			return ci;
181125e992a4SHeiner Kallweit 	}
181225e992a4SHeiner Kallweit 
181325e992a4SHeiner Kallweit 	return ERR_PTR(-ELNRNG);
181425e992a4SHeiner Kallweit }
181525e992a4SHeiner Kallweit 
rtl_get_coalesce(struct net_device * dev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1816f3ccfda1SYufeng Mo static int rtl_get_coalesce(struct net_device *dev,
1817f3ccfda1SYufeng Mo 			    struct ethtool_coalesce *ec,
1818f3ccfda1SYufeng Mo 			    struct kernel_ethtool_coalesce *kernel_coal,
1819f3ccfda1SYufeng Mo 			    struct netlink_ext_ack *extack)
182025e992a4SHeiner Kallweit {
182125e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
182225e992a4SHeiner Kallweit 	const struct rtl_coalesce_info *ci;
18236cf96dd4SHeiner Kallweit 	u32 scale, c_us, c_fr;
18246cf96dd4SHeiner Kallweit 	u16 intrmit;
182525e992a4SHeiner Kallweit 
1826f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1827f1bce4adSHeiner Kallweit 		return -EOPNOTSUPP;
1828f1bce4adSHeiner Kallweit 
182925e992a4SHeiner Kallweit 	memset(ec, 0, sizeof(*ec));
183025e992a4SHeiner Kallweit 
183125e992a4SHeiner Kallweit 	/* get rx/tx scale corresponding to current speed and CPlusCmd[0:1] */
1832ef2c0a78SHeiner Kallweit 	ci = rtl_coalesce_info(tp);
183325e992a4SHeiner Kallweit 	if (IS_ERR(ci))
183425e992a4SHeiner Kallweit 		return PTR_ERR(ci);
183525e992a4SHeiner Kallweit 
18362815b305SHeiner Kallweit 	scale = ci->scale_nsecs[tp->cp_cmd & INTT_MASK];
183725e992a4SHeiner Kallweit 
18386cf96dd4SHeiner Kallweit 	intrmit = RTL_R16(tp, IntrMitigate);
183925e992a4SHeiner Kallweit 
18406cf96dd4SHeiner Kallweit 	c_us = FIELD_GET(RTL_COALESCE_TX_USECS, intrmit);
18416cf96dd4SHeiner Kallweit 	ec->tx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);
184225e992a4SHeiner Kallweit 
18436cf96dd4SHeiner Kallweit 	c_fr = FIELD_GET(RTL_COALESCE_TX_FRAMES, intrmit);
18446cf96dd4SHeiner Kallweit 	/* ethtool_coalesce states usecs and max_frames must not both be 0 */
18456cf96dd4SHeiner Kallweit 	ec->tx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;
18466cf96dd4SHeiner Kallweit 
18476cf96dd4SHeiner Kallweit 	c_us = FIELD_GET(RTL_COALESCE_RX_USECS, intrmit);
18486cf96dd4SHeiner Kallweit 	ec->rx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);
18496cf96dd4SHeiner Kallweit 
18506cf96dd4SHeiner Kallweit 	c_fr = FIELD_GET(RTL_COALESCE_RX_FRAMES, intrmit);
18516cf96dd4SHeiner Kallweit 	ec->rx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;
185225e992a4SHeiner Kallweit 
185325e992a4SHeiner Kallweit 	return 0;
185425e992a4SHeiner Kallweit }
185525e992a4SHeiner Kallweit 
1856cb9d97deSHeiner Kallweit /* choose appropriate scale factor and CPlusCmd[0:1] for (speed, usec) */
rtl_coalesce_choose_scale(struct rtl8169_private * tp,u32 usec,u16 * cp01)1857cb9d97deSHeiner Kallweit static int rtl_coalesce_choose_scale(struct rtl8169_private *tp, u32 usec,
18582815b305SHeiner Kallweit 				     u16 *cp01)
185925e992a4SHeiner Kallweit {
186025e992a4SHeiner Kallweit 	const struct rtl_coalesce_info *ci;
186125e992a4SHeiner Kallweit 	u16 i;
186225e992a4SHeiner Kallweit 
1863ef2c0a78SHeiner Kallweit 	ci = rtl_coalesce_info(tp);
186425e992a4SHeiner Kallweit 	if (IS_ERR(ci))
18652815b305SHeiner Kallweit 		return PTR_ERR(ci);
186625e992a4SHeiner Kallweit 
186725e992a4SHeiner Kallweit 	for (i = 0; i < 4; i++) {
1868cb9d97deSHeiner Kallweit 		if (usec <= ci->scale_nsecs[i] * RTL_COALESCE_T_MAX / 1000U) {
186925e992a4SHeiner Kallweit 			*cp01 = i;
18702815b305SHeiner Kallweit 			return ci->scale_nsecs[i];
187125e992a4SHeiner Kallweit 		}
187225e992a4SHeiner Kallweit 	}
187325e992a4SHeiner Kallweit 
1874cb9d97deSHeiner Kallweit 	return -ERANGE;
187525e992a4SHeiner Kallweit }
187625e992a4SHeiner Kallweit 
rtl_set_coalesce(struct net_device * dev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1877f3ccfda1SYufeng Mo static int rtl_set_coalesce(struct net_device *dev,
1878f3ccfda1SYufeng Mo 			    struct ethtool_coalesce *ec,
1879f3ccfda1SYufeng Mo 			    struct kernel_ethtool_coalesce *kernel_coal,
1880f3ccfda1SYufeng Mo 			    struct netlink_ext_ack *extack)
188125e992a4SHeiner Kallweit {
188225e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
18832b3e48b6SHeiner Kallweit 	u32 tx_fr = ec->tx_max_coalesced_frames;
18842b3e48b6SHeiner Kallweit 	u32 rx_fr = ec->rx_max_coalesced_frames;
18852b3e48b6SHeiner Kallweit 	u32 coal_usec_max, units;
18862815b305SHeiner Kallweit 	u16 w = 0, cp01 = 0;
18872b3e48b6SHeiner Kallweit 	int scale;
188825e992a4SHeiner Kallweit 
1889f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
1890f1bce4adSHeiner Kallweit 		return -EOPNOTSUPP;
1891f1bce4adSHeiner Kallweit 
18922b3e48b6SHeiner Kallweit 	if (rx_fr > RTL_COALESCE_FRAME_MAX || tx_fr > RTL_COALESCE_FRAME_MAX)
18932b3e48b6SHeiner Kallweit 		return -ERANGE;
18942b3e48b6SHeiner Kallweit 
1895cb9d97deSHeiner Kallweit 	coal_usec_max = max(ec->rx_coalesce_usecs, ec->tx_coalesce_usecs);
1896cb9d97deSHeiner Kallweit 	scale = rtl_coalesce_choose_scale(tp, coal_usec_max, &cp01);
18972815b305SHeiner Kallweit 	if (scale < 0)
18982815b305SHeiner Kallweit 		return scale;
189925e992a4SHeiner Kallweit 
19002b3e48b6SHeiner Kallweit 	/* Accept max_frames=1 we returned in rtl_get_coalesce. Accept it
19012b3e48b6SHeiner Kallweit 	 * not only when usecs=0 because of e.g. the following scenario:
190225e992a4SHeiner Kallweit 	 *
190325e992a4SHeiner Kallweit 	 * - both rx_usecs=0 & rx_frames=0 in hardware (no delay on RX)
190425e992a4SHeiner Kallweit 	 * - rtl_get_coalesce returns rx_usecs=0, rx_frames=1
190525e992a4SHeiner Kallweit 	 * - then user does `ethtool -C eth0 rx-usecs 100`
190625e992a4SHeiner Kallweit 	 *
19072b3e48b6SHeiner Kallweit 	 * Since ethtool sends to kernel whole ethtool_coalesce settings,
19082b3e48b6SHeiner Kallweit 	 * if we want to ignore rx_frames then it has to be set to 0.
190925e992a4SHeiner Kallweit 	 */
19102b3e48b6SHeiner Kallweit 	if (rx_fr == 1)
19112b3e48b6SHeiner Kallweit 		rx_fr = 0;
19122b3e48b6SHeiner Kallweit 	if (tx_fr == 1)
19132b3e48b6SHeiner Kallweit 		tx_fr = 0;
191425e992a4SHeiner Kallweit 
191581496b72SHeiner Kallweit 	/* HW requires time limit to be set if frame limit is set */
191681496b72SHeiner Kallweit 	if ((tx_fr && !ec->tx_coalesce_usecs) ||
191781496b72SHeiner Kallweit 	    (rx_fr && !ec->rx_coalesce_usecs))
191881496b72SHeiner Kallweit 		return -EINVAL;
191981496b72SHeiner Kallweit 
19202b3e48b6SHeiner Kallweit 	w |= FIELD_PREP(RTL_COALESCE_TX_FRAMES, DIV_ROUND_UP(tx_fr, 4));
19212b3e48b6SHeiner Kallweit 	w |= FIELD_PREP(RTL_COALESCE_RX_FRAMES, DIV_ROUND_UP(rx_fr, 4));
192225e992a4SHeiner Kallweit 
19232b3e48b6SHeiner Kallweit 	units = DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000U, scale);
19242b3e48b6SHeiner Kallweit 	w |= FIELD_PREP(RTL_COALESCE_TX_USECS, units);
19252b3e48b6SHeiner Kallweit 	units = DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000U, scale);
19262b3e48b6SHeiner Kallweit 	w |= FIELD_PREP(RTL_COALESCE_RX_USECS, units);
192725e992a4SHeiner Kallweit 
19282b3e48b6SHeiner Kallweit 	RTL_W16(tp, IntrMitigate, w);
192925e992a4SHeiner Kallweit 
19305cdfe830SHeiner Kallweit 	/* Meaning of PktCntrDisable bit changed from RTL8168e-vl */
19315cdfe830SHeiner Kallweit 	if (rtl_is_8168evl_up(tp)) {
19325cdfe830SHeiner Kallweit 		if (!rx_fr && !tx_fr)
19335cdfe830SHeiner Kallweit 			/* disable packet counter */
19345cdfe830SHeiner Kallweit 			tp->cp_cmd |= PktCntrDisable;
19355cdfe830SHeiner Kallweit 		else
19365cdfe830SHeiner Kallweit 			tp->cp_cmd &= ~PktCntrDisable;
19375cdfe830SHeiner Kallweit 	}
19385cdfe830SHeiner Kallweit 
193925e992a4SHeiner Kallweit 	tp->cp_cmd = (tp->cp_cmd & ~INTT_MASK) | cp01;
194025e992a4SHeiner Kallweit 	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
1941711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
194225e992a4SHeiner Kallweit 
194325e992a4SHeiner Kallweit 	return 0;
194425e992a4SHeiner Kallweit }
194525e992a4SHeiner Kallweit 
rtl8169_get_eee(struct net_device * dev,struct ethtool_eee * data)194625e992a4SHeiner Kallweit static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data)
194725e992a4SHeiner Kallweit {
194825e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
194925e992a4SHeiner Kallweit 
19502e779ddbSHeiner Kallweit 	if (!rtl_supports_eee(tp))
19512e779ddbSHeiner Kallweit 		return -EOPNOTSUPP;
19522e779ddbSHeiner Kallweit 
1953ec2f204bSHeiner Kallweit 	return phy_ethtool_get_eee(tp->phydev, data);
195425e992a4SHeiner Kallweit }
195525e992a4SHeiner Kallweit 
rtl8169_set_eee(struct net_device * dev,struct ethtool_eee * data)195625e992a4SHeiner Kallweit static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data)
195725e992a4SHeiner Kallweit {
195825e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
19592e779ddbSHeiner Kallweit 	int ret;
19602e779ddbSHeiner Kallweit 
19612e779ddbSHeiner Kallweit 	if (!rtl_supports_eee(tp))
19622e779ddbSHeiner Kallweit 		return -EOPNOTSUPP;
196325e992a4SHeiner Kallweit 
19642e779ddbSHeiner Kallweit 	ret = phy_ethtool_set_eee(tp->phydev, data);
19657ec3f872SHeiner Kallweit 
19667ec3f872SHeiner Kallweit 	if (!ret)
19677ec3f872SHeiner Kallweit 		tp->eee_adv = phy_read_mmd(dev->phydev, MDIO_MMD_AN,
19687ec3f872SHeiner Kallweit 					   MDIO_AN_EEE_ADV);
19692e779ddbSHeiner Kallweit 	return ret;
197025e992a4SHeiner Kallweit }
197125e992a4SHeiner Kallweit 
rtl8169_get_ringparam(struct net_device * dev,struct ethtool_ringparam * data,struct kernel_ethtool_ringparam * kernel_data,struct netlink_ext_ack * extack)1972dc4aa50bSHeiner Kallweit static void rtl8169_get_ringparam(struct net_device *dev,
197374624944SHao Chen 				  struct ethtool_ringparam *data,
197474624944SHao Chen 				  struct kernel_ethtool_ringparam *kernel_data,
197574624944SHao Chen 				  struct netlink_ext_ack *extack)
1976dc4aa50bSHeiner Kallweit {
1977dc4aa50bSHeiner Kallweit 	data->rx_max_pending = NUM_RX_DESC;
1978dc4aa50bSHeiner Kallweit 	data->rx_pending = NUM_RX_DESC;
1979dc4aa50bSHeiner Kallweit 	data->tx_max_pending = NUM_TX_DESC;
1980dc4aa50bSHeiner Kallweit 	data->tx_pending = NUM_TX_DESC;
1981dc4aa50bSHeiner Kallweit }
1982dc4aa50bSHeiner Kallweit 
rtl8169_get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * data)1983216f78eaSHeiner Kallweit static void rtl8169_get_pauseparam(struct net_device *dev,
1984216f78eaSHeiner Kallweit 				   struct ethtool_pauseparam *data)
1985216f78eaSHeiner Kallweit {
1986216f78eaSHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
1987216f78eaSHeiner Kallweit 	bool tx_pause, rx_pause;
1988216f78eaSHeiner Kallweit 
1989216f78eaSHeiner Kallweit 	phy_get_pause(tp->phydev, &tx_pause, &rx_pause);
1990216f78eaSHeiner Kallweit 
1991216f78eaSHeiner Kallweit 	data->autoneg = tp->phydev->autoneg;
1992216f78eaSHeiner Kallweit 	data->tx_pause = tx_pause ? 1 : 0;
1993216f78eaSHeiner Kallweit 	data->rx_pause = rx_pause ? 1 : 0;
1994216f78eaSHeiner Kallweit }
1995216f78eaSHeiner Kallweit 
rtl8169_set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * data)1996216f78eaSHeiner Kallweit static int rtl8169_set_pauseparam(struct net_device *dev,
1997216f78eaSHeiner Kallweit 				  struct ethtool_pauseparam *data)
1998216f78eaSHeiner Kallweit {
1999216f78eaSHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
2000216f78eaSHeiner Kallweit 
2001216f78eaSHeiner Kallweit 	if (dev->mtu > ETH_DATA_LEN)
2002216f78eaSHeiner Kallweit 		return -EOPNOTSUPP;
2003216f78eaSHeiner Kallweit 
2004216f78eaSHeiner Kallweit 	phy_set_asym_pause(tp->phydev, data->rx_pause, data->tx_pause);
2005216f78eaSHeiner Kallweit 
2006216f78eaSHeiner Kallweit 	return 0;
2007216f78eaSHeiner Kallweit }
2008216f78eaSHeiner Kallweit 
200925e992a4SHeiner Kallweit static const struct ethtool_ops rtl8169_ethtool_ops = {
2010b604eb31SJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2011b604eb31SJakub Kicinski 				     ETHTOOL_COALESCE_MAX_FRAMES,
201225e992a4SHeiner Kallweit 	.get_drvinfo		= rtl8169_get_drvinfo,
201325e992a4SHeiner Kallweit 	.get_regs_len		= rtl8169_get_regs_len,
201425e992a4SHeiner Kallweit 	.get_link		= ethtool_op_get_link,
201525e992a4SHeiner Kallweit 	.get_coalesce		= rtl_get_coalesce,
201625e992a4SHeiner Kallweit 	.set_coalesce		= rtl_set_coalesce,
201725e992a4SHeiner Kallweit 	.get_regs		= rtl8169_get_regs,
201825e992a4SHeiner Kallweit 	.get_wol		= rtl8169_get_wol,
201925e992a4SHeiner Kallweit 	.set_wol		= rtl8169_set_wol,
202025e992a4SHeiner Kallweit 	.get_strings		= rtl8169_get_strings,
202125e992a4SHeiner Kallweit 	.get_sset_count		= rtl8169_get_sset_count,
202225e992a4SHeiner Kallweit 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
202325e992a4SHeiner Kallweit 	.get_ts_info		= ethtool_op_get_ts_info,
202425e992a4SHeiner Kallweit 	.nway_reset		= phy_ethtool_nway_reset,
202525e992a4SHeiner Kallweit 	.get_eee		= rtl8169_get_eee,
202625e992a4SHeiner Kallweit 	.set_eee		= rtl8169_set_eee,
202725e992a4SHeiner Kallweit 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
202825e992a4SHeiner Kallweit 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
2029dc4aa50bSHeiner Kallweit 	.get_ringparam		= rtl8169_get_ringparam,
2030216f78eaSHeiner Kallweit 	.get_pauseparam		= rtl8169_get_pauseparam,
2031216f78eaSHeiner Kallweit 	.set_pauseparam		= rtl8169_set_pauseparam,
203225e992a4SHeiner Kallweit };
203325e992a4SHeiner Kallweit 
rtl_enable_eee(struct rtl8169_private * tp)203425e992a4SHeiner Kallweit static void rtl_enable_eee(struct rtl8169_private *tp)
203525e992a4SHeiner Kallweit {
20362e779ddbSHeiner Kallweit 	struct phy_device *phydev = tp->phydev;
20377ec3f872SHeiner Kallweit 	int adv;
203825e992a4SHeiner Kallweit 
20397ec3f872SHeiner Kallweit 	/* respect EEE advertisement the user may have set */
20407ec3f872SHeiner Kallweit 	if (tp->eee_adv >= 0)
20417ec3f872SHeiner Kallweit 		adv = tp->eee_adv;
20427ec3f872SHeiner Kallweit 	else
20437ec3f872SHeiner Kallweit 		adv = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
20447ec3f872SHeiner Kallweit 
20457ec3f872SHeiner Kallweit 	if (adv >= 0)
20467ec3f872SHeiner Kallweit 		phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
204725e992a4SHeiner Kallweit }
204825e992a4SHeiner Kallweit 
rtl8169_get_mac_version(u16 xid,bool gmii)2049f1f9ca28SHeiner Kallweit static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
205025e992a4SHeiner Kallweit {
205125e992a4SHeiner Kallweit 	/*
205225e992a4SHeiner Kallweit 	 * The driver currently handles the 8168Bf and the 8168Be identically
205325e992a4SHeiner Kallweit 	 * but they can be identified more specifically through the test below
205425e992a4SHeiner Kallweit 	 * if needed:
205525e992a4SHeiner Kallweit 	 *
205625e992a4SHeiner Kallweit 	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
205725e992a4SHeiner Kallweit 	 *
205825e992a4SHeiner Kallweit 	 * Same thing for the 8101Eb and the 8101Ec:
205925e992a4SHeiner Kallweit 	 *
206025e992a4SHeiner Kallweit 	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
206125e992a4SHeiner Kallweit 	 */
206225e992a4SHeiner Kallweit 	static const struct rtl_mac_info {
206325e992a4SHeiner Kallweit 		u16 mask;
206425e992a4SHeiner Kallweit 		u16 val;
2065f1f9ca28SHeiner Kallweit 		enum mac_version ver;
206625e992a4SHeiner Kallweit 	} mac_info[] = {
20670439297bSHeiner Kallweit 		/* 8125B family. */
20680439297bSHeiner Kallweit 		{ 0x7cf, 0x641,	RTL_GIGA_MAC_VER_63 },
20690439297bSHeiner Kallweit 
20700439297bSHeiner Kallweit 		/* 8125A family. */
20714e9c91cfSHeiner Kallweit 		{ 0x7cf, 0x609,	RTL_GIGA_MAC_VER_61 },
20724e9c91cfSHeiner Kallweit 		/* It seems only XID 609 made it to the mass market.
20734e9c91cfSHeiner Kallweit 		 * { 0x7cf, 0x608,	RTL_GIGA_MAC_VER_60 },
20744e9c91cfSHeiner Kallweit 		 * { 0x7c8, 0x608,	RTL_GIGA_MAC_VER_61 },
20754e9c91cfSHeiner Kallweit 		 */
2076f1bce4adSHeiner Kallweit 
20771287723aSHeiner Kallweit 		/* RTL8117 */
2078e6d6ca6eSKai-Heng Feng 		{ 0x7cf, 0x54b,	RTL_GIGA_MAC_VER_53 },
20791287723aSHeiner Kallweit 		{ 0x7cf, 0x54a,	RTL_GIGA_MAC_VER_52 },
20801287723aSHeiner Kallweit 
208125e992a4SHeiner Kallweit 		/* 8168EP family. */
208225e992a4SHeiner Kallweit 		{ 0x7cf, 0x502,	RTL_GIGA_MAC_VER_51 },
20832d6600c7SHeiner Kallweit 		/* It seems this chip version never made it to
20842d6600c7SHeiner Kallweit 		 * the wild. Let's disable detection.
20852d6600c7SHeiner Kallweit 		 * { 0x7cf, 0x501,      RTL_GIGA_MAC_VER_50 },
20862d6600c7SHeiner Kallweit 		 * { 0x7cf, 0x500,      RTL_GIGA_MAC_VER_49 },
20872d6600c7SHeiner Kallweit 		 */
208825e992a4SHeiner Kallweit 
208925e992a4SHeiner Kallweit 		/* 8168H family. */
209025e992a4SHeiner Kallweit 		{ 0x7cf, 0x541,	RTL_GIGA_MAC_VER_46 },
20916c8a5cf9SHeiner Kallweit 		/* It seems this chip version never made it to
20926c8a5cf9SHeiner Kallweit 		 * the wild. Let's disable detection.
20936c8a5cf9SHeiner Kallweit 		 * { 0x7cf, 0x540,	RTL_GIGA_MAC_VER_45 },
20946c8a5cf9SHeiner Kallweit 		 */
209525e992a4SHeiner Kallweit 
209625e992a4SHeiner Kallweit 		/* 8168G family. */
209725e992a4SHeiner Kallweit 		{ 0x7cf, 0x5c8,	RTL_GIGA_MAC_VER_44 },
209825e992a4SHeiner Kallweit 		{ 0x7cf, 0x509,	RTL_GIGA_MAC_VER_42 },
2099364ef1f3SHeiner Kallweit 		/* It seems this chip version never made it to
2100364ef1f3SHeiner Kallweit 		 * the wild. Let's disable detection.
2101364ef1f3SHeiner Kallweit 		 * { 0x7cf, 0x4c1,	RTL_GIGA_MAC_VER_41 },
2102364ef1f3SHeiner Kallweit 		 */
210325e992a4SHeiner Kallweit 		{ 0x7cf, 0x4c0,	RTL_GIGA_MAC_VER_40 },
210425e992a4SHeiner Kallweit 
210525e992a4SHeiner Kallweit 		/* 8168F family. */
210625e992a4SHeiner Kallweit 		{ 0x7c8, 0x488,	RTL_GIGA_MAC_VER_38 },
21072ea26b4dSHeiner Kallweit 		{ 0x7cf, 0x481,	RTL_GIGA_MAC_VER_36 },
210825e992a4SHeiner Kallweit 		{ 0x7cf, 0x480,	RTL_GIGA_MAC_VER_35 },
210925e992a4SHeiner Kallweit 
211025e992a4SHeiner Kallweit 		/* 8168E family. */
211125e992a4SHeiner Kallweit 		{ 0x7c8, 0x2c8,	RTL_GIGA_MAC_VER_34 },
211225e992a4SHeiner Kallweit 		{ 0x7cf, 0x2c1,	RTL_GIGA_MAC_VER_32 },
211325e992a4SHeiner Kallweit 		{ 0x7c8, 0x2c0,	RTL_GIGA_MAC_VER_33 },
211425e992a4SHeiner Kallweit 
211525e992a4SHeiner Kallweit 		/* 8168D family. */
211625e992a4SHeiner Kallweit 		{ 0x7cf, 0x281,	RTL_GIGA_MAC_VER_25 },
211725e992a4SHeiner Kallweit 		{ 0x7c8, 0x280,	RTL_GIGA_MAC_VER_26 },
211825e992a4SHeiner Kallweit 
211925e992a4SHeiner Kallweit 		/* 8168DP family. */
2120beb401ecSHeiner Kallweit 		/* It seems this early RTL8168dp version never made it to
212101649011SHeiner Kallweit 		 * the wild. Support has been removed.
2122beb401ecSHeiner Kallweit 		 * { 0x7cf, 0x288,      RTL_GIGA_MAC_VER_27 },
2123beb401ecSHeiner Kallweit 		 */
212425e992a4SHeiner Kallweit 		{ 0x7cf, 0x28a,	RTL_GIGA_MAC_VER_28 },
212525e992a4SHeiner Kallweit 		{ 0x7cf, 0x28b,	RTL_GIGA_MAC_VER_31 },
212625e992a4SHeiner Kallweit 
212725e992a4SHeiner Kallweit 		/* 8168C family. */
212825e992a4SHeiner Kallweit 		{ 0x7cf, 0x3c9,	RTL_GIGA_MAC_VER_23 },
212925e992a4SHeiner Kallweit 		{ 0x7cf, 0x3c8,	RTL_GIGA_MAC_VER_18 },
213025e992a4SHeiner Kallweit 		{ 0x7c8, 0x3c8,	RTL_GIGA_MAC_VER_24 },
213125e992a4SHeiner Kallweit 		{ 0x7cf, 0x3c0,	RTL_GIGA_MAC_VER_19 },
213225e992a4SHeiner Kallweit 		{ 0x7cf, 0x3c2,	RTL_GIGA_MAC_VER_20 },
213325e992a4SHeiner Kallweit 		{ 0x7cf, 0x3c3,	RTL_GIGA_MAC_VER_21 },
213425e992a4SHeiner Kallweit 		{ 0x7c8, 0x3c0,	RTL_GIGA_MAC_VER_22 },
213525e992a4SHeiner Kallweit 
213625e992a4SHeiner Kallweit 		/* 8168B family. */
213725e992a4SHeiner Kallweit 		{ 0x7c8, 0x380,	RTL_GIGA_MAC_VER_17 },
213825e992a4SHeiner Kallweit 		{ 0x7c8, 0x300,	RTL_GIGA_MAC_VER_11 },
213925e992a4SHeiner Kallweit 
214025e992a4SHeiner Kallweit 		/* 8101 family. */
214125e992a4SHeiner Kallweit 		{ 0x7c8, 0x448,	RTL_GIGA_MAC_VER_39 },
214225e992a4SHeiner Kallweit 		{ 0x7c8, 0x440,	RTL_GIGA_MAC_VER_37 },
214325e992a4SHeiner Kallweit 		{ 0x7cf, 0x409,	RTL_GIGA_MAC_VER_29 },
214425e992a4SHeiner Kallweit 		{ 0x7c8, 0x408,	RTL_GIGA_MAC_VER_30 },
214525e992a4SHeiner Kallweit 		{ 0x7cf, 0x349,	RTL_GIGA_MAC_VER_08 },
214625e992a4SHeiner Kallweit 		{ 0x7cf, 0x249,	RTL_GIGA_MAC_VER_08 },
214725e992a4SHeiner Kallweit 		{ 0x7cf, 0x348,	RTL_GIGA_MAC_VER_07 },
214825e992a4SHeiner Kallweit 		{ 0x7cf, 0x248,	RTL_GIGA_MAC_VER_07 },
2149cdafdc29SHeiner Kallweit 		{ 0x7cf, 0x240,	RTL_GIGA_MAC_VER_14 },
215025e992a4SHeiner Kallweit 		{ 0x7c8, 0x348,	RTL_GIGA_MAC_VER_09 },
215125e992a4SHeiner Kallweit 		{ 0x7c8, 0x248,	RTL_GIGA_MAC_VER_09 },
2152e66d6586SHeiner Kallweit 		{ 0x7c8, 0x340,	RTL_GIGA_MAC_VER_10 },
215325e992a4SHeiner Kallweit 
215425e992a4SHeiner Kallweit 		/* 8110 family. */
215525e992a4SHeiner Kallweit 		{ 0xfc8, 0x980,	RTL_GIGA_MAC_VER_06 },
215625e992a4SHeiner Kallweit 		{ 0xfc8, 0x180,	RTL_GIGA_MAC_VER_05 },
215725e992a4SHeiner Kallweit 		{ 0xfc8, 0x100,	RTL_GIGA_MAC_VER_04 },
215825e992a4SHeiner Kallweit 		{ 0xfc8, 0x040,	RTL_GIGA_MAC_VER_03 },
215925e992a4SHeiner Kallweit 		{ 0xfc8, 0x008,	RTL_GIGA_MAC_VER_02 },
216025e992a4SHeiner Kallweit 
216125e992a4SHeiner Kallweit 		/* Catch-all */
216225e992a4SHeiner Kallweit 		{ 0x000, 0x000,	RTL_GIGA_MAC_NONE   }
216325e992a4SHeiner Kallweit 	};
216425e992a4SHeiner Kallweit 	const struct rtl_mac_info *p = mac_info;
2165f1f9ca28SHeiner Kallweit 	enum mac_version ver;
216625e992a4SHeiner Kallweit 
2167f1f9ca28SHeiner Kallweit 	while ((xid & p->mask) != p->val)
216825e992a4SHeiner Kallweit 		p++;
2169f1f9ca28SHeiner Kallweit 	ver = p->ver;
217025e992a4SHeiner Kallweit 
2171f1f9ca28SHeiner Kallweit 	if (ver != RTL_GIGA_MAC_NONE && !gmii) {
2172f1f9ca28SHeiner Kallweit 		if (ver == RTL_GIGA_MAC_VER_42)
2173f1f9ca28SHeiner Kallweit 			ver = RTL_GIGA_MAC_VER_43;
2174f1f9ca28SHeiner Kallweit 		else if (ver == RTL_GIGA_MAC_VER_46)
2175f1f9ca28SHeiner Kallweit 			ver = RTL_GIGA_MAC_VER_48;
217625e992a4SHeiner Kallweit 	}
2177f1f9ca28SHeiner Kallweit 
2178f1f9ca28SHeiner Kallweit 	return ver;
217925e992a4SHeiner Kallweit }
218025e992a4SHeiner Kallweit 
rtl_release_firmware(struct rtl8169_private * tp)218125e992a4SHeiner Kallweit static void rtl_release_firmware(struct rtl8169_private *tp)
218225e992a4SHeiner Kallweit {
218325e992a4SHeiner Kallweit 	if (tp->rtl_fw) {
218425e992a4SHeiner Kallweit 		rtl_fw_release_firmware(tp->rtl_fw);
218525e992a4SHeiner Kallweit 		kfree(tp->rtl_fw);
218625e992a4SHeiner Kallweit 		tp->rtl_fw = NULL;
218725e992a4SHeiner Kallweit 	}
218825e992a4SHeiner Kallweit }
218925e992a4SHeiner Kallweit 
r8169_apply_firmware(struct rtl8169_private * tp)21902992bdfaSHeiner Kallweit void r8169_apply_firmware(struct rtl8169_private *tp)
219125e992a4SHeiner Kallweit {
219247dda786SHeiner Kallweit 	int val;
219347dda786SHeiner Kallweit 
219425e992a4SHeiner Kallweit 	/* TODO: release firmware if rtl_fw_write_firmware signals failure. */
219589fbd26cSHeiner Kallweit 	if (tp->rtl_fw) {
219625e992a4SHeiner Kallweit 		rtl_fw_write_firmware(tp, tp->rtl_fw);
219789fbd26cSHeiner Kallweit 		/* At least one firmware doesn't reset tp->ocp_base. */
219889fbd26cSHeiner Kallweit 		tp->ocp_base = OCP_STD_PHY_BASE;
219947dda786SHeiner Kallweit 
220047dda786SHeiner Kallweit 		/* PHY soft reset may still be in progress */
220147dda786SHeiner Kallweit 		phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
220247dda786SHeiner Kallweit 				      !(val & BMCR_RESET),
220347dda786SHeiner Kallweit 				      50000, 600000, true);
220489fbd26cSHeiner Kallweit 	}
220525e992a4SHeiner Kallweit }
220625e992a4SHeiner Kallweit 
rtl8168_config_eee_mac(struct rtl8169_private * tp)220725e992a4SHeiner Kallweit static void rtl8168_config_eee_mac(struct rtl8169_private *tp)
220825e992a4SHeiner Kallweit {
220925e992a4SHeiner Kallweit 	/* Adjust EEE LED frequency */
221025e992a4SHeiner Kallweit 	if (tp->mac_version != RTL_GIGA_MAC_VER_38)
221125e992a4SHeiner Kallweit 		RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
221225e992a4SHeiner Kallweit 
221354113dedSHeiner Kallweit 	rtl_eri_set_bits(tp, 0x1b0, 0x0003);
221425e992a4SHeiner Kallweit }
221525e992a4SHeiner Kallweit 
rtl8125a_config_eee_mac(struct rtl8169_private * tp)22164640338cSHeiner Kallweit static void rtl8125a_config_eee_mac(struct rtl8169_private *tp)
2217b3a42e3aSHeiner Kallweit {
2218b3a42e3aSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
2219b3a42e3aSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1));
2220b3a42e3aSHeiner Kallweit }
2221b3a42e3aSHeiner Kallweit 
rtl8125_set_eee_txidle_timer(struct rtl8169_private * tp)22220439297bSHeiner Kallweit static void rtl8125_set_eee_txidle_timer(struct rtl8169_private *tp)
22230439297bSHeiner Kallweit {
22240439297bSHeiner Kallweit 	RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->dev->mtu + ETH_HLEN + 0x20);
22250439297bSHeiner Kallweit }
22260439297bSHeiner Kallweit 
rtl8125b_config_eee_mac(struct rtl8169_private * tp)22270439297bSHeiner Kallweit static void rtl8125b_config_eee_mac(struct rtl8169_private *tp)
22280439297bSHeiner Kallweit {
22290439297bSHeiner Kallweit 	rtl8125_set_eee_txidle_timer(tp);
22300439297bSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
22310439297bSHeiner Kallweit }
22320439297bSHeiner Kallweit 
rtl_rar_exgmac_set(struct rtl8169_private * tp,const u8 * addr)2233ae1e82c6SHeiner Kallweit static void rtl_rar_exgmac_set(struct rtl8169_private *tp, const u8 *addr)
223425e992a4SHeiner Kallweit {
2235ae1e82c6SHeiner Kallweit 	rtl_eri_write(tp, 0xe0, ERIAR_MASK_1111, get_unaligned_le32(addr));
2236ae1e82c6SHeiner Kallweit 	rtl_eri_write(tp, 0xe4, ERIAR_MASK_1111, get_unaligned_le16(addr + 4));
2237ae1e82c6SHeiner Kallweit 	rtl_eri_write(tp, 0xf0, ERIAR_MASK_1111, get_unaligned_le16(addr) << 16);
2238ae1e82c6SHeiner Kallweit 	rtl_eri_write(tp, 0xf4, ERIAR_MASK_1111, get_unaligned_le32(addr + 2));
223925e992a4SHeiner Kallweit }
224025e992a4SHeiner Kallweit 
rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private * tp)22412992bdfaSHeiner Kallweit u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp)
22423127f7c9SHeiner Kallweit {
22433127f7c9SHeiner Kallweit 	u16 data1, data2, ioffset;
22443127f7c9SHeiner Kallweit 
22453127f7c9SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
22463127f7c9SHeiner Kallweit 	data1 = r8168_mac_ocp_read(tp, 0xdd02);
22473127f7c9SHeiner Kallweit 	data2 = r8168_mac_ocp_read(tp, 0xdd00);
22483127f7c9SHeiner Kallweit 
22493127f7c9SHeiner Kallweit 	ioffset = (data2 >> 1) & 0x7ff8;
22503127f7c9SHeiner Kallweit 	ioffset |= data2 & 0x0007;
22513127f7c9SHeiner Kallweit 	if (data1 & BIT(7))
22523127f7c9SHeiner Kallweit 		ioffset |= BIT(15);
22533127f7c9SHeiner Kallweit 
22543127f7c9SHeiner Kallweit 	return ioffset;
22553127f7c9SHeiner Kallweit }
22563127f7c9SHeiner Kallweit 
rtl_schedule_task(struct rtl8169_private * tp,enum rtl_flag flag)225725e992a4SHeiner Kallweit static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
225825e992a4SHeiner Kallweit {
22593f6ca6c7SHeiner Kallweit 	set_bit(flag, tp->wk.flags);
226025e992a4SHeiner Kallweit 	schedule_work(&tp->wk.work);
226125e992a4SHeiner Kallweit }
226225e992a4SHeiner Kallweit 
rtl8169_init_phy(struct rtl8169_private * tp)2263b5aed0b3SHeiner Kallweit static void rtl8169_init_phy(struct rtl8169_private *tp)
226425e992a4SHeiner Kallweit {
2265becd837eSHeiner Kallweit 	r8169_hw_phy_config(tp, tp->phydev, tp->mac_version);
226625e992a4SHeiner Kallweit 
226725e992a4SHeiner Kallweit 	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
226825e992a4SHeiner Kallweit 		pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
226925e992a4SHeiner Kallweit 		pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
2270b5aed0b3SHeiner Kallweit 		/* set undocumented MAC Reg C+CR Offset 0x82h */
227125e992a4SHeiner Kallweit 		RTL_W8(tp, 0x82, 0x01);
227225e992a4SHeiner Kallweit 	}
227325e992a4SHeiner Kallweit 
2274fc712387SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_05 &&
2275fc712387SHeiner Kallweit 	    tp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_GIGABYTE &&
2276fc712387SHeiner Kallweit 	    tp->pci_dev->subsystem_device == 0xe000)
2277fc712387SHeiner Kallweit 		phy_write_paged(tp->phydev, 0x0001, 0x10, 0xf01b);
2278fc712387SHeiner Kallweit 
227925e992a4SHeiner Kallweit 	/* We may have called phy_speed_down before */
228025e992a4SHeiner Kallweit 	phy_speed_up(tp->phydev);
228125e992a4SHeiner Kallweit 
2282af779778SHeiner Kallweit 	if (rtl_supports_eee(tp))
2283af779778SHeiner Kallweit 		rtl_enable_eee(tp);
2284af779778SHeiner Kallweit 
228525e992a4SHeiner Kallweit 	genphy_soft_reset(tp->phydev);
228625e992a4SHeiner Kallweit }
228725e992a4SHeiner Kallweit 
rtl_rar_set(struct rtl8169_private * tp,const u8 * addr)2288ae1e82c6SHeiner Kallweit static void rtl_rar_set(struct rtl8169_private *tp, const u8 *addr)
228925e992a4SHeiner Kallweit {
229025e992a4SHeiner Kallweit 	rtl_unlock_config_regs(tp);
229125e992a4SHeiner Kallweit 
2292ae1e82c6SHeiner Kallweit 	RTL_W32(tp, MAC4, get_unaligned_le16(addr + 4));
2293711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
229425e992a4SHeiner Kallweit 
2295ae1e82c6SHeiner Kallweit 	RTL_W32(tp, MAC0, get_unaligned_le32(addr));
2296711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
229725e992a4SHeiner Kallweit 
229825e992a4SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_34)
229925e992a4SHeiner Kallweit 		rtl_rar_exgmac_set(tp, addr);
230025e992a4SHeiner Kallweit 
230125e992a4SHeiner Kallweit 	rtl_lock_config_regs(tp);
230225e992a4SHeiner Kallweit }
230325e992a4SHeiner Kallweit 
rtl_set_mac_address(struct net_device * dev,void * p)230425e992a4SHeiner Kallweit static int rtl_set_mac_address(struct net_device *dev, void *p)
230525e992a4SHeiner Kallweit {
230625e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
230725e992a4SHeiner Kallweit 	int ret;
230825e992a4SHeiner Kallweit 
230925e992a4SHeiner Kallweit 	ret = eth_mac_addr(dev, p);
231025e992a4SHeiner Kallweit 	if (ret)
231125e992a4SHeiner Kallweit 		return ret;
231225e992a4SHeiner Kallweit 
231325e992a4SHeiner Kallweit 	rtl_rar_set(tp, dev->dev_addr);
231425e992a4SHeiner Kallweit 
231525e992a4SHeiner Kallweit 	return 0;
231625e992a4SHeiner Kallweit }
231725e992a4SHeiner Kallweit 
rtl_init_rxcfg(struct rtl8169_private * tp)231825e992a4SHeiner Kallweit static void rtl_init_rxcfg(struct rtl8169_private *tp)
231925e992a4SHeiner Kallweit {
232025e992a4SHeiner Kallweit 	switch (tp->mac_version) {
232125e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
232225e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_10 ... RTL_GIGA_MAC_VER_17:
232325e992a4SHeiner Kallweit 		RTL_W32(tp, RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
232425e992a4SHeiner Kallweit 		break;
232525e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24:
232625e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36:
232725e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_38:
232825e992a4SHeiner Kallweit 		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
232925e992a4SHeiner Kallweit 		break;
2330e6d6ca6eSKai-Heng Feng 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
233125e992a4SHeiner Kallweit 		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
233225e992a4SHeiner Kallweit 		break;
23332e04cfddSChunHao Lin 	case RTL_GIGA_MAC_VER_61:
233410478283SHeiner Kallweit 		RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
2335f1bce4adSHeiner Kallweit 		break;
23362e04cfddSChunHao Lin 	case RTL_GIGA_MAC_VER_63:
23372e04cfddSChunHao Lin 		RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
23382e04cfddSChunHao Lin 			RX_PAUSE_SLOT_ON);
23392e04cfddSChunHao Lin 		break;
234025e992a4SHeiner Kallweit 	default:
234125e992a4SHeiner Kallweit 		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_DMA_BURST);
234225e992a4SHeiner Kallweit 		break;
234325e992a4SHeiner Kallweit 	}
234425e992a4SHeiner Kallweit }
234525e992a4SHeiner Kallweit 
rtl8169_init_ring_indexes(struct rtl8169_private * tp)234625e992a4SHeiner Kallweit static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
234725e992a4SHeiner Kallweit {
234825e992a4SHeiner Kallweit 	tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
234925e992a4SHeiner Kallweit }
235025e992a4SHeiner Kallweit 
r8168c_hw_jumbo_enable(struct rtl8169_private * tp)235125e992a4SHeiner Kallweit static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
235225e992a4SHeiner Kallweit {
235325e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
235425e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1);
235525e992a4SHeiner Kallweit }
235625e992a4SHeiner Kallweit 
r8168c_hw_jumbo_disable(struct rtl8169_private * tp)235725e992a4SHeiner Kallweit static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
235825e992a4SHeiner Kallweit {
235925e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
236025e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1);
236125e992a4SHeiner Kallweit }
236225e992a4SHeiner Kallweit 
r8168dp_hw_jumbo_enable(struct rtl8169_private * tp)236325e992a4SHeiner Kallweit static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
236425e992a4SHeiner Kallweit {
236525e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
236625e992a4SHeiner Kallweit }
236725e992a4SHeiner Kallweit 
r8168dp_hw_jumbo_disable(struct rtl8169_private * tp)236825e992a4SHeiner Kallweit static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
236925e992a4SHeiner Kallweit {
237025e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
237125e992a4SHeiner Kallweit }
237225e992a4SHeiner Kallweit 
r8168e_hw_jumbo_enable(struct rtl8169_private * tp)237325e992a4SHeiner Kallweit static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
237425e992a4SHeiner Kallweit {
23756cf73913SHeiner Kallweit 	RTL_W8(tp, MaxTxPacketSize, 0x24);
237625e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
237725e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01);
237825e992a4SHeiner Kallweit }
237925e992a4SHeiner Kallweit 
r8168e_hw_jumbo_disable(struct rtl8169_private * tp)238025e992a4SHeiner Kallweit static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
238125e992a4SHeiner Kallweit {
23826cf73913SHeiner Kallweit 	RTL_W8(tp, MaxTxPacketSize, 0x3f);
238325e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
238425e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01);
238525e992a4SHeiner Kallweit }
238625e992a4SHeiner Kallweit 
r8168b_1_hw_jumbo_enable(struct rtl8169_private * tp)238725e992a4SHeiner Kallweit static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
238825e992a4SHeiner Kallweit {
238925e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0));
239025e992a4SHeiner Kallweit }
239125e992a4SHeiner Kallweit 
r8168b_1_hw_jumbo_disable(struct rtl8169_private * tp)239225e992a4SHeiner Kallweit static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
239325e992a4SHeiner Kallweit {
239425e992a4SHeiner Kallweit 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0));
239525e992a4SHeiner Kallweit }
239625e992a4SHeiner Kallweit 
rtl_jumbo_config(struct rtl8169_private * tp)23979db0ac57SHeiner Kallweit static void rtl_jumbo_config(struct rtl8169_private *tp)
239825e992a4SHeiner Kallweit {
23999db0ac57SHeiner Kallweit 	bool jumbo = tp->dev->mtu > ETH_DATA_LEN;
24005e00e16cSHeiner Kallweit 	int readrq = 4096;
24019db0ac57SHeiner Kallweit 
240225e992a4SHeiner Kallweit 	rtl_unlock_config_regs(tp);
240325e992a4SHeiner Kallweit 	switch (tp->mac_version) {
240425e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_17:
24059db0ac57SHeiner Kallweit 		if (jumbo) {
24065e00e16cSHeiner Kallweit 			readrq = 512;
240725e992a4SHeiner Kallweit 			r8168b_1_hw_jumbo_enable(tp);
24089db0ac57SHeiner Kallweit 		} else {
24099db0ac57SHeiner Kallweit 			r8168b_1_hw_jumbo_disable(tp);
24109db0ac57SHeiner Kallweit 		}
241125e992a4SHeiner Kallweit 		break;
241225e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:
24139db0ac57SHeiner Kallweit 		if (jumbo) {
24145e00e16cSHeiner Kallweit 			readrq = 512;
241525e992a4SHeiner Kallweit 			r8168c_hw_jumbo_enable(tp);
24169db0ac57SHeiner Kallweit 		} else {
241725e992a4SHeiner Kallweit 			r8168c_hw_jumbo_disable(tp);
24189db0ac57SHeiner Kallweit 		}
241925e992a4SHeiner Kallweit 		break;
242001649011SHeiner Kallweit 	case RTL_GIGA_MAC_VER_28:
24219db0ac57SHeiner Kallweit 		if (jumbo)
24229db0ac57SHeiner Kallweit 			r8168dp_hw_jumbo_enable(tp);
24239db0ac57SHeiner Kallweit 		else
242425e992a4SHeiner Kallweit 			r8168dp_hw_jumbo_disable(tp);
242525e992a4SHeiner Kallweit 		break;
24260fc75219SHeiner Kallweit 	case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_33:
24272007317eSHeiner Kallweit 		if (jumbo)
24289db0ac57SHeiner Kallweit 			r8168e_hw_jumbo_enable(tp);
24292007317eSHeiner Kallweit 		else
243025e992a4SHeiner Kallweit 			r8168e_hw_jumbo_disable(tp);
243125e992a4SHeiner Kallweit 		break;
243225e992a4SHeiner Kallweit 	default:
243325e992a4SHeiner Kallweit 		break;
243425e992a4SHeiner Kallweit 	}
243525e992a4SHeiner Kallweit 	rtl_lock_config_regs(tp);
243621b5f672SHeiner Kallweit 
24375e00e16cSHeiner Kallweit 	if (pci_is_pcie(tp->pci_dev) && tp->supports_gmii)
24385e00e16cSHeiner Kallweit 		pcie_set_readrq(tp->pci_dev, readrq);
2439453a7789SHeiner Kallweit 
2440453a7789SHeiner Kallweit 	/* Chip doesn't support pause in jumbo mode */
244111ac4e66SHeiner Kallweit 	if (jumbo) {
244211ac4e66SHeiner Kallweit 		linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
244311ac4e66SHeiner Kallweit 				   tp->phydev->advertising);
244411ac4e66SHeiner Kallweit 		linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
244511ac4e66SHeiner Kallweit 				   tp->phydev->advertising);
2446453a7789SHeiner Kallweit 		phy_start_aneg(tp->phydev);
244725e992a4SHeiner Kallweit 	}
244811ac4e66SHeiner Kallweit }
244925e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_chipcmd_cond)245025e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_chipcmd_cond)
245125e992a4SHeiner Kallweit {
245225e992a4SHeiner Kallweit 	return RTL_R8(tp, ChipCmd) & CmdReset;
245325e992a4SHeiner Kallweit }
245425e992a4SHeiner Kallweit 
rtl_hw_reset(struct rtl8169_private * tp)245525e992a4SHeiner Kallweit static void rtl_hw_reset(struct rtl8169_private *tp)
245625e992a4SHeiner Kallweit {
245725e992a4SHeiner Kallweit 	RTL_W8(tp, ChipCmd, CmdReset);
245825e992a4SHeiner Kallweit 
2459d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
246025e992a4SHeiner Kallweit }
246125e992a4SHeiner Kallweit 
rtl_request_firmware(struct rtl8169_private * tp)246225e992a4SHeiner Kallweit static void rtl_request_firmware(struct rtl8169_private *tp)
246325e992a4SHeiner Kallweit {
246425e992a4SHeiner Kallweit 	struct rtl_fw *rtl_fw;
246525e992a4SHeiner Kallweit 
246625e992a4SHeiner Kallweit 	/* firmware loaded already or no firmware available */
246725e992a4SHeiner Kallweit 	if (tp->rtl_fw || !tp->fw_name)
246825e992a4SHeiner Kallweit 		return;
246925e992a4SHeiner Kallweit 
247025e992a4SHeiner Kallweit 	rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
24713bf6ff3cSHeiner Kallweit 	if (!rtl_fw)
247225e992a4SHeiner Kallweit 		return;
247325e992a4SHeiner Kallweit 
247425e992a4SHeiner Kallweit 	rtl_fw->phy_write = rtl_writephy;
247525e992a4SHeiner Kallweit 	rtl_fw->phy_read = rtl_readphy;
247625e992a4SHeiner Kallweit 	rtl_fw->mac_mcu_write = mac_mcu_write;
247725e992a4SHeiner Kallweit 	rtl_fw->mac_mcu_read = mac_mcu_read;
247825e992a4SHeiner Kallweit 	rtl_fw->fw_name = tp->fw_name;
247925e992a4SHeiner Kallweit 	rtl_fw->dev = tp_to_dev(tp);
248025e992a4SHeiner Kallweit 
248125e992a4SHeiner Kallweit 	if (rtl_fw_request_firmware(rtl_fw))
248225e992a4SHeiner Kallweit 		kfree(rtl_fw);
248325e992a4SHeiner Kallweit 	else
248425e992a4SHeiner Kallweit 		tp->rtl_fw = rtl_fw;
248525e992a4SHeiner Kallweit }
248625e992a4SHeiner Kallweit 
rtl_rx_close(struct rtl8169_private * tp)248725e992a4SHeiner Kallweit static void rtl_rx_close(struct rtl8169_private *tp)
248825e992a4SHeiner Kallweit {
248925e992a4SHeiner Kallweit 	RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
249025e992a4SHeiner Kallweit }
249125e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_npq_cond)249225e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_npq_cond)
249325e992a4SHeiner Kallweit {
249425e992a4SHeiner Kallweit 	return RTL_R8(tp, TxPoll) & NPQ;
249525e992a4SHeiner Kallweit }
249625e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_txcfg_empty_cond)249725e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_txcfg_empty_cond)
249825e992a4SHeiner Kallweit {
249925e992a4SHeiner Kallweit 	return RTL_R32(tp, TxConfig) & TXCFG_EMPTY;
250025e992a4SHeiner Kallweit }
250125e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_rxtx_empty_cond)25026f9395c6SHeiner Kallweit DECLARE_RTL_COND(rtl_rxtx_empty_cond)
25036f9395c6SHeiner Kallweit {
25046f9395c6SHeiner Kallweit 	return (RTL_R8(tp, MCU) & RXTX_EMPTY) == RXTX_EMPTY;
25056f9395c6SHeiner Kallweit }
25066f9395c6SHeiner Kallweit 
DECLARE_RTL_COND(rtl_rxtx_empty_cond_2)25070439297bSHeiner Kallweit DECLARE_RTL_COND(rtl_rxtx_empty_cond_2)
25080439297bSHeiner Kallweit {
25090439297bSHeiner Kallweit 	/* IntrMitigate has new functionality on RTL8125 */
25100439297bSHeiner Kallweit 	return (RTL_R16(tp, IntrMitigate) & 0x0103) == 0x0103;
25110439297bSHeiner Kallweit }
25120439297bSHeiner Kallweit 
rtl_wait_txrx_fifo_empty(struct rtl8169_private * tp)25136f9395c6SHeiner Kallweit static void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp)
25146f9395c6SHeiner Kallweit {
25156f9395c6SHeiner Kallweit 	switch (tp->mac_version) {
2516e6d6ca6eSKai-Heng Feng 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
25176f9395c6SHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42);
25186f9395c6SHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25196f9395c6SHeiner Kallweit 		break;
2520efc37109SHeiner Kallweit 	case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
25216f9395c6SHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25226f9395c6SHeiner Kallweit 		break;
25230439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_63:
25240439297bSHeiner Kallweit 		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
25250439297bSHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25260439297bSHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
25270439297bSHeiner Kallweit 		break;
25286f9395c6SHeiner Kallweit 	default:
25296f9395c6SHeiner Kallweit 		break;
25306f9395c6SHeiner Kallweit 	}
25316f9395c6SHeiner Kallweit }
25326f9395c6SHeiner Kallweit 
rtl_disable_rxdvgate(struct rtl8169_private * tp)25333406079bSChunhao Lin static void rtl_disable_rxdvgate(struct rtl8169_private *tp)
25343406079bSChunhao Lin {
25353406079bSChunhao Lin 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
25363406079bSChunhao Lin }
25373406079bSChunhao Lin 
rtl_enable_rxdvgate(struct rtl8169_private * tp)25389617886fSHeiner Kallweit static void rtl_enable_rxdvgate(struct rtl8169_private *tp)
25399617886fSHeiner Kallweit {
25409617886fSHeiner Kallweit 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN);
25419617886fSHeiner Kallweit 	fsleep(2000);
25426f9395c6SHeiner Kallweit 	rtl_wait_txrx_fifo_empty(tp);
25439617886fSHeiner Kallweit }
25449617886fSHeiner Kallweit 
rtl_wol_enable_rx(struct rtl8169_private * tp)2545ad425666SChunhao Lin static void rtl_wol_enable_rx(struct rtl8169_private *tp)
2546ad425666SChunhao Lin {
2547ad425666SChunhao Lin 	if (tp->mac_version >= RTL_GIGA_MAC_VER_25)
2548ad425666SChunhao Lin 		RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) |
2549ad425666SChunhao Lin 			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
2550bb41c13cSChunhao Lin 
2551bb41c13cSChunhao Lin 	if (tp->mac_version >= RTL_GIGA_MAC_VER_40)
2552bb41c13cSChunhao Lin 		rtl_disable_rxdvgate(tp);
2553ad425666SChunhao Lin }
2554ad425666SChunhao Lin 
rtl_prepare_power_down(struct rtl8169_private * tp)2555ad425666SChunhao Lin static void rtl_prepare_power_down(struct rtl8169_private *tp)
2556ad425666SChunhao Lin {
2557c61d525fSChunHao Lin 	if (tp->dash_enabled)
2558ad425666SChunhao Lin 		return;
2559ad425666SChunhao Lin 
2560ad425666SChunhao Lin 	if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
2561ad425666SChunhao Lin 	    tp->mac_version == RTL_GIGA_MAC_VER_33)
2562ad425666SChunhao Lin 		rtl_ephy_write(tp, 0x19, 0xff64);
2563ad425666SChunhao Lin 
2564ad425666SChunhao Lin 	if (device_may_wakeup(tp_to_dev(tp))) {
2565ad425666SChunhao Lin 		phy_speed_down(tp->phydev, false);
2566ad425666SChunhao Lin 		rtl_wol_enable_rx(tp);
2567ad425666SChunhao Lin 	}
2568ad425666SChunhao Lin }
2569ad425666SChunhao Lin 
rtl_set_tx_config_registers(struct rtl8169_private * tp)257025e992a4SHeiner Kallweit static void rtl_set_tx_config_registers(struct rtl8169_private *tp)
257125e992a4SHeiner Kallweit {
257225e992a4SHeiner Kallweit 	u32 val = TX_DMA_BURST << TxDMAShift |
257325e992a4SHeiner Kallweit 		  InterFrameGap << TxInterFrameGapShift;
257425e992a4SHeiner Kallweit 
25759e9f33baSHeiner Kallweit 	if (rtl_is_8168evl_up(tp))
257625e992a4SHeiner Kallweit 		val |= TXCFG_AUTO_FIFO;
257725e992a4SHeiner Kallweit 
257825e992a4SHeiner Kallweit 	RTL_W32(tp, TxConfig, val);
257925e992a4SHeiner Kallweit }
258025e992a4SHeiner Kallweit 
rtl_set_rx_max_size(struct rtl8169_private * tp)258125e992a4SHeiner Kallweit static void rtl_set_rx_max_size(struct rtl8169_private *tp)
258225e992a4SHeiner Kallweit {
258325e992a4SHeiner Kallweit 	/* Low hurts. Let's disable the filtering. */
258425e992a4SHeiner Kallweit 	RTL_W16(tp, RxMaxSize, R8169_RX_BUF_SIZE + 1);
258525e992a4SHeiner Kallweit }
258625e992a4SHeiner Kallweit 
rtl_set_rx_tx_desc_registers(struct rtl8169_private * tp)258725e992a4SHeiner Kallweit static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp)
258825e992a4SHeiner Kallweit {
258925e992a4SHeiner Kallweit 	/*
259025e992a4SHeiner Kallweit 	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
259125e992a4SHeiner Kallweit 	 * register to be written before TxDescAddrLow to work.
259225e992a4SHeiner Kallweit 	 * Switching from MMIO to I/O access fixes the issue as well.
259325e992a4SHeiner Kallweit 	 */
259425e992a4SHeiner Kallweit 	RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
259525e992a4SHeiner Kallweit 	RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
259625e992a4SHeiner Kallweit 	RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
259725e992a4SHeiner Kallweit 	RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
259825e992a4SHeiner Kallweit }
259925e992a4SHeiner Kallweit 
rtl8169_set_magic_reg(struct rtl8169_private * tp)2600ef891284SHeiner Kallweit static void rtl8169_set_magic_reg(struct rtl8169_private *tp)
260125e992a4SHeiner Kallweit {
260225e992a4SHeiner Kallweit 	u32 val;
260325e992a4SHeiner Kallweit 
260425e992a4SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
260525e992a4SHeiner Kallweit 		val = 0x000fff00;
260625e992a4SHeiner Kallweit 	else if (tp->mac_version == RTL_GIGA_MAC_VER_06)
260725e992a4SHeiner Kallweit 		val = 0x00ffff00;
260825e992a4SHeiner Kallweit 	else
260925e992a4SHeiner Kallweit 		return;
261025e992a4SHeiner Kallweit 
261125e992a4SHeiner Kallweit 	if (RTL_R8(tp, Config2) & PCI_Clock_66MHz)
261225e992a4SHeiner Kallweit 		val |= 0xff;
261325e992a4SHeiner Kallweit 
261425e992a4SHeiner Kallweit 	RTL_W32(tp, 0x7c, val);
261525e992a4SHeiner Kallweit }
261625e992a4SHeiner Kallweit 
rtl_set_rx_mode(struct net_device * dev)261725e992a4SHeiner Kallweit static void rtl_set_rx_mode(struct net_device *dev)
261825e992a4SHeiner Kallweit {
261981cd17a4SHeiner Kallweit 	u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
262081cd17a4SHeiner Kallweit 	/* Multicast hash filter */
262181cd17a4SHeiner Kallweit 	u32 mc_filter[2] = { 0xffffffff, 0xffffffff };
262225e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
262381cd17a4SHeiner Kallweit 	u32 tmp;
262425e992a4SHeiner Kallweit 
262525e992a4SHeiner Kallweit 	if (dev->flags & IFF_PROMISC) {
262681cd17a4SHeiner Kallweit 		rx_mode |= AcceptAllPhys;
26271a76fd99SHeiner Kallweit 	} else if (!(dev->flags & IFF_MULTICAST)) {
26281a76fd99SHeiner Kallweit 		rx_mode &= ~AcceptMulticast;
262981cd17a4SHeiner Kallweit 	} else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
263081cd17a4SHeiner Kallweit 		   dev->flags & IFF_ALLMULTI ||
26310c7a3af8SHeiner Kallweit 		   tp->mac_version == RTL_GIGA_MAC_VER_35) {
263281cd17a4SHeiner Kallweit 		/* accept all multicasts */
263381cd17a4SHeiner Kallweit 	} else if (netdev_mc_empty(dev)) {
263481cd17a4SHeiner Kallweit 		rx_mode &= ~AcceptMulticast;
263525e992a4SHeiner Kallweit 	} else {
263625e992a4SHeiner Kallweit 		struct netdev_hw_addr *ha;
263725e992a4SHeiner Kallweit 
263825e992a4SHeiner Kallweit 		mc_filter[1] = mc_filter[0] = 0;
263925e992a4SHeiner Kallweit 		netdev_for_each_mc_addr(ha, dev) {
2640bc54ac36SHeiner Kallweit 			u32 bit_nr = eth_hw_addr_crc(ha) >> 26;
264181cd17a4SHeiner Kallweit 			mc_filter[bit_nr >> 5] |= BIT(bit_nr & 31);
264281cd17a4SHeiner Kallweit 		}
264381cd17a4SHeiner Kallweit 
264481cd17a4SHeiner Kallweit 		if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
264581cd17a4SHeiner Kallweit 			tmp = mc_filter[0];
264681cd17a4SHeiner Kallweit 			mc_filter[0] = swab32(mc_filter[1]);
264781cd17a4SHeiner Kallweit 			mc_filter[1] = swab32(tmp);
264825e992a4SHeiner Kallweit 		}
264925e992a4SHeiner Kallweit 	}
265025e992a4SHeiner Kallweit 
265125e992a4SHeiner Kallweit 	RTL_W32(tp, MAR0 + 4, mc_filter[1]);
265225e992a4SHeiner Kallweit 	RTL_W32(tp, MAR0 + 0, mc_filter[0]);
265325e992a4SHeiner Kallweit 
265481cd17a4SHeiner Kallweit 	tmp = RTL_R32(tp, RxConfig);
265510478283SHeiner Kallweit 	RTL_W32(tp, RxConfig, (tmp & ~RX_CONFIG_ACCEPT_OK_MASK) | rx_mode);
265625e992a4SHeiner Kallweit }
265725e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_csiar_cond)265825e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_csiar_cond)
265925e992a4SHeiner Kallweit {
266025e992a4SHeiner Kallweit 	return RTL_R32(tp, CSIAR) & CSIAR_FLAG;
266125e992a4SHeiner Kallweit }
266225e992a4SHeiner Kallweit 
rtl_csi_write(struct rtl8169_private * tp,int addr,int value)266325e992a4SHeiner Kallweit static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
266425e992a4SHeiner Kallweit {
266525e992a4SHeiner Kallweit 	u32 func = PCI_FUNC(tp->pci_dev->devfn);
266625e992a4SHeiner Kallweit 
266725e992a4SHeiner Kallweit 	RTL_W32(tp, CSIDR, value);
266825e992a4SHeiner Kallweit 	RTL_W32(tp, CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
266925e992a4SHeiner Kallweit 		CSIAR_BYTE_ENABLE | func << 16);
267025e992a4SHeiner Kallweit 
2671d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
267225e992a4SHeiner Kallweit }
267325e992a4SHeiner Kallweit 
rtl_csi_read(struct rtl8169_private * tp,int addr)267425e992a4SHeiner Kallweit static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
267525e992a4SHeiner Kallweit {
267625e992a4SHeiner Kallweit 	u32 func = PCI_FUNC(tp->pci_dev->devfn);
267725e992a4SHeiner Kallweit 
267825e992a4SHeiner Kallweit 	RTL_W32(tp, CSIAR, (addr & CSIAR_ADDR_MASK) | func << 16 |
267925e992a4SHeiner Kallweit 		CSIAR_BYTE_ENABLE);
268025e992a4SHeiner Kallweit 
2681d6836ef0SHeiner Kallweit 	return rtl_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
268225e992a4SHeiner Kallweit 		RTL_R32(tp, CSIDR) : ~0;
268325e992a4SHeiner Kallweit }
268425e992a4SHeiner Kallweit 
rtl_set_aspm_entry_latency(struct rtl8169_private * tp,u8 val)2685c07c8ffcSHeiner Kallweit static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val)
268625e992a4SHeiner Kallweit {
268725e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
268825e992a4SHeiner Kallweit 	u32 csi;
268925e992a4SHeiner Kallweit 
269025e992a4SHeiner Kallweit 	/* According to Realtek the value at config space address 0x070f
269125e992a4SHeiner Kallweit 	 * controls the L0s/L1 entrance latency. We try standard ECAM access
269225e992a4SHeiner Kallweit 	 * first and if it fails fall back to CSI.
2693c07c8ffcSHeiner Kallweit 	 * bit 0..2: L0: 0 = 1us, 1 = 2us .. 6 = 7us, 7 = 7us (no typo)
2694c07c8ffcSHeiner Kallweit 	 * bit 3..5: L1: 0 = 1us, 1 = 2us .. 6 = 64us, 7 = 64us
269525e992a4SHeiner Kallweit 	 */
269625e992a4SHeiner Kallweit 	if (pdev->cfg_size > 0x070f &&
269725e992a4SHeiner Kallweit 	    pci_write_config_byte(pdev, 0x070f, val) == PCIBIOS_SUCCESSFUL)
269825e992a4SHeiner Kallweit 		return;
269925e992a4SHeiner Kallweit 
270025e992a4SHeiner Kallweit 	netdev_notice_once(tp->dev,
270125e992a4SHeiner Kallweit 		"No native access to PCI extended config space, falling back to CSI\n");
270225e992a4SHeiner Kallweit 	csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
270325e992a4SHeiner Kallweit 	rtl_csi_write(tp, 0x070c, csi | val << 24);
270425e992a4SHeiner Kallweit }
270525e992a4SHeiner Kallweit 
rtl_set_def_aspm_entry_latency(struct rtl8169_private * tp)270625e992a4SHeiner Kallweit static void rtl_set_def_aspm_entry_latency(struct rtl8169_private *tp)
270725e992a4SHeiner Kallweit {
2708c07c8ffcSHeiner Kallweit 	/* L0 7us, L1 16us */
2709c07c8ffcSHeiner Kallweit 	rtl_set_aspm_entry_latency(tp, 0x27);
271025e992a4SHeiner Kallweit }
271125e992a4SHeiner Kallweit 
271225e992a4SHeiner Kallweit struct ephy_info {
271325e992a4SHeiner Kallweit 	unsigned int offset;
271425e992a4SHeiner Kallweit 	u16 mask;
271525e992a4SHeiner Kallweit 	u16 bits;
271625e992a4SHeiner Kallweit };
271725e992a4SHeiner Kallweit 
__rtl_ephy_init(struct rtl8169_private * tp,const struct ephy_info * e,int len)271825e992a4SHeiner Kallweit static void __rtl_ephy_init(struct rtl8169_private *tp,
271925e992a4SHeiner Kallweit 			    const struct ephy_info *e, int len)
272025e992a4SHeiner Kallweit {
272125e992a4SHeiner Kallweit 	u16 w;
272225e992a4SHeiner Kallweit 
272325e992a4SHeiner Kallweit 	while (len-- > 0) {
272425e992a4SHeiner Kallweit 		w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
272525e992a4SHeiner Kallweit 		rtl_ephy_write(tp, e->offset, w);
272625e992a4SHeiner Kallweit 		e++;
272725e992a4SHeiner Kallweit 	}
272825e992a4SHeiner Kallweit }
272925e992a4SHeiner Kallweit 
273025e992a4SHeiner Kallweit #define rtl_ephy_init(tp, a) __rtl_ephy_init(tp, a, ARRAY_SIZE(a))
273125e992a4SHeiner Kallweit 
rtl_disable_clock_request(struct rtl8169_private * tp)273225e992a4SHeiner Kallweit static void rtl_disable_clock_request(struct rtl8169_private *tp)
273325e992a4SHeiner Kallweit {
273425e992a4SHeiner Kallweit 	pcie_capability_clear_word(tp->pci_dev, PCI_EXP_LNKCTL,
273525e992a4SHeiner Kallweit 				   PCI_EXP_LNKCTL_CLKREQ_EN);
273625e992a4SHeiner Kallweit }
273725e992a4SHeiner Kallweit 
rtl_enable_clock_request(struct rtl8169_private * tp)273825e992a4SHeiner Kallweit static void rtl_enable_clock_request(struct rtl8169_private *tp)
273925e992a4SHeiner Kallweit {
274025e992a4SHeiner Kallweit 	pcie_capability_set_word(tp->pci_dev, PCI_EXP_LNKCTL,
274125e992a4SHeiner Kallweit 				 PCI_EXP_LNKCTL_CLKREQ_EN);
274225e992a4SHeiner Kallweit }
274325e992a4SHeiner Kallweit 
rtl_pcie_state_l2l3_disable(struct rtl8169_private * tp)274425e992a4SHeiner Kallweit static void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp)
274525e992a4SHeiner Kallweit {
274625e992a4SHeiner Kallweit 	/* work around an issue when PCI reset occurs during L2/L3 state */
274725e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23);
274825e992a4SHeiner Kallweit }
274925e992a4SHeiner Kallweit 
rtl_enable_exit_l1(struct rtl8169_private * tp)27504b33433eSHeiner Kallweit static void rtl_enable_exit_l1(struct rtl8169_private *tp)
27514b33433eSHeiner Kallweit {
27524b33433eSHeiner Kallweit 	/* Bits control which events trigger ASPM L1 exit:
27534b33433eSHeiner Kallweit 	 * Bit 12: rxdv
27544b33433eSHeiner Kallweit 	 * Bit 11: ltr_msg
27554b33433eSHeiner Kallweit 	 * Bit 10: txdma_poll
27564b33433eSHeiner Kallweit 	 * Bit  9: xadm
27574b33433eSHeiner Kallweit 	 * Bit  8: pktavi
27584b33433eSHeiner Kallweit 	 * Bit  7: txpla
27594b33433eSHeiner Kallweit 	 */
27604b33433eSHeiner Kallweit 	switch (tp->mac_version) {
27614b33433eSHeiner Kallweit 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36:
27624b33433eSHeiner Kallweit 		rtl_eri_set_bits(tp, 0xd4, 0x1f00);
27634b33433eSHeiner Kallweit 		break;
27644b33433eSHeiner Kallweit 	case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38:
27654b33433eSHeiner Kallweit 		rtl_eri_set_bits(tp, 0xd4, 0x0c00);
27664b33433eSHeiner Kallweit 		break;
2767d192181cSHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
27684b33433eSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80);
27694b33433eSHeiner Kallweit 		break;
27704b33433eSHeiner Kallweit 	default:
27714b33433eSHeiner Kallweit 		break;
27724b33433eSHeiner Kallweit 	}
27734b33433eSHeiner Kallweit }
27744b33433eSHeiner Kallweit 
rtl_disable_exit_l1(struct rtl8169_private * tp)2775d192181cSHeiner Kallweit static void rtl_disable_exit_l1(struct rtl8169_private *tp)
2776d192181cSHeiner Kallweit {
2777d192181cSHeiner Kallweit 	switch (tp->mac_version) {
2778d192181cSHeiner Kallweit 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
2779d192181cSHeiner Kallweit 		rtl_eri_clear_bits(tp, 0xd4, 0x1f00);
2780d192181cSHeiner Kallweit 		break;
2781d192181cSHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
2782d192181cSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0);
2783d192181cSHeiner Kallweit 		break;
2784d192181cSHeiner Kallweit 	default:
2785d192181cSHeiner Kallweit 		break;
2786d192181cSHeiner Kallweit 	}
2787d192181cSHeiner Kallweit }
2788d192181cSHeiner Kallweit 
rtl_hw_aspm_clkreq_enable(struct rtl8169_private * tp,bool enable)278925e992a4SHeiner Kallweit static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
279025e992a4SHeiner Kallweit {
279149ef7d84SHeiner Kallweit 	if (tp->mac_version < RTL_GIGA_MAC_VER_32)
279249ef7d84SHeiner Kallweit 		return;
279349ef7d84SHeiner Kallweit 
2794cf2ffdeaSHeiner Kallweit 	/* Don't enable ASPM in the chip if OS can't control ASPM */
2795cf2ffdeaSHeiner Kallweit 	if (enable && tp->aspm_manageable) {
2796162d626fSHeiner Kallweit 		/* On these chip versions ASPM can even harm
2797162d626fSHeiner Kallweit 		 * bus communication of other PCI devices.
2798162d626fSHeiner Kallweit 		 */
2799162d626fSHeiner Kallweit 		if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
2800162d626fSHeiner Kallweit 		    tp->mac_version == RTL_GIGA_MAC_VER_43)
2801162d626fSHeiner Kallweit 			return;
2802162d626fSHeiner Kallweit 
28036bc6c4e6SHeiner Kallweit 		rtl_mod_config5(tp, 0, ASPM_en);
28046bc6c4e6SHeiner Kallweit 		rtl_mod_config2(tp, 0, ClkReqEn);
2805c217ab7aSHeiner Kallweit 
2806c217ab7aSHeiner Kallweit 		switch (tp->mac_version) {
2807ebe59898SHeiner Kallweit 		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
2808efc37109SHeiner Kallweit 		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
2809c217ab7aSHeiner Kallweit 			/* reset ephy tx/rx disable timer */
2810c217ab7aSHeiner Kallweit 			r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
2811c217ab7aSHeiner Kallweit 			/* chip can trigger L1.2 */
2812c217ab7aSHeiner Kallweit 			r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, BIT(2));
2813c217ab7aSHeiner Kallweit 			break;
2814c217ab7aSHeiner Kallweit 		default:
2815c217ab7aSHeiner Kallweit 			break;
2816c217ab7aSHeiner Kallweit 		}
281725e992a4SHeiner Kallweit 	} else {
2818c217ab7aSHeiner Kallweit 		switch (tp->mac_version) {
2819ebe59898SHeiner Kallweit 		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
2820efc37109SHeiner Kallweit 		case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
2821c217ab7aSHeiner Kallweit 			r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
2822c217ab7aSHeiner Kallweit 			break;
2823c217ab7aSHeiner Kallweit 		default:
2824c217ab7aSHeiner Kallweit 			break;
2825c217ab7aSHeiner Kallweit 		}
2826c217ab7aSHeiner Kallweit 
28276bc6c4e6SHeiner Kallweit 		rtl_mod_config2(tp, ClkReqEn, 0);
28286bc6c4e6SHeiner Kallweit 		rtl_mod_config5(tp, ASPM_en, 0);
282925e992a4SHeiner Kallweit 	}
283025e992a4SHeiner Kallweit }
283125e992a4SHeiner Kallweit 
rtl_set_fifo_size(struct rtl8169_private * tp,u16 rx_stat,u16 tx_stat,u16 rx_dyn,u16 tx_dyn)283225e992a4SHeiner Kallweit static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
283325e992a4SHeiner Kallweit 			      u16 tx_stat, u16 rx_dyn, u16 tx_dyn)
283425e992a4SHeiner Kallweit {
283525e992a4SHeiner Kallweit 	/* Usage of dynamic vs. static FIFO is controlled by bit
283625e992a4SHeiner Kallweit 	 * TXCFG_AUTO_FIFO. Exact meaning of FIFO values isn't known.
283725e992a4SHeiner Kallweit 	 */
283825e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, (rx_stat << 16) | rx_dyn);
283925e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, (tx_stat << 16) | tx_dyn);
284025e992a4SHeiner Kallweit }
284125e992a4SHeiner Kallweit 
rtl8168g_set_pause_thresholds(struct rtl8169_private * tp,u8 low,u8 high)284225e992a4SHeiner Kallweit static void rtl8168g_set_pause_thresholds(struct rtl8169_private *tp,
284325e992a4SHeiner Kallweit 					  u8 low, u8 high)
284425e992a4SHeiner Kallweit {
284525e992a4SHeiner Kallweit 	/* FIFO thresholds for pause flow control */
284625e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, low);
284725e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, high);
284825e992a4SHeiner Kallweit }
284925e992a4SHeiner Kallweit 
rtl_hw_start_8168b(struct rtl8169_private * tp)285094b5ff74SHeiner Kallweit static void rtl_hw_start_8168b(struct rtl8169_private *tp)
285125e992a4SHeiner Kallweit {
285225e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
285325e992a4SHeiner Kallweit }
285425e992a4SHeiner Kallweit 
__rtl_hw_start_8168cp(struct rtl8169_private * tp)285525e992a4SHeiner Kallweit static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
285625e992a4SHeiner Kallweit {
285725e992a4SHeiner Kallweit 	RTL_W8(tp, Config1, RTL_R8(tp, Config1) | Speed_down);
285825e992a4SHeiner Kallweit 
285925e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
286025e992a4SHeiner Kallweit 
286125e992a4SHeiner Kallweit 	rtl_disable_clock_request(tp);
286225e992a4SHeiner Kallweit }
286325e992a4SHeiner Kallweit 
rtl_hw_start_8168cp_1(struct rtl8169_private * tp)286425e992a4SHeiner Kallweit static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
286525e992a4SHeiner Kallweit {
286625e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168cp[] = {
286725e992a4SHeiner Kallweit 		{ 0x01, 0,	0x0001 },
286825e992a4SHeiner Kallweit 		{ 0x02, 0x0800,	0x1000 },
286925e992a4SHeiner Kallweit 		{ 0x03, 0,	0x0042 },
287025e992a4SHeiner Kallweit 		{ 0x06, 0x0080,	0x0000 },
287125e992a4SHeiner Kallweit 		{ 0x07, 0,	0x2000 }
287225e992a4SHeiner Kallweit 	};
287325e992a4SHeiner Kallweit 
287425e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
287525e992a4SHeiner Kallweit 
287625e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168cp);
287725e992a4SHeiner Kallweit 
287825e992a4SHeiner Kallweit 	__rtl_hw_start_8168cp(tp);
287925e992a4SHeiner Kallweit }
288025e992a4SHeiner Kallweit 
rtl_hw_start_8168cp_2(struct rtl8169_private * tp)288125e992a4SHeiner Kallweit static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
288225e992a4SHeiner Kallweit {
288325e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
288425e992a4SHeiner Kallweit 
288525e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
288625e992a4SHeiner Kallweit }
288725e992a4SHeiner Kallweit 
rtl_hw_start_8168cp_3(struct rtl8169_private * tp)288825e992a4SHeiner Kallweit static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
288925e992a4SHeiner Kallweit {
289025e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
289125e992a4SHeiner Kallweit 
289225e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
289325e992a4SHeiner Kallweit 
289425e992a4SHeiner Kallweit 	/* Magic. */
289525e992a4SHeiner Kallweit 	RTL_W8(tp, DBG_REG, 0x20);
289625e992a4SHeiner Kallweit }
289725e992a4SHeiner Kallweit 
rtl_hw_start_8168c_1(struct rtl8169_private * tp)289825e992a4SHeiner Kallweit static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
289925e992a4SHeiner Kallweit {
290025e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168c_1[] = {
290125e992a4SHeiner Kallweit 		{ 0x02, 0x0800,	0x1000 },
290225e992a4SHeiner Kallweit 		{ 0x03, 0,	0x0002 },
290325e992a4SHeiner Kallweit 		{ 0x06, 0x0080,	0x0000 }
290425e992a4SHeiner Kallweit 	};
290525e992a4SHeiner Kallweit 
290625e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
290725e992a4SHeiner Kallweit 
290825e992a4SHeiner Kallweit 	RTL_W8(tp, DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
290925e992a4SHeiner Kallweit 
291025e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168c_1);
291125e992a4SHeiner Kallweit 
291225e992a4SHeiner Kallweit 	__rtl_hw_start_8168cp(tp);
291325e992a4SHeiner Kallweit }
291425e992a4SHeiner Kallweit 
rtl_hw_start_8168c_2(struct rtl8169_private * tp)291525e992a4SHeiner Kallweit static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
291625e992a4SHeiner Kallweit {
291725e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168c_2[] = {
291825e992a4SHeiner Kallweit 		{ 0x01, 0,	0x0001 },
2919a7a92cf8SHeiner Kallweit 		{ 0x03, 0x0400,	0x0020 }
292025e992a4SHeiner Kallweit 	};
292125e992a4SHeiner Kallweit 
292225e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
292325e992a4SHeiner Kallweit 
292425e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168c_2);
292525e992a4SHeiner Kallweit 
292625e992a4SHeiner Kallweit 	__rtl_hw_start_8168cp(tp);
292725e992a4SHeiner Kallweit }
292825e992a4SHeiner Kallweit 
rtl_hw_start_8168c_4(struct rtl8169_private * tp)292925e992a4SHeiner Kallweit static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
293025e992a4SHeiner Kallweit {
293125e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
293225e992a4SHeiner Kallweit 
293325e992a4SHeiner Kallweit 	__rtl_hw_start_8168cp(tp);
293425e992a4SHeiner Kallweit }
293525e992a4SHeiner Kallweit 
rtl_hw_start_8168d(struct rtl8169_private * tp)293625e992a4SHeiner Kallweit static void rtl_hw_start_8168d(struct rtl8169_private *tp)
293725e992a4SHeiner Kallweit {
293825e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
293925e992a4SHeiner Kallweit 
294025e992a4SHeiner Kallweit 	rtl_disable_clock_request(tp);
294125e992a4SHeiner Kallweit }
294225e992a4SHeiner Kallweit 
rtl_hw_start_8168d_4(struct rtl8169_private * tp)294325e992a4SHeiner Kallweit static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
294425e992a4SHeiner Kallweit {
294525e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168d_4[] = {
294625e992a4SHeiner Kallweit 		{ 0x0b, 0x0000,	0x0048 },
294725e992a4SHeiner Kallweit 		{ 0x19, 0x0020,	0x0050 },
2948a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x0100,	0x0020 },
2949a7a92cf8SHeiner Kallweit 		{ 0x10, 0x0004,	0x0000 },
295025e992a4SHeiner Kallweit 	};
295125e992a4SHeiner Kallweit 
295225e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
295325e992a4SHeiner Kallweit 
295425e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168d_4);
295525e992a4SHeiner Kallweit 
295625e992a4SHeiner Kallweit 	rtl_enable_clock_request(tp);
295725e992a4SHeiner Kallweit }
295825e992a4SHeiner Kallweit 
rtl_hw_start_8168e_1(struct rtl8169_private * tp)295925e992a4SHeiner Kallweit static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
296025e992a4SHeiner Kallweit {
296125e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168e_1[] = {
296225e992a4SHeiner Kallweit 		{ 0x00, 0x0200,	0x0100 },
296325e992a4SHeiner Kallweit 		{ 0x00, 0x0000,	0x0004 },
296425e992a4SHeiner Kallweit 		{ 0x06, 0x0002,	0x0001 },
296525e992a4SHeiner Kallweit 		{ 0x06, 0x0000,	0x0030 },
296625e992a4SHeiner Kallweit 		{ 0x07, 0x0000,	0x2000 },
296725e992a4SHeiner Kallweit 		{ 0x00, 0x0000,	0x0020 },
296825e992a4SHeiner Kallweit 		{ 0x03, 0x5800,	0x2000 },
296925e992a4SHeiner Kallweit 		{ 0x03, 0x0000,	0x0001 },
297025e992a4SHeiner Kallweit 		{ 0x01, 0x0800,	0x1000 },
297125e992a4SHeiner Kallweit 		{ 0x07, 0x0000,	0x4000 },
297225e992a4SHeiner Kallweit 		{ 0x1e, 0x0000,	0x2000 },
297325e992a4SHeiner Kallweit 		{ 0x19, 0xffff,	0xfe6c },
297425e992a4SHeiner Kallweit 		{ 0x0a, 0x0000,	0x0040 }
297525e992a4SHeiner Kallweit 	};
297625e992a4SHeiner Kallweit 
297725e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
297825e992a4SHeiner Kallweit 
297925e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168e_1);
298025e992a4SHeiner Kallweit 
298125e992a4SHeiner Kallweit 	rtl_disable_clock_request(tp);
298225e992a4SHeiner Kallweit 
298325e992a4SHeiner Kallweit 	/* Reset tx FIFO pointer */
298425e992a4SHeiner Kallweit 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
298525e992a4SHeiner Kallweit 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
298625e992a4SHeiner Kallweit 
29876bc6c4e6SHeiner Kallweit 	rtl_mod_config5(tp, Spi_en, 0);
298825e992a4SHeiner Kallweit }
298925e992a4SHeiner Kallweit 
rtl_hw_start_8168e_2(struct rtl8169_private * tp)299025e992a4SHeiner Kallweit static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
299125e992a4SHeiner Kallweit {
299225e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168e_2[] = {
299325e992a4SHeiner Kallweit 		{ 0x09, 0x0000,	0x0080 },
2994a7a92cf8SHeiner Kallweit 		{ 0x19, 0x0000,	0x0224 },
2995a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0000,	0x0004 },
2996a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x3df0,	0x0200 },
299725e992a4SHeiner Kallweit 	};
299825e992a4SHeiner Kallweit 
299925e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
300025e992a4SHeiner Kallweit 
300125e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168e_2);
300225e992a4SHeiner Kallweit 
300325e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
300433b00ca1SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
300525e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
300633b00ca1SHeiner Kallweit 	rtl_eri_set_bits(tp, 0x1d0, BIT(1));
300733b00ca1SHeiner Kallweit 	rtl_reset_packet_filter(tp);
300833b00ca1SHeiner Kallweit 	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
300925e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
301025e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060);
301125e992a4SHeiner Kallweit 
301225e992a4SHeiner Kallweit 	rtl_disable_clock_request(tp);
301325e992a4SHeiner Kallweit 
301425e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
301525e992a4SHeiner Kallweit 
301625e992a4SHeiner Kallweit 	rtl8168_config_eee_mac(tp);
301725e992a4SHeiner Kallweit 
301825e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
301925e992a4SHeiner Kallweit 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
30206bc6c4e6SHeiner Kallweit 	rtl_mod_config5(tp, Spi_en, 0);
302125e992a4SHeiner Kallweit }
302225e992a4SHeiner Kallweit 
rtl_hw_start_8168f(struct rtl8169_private * tp)302325e992a4SHeiner Kallweit static void rtl_hw_start_8168f(struct rtl8169_private *tp)
302425e992a4SHeiner Kallweit {
302525e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
302625e992a4SHeiner Kallweit 
302725e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
3028d05890c5SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
302925e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
303025e992a4SHeiner Kallweit 	rtl_reset_packet_filter(tp);
303154113dedSHeiner Kallweit 	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
3032d05890c5SHeiner Kallweit 	rtl_eri_set_bits(tp, 0x1d0, BIT(4) | BIT(1));
303325e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
303425e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060);
303525e992a4SHeiner Kallweit 
303625e992a4SHeiner Kallweit 	rtl_disable_clock_request(tp);
303725e992a4SHeiner Kallweit 
303825e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
303925e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
304025e992a4SHeiner Kallweit 	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
30416bc6c4e6SHeiner Kallweit 	rtl_mod_config5(tp, Spi_en, 0);
304225e992a4SHeiner Kallweit 
304325e992a4SHeiner Kallweit 	rtl8168_config_eee_mac(tp);
304425e992a4SHeiner Kallweit }
304525e992a4SHeiner Kallweit 
rtl_hw_start_8168f_1(struct rtl8169_private * tp)304625e992a4SHeiner Kallweit static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
304725e992a4SHeiner Kallweit {
304825e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168f_1[] = {
304925e992a4SHeiner Kallweit 		{ 0x06, 0x00c0,	0x0020 },
305025e992a4SHeiner Kallweit 		{ 0x08, 0x0001,	0x0002 },
305125e992a4SHeiner Kallweit 		{ 0x09, 0x0000,	0x0080 },
3052a7a92cf8SHeiner Kallweit 		{ 0x19, 0x0000,	0x0224 },
3053709a16beSHeiner Kallweit 		{ 0x00, 0x0000,	0x0008 },
3054a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x3df0,	0x0200 },
305525e992a4SHeiner Kallweit 	};
305625e992a4SHeiner Kallweit 
305725e992a4SHeiner Kallweit 	rtl_hw_start_8168f(tp);
305825e992a4SHeiner Kallweit 
305925e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168f_1);
306025e992a4SHeiner Kallweit }
306125e992a4SHeiner Kallweit 
rtl_hw_start_8411(struct rtl8169_private * tp)306225e992a4SHeiner Kallweit static void rtl_hw_start_8411(struct rtl8169_private *tp)
306325e992a4SHeiner Kallweit {
306425e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168f_1[] = {
306525e992a4SHeiner Kallweit 		{ 0x06, 0x00c0,	0x0020 },
306625e992a4SHeiner Kallweit 		{ 0x0f, 0xffff,	0x5200 },
3067a7a92cf8SHeiner Kallweit 		{ 0x19, 0x0000,	0x0224 },
3068709a16beSHeiner Kallweit 		{ 0x00, 0x0000,	0x0008 },
3069a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x3df0,	0x0200 },
307025e992a4SHeiner Kallweit 	};
307125e992a4SHeiner Kallweit 
307225e992a4SHeiner Kallweit 	rtl_hw_start_8168f(tp);
307325e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
307425e992a4SHeiner Kallweit 
307525e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168f_1);
307625e992a4SHeiner Kallweit }
307725e992a4SHeiner Kallweit 
rtl_hw_start_8168g(struct rtl8169_private * tp)307825e992a4SHeiner Kallweit static void rtl_hw_start_8168g(struct rtl8169_private *tp)
307925e992a4SHeiner Kallweit {
308025e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
308125e992a4SHeiner Kallweit 	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
308225e992a4SHeiner Kallweit 
308325e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
308425e992a4SHeiner Kallweit 
308525e992a4SHeiner Kallweit 	rtl_reset_packet_filter(tp);
308625e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f);
308725e992a4SHeiner Kallweit 
30883406079bSChunhao Lin 	rtl_disable_rxdvgate(tp);
308925e992a4SHeiner Kallweit 
309025e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
309125e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
309225e992a4SHeiner Kallweit 
309325e992a4SHeiner Kallweit 	rtl8168_config_eee_mac(tp);
309425e992a4SHeiner Kallweit 
309554113dedSHeiner Kallweit 	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
309654113dedSHeiner Kallweit 	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
309725e992a4SHeiner Kallweit 
309825e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
309925e992a4SHeiner Kallweit }
310025e992a4SHeiner Kallweit 
rtl_hw_start_8168g_1(struct rtl8169_private * tp)310125e992a4SHeiner Kallweit static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
310225e992a4SHeiner Kallweit {
310325e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168g_1[] = {
3104a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0008,	0x0000 },
3105a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x3ff0,	0x0820 },
310625e992a4SHeiner Kallweit 		{ 0x1e, 0x0000,	0x0001 },
310725e992a4SHeiner Kallweit 		{ 0x19, 0x8000,	0x0000 }
310825e992a4SHeiner Kallweit 	};
310925e992a4SHeiner Kallweit 
311025e992a4SHeiner Kallweit 	rtl_hw_start_8168g(tp);
311125e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168g_1);
311225e992a4SHeiner Kallweit }
311325e992a4SHeiner Kallweit 
rtl_hw_start_8168g_2(struct rtl8169_private * tp)311425e992a4SHeiner Kallweit static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
311525e992a4SHeiner Kallweit {
311625e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168g_2[] = {
3117a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0008,	0x0000 },
3118a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x3ff0,	0x0820 },
3119a7a92cf8SHeiner Kallweit 		{ 0x19, 0xffff,	0x7c00 },
3120a7a92cf8SHeiner Kallweit 		{ 0x1e, 0xffff,	0x20eb },
3121a7a92cf8SHeiner Kallweit 		{ 0x0d, 0xffff,	0x1666 },
3122a7a92cf8SHeiner Kallweit 		{ 0x00, 0xffff,	0x10a3 },
3123a7a92cf8SHeiner Kallweit 		{ 0x06, 0xffff,	0xf050 },
3124a7a92cf8SHeiner Kallweit 		{ 0x04, 0x0000,	0x0010 },
3125a7a92cf8SHeiner Kallweit 		{ 0x1d, 0x4000,	0x0000 },
312625e992a4SHeiner Kallweit 	};
312725e992a4SHeiner Kallweit 
312825e992a4SHeiner Kallweit 	rtl_hw_start_8168g(tp);
312925e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168g_2);
313025e992a4SHeiner Kallweit }
313125e992a4SHeiner Kallweit 
rtl_hw_start_8411_2(struct rtl8169_private * tp)313225e992a4SHeiner Kallweit static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
313325e992a4SHeiner Kallweit {
313425e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8411_2[] = {
3135a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0008,	0x0000 },
3136a7a92cf8SHeiner Kallweit 		{ 0x0c, 0x37d0,	0x0820 },
3137a7a92cf8SHeiner Kallweit 		{ 0x1e, 0x0000,	0x0001 },
3138a7a92cf8SHeiner Kallweit 		{ 0x19, 0x8021,	0x0000 },
3139a7a92cf8SHeiner Kallweit 		{ 0x1e, 0x0000,	0x2000 },
3140a7a92cf8SHeiner Kallweit 		{ 0x0d, 0x0100,	0x0200 },
3141a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0000,	0x0080 },
3142a7a92cf8SHeiner Kallweit 		{ 0x06, 0x0000,	0x0010 },
3143a7a92cf8SHeiner Kallweit 		{ 0x04, 0x0000,	0x0010 },
3144a7a92cf8SHeiner Kallweit 		{ 0x1d, 0x0000,	0x4000 },
314525e992a4SHeiner Kallweit 	};
314625e992a4SHeiner Kallweit 
314725e992a4SHeiner Kallweit 	rtl_hw_start_8168g(tp);
314825e992a4SHeiner Kallweit 
314925e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8411_2);
3150fe4e8db0SHeiner Kallweit 
3151fe4e8db0SHeiner Kallweit 	/* The following Realtek-provided magic fixes an issue with the RX unit
3152fe4e8db0SHeiner Kallweit 	 * getting confused after the PHY having been powered-down.
3153fe4e8db0SHeiner Kallweit 	 */
3154fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC28, 0x0000);
3155fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2A, 0x0000);
3156fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2C, 0x0000);
3157fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2E, 0x0000);
3158fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC30, 0x0000);
3159fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC32, 0x0000);
3160fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC34, 0x0000);
3161fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC36, 0x0000);
3162fe4e8db0SHeiner Kallweit 	mdelay(3);
3163fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC26, 0x0000);
3164fe4e8db0SHeiner Kallweit 
3165fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF800, 0xE008);
3166fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF802, 0xE00A);
3167fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF804, 0xE00C);
3168fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF806, 0xE00E);
3169fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF808, 0xE027);
3170fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF80A, 0xE04F);
3171fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF80C, 0xE05E);
3172fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF80E, 0xE065);
3173fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF810, 0xC602);
3174fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF812, 0xBE00);
3175fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF814, 0x0000);
3176fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF816, 0xC502);
3177fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF818, 0xBD00);
3178fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF81A, 0x074C);
3179fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF81C, 0xC302);
3180fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF81E, 0xBB00);
3181fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF820, 0x080A);
3182fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF822, 0x6420);
3183fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF824, 0x48C2);
3184fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF826, 0x8C20);
3185fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF828, 0xC516);
3186fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF82A, 0x64A4);
3187fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF82C, 0x49C0);
3188fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF82E, 0xF009);
3189fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF830, 0x74A2);
3190fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF832, 0x8CA5);
3191fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF834, 0x74A0);
3192fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF836, 0xC50E);
3193fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF838, 0x9CA2);
3194fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF83A, 0x1C11);
3195fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF83C, 0x9CA0);
3196fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF83E, 0xE006);
3197fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF840, 0x74F8);
3198fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF842, 0x48C4);
3199fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF844, 0x8CF8);
3200fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF846, 0xC404);
3201fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF848, 0xBC00);
3202fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF84A, 0xC403);
3203fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF84C, 0xBC00);
3204fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF84E, 0x0BF2);
3205fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF850, 0x0C0A);
3206fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF852, 0xE434);
3207fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF854, 0xD3C0);
3208fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF856, 0x49D9);
3209fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF858, 0xF01F);
3210fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF85A, 0xC526);
3211fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF85C, 0x64A5);
3212fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF85E, 0x1400);
3213fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF860, 0xF007);
3214fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF862, 0x0C01);
3215fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF864, 0x8CA5);
3216fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF866, 0x1C15);
3217fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF868, 0xC51B);
3218fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF86A, 0x9CA0);
3219fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF86C, 0xE013);
3220fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF86E, 0xC519);
3221fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF870, 0x74A0);
3222fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF872, 0x48C4);
3223fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF874, 0x8CA0);
3224fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF876, 0xC516);
3225fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF878, 0x74A4);
3226fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF87A, 0x48C8);
3227fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF87C, 0x48CA);
3228fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF87E, 0x9CA4);
3229fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF880, 0xC512);
3230fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF882, 0x1B00);
3231fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF884, 0x9BA0);
3232fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF886, 0x1B1C);
3233fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF888, 0x483F);
3234fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF88A, 0x9BA2);
3235fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF88C, 0x1B04);
3236fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF88E, 0xC508);
3237fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF890, 0x9BA0);
3238fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF892, 0xC505);
3239fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF894, 0xBD00);
3240fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF896, 0xC502);
3241fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF898, 0xBD00);
3242fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF89A, 0x0300);
3243fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF89C, 0x051E);
3244fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF89E, 0xE434);
3245fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8A0, 0xE018);
3246fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8A2, 0xE092);
3247fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8A4, 0xDE20);
3248fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8A6, 0xD3C0);
3249fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8A8, 0xC50F);
3250fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8AA, 0x76A4);
3251fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8AC, 0x49E3);
3252fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8AE, 0xF007);
3253fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8B0, 0x49C0);
3254fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8B2, 0xF103);
3255fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8B4, 0xC607);
3256fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8B6, 0xBE00);
3257fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8B8, 0xC606);
3258fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8BA, 0xBE00);
3259fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8BC, 0xC602);
3260fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8BE, 0xBE00);
3261fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8C0, 0x0C4C);
3262fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8C2, 0x0C28);
3263fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8C4, 0x0C2C);
3264fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8C6, 0xDC00);
3265fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8C8, 0xC707);
3266fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8CA, 0x1D00);
3267fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8CC, 0x8DE2);
3268fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8CE, 0x48C1);
3269fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8D0, 0xC502);
3270fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8D2, 0xBD00);
3271fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8D4, 0x00AA);
3272fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8D6, 0xE0C0);
3273fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8D8, 0xC502);
3274fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8DA, 0xBD00);
3275fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xF8DC, 0x0132);
3276fe4e8db0SHeiner Kallweit 
3277fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC26, 0x8000);
3278fe4e8db0SHeiner Kallweit 
3279fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2A, 0x0743);
3280fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2C, 0x0801);
3281fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC2E, 0x0BE9);
3282fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC30, 0x02FD);
3283fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC32, 0x0C25);
3284fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC34, 0x00A9);
3285fe4e8db0SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xFC36, 0x012D);
328625e992a4SHeiner Kallweit }
328725e992a4SHeiner Kallweit 
rtl_hw_start_8168h_1(struct rtl8169_private * tp)328825e992a4SHeiner Kallweit static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
328925e992a4SHeiner Kallweit {
329025e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168h_1[] = {
329125e992a4SHeiner Kallweit 		{ 0x1e, 0x0800,	0x0001 },
329225e992a4SHeiner Kallweit 		{ 0x1d, 0x0000,	0x0800 },
329325e992a4SHeiner Kallweit 		{ 0x05, 0xffff,	0x2089 },
329425e992a4SHeiner Kallweit 		{ 0x06, 0xffff,	0x5881 },
3295a7a92cf8SHeiner Kallweit 		{ 0x04, 0xffff,	0x854a },
329625e992a4SHeiner Kallweit 		{ 0x01, 0xffff,	0x068b }
329725e992a4SHeiner Kallweit 	};
3298ef712edeSHeiner Kallweit 	int rg_saw_cnt;
329925e992a4SHeiner Kallweit 
330025e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168h_1);
330125e992a4SHeiner Kallweit 
330225e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
330325e992a4SHeiner Kallweit 	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
330425e992a4SHeiner Kallweit 
330525e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
330625e992a4SHeiner Kallweit 
330725e992a4SHeiner Kallweit 	rtl_reset_packet_filter(tp);
330825e992a4SHeiner Kallweit 
3309ee1350f9SHeiner Kallweit 	rtl_eri_set_bits(tp, 0xdc, 0x001c);
331025e992a4SHeiner Kallweit 
331125e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
331225e992a4SHeiner Kallweit 
33133406079bSChunhao Lin 	rtl_disable_rxdvgate(tp);
331425e992a4SHeiner Kallweit 
331525e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
331625e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
331725e992a4SHeiner Kallweit 
331825e992a4SHeiner Kallweit 	rtl8168_config_eee_mac(tp);
331925e992a4SHeiner Kallweit 
332025e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
332125e992a4SHeiner Kallweit 	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
332225e992a4SHeiner Kallweit 
332325e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
332425e992a4SHeiner Kallweit 
332554113dedSHeiner Kallweit 	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
332625e992a4SHeiner Kallweit 
332725e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
332825e992a4SHeiner Kallweit 
33293ab077d2SHeiner Kallweit 	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
333025e992a4SHeiner Kallweit 	if (rg_saw_cnt > 0) {
333125e992a4SHeiner Kallweit 		u16 sw_cnt_1ms_ini;
333225e992a4SHeiner Kallweit 
333325e992a4SHeiner Kallweit 		sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
333425e992a4SHeiner Kallweit 		sw_cnt_1ms_ini &= 0x0fff;
3335ef712edeSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
333625e992a4SHeiner Kallweit 	}
333725e992a4SHeiner Kallweit 
3338ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
3339ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe052, 0x6000, 0x8008);
3340ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe0d6, 0x01ff, 0x017f);
3341ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
334225e992a4SHeiner Kallweit 
334325e992a4SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
334425e992a4SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
334525e992a4SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
334625e992a4SHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
334725e992a4SHeiner Kallweit }
334825e992a4SHeiner Kallweit 
rtl_hw_start_8168ep(struct rtl8169_private * tp)334925e992a4SHeiner Kallweit static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
335025e992a4SHeiner Kallweit {
335125e992a4SHeiner Kallweit 	rtl8168ep_stop_cmac(tp);
335225e992a4SHeiner Kallweit 
335325e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
335425e992a4SHeiner Kallweit 	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
335525e992a4SHeiner Kallweit 
335625e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
335725e992a4SHeiner Kallweit 
335825e992a4SHeiner Kallweit 	rtl_reset_packet_filter(tp);
335925e992a4SHeiner Kallweit 
336025e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
336125e992a4SHeiner Kallweit 
33623406079bSChunhao Lin 	rtl_disable_rxdvgate(tp);
336325e992a4SHeiner Kallweit 
336425e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
336525e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
336625e992a4SHeiner Kallweit 
336725e992a4SHeiner Kallweit 	rtl8168_config_eee_mac(tp);
336825e992a4SHeiner Kallweit 
336954113dedSHeiner Kallweit 	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
337025e992a4SHeiner Kallweit 
337125e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
337225e992a4SHeiner Kallweit 
337325e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
337425e992a4SHeiner Kallweit }
337525e992a4SHeiner Kallweit 
rtl_hw_start_8168ep_3(struct rtl8169_private * tp)337625e992a4SHeiner Kallweit static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
337725e992a4SHeiner Kallweit {
337825e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8168ep_3[] = {
3379a7a92cf8SHeiner Kallweit 		{ 0x00, 0x0000,	0x0080 },
3380a7a92cf8SHeiner Kallweit 		{ 0x0d, 0x0100,	0x0200 },
3381a7a92cf8SHeiner Kallweit 		{ 0x19, 0x8021,	0x0000 },
3382a7a92cf8SHeiner Kallweit 		{ 0x1e, 0x0000,	0x2000 },
338325e992a4SHeiner Kallweit 	};
338425e992a4SHeiner Kallweit 
338525e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8168ep_3);
338625e992a4SHeiner Kallweit 
338725e992a4SHeiner Kallweit 	rtl_hw_start_8168ep(tp);
338825e992a4SHeiner Kallweit 
338925e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
339025e992a4SHeiner Kallweit 	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
339125e992a4SHeiner Kallweit 
3392ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271);
3393ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
3394ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
339525e992a4SHeiner Kallweit }
339625e992a4SHeiner Kallweit 
rtl_hw_start_8117(struct rtl8169_private * tp)33971287723aSHeiner Kallweit static void rtl_hw_start_8117(struct rtl8169_private *tp)
33981287723aSHeiner Kallweit {
33991287723aSHeiner Kallweit 	static const struct ephy_info e_info_8117[] = {
34001287723aSHeiner Kallweit 		{ 0x19, 0x0040,	0x1100 },
34011287723aSHeiner Kallweit 		{ 0x59, 0x0040,	0x1100 },
34021287723aSHeiner Kallweit 	};
34031287723aSHeiner Kallweit 	int rg_saw_cnt;
34041287723aSHeiner Kallweit 
34051287723aSHeiner Kallweit 	rtl8168ep_stop_cmac(tp);
34061287723aSHeiner Kallweit 	rtl_ephy_init(tp, e_info_8117);
34071287723aSHeiner Kallweit 
34081287723aSHeiner Kallweit 	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
34091287723aSHeiner Kallweit 	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
34101287723aSHeiner Kallweit 
34111287723aSHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
34121287723aSHeiner Kallweit 
34131287723aSHeiner Kallweit 	rtl_reset_packet_filter(tp);
34141287723aSHeiner Kallweit 
34154b33433eSHeiner Kallweit 	rtl_eri_set_bits(tp, 0xd4, 0x0010);
34161287723aSHeiner Kallweit 
34171287723aSHeiner Kallweit 	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
34181287723aSHeiner Kallweit 
34193406079bSChunhao Lin 	rtl_disable_rxdvgate(tp);
34201287723aSHeiner Kallweit 
34211287723aSHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
34221287723aSHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
34231287723aSHeiner Kallweit 
34241287723aSHeiner Kallweit 	rtl8168_config_eee_mac(tp);
34251287723aSHeiner Kallweit 
34261287723aSHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
34271287723aSHeiner Kallweit 	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
34281287723aSHeiner Kallweit 
34291287723aSHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
34301287723aSHeiner Kallweit 
343154113dedSHeiner Kallweit 	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
34321287723aSHeiner Kallweit 
34331287723aSHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
34341287723aSHeiner Kallweit 
34351287723aSHeiner Kallweit 	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
34361287723aSHeiner Kallweit 	if (rg_saw_cnt > 0) {
34371287723aSHeiner Kallweit 		u16 sw_cnt_1ms_ini;
34381287723aSHeiner Kallweit 
34391287723aSHeiner Kallweit 		sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
34401287723aSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
34411287723aSHeiner Kallweit 	}
34421287723aSHeiner Kallweit 
34431287723aSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
34441287723aSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xea80, 0x0003);
34451287723aSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe052, 0x0000, 0x0009);
34461287723aSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
34471287723aSHeiner Kallweit 
34481287723aSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
34491287723aSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
34501287723aSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
34511287723aSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
34521287723aSHeiner Kallweit 
3453229c1e0dSHeiner Kallweit 	/* firmware is for MAC only */
34541c5be5e9SHeiner Kallweit 	r8169_apply_firmware(tp);
34551287723aSHeiner Kallweit }
34561287723aSHeiner Kallweit 
rtl_hw_start_8102e_1(struct rtl8169_private * tp)345725e992a4SHeiner Kallweit static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
345825e992a4SHeiner Kallweit {
345925e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8102e_1[] = {
346025e992a4SHeiner Kallweit 		{ 0x01,	0, 0x6e65 },
346125e992a4SHeiner Kallweit 		{ 0x02,	0, 0x091f },
346225e992a4SHeiner Kallweit 		{ 0x03,	0, 0xc2f9 },
346325e992a4SHeiner Kallweit 		{ 0x06,	0, 0xafb5 },
346425e992a4SHeiner Kallweit 		{ 0x07,	0, 0x0e00 },
346525e992a4SHeiner Kallweit 		{ 0x19,	0, 0xec80 },
346625e992a4SHeiner Kallweit 		{ 0x01,	0, 0x2e65 },
346725e992a4SHeiner Kallweit 		{ 0x01,	0, 0x6e65 }
346825e992a4SHeiner Kallweit 	};
346925e992a4SHeiner Kallweit 	u8 cfg1;
347025e992a4SHeiner Kallweit 
347125e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
347225e992a4SHeiner Kallweit 
347325e992a4SHeiner Kallweit 	RTL_W8(tp, DBG_REG, FIX_NAK_1);
347425e992a4SHeiner Kallweit 
347525e992a4SHeiner Kallweit 	RTL_W8(tp, Config1,
347625e992a4SHeiner Kallweit 	       LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
347725e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
347825e992a4SHeiner Kallweit 
347925e992a4SHeiner Kallweit 	cfg1 = RTL_R8(tp, Config1);
348025e992a4SHeiner Kallweit 	if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
348125e992a4SHeiner Kallweit 		RTL_W8(tp, Config1, cfg1 & ~LEDS0);
348225e992a4SHeiner Kallweit 
348325e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8102e_1);
348425e992a4SHeiner Kallweit }
348525e992a4SHeiner Kallweit 
rtl_hw_start_8102e_2(struct rtl8169_private * tp)348625e992a4SHeiner Kallweit static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
348725e992a4SHeiner Kallweit {
348825e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
348925e992a4SHeiner Kallweit 
349025e992a4SHeiner Kallweit 	RTL_W8(tp, Config1, MEMMAP | IOMAP | VPD | PMEnable);
349125e992a4SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
349225e992a4SHeiner Kallweit }
349325e992a4SHeiner Kallweit 
rtl_hw_start_8102e_3(struct rtl8169_private * tp)349425e992a4SHeiner Kallweit static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
349525e992a4SHeiner Kallweit {
349625e992a4SHeiner Kallweit 	rtl_hw_start_8102e_2(tp);
349725e992a4SHeiner Kallweit 
349825e992a4SHeiner Kallweit 	rtl_ephy_write(tp, 0x03, 0xc2f9);
349925e992a4SHeiner Kallweit }
350025e992a4SHeiner Kallweit 
rtl_hw_start_8401(struct rtl8169_private * tp)3501cdafdc29SHeiner Kallweit static void rtl_hw_start_8401(struct rtl8169_private *tp)
3502cdafdc29SHeiner Kallweit {
3503cdafdc29SHeiner Kallweit 	static const struct ephy_info e_info_8401[] = {
3504cdafdc29SHeiner Kallweit 		{ 0x01,	0xffff, 0x6fe5 },
3505cdafdc29SHeiner Kallweit 		{ 0x03,	0xffff, 0x0599 },
3506cdafdc29SHeiner Kallweit 		{ 0x06,	0xffff, 0xaf25 },
3507cdafdc29SHeiner Kallweit 		{ 0x07,	0xffff, 0x8e68 },
3508cdafdc29SHeiner Kallweit 	};
3509cdafdc29SHeiner Kallweit 
3510cdafdc29SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8401);
3511cdafdc29SHeiner Kallweit 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
3512cdafdc29SHeiner Kallweit }
3513cdafdc29SHeiner Kallweit 
rtl_hw_start_8105e_1(struct rtl8169_private * tp)351425e992a4SHeiner Kallweit static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
351525e992a4SHeiner Kallweit {
351625e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8105e_1[] = {
351725e992a4SHeiner Kallweit 		{ 0x07,	0, 0x4000 },
351825e992a4SHeiner Kallweit 		{ 0x19,	0, 0x0200 },
351925e992a4SHeiner Kallweit 		{ 0x19,	0, 0x0020 },
352025e992a4SHeiner Kallweit 		{ 0x1e,	0, 0x2000 },
352125e992a4SHeiner Kallweit 		{ 0x03,	0, 0x0001 },
352225e992a4SHeiner Kallweit 		{ 0x19,	0, 0x0100 },
352325e992a4SHeiner Kallweit 		{ 0x19,	0, 0x0004 },
352425e992a4SHeiner Kallweit 		{ 0x0a,	0, 0x0020 }
352525e992a4SHeiner Kallweit 	};
352625e992a4SHeiner Kallweit 
352725e992a4SHeiner Kallweit 	/* Force LAN exit from ASPM if Rx/Tx are not idle */
352825e992a4SHeiner Kallweit 	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
352925e992a4SHeiner Kallweit 
353025e992a4SHeiner Kallweit 	/* Disable Early Tally Counter */
353125e992a4SHeiner Kallweit 	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) & ~0x010000);
353225e992a4SHeiner Kallweit 
353325e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
353425e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
353525e992a4SHeiner Kallweit 
353625e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8105e_1);
353725e992a4SHeiner Kallweit 
353825e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
353925e992a4SHeiner Kallweit }
354025e992a4SHeiner Kallweit 
rtl_hw_start_8105e_2(struct rtl8169_private * tp)354125e992a4SHeiner Kallweit static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
354225e992a4SHeiner Kallweit {
354325e992a4SHeiner Kallweit 	rtl_hw_start_8105e_1(tp);
354425e992a4SHeiner Kallweit 	rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
354525e992a4SHeiner Kallweit }
354625e992a4SHeiner Kallweit 
rtl_hw_start_8402(struct rtl8169_private * tp)354725e992a4SHeiner Kallweit static void rtl_hw_start_8402(struct rtl8169_private *tp)
354825e992a4SHeiner Kallweit {
354925e992a4SHeiner Kallweit 	static const struct ephy_info e_info_8402[] = {
355025e992a4SHeiner Kallweit 		{ 0x19,	0xffff, 0xff64 },
355125e992a4SHeiner Kallweit 		{ 0x1e,	0, 0x4000 }
355225e992a4SHeiner Kallweit 	};
355325e992a4SHeiner Kallweit 
355425e992a4SHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
355525e992a4SHeiner Kallweit 
355625e992a4SHeiner Kallweit 	/* Force LAN exit from ASPM if Rx/Tx are not idle */
355725e992a4SHeiner Kallweit 	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
355825e992a4SHeiner Kallweit 
355925e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
356025e992a4SHeiner Kallweit 
356125e992a4SHeiner Kallweit 	rtl_ephy_init(tp, e_info_8402);
356225e992a4SHeiner Kallweit 
356325e992a4SHeiner Kallweit 	rtl_set_fifo_size(tp, 0x00, 0x00, 0x02, 0x06);
356425e992a4SHeiner Kallweit 	rtl_reset_packet_filter(tp);
356525e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
356625e992a4SHeiner Kallweit 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
356754113dedSHeiner Kallweit 	rtl_w0w1_eri(tp, 0x0d4, 0x0e00, 0xff00);
356825e992a4SHeiner Kallweit 
35696d7a631eSHeiner Kallweit 	/* disable EEE */
35706d7a631eSHeiner Kallweit 	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
35716d7a631eSHeiner Kallweit 
357225e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
357325e992a4SHeiner Kallweit }
357425e992a4SHeiner Kallweit 
rtl_hw_start_8106(struct rtl8169_private * tp)357525e992a4SHeiner Kallweit static void rtl_hw_start_8106(struct rtl8169_private *tp)
357625e992a4SHeiner Kallweit {
357725e992a4SHeiner Kallweit 	/* Force LAN exit from ASPM if Rx/Tx are not idle */
357825e992a4SHeiner Kallweit 	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
357925e992a4SHeiner Kallweit 
358025e992a4SHeiner Kallweit 	RTL_W32(tp, MISC, (RTL_R32(tp, MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
358125e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
358225e992a4SHeiner Kallweit 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
358325e992a4SHeiner Kallweit 
3584c07c8ffcSHeiner Kallweit 	/* L0 7us, L1 32us - needed to avoid issues with link-up detection */
3585c07c8ffcSHeiner Kallweit 	rtl_set_aspm_entry_latency(tp, 0x2f);
35869c401864SHayes Wang 
35878d46f620SHeiner Kallweit 	rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
35888d46f620SHeiner Kallweit 
35896d7a631eSHeiner Kallweit 	/* disable EEE */
35906d7a631eSHeiner Kallweit 	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
35916d7a631eSHeiner Kallweit 
359225e992a4SHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
359325e992a4SHeiner Kallweit }
359425e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)3595f1bce4adSHeiner Kallweit DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
3596f1bce4adSHeiner Kallweit {
3597f1bce4adSHeiner Kallweit 	return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13);
3598f1bce4adSHeiner Kallweit }
3599f1bce4adSHeiner Kallweit 
rtl_hw_start_8125_common(struct rtl8169_private * tp)3600f1bce4adSHeiner Kallweit static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
3601f1bce4adSHeiner Kallweit {
3602f1bce4adSHeiner Kallweit 	rtl_pcie_state_l2l3_disable(tp);
3603f1bce4adSHeiner Kallweit 
3604f1bce4adSHeiner Kallweit 	RTL_W16(tp, 0x382, 0x221b);
3605f1bce4adSHeiner Kallweit 	RTL_W8(tp, 0x4500, 0);
3606f1bce4adSHeiner Kallweit 	RTL_W16(tp, 0x4800, 0);
3607f1bce4adSHeiner Kallweit 
3608f1bce4adSHeiner Kallweit 	/* disable UPS */
3609f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000);
3610f1bce4adSHeiner Kallweit 
3611f1bce4adSHeiner Kallweit 	RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10);
3612f1bce4adSHeiner Kallweit 
3613f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc140, 0xffff);
3614f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc142, 0xffff);
3615f1bce4adSHeiner Kallweit 
3616f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x03a9);
3617f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
3618f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
3619f1bce4adSHeiner Kallweit 
3620f1bce4adSHeiner Kallweit 	/* disable new tx descriptor format */
3621f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
3622f1bce4adSHeiner Kallweit 
36230439297bSHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
36240439297bSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
36250439297bSHeiner Kallweit 	else
3626f1bce4adSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
36270439297bSHeiner Kallweit 
36280439297bSHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
36290439297bSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0000);
36300439297bSHeiner Kallweit 	else
3631f1bce4adSHeiner Kallweit 		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0020);
36320439297bSHeiner Kallweit 
3633f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xc0b4, 0x0000, 0x000c);
3634f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb6a, 0x00ff, 0x0033);
3635f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb50, 0x03e0, 0x0040);
3636f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
3637f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
36380439297bSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
3639f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403);
36400439297bSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0068);
3641f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f);
36420439297bSHeiner Kallweit 
3643f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
3644f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb54, 0x0000, 0x0001);
3645f1bce4adSHeiner Kallweit 	udelay(1);
3646f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xeb54, 0x0001, 0x0000);
3647f1bce4adSHeiner Kallweit 	RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~0x0030);
3648f1bce4adSHeiner Kallweit 
3649f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xe098, 0xc302);
3650f1bce4adSHeiner Kallweit 
3651d6836ef0SHeiner Kallweit 	rtl_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
3652f1bce4adSHeiner Kallweit 
36530439297bSHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
36540439297bSHeiner Kallweit 		rtl8125b_config_eee_mac(tp);
36550439297bSHeiner Kallweit 	else
36564640338cSHeiner Kallweit 		rtl8125a_config_eee_mac(tp);
3657b3a42e3aSHeiner Kallweit 
36583406079bSChunhao Lin 	rtl_disable_rxdvgate(tp);
3659f1bce4adSHeiner Kallweit }
3660f1bce4adSHeiner Kallweit 
rtl_hw_start_8125a_2(struct rtl8169_private * tp)36614640338cSHeiner Kallweit static void rtl_hw_start_8125a_2(struct rtl8169_private *tp)
3662f1bce4adSHeiner Kallweit {
36634640338cSHeiner Kallweit 	static const struct ephy_info e_info_8125a_2[] = {
3664f1bce4adSHeiner Kallweit 		{ 0x04, 0xffff, 0xd000 },
3665f1bce4adSHeiner Kallweit 		{ 0x0a, 0xffff, 0x8653 },
3666f1bce4adSHeiner Kallweit 		{ 0x23, 0xffff, 0xab66 },
3667f1bce4adSHeiner Kallweit 		{ 0x20, 0xffff, 0x9455 },
3668f1bce4adSHeiner Kallweit 		{ 0x21, 0xffff, 0x99ff },
3669f1bce4adSHeiner Kallweit 		{ 0x29, 0xffff, 0xfe04 },
3670f1bce4adSHeiner Kallweit 
3671f1bce4adSHeiner Kallweit 		{ 0x44, 0xffff, 0xd000 },
3672f1bce4adSHeiner Kallweit 		{ 0x4a, 0xffff, 0x8653 },
3673f1bce4adSHeiner Kallweit 		{ 0x63, 0xffff, 0xab66 },
3674f1bce4adSHeiner Kallweit 		{ 0x60, 0xffff, 0x9455 },
3675f1bce4adSHeiner Kallweit 		{ 0x61, 0xffff, 0x99ff },
3676f1bce4adSHeiner Kallweit 		{ 0x69, 0xffff, 0xfe04 },
3677f1bce4adSHeiner Kallweit 	};
3678f1bce4adSHeiner Kallweit 
3679f1bce4adSHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
36804640338cSHeiner Kallweit 	rtl_ephy_init(tp, e_info_8125a_2);
3681f1bce4adSHeiner Kallweit 	rtl_hw_start_8125_common(tp);
3682f1bce4adSHeiner Kallweit }
3683f1bce4adSHeiner Kallweit 
rtl_hw_start_8125b(struct rtl8169_private * tp)36840439297bSHeiner Kallweit static void rtl_hw_start_8125b(struct rtl8169_private *tp)
36850439297bSHeiner Kallweit {
36860439297bSHeiner Kallweit 	static const struct ephy_info e_info_8125b[] = {
36870439297bSHeiner Kallweit 		{ 0x0b, 0xffff, 0xa908 },
36880439297bSHeiner Kallweit 		{ 0x1e, 0xffff, 0x20eb },
36890439297bSHeiner Kallweit 		{ 0x4b, 0xffff, 0xa908 },
36900439297bSHeiner Kallweit 		{ 0x5e, 0xffff, 0x20eb },
36910439297bSHeiner Kallweit 		{ 0x22, 0x0030, 0x0020 },
36920439297bSHeiner Kallweit 		{ 0x62, 0x0030, 0x0020 },
36930439297bSHeiner Kallweit 	};
36940439297bSHeiner Kallweit 
36950439297bSHeiner Kallweit 	rtl_set_def_aspm_entry_latency(tp);
36960439297bSHeiner Kallweit 	rtl_ephy_init(tp, e_info_8125b);
36970439297bSHeiner Kallweit 	rtl_hw_start_8125_common(tp);
36980439297bSHeiner Kallweit }
36990439297bSHeiner Kallweit 
rtl_hw_config(struct rtl8169_private * tp)370025e992a4SHeiner Kallweit static void rtl_hw_config(struct rtl8169_private *tp)
370125e992a4SHeiner Kallweit {
370225e992a4SHeiner Kallweit 	static const rtl_generic_fct hw_configs[] = {
370325e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_07] = rtl_hw_start_8102e_1,
370425e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_08] = rtl_hw_start_8102e_3,
370525e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_09] = rtl_hw_start_8102e_2,
370625e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_10] = NULL,
370794b5ff74SHeiner Kallweit 		[RTL_GIGA_MAC_VER_11] = rtl_hw_start_8168b,
3708cdafdc29SHeiner Kallweit 		[RTL_GIGA_MAC_VER_14] = rtl_hw_start_8401,
370994b5ff74SHeiner Kallweit 		[RTL_GIGA_MAC_VER_17] = rtl_hw_start_8168b,
371025e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_18] = rtl_hw_start_8168cp_1,
371125e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_19] = rtl_hw_start_8168c_1,
371225e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_20] = rtl_hw_start_8168c_2,
371396ef6928SHeiner Kallweit 		[RTL_GIGA_MAC_VER_21] = rtl_hw_start_8168c_2,
371425e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_22] = rtl_hw_start_8168c_4,
371525e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_23] = rtl_hw_start_8168cp_2,
371625e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_24] = rtl_hw_start_8168cp_3,
371725e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_25] = rtl_hw_start_8168d,
371825e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_26] = rtl_hw_start_8168d,
371925e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_28] = rtl_hw_start_8168d_4,
372025e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_29] = rtl_hw_start_8105e_1,
372125e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_30] = rtl_hw_start_8105e_2,
37220a413e6bSHeiner Kallweit 		[RTL_GIGA_MAC_VER_31] = rtl_hw_start_8168d,
372325e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_32] = rtl_hw_start_8168e_1,
372425e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_33] = rtl_hw_start_8168e_1,
372525e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_34] = rtl_hw_start_8168e_2,
372625e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_35] = rtl_hw_start_8168f_1,
372725e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_36] = rtl_hw_start_8168f_1,
372825e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_37] = rtl_hw_start_8402,
372925e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_38] = rtl_hw_start_8411,
373025e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_39] = rtl_hw_start_8106,
373125e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_40] = rtl_hw_start_8168g_1,
373225e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_42] = rtl_hw_start_8168g_2,
373325e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_43] = rtl_hw_start_8168g_2,
373425e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_44] = rtl_hw_start_8411_2,
373525e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_46] = rtl_hw_start_8168h_1,
373625e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1,
373725e992a4SHeiner Kallweit 		[RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3,
37381287723aSHeiner Kallweit 		[RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117,
3739e6d6ca6eSKai-Heng Feng 		[RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
37404640338cSHeiner Kallweit 		[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
37410439297bSHeiner Kallweit 		[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
374225e992a4SHeiner Kallweit 	};
374325e992a4SHeiner Kallweit 
374425e992a4SHeiner Kallweit 	if (hw_configs[tp->mac_version])
374525e992a4SHeiner Kallweit 		hw_configs[tp->mac_version](tp);
374625e992a4SHeiner Kallweit }
374725e992a4SHeiner Kallweit 
rtl_hw_start_8125(struct rtl8169_private * tp)3748f1bce4adSHeiner Kallweit static void rtl_hw_start_8125(struct rtl8169_private *tp)
3749f1bce4adSHeiner Kallweit {
3750f1bce4adSHeiner Kallweit 	int i;
3751f1bce4adSHeiner Kallweit 
3752f1bce4adSHeiner Kallweit 	/* disable interrupt coalescing */
3753f1bce4adSHeiner Kallweit 	for (i = 0xa00; i < 0xb00; i += 4)
3754f1bce4adSHeiner Kallweit 		RTL_W32(tp, i, 0);
3755f1bce4adSHeiner Kallweit 
3756f1bce4adSHeiner Kallweit 	rtl_hw_config(tp);
3757f1bce4adSHeiner Kallweit }
3758f1bce4adSHeiner Kallweit 
rtl_hw_start_8168(struct rtl8169_private * tp)375925e992a4SHeiner Kallweit static void rtl_hw_start_8168(struct rtl8169_private *tp)
376025e992a4SHeiner Kallweit {
3761272b2265SHeiner Kallweit 	if (rtl_is_8168evl_up(tp))
3762272b2265SHeiner Kallweit 		RTL_W8(tp, MaxTxPacketSize, EarlySize);
3763272b2265SHeiner Kallweit 	else
376425e992a4SHeiner Kallweit 		RTL_W8(tp, MaxTxPacketSize, TxPacketMax);
376525e992a4SHeiner Kallweit 
376625e992a4SHeiner Kallweit 	rtl_hw_config(tp);
3767bcf2b868SHeiner Kallweit 
3768bcf2b868SHeiner Kallweit 	/* disable interrupt coalescing */
3769bcf2b868SHeiner Kallweit 	RTL_W16(tp, IntrMitigate, 0x0000);
377025e992a4SHeiner Kallweit }
377125e992a4SHeiner Kallweit 
rtl_hw_start_8169(struct rtl8169_private * tp)37726c19156eSHeiner Kallweit static void rtl_hw_start_8169(struct rtl8169_private *tp)
37736c19156eSHeiner Kallweit {
37746c19156eSHeiner Kallweit 	RTL_W8(tp, EarlyTxThres, NoEarlyTx);
37756c19156eSHeiner Kallweit 
37766c19156eSHeiner Kallweit 	tp->cp_cmd |= PCIMulRW;
37776c19156eSHeiner Kallweit 
37786c19156eSHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
377909e65335SHeiner Kallweit 	    tp->mac_version == RTL_GIGA_MAC_VER_03)
378009e65335SHeiner Kallweit 		tp->cp_cmd |= EnAnaPLL;
37816c19156eSHeiner Kallweit 
37826c19156eSHeiner Kallweit 	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
37836c19156eSHeiner Kallweit 
3784ef891284SHeiner Kallweit 	rtl8169_set_magic_reg(tp);
37856c19156eSHeiner Kallweit 
3786bcf2b868SHeiner Kallweit 	/* disable interrupt coalescing */
3787bcf2b868SHeiner Kallweit 	RTL_W16(tp, IntrMitigate, 0x0000);
37886c19156eSHeiner Kallweit }
37896c19156eSHeiner Kallweit 
rtl_hw_start(struct rtl8169_private * tp)37906c19156eSHeiner Kallweit static void rtl_hw_start(struct  rtl8169_private *tp)
37916c19156eSHeiner Kallweit {
37926c19156eSHeiner Kallweit 	rtl_unlock_config_regs(tp);
37935fc3f6c9SHeiner Kallweit 	/* disable aspm and clock request before ephy access */
37945fc3f6c9SHeiner Kallweit 	rtl_hw_aspm_clkreq_enable(tp, false);
37956c19156eSHeiner Kallweit 	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
37966c19156eSHeiner Kallweit 
37976c19156eSHeiner Kallweit 	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
37986c19156eSHeiner Kallweit 		rtl_hw_start_8169(tp);
3799f1bce4adSHeiner Kallweit 	else if (rtl_is_8125(tp))
3800f1bce4adSHeiner Kallweit 		rtl_hw_start_8125(tp);
38016c19156eSHeiner Kallweit 	else
38026c19156eSHeiner Kallweit 		rtl_hw_start_8168(tp);
38036c19156eSHeiner Kallweit 
38044b33433eSHeiner Kallweit 	rtl_enable_exit_l1(tp);
38055fc3f6c9SHeiner Kallweit 	rtl_hw_aspm_clkreq_enable(tp, true);
38066c19156eSHeiner Kallweit 	rtl_set_rx_max_size(tp);
38076c19156eSHeiner Kallweit 	rtl_set_rx_tx_desc_registers(tp);
38086c19156eSHeiner Kallweit 	rtl_lock_config_regs(tp);
38096c19156eSHeiner Kallweit 
38109db0ac57SHeiner Kallweit 	rtl_jumbo_config(tp);
38114ebcb113SHeiner Kallweit 
38126c19156eSHeiner Kallweit 	/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
3813711463f8SHeiner Kallweit 	rtl_pci_commit(tp);
3814711463f8SHeiner Kallweit 
38156c19156eSHeiner Kallweit 	RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb);
38166c19156eSHeiner Kallweit 	rtl_init_rxcfg(tp);
38176c19156eSHeiner Kallweit 	rtl_set_tx_config_registers(tp);
381810478283SHeiner Kallweit 	rtl_set_rx_config_features(tp, tp->dev->features);
38196c19156eSHeiner Kallweit 	rtl_set_rx_mode(tp->dev);
38206c19156eSHeiner Kallweit 	rtl_irq_enable(tp);
38216c19156eSHeiner Kallweit }
38226c19156eSHeiner Kallweit 
rtl8169_change_mtu(struct net_device * dev,int new_mtu)382325e992a4SHeiner Kallweit static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
382425e992a4SHeiner Kallweit {
382525e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
382625e992a4SHeiner Kallweit 
382725e992a4SHeiner Kallweit 	dev->mtu = new_mtu;
382825e992a4SHeiner Kallweit 	netdev_update_features(dev);
38299db0ac57SHeiner Kallweit 	rtl_jumbo_config(tp);
383025e992a4SHeiner Kallweit 
38310439297bSHeiner Kallweit 	switch (tp->mac_version) {
38320439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_61:
38330439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_63:
38340439297bSHeiner Kallweit 		rtl8125_set_eee_txidle_timer(tp);
38350439297bSHeiner Kallweit 		break;
38360439297bSHeiner Kallweit 	default:
38370439297bSHeiner Kallweit 		break;
38380439297bSHeiner Kallweit 	}
38390439297bSHeiner Kallweit 
384025e992a4SHeiner Kallweit 	return 0;
384125e992a4SHeiner Kallweit }
384225e992a4SHeiner Kallweit 
rtl8169_mark_to_asic(struct RxDesc * desc)3843e2e5fb8dSHeiner Kallweit static void rtl8169_mark_to_asic(struct RxDesc *desc)
384425e992a4SHeiner Kallweit {
384525e992a4SHeiner Kallweit 	u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
384625e992a4SHeiner Kallweit 
3847047521d7SHeiner Kallweit 	desc->opts2 = 0;
384825e992a4SHeiner Kallweit 	/* Force memory writes to complete before releasing descriptor */
384925e992a4SHeiner Kallweit 	dma_wmb();
3850e2e5fb8dSHeiner Kallweit 	WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE));
385125e992a4SHeiner Kallweit }
385225e992a4SHeiner Kallweit 
rtl8169_alloc_rx_data(struct rtl8169_private * tp,struct RxDesc * desc)385332879f00SHeiner Kallweit static struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
385425e992a4SHeiner Kallweit 					  struct RxDesc *desc)
385525e992a4SHeiner Kallweit {
385625e992a4SHeiner Kallweit 	struct device *d = tp_to_dev(tp);
385725e992a4SHeiner Kallweit 	int node = dev_to_node(d);
385832879f00SHeiner Kallweit 	dma_addr_t mapping;
385932879f00SHeiner Kallweit 	struct page *data;
386025e992a4SHeiner Kallweit 
386132879f00SHeiner Kallweit 	data = alloc_pages_node(node, GFP_KERNEL, get_order(R8169_RX_BUF_SIZE));
386225e992a4SHeiner Kallweit 	if (!data)
386325e992a4SHeiner Kallweit 		return NULL;
386425e992a4SHeiner Kallweit 
386532879f00SHeiner Kallweit 	mapping = dma_map_page(d, data, 0, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
386625e992a4SHeiner Kallweit 	if (unlikely(dma_mapping_error(d, mapping))) {
386793882c6fSHeiner Kallweit 		netdev_err(tp->dev, "Failed to map RX DMA!\n");
386832879f00SHeiner Kallweit 		__free_pages(data, get_order(R8169_RX_BUF_SIZE));
386932879f00SHeiner Kallweit 		return NULL;
387025e992a4SHeiner Kallweit 	}
387125e992a4SHeiner Kallweit 
387225e992a4SHeiner Kallweit 	desc->addr = cpu_to_le64(mapping);
387325e992a4SHeiner Kallweit 	rtl8169_mark_to_asic(desc);
387425e992a4SHeiner Kallweit 
387532879f00SHeiner Kallweit 	return data;
387625e992a4SHeiner Kallweit }
387725e992a4SHeiner Kallweit 
rtl8169_rx_clear(struct rtl8169_private * tp)387825e992a4SHeiner Kallweit static void rtl8169_rx_clear(struct rtl8169_private *tp)
387925e992a4SHeiner Kallweit {
3880ed22a8ffSHeiner Kallweit 	int i;
388125e992a4SHeiner Kallweit 
3882eb2e7f09SHeiner Kallweit 	for (i = 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) {
3883eb2e7f09SHeiner Kallweit 		dma_unmap_page(tp_to_dev(tp),
3884eb2e7f09SHeiner Kallweit 			       le64_to_cpu(tp->RxDescArray[i].addr),
3885eb2e7f09SHeiner Kallweit 			       R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
3886eb2e7f09SHeiner Kallweit 		__free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE));
3887eb2e7f09SHeiner Kallweit 		tp->Rx_databuff[i] = NULL;
38889d3679feSHeiner Kallweit 		tp->RxDescArray[i].addr = 0;
38899d3679feSHeiner Kallweit 		tp->RxDescArray[i].opts1 = 0;
389025e992a4SHeiner Kallweit 	}
389125e992a4SHeiner Kallweit }
389225e992a4SHeiner Kallweit 
rtl8169_rx_fill(struct rtl8169_private * tp)389325e992a4SHeiner Kallweit static int rtl8169_rx_fill(struct rtl8169_private *tp)
389425e992a4SHeiner Kallweit {
3895ed22a8ffSHeiner Kallweit 	int i;
389625e992a4SHeiner Kallweit 
389725e992a4SHeiner Kallweit 	for (i = 0; i < NUM_RX_DESC; i++) {
389832879f00SHeiner Kallweit 		struct page *data;
389925e992a4SHeiner Kallweit 
390025e992a4SHeiner Kallweit 		data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
390125e992a4SHeiner Kallweit 		if (!data) {
3902e4b5c7a5SHeiner Kallweit 			rtl8169_rx_clear(tp);
3903e4b5c7a5SHeiner Kallweit 			return -ENOMEM;
390425e992a4SHeiner Kallweit 		}
390525e992a4SHeiner Kallweit 		tp->Rx_databuff[i] = data;
390625e992a4SHeiner Kallweit 	}
390725e992a4SHeiner Kallweit 
39082ac1fa43SHeiner Kallweit 	/* mark as last descriptor in the ring */
39092ac1fa43SHeiner Kallweit 	tp->RxDescArray[NUM_RX_DESC - 1].opts1 |= cpu_to_le32(RingEnd);
391025e992a4SHeiner Kallweit 
3911e4b5c7a5SHeiner Kallweit 	return 0;
391225e992a4SHeiner Kallweit }
391325e992a4SHeiner Kallweit 
rtl8169_init_ring(struct rtl8169_private * tp)391425e992a4SHeiner Kallweit static int rtl8169_init_ring(struct rtl8169_private *tp)
391525e992a4SHeiner Kallweit {
391625e992a4SHeiner Kallweit 	rtl8169_init_ring_indexes(tp);
391725e992a4SHeiner Kallweit 
391825e992a4SHeiner Kallweit 	memset(tp->tx_skb, 0, sizeof(tp->tx_skb));
391925e992a4SHeiner Kallweit 	memset(tp->Rx_databuff, 0, sizeof(tp->Rx_databuff));
392025e992a4SHeiner Kallweit 
392125e992a4SHeiner Kallweit 	return rtl8169_rx_fill(tp);
392225e992a4SHeiner Kallweit }
392325e992a4SHeiner Kallweit 
rtl8169_unmap_tx_skb(struct rtl8169_private * tp,unsigned int entry)392422d352c5SHeiner Kallweit static void rtl8169_unmap_tx_skb(struct rtl8169_private *tp, unsigned int entry)
392525e992a4SHeiner Kallweit {
392622d352c5SHeiner Kallweit 	struct ring_info *tx_skb = tp->tx_skb + entry;
392722d352c5SHeiner Kallweit 	struct TxDesc *desc = tp->TxDescArray + entry;
392825e992a4SHeiner Kallweit 
392922d352c5SHeiner Kallweit 	dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), tx_skb->len,
393022d352c5SHeiner Kallweit 			 DMA_TO_DEVICE);
39316a41f2b2SHeiner Kallweit 	memset(desc, 0, sizeof(*desc));
39326a41f2b2SHeiner Kallweit 	memset(tx_skb, 0, sizeof(*tx_skb));
393325e992a4SHeiner Kallweit }
393425e992a4SHeiner Kallweit 
rtl8169_tx_clear_range(struct rtl8169_private * tp,u32 start,unsigned int n)393525e992a4SHeiner Kallweit static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
393625e992a4SHeiner Kallweit 				   unsigned int n)
393725e992a4SHeiner Kallweit {
393825e992a4SHeiner Kallweit 	unsigned int i;
393925e992a4SHeiner Kallweit 
394025e992a4SHeiner Kallweit 	for (i = 0; i < n; i++) {
394125e992a4SHeiner Kallweit 		unsigned int entry = (start + i) % NUM_TX_DESC;
394225e992a4SHeiner Kallweit 		struct ring_info *tx_skb = tp->tx_skb + entry;
394325e992a4SHeiner Kallweit 		unsigned int len = tx_skb->len;
394425e992a4SHeiner Kallweit 
394525e992a4SHeiner Kallweit 		if (len) {
394625e992a4SHeiner Kallweit 			struct sk_buff *skb = tx_skb->skb;
394725e992a4SHeiner Kallweit 
394822d352c5SHeiner Kallweit 			rtl8169_unmap_tx_skb(tp, entry);
39496a41f2b2SHeiner Kallweit 			if (skb)
395025e992a4SHeiner Kallweit 				dev_consume_skb_any(skb);
395125e992a4SHeiner Kallweit 		}
395225e992a4SHeiner Kallweit 	}
395325e992a4SHeiner Kallweit }
395425e992a4SHeiner Kallweit 
rtl8169_tx_clear(struct rtl8169_private * tp)395525e992a4SHeiner Kallweit static void rtl8169_tx_clear(struct rtl8169_private *tp)
395625e992a4SHeiner Kallweit {
395725e992a4SHeiner Kallweit 	rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
395825e992a4SHeiner Kallweit 	netdev_reset_queue(tp->dev);
395925e992a4SHeiner Kallweit }
396025e992a4SHeiner Kallweit 
rtl8169_cleanup(struct rtl8169_private * tp)3961bb41c13cSChunhao Lin static void rtl8169_cleanup(struct rtl8169_private *tp)
3962bac75d85SHeiner Kallweit {
39630c28a63aSHeiner Kallweit 	napi_disable(&tp->napi);
39640c28a63aSHeiner Kallweit 
3965bac75d85SHeiner Kallweit 	/* Give a racing hard_start_xmit a few cycles to complete. */
39667190aeecSHeiner Kallweit 	synchronize_net();
3967bac75d85SHeiner Kallweit 
3968bac75d85SHeiner Kallweit 	/* Disable interrupts */
3969bac75d85SHeiner Kallweit 	rtl8169_irq_mask_and_ack(tp);
3970bac75d85SHeiner Kallweit 
3971bac75d85SHeiner Kallweit 	rtl_rx_close(tp);
3972bac75d85SHeiner Kallweit 
3973bac75d85SHeiner Kallweit 	switch (tp->mac_version) {
3974bac75d85SHeiner Kallweit 	case RTL_GIGA_MAC_VER_28:
3975bac75d85SHeiner Kallweit 	case RTL_GIGA_MAC_VER_31:
3976bac75d85SHeiner Kallweit 		rtl_loop_wait_low(tp, &rtl_npq_cond, 20, 2000);
3977bac75d85SHeiner Kallweit 		break;
3978bac75d85SHeiner Kallweit 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
3979bac75d85SHeiner Kallweit 		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
3980bac75d85SHeiner Kallweit 		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
3981bac75d85SHeiner Kallweit 		break;
39820439297bSHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
3983bac75d85SHeiner Kallweit 		rtl_enable_rxdvgate(tp);
3984bac75d85SHeiner Kallweit 		fsleep(2000);
3985bac75d85SHeiner Kallweit 		break;
3986bac75d85SHeiner Kallweit 	default:
3987bac75d85SHeiner Kallweit 		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
3988bac75d85SHeiner Kallweit 		fsleep(100);
3989bac75d85SHeiner Kallweit 		break;
3990bac75d85SHeiner Kallweit 	}
3991bac75d85SHeiner Kallweit 
3992bac75d85SHeiner Kallweit 	rtl_hw_reset(tp);
3993bb41c13cSChunhao Lin 
3994bac75d85SHeiner Kallweit 	rtl8169_tx_clear(tp);
3995bac75d85SHeiner Kallweit 	rtl8169_init_ring_indexes(tp);
3996bac75d85SHeiner Kallweit }
3997bac75d85SHeiner Kallweit 
rtl_reset_work(struct rtl8169_private * tp)399825e992a4SHeiner Kallweit static void rtl_reset_work(struct rtl8169_private *tp)
399925e992a4SHeiner Kallweit {
400025e992a4SHeiner Kallweit 	int i;
400125e992a4SHeiner Kallweit 
4002476c4f5dSHeiner Kallweit 	netif_stop_queue(tp->dev);
400325e992a4SHeiner Kallweit 
4004bb41c13cSChunhao Lin 	rtl8169_cleanup(tp);
400525e992a4SHeiner Kallweit 
400625e992a4SHeiner Kallweit 	for (i = 0; i < NUM_RX_DESC; i++)
400725e992a4SHeiner Kallweit 		rtl8169_mark_to_asic(tp->RxDescArray + i);
400825e992a4SHeiner Kallweit 
400925e992a4SHeiner Kallweit 	napi_enable(&tp->napi);
401025e992a4SHeiner Kallweit 	rtl_hw_start(tp);
401125e992a4SHeiner Kallweit }
401225e992a4SHeiner Kallweit 
rtl8169_tx_timeout(struct net_device * dev,unsigned int txqueue)40130290bd29SMichael S. Tsirkin static void rtl8169_tx_timeout(struct net_device *dev, unsigned int txqueue)
401425e992a4SHeiner Kallweit {
401525e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
401625e992a4SHeiner Kallweit 
401780c0576eSHeiner Kallweit 	rtl_schedule_task(tp, RTL_FLAG_TASK_TX_TIMEOUT);
401825e992a4SHeiner Kallweit }
401925e992a4SHeiner Kallweit 
rtl8169_tx_map(struct rtl8169_private * tp,const u32 * opts,u32 len,void * addr,unsigned int entry,bool desc_own)4020b8447abcSHeiner Kallweit static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len,
4021b8447abcSHeiner Kallweit 			  void *addr, unsigned int entry, bool desc_own)
402225e992a4SHeiner Kallweit {
4023b8447abcSHeiner Kallweit 	struct TxDesc *txd = tp->TxDescArray + entry;
4024b8447abcSHeiner Kallweit 	struct device *d = tp_to_dev(tp);
4025b8447abcSHeiner Kallweit 	dma_addr_t mapping;
4026b8447abcSHeiner Kallweit 	u32 opts1;
4027b8447abcSHeiner Kallweit 	int ret;
402825e992a4SHeiner Kallweit 
4029b8447abcSHeiner Kallweit 	mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
4030b8447abcSHeiner Kallweit 	ret = dma_mapping_error(d, mapping);
4031b8447abcSHeiner Kallweit 	if (unlikely(ret)) {
4032b8447abcSHeiner Kallweit 		if (net_ratelimit())
403393882c6fSHeiner Kallweit 			netdev_err(tp->dev, "Failed to map TX data!\n");
4034b8447abcSHeiner Kallweit 		return ret;
4035b8447abcSHeiner Kallweit 	}
4036b8447abcSHeiner Kallweit 
4037b8447abcSHeiner Kallweit 	txd->addr = cpu_to_le64(mapping);
4038b8447abcSHeiner Kallweit 	txd->opts2 = cpu_to_le32(opts[1]);
4039b8447abcSHeiner Kallweit 
4040b8447abcSHeiner Kallweit 	opts1 = opts[0] | len;
404125e992a4SHeiner Kallweit 	if (entry == NUM_TX_DESC - 1)
4042b8447abcSHeiner Kallweit 		opts1 |= RingEnd;
4043b8447abcSHeiner Kallweit 	if (desc_own)
4044b8447abcSHeiner Kallweit 		opts1 |= DescOwn;
4045b8447abcSHeiner Kallweit 	txd->opts1 = cpu_to_le32(opts1);
404625e992a4SHeiner Kallweit 
4047b8447abcSHeiner Kallweit 	tp->tx_skb[entry].len = len;
4048b8447abcSHeiner Kallweit 
4049b8447abcSHeiner Kallweit 	return 0;
405025e992a4SHeiner Kallweit }
405125e992a4SHeiner Kallweit 
rtl8169_xmit_frags(struct rtl8169_private * tp,struct sk_buff * skb,const u32 * opts,unsigned int entry)405225e992a4SHeiner Kallweit static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
4053b8447abcSHeiner Kallweit 			      const u32 *opts, unsigned int entry)
405425e992a4SHeiner Kallweit {
405525e992a4SHeiner Kallweit 	struct skb_shared_info *info = skb_shinfo(skb);
4056b8447abcSHeiner Kallweit 	unsigned int cur_frag;
405725e992a4SHeiner Kallweit 
405825e992a4SHeiner Kallweit 	for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
405925e992a4SHeiner Kallweit 		const skb_frag_t *frag = info->frags + cur_frag;
4060b8447abcSHeiner Kallweit 		void *addr = skb_frag_address(frag);
4061b8447abcSHeiner Kallweit 		u32 len = skb_frag_size(frag);
406225e992a4SHeiner Kallweit 
406325e992a4SHeiner Kallweit 		entry = (entry + 1) % NUM_TX_DESC;
406425e992a4SHeiner Kallweit 
4065b8447abcSHeiner Kallweit 		if (unlikely(rtl8169_tx_map(tp, opts, len, addr, entry, true)))
406625e992a4SHeiner Kallweit 			goto err_out;
406725e992a4SHeiner Kallweit 	}
406825e992a4SHeiner Kallweit 
40699020845fSHeiner Kallweit 	return 0;
407025e992a4SHeiner Kallweit 
407125e992a4SHeiner Kallweit err_out:
407225e992a4SHeiner Kallweit 	rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
407325e992a4SHeiner Kallweit 	return -EIO;
407425e992a4SHeiner Kallweit }
407525e992a4SHeiner Kallweit 
rtl_skb_is_udp(struct sk_buff * skb)40768d520b4dSHeiner Kallweit static bool rtl_skb_is_udp(struct sk_buff *skb)
407725e992a4SHeiner Kallweit {
40788d520b4dSHeiner Kallweit 	int no = skb_network_offset(skb);
40798d520b4dSHeiner Kallweit 	struct ipv6hdr *i6h, _i6h;
40808d520b4dSHeiner Kallweit 	struct iphdr *ih, _ih;
40818d520b4dSHeiner Kallweit 
40828d520b4dSHeiner Kallweit 	switch (vlan_get_protocol(skb)) {
40838d520b4dSHeiner Kallweit 	case htons(ETH_P_IP):
40848d520b4dSHeiner Kallweit 		ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
40858d520b4dSHeiner Kallweit 		return ih && ih->protocol == IPPROTO_UDP;
40868d520b4dSHeiner Kallweit 	case htons(ETH_P_IPV6):
40878d520b4dSHeiner Kallweit 		i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
40888d520b4dSHeiner Kallweit 		return i6h && i6h->nexthdr == IPPROTO_UDP;
40898d520b4dSHeiner Kallweit 	default:
40908d520b4dSHeiner Kallweit 		return false;
40918d520b4dSHeiner Kallweit 	}
40928d520b4dSHeiner Kallweit }
40938d520b4dSHeiner Kallweit 
40948d520b4dSHeiner Kallweit #define RTL_MIN_PATCH_LEN	47
40958d520b4dSHeiner Kallweit 
40968d520b4dSHeiner Kallweit /* see rtl8125_get_patch_pad_len() in r8125 vendor driver */
rtl8125_quirk_udp_padto(struct rtl8169_private * tp,struct sk_buff * skb)40978d520b4dSHeiner Kallweit static unsigned int rtl8125_quirk_udp_padto(struct rtl8169_private *tp,
40988d520b4dSHeiner Kallweit 					    struct sk_buff *skb)
40998d520b4dSHeiner Kallweit {
41008d520b4dSHeiner Kallweit 	unsigned int padto = 0, len = skb->len;
41018d520b4dSHeiner Kallweit 
41028d520b4dSHeiner Kallweit 	if (rtl_is_8125(tp) && len < 128 + RTL_MIN_PATCH_LEN &&
41038d520b4dSHeiner Kallweit 	    rtl_skb_is_udp(skb) && skb_transport_header_was_set(skb)) {
41048d520b4dSHeiner Kallweit 		unsigned int trans_data_len = skb_tail_pointer(skb) -
41058d520b4dSHeiner Kallweit 					      skb_transport_header(skb);
41068d520b4dSHeiner Kallweit 
41078d520b4dSHeiner Kallweit 		if (trans_data_len >= offsetof(struct udphdr, len) &&
41088d520b4dSHeiner Kallweit 		    trans_data_len < RTL_MIN_PATCH_LEN) {
41098d520b4dSHeiner Kallweit 			u16 dest = ntohs(udp_hdr(skb)->dest);
41108d520b4dSHeiner Kallweit 
41118d520b4dSHeiner Kallweit 			/* dest is a standard PTP port */
41128d520b4dSHeiner Kallweit 			if (dest == 319 || dest == 320)
41138d520b4dSHeiner Kallweit 				padto = len + RTL_MIN_PATCH_LEN - trans_data_len;
41148d520b4dSHeiner Kallweit 		}
41158d520b4dSHeiner Kallweit 
41168d520b4dSHeiner Kallweit 		if (trans_data_len < sizeof(struct udphdr))
41178d520b4dSHeiner Kallweit 			padto = max_t(unsigned int, padto,
41188d520b4dSHeiner Kallweit 				      len + sizeof(struct udphdr) - trans_data_len);
41198d520b4dSHeiner Kallweit 	}
41208d520b4dSHeiner Kallweit 
41218d520b4dSHeiner Kallweit 	return padto;
41228d520b4dSHeiner Kallweit }
41238d520b4dSHeiner Kallweit 
rtl_quirk_packet_padto(struct rtl8169_private * tp,struct sk_buff * skb)41248d520b4dSHeiner Kallweit static unsigned int rtl_quirk_packet_padto(struct rtl8169_private *tp,
41258d520b4dSHeiner Kallweit 					   struct sk_buff *skb)
41268d520b4dSHeiner Kallweit {
41278d520b4dSHeiner Kallweit 	unsigned int padto;
41288d520b4dSHeiner Kallweit 
41298d520b4dSHeiner Kallweit 	padto = rtl8125_quirk_udp_padto(tp, skb);
41308d520b4dSHeiner Kallweit 
41312aaf09a0SHeiner Kallweit 	switch (tp->mac_version) {
41322aaf09a0SHeiner Kallweit 	case RTL_GIGA_MAC_VER_34:
41332aaf09a0SHeiner Kallweit 	case RTL_GIGA_MAC_VER_61:
41342aaf09a0SHeiner Kallweit 	case RTL_GIGA_MAC_VER_63:
41358d520b4dSHeiner Kallweit 		padto = max_t(unsigned int, padto, ETH_ZLEN);
4136ffb35c67SGustavo A. R. Silva 		break;
41372aaf09a0SHeiner Kallweit 	default:
41388d520b4dSHeiner Kallweit 		break;
41392aaf09a0SHeiner Kallweit 	}
41408d520b4dSHeiner Kallweit 
41418d520b4dSHeiner Kallweit 	return padto;
414225e992a4SHeiner Kallweit }
414325e992a4SHeiner Kallweit 
rtl8169_tso_csum_v1(struct sk_buff * skb,u32 * opts)414425e992a4SHeiner Kallweit static void rtl8169_tso_csum_v1(struct sk_buff *skb, u32 *opts)
414525e992a4SHeiner Kallweit {
414625e992a4SHeiner Kallweit 	u32 mss = skb_shinfo(skb)->gso_size;
414725e992a4SHeiner Kallweit 
414825e992a4SHeiner Kallweit 	if (mss) {
414925e992a4SHeiner Kallweit 		opts[0] |= TD_LSO;
41504abc3c04SHeiner Kallweit 		opts[0] |= mss << TD0_MSS_SHIFT;
415125e992a4SHeiner Kallweit 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
415225e992a4SHeiner Kallweit 		const struct iphdr *ip = ip_hdr(skb);
415325e992a4SHeiner Kallweit 
415425e992a4SHeiner Kallweit 		if (ip->protocol == IPPROTO_TCP)
415525e992a4SHeiner Kallweit 			opts[0] |= TD0_IP_CS | TD0_TCP_CS;
415625e992a4SHeiner Kallweit 		else if (ip->protocol == IPPROTO_UDP)
415725e992a4SHeiner Kallweit 			opts[0] |= TD0_IP_CS | TD0_UDP_CS;
415825e992a4SHeiner Kallweit 		else
415925e992a4SHeiner Kallweit 			WARN_ON_ONCE(1);
416025e992a4SHeiner Kallweit 	}
416125e992a4SHeiner Kallweit }
416225e992a4SHeiner Kallweit 
rtl8169_tso_csum_v2(struct rtl8169_private * tp,struct sk_buff * skb,u32 * opts)416325e992a4SHeiner Kallweit static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
416425e992a4SHeiner Kallweit 				struct sk_buff *skb, u32 *opts)
416525e992a4SHeiner Kallweit {
41660623b98bSHeiner Kallweit 	struct skb_shared_info *shinfo = skb_shinfo(skb);
41670623b98bSHeiner Kallweit 	u32 mss = shinfo->gso_size;
416825e992a4SHeiner Kallweit 
416925e992a4SHeiner Kallweit 	if (mss) {
41700623b98bSHeiner Kallweit 		if (shinfo->gso_type & SKB_GSO_TCPV4) {
417125e992a4SHeiner Kallweit 			opts[0] |= TD1_GTSENV4;
41720623b98bSHeiner Kallweit 		} else if (shinfo->gso_type & SKB_GSO_TCPV6) {
41738b19c68cSHeiner Kallweit 			if (skb_cow_head(skb, 0))
417425e992a4SHeiner Kallweit 				return false;
417525e992a4SHeiner Kallweit 
41768b19c68cSHeiner Kallweit 			tcp_v6_gso_csum_prep(skb);
417725e992a4SHeiner Kallweit 			opts[0] |= TD1_GTSENV6;
41780623b98bSHeiner Kallweit 		} else {
417925e992a4SHeiner Kallweit 			WARN_ON_ONCE(1);
418025e992a4SHeiner Kallweit 		}
418125e992a4SHeiner Kallweit 
4182faa4e04eSHeiner Kallweit 		opts[0] |= skb_transport_offset(skb) << GTTCPHO_SHIFT;
41834abc3c04SHeiner Kallweit 		opts[1] |= mss << TD1_MSS_SHIFT;
418425e992a4SHeiner Kallweit 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
418525e992a4SHeiner Kallweit 		u8 ip_protocol;
418625e992a4SHeiner Kallweit 
418725e992a4SHeiner Kallweit 		switch (vlan_get_protocol(skb)) {
418825e992a4SHeiner Kallweit 		case htons(ETH_P_IP):
418925e992a4SHeiner Kallweit 			opts[1] |= TD1_IPv4_CS;
419025e992a4SHeiner Kallweit 			ip_protocol = ip_hdr(skb)->protocol;
419125e992a4SHeiner Kallweit 			break;
419225e992a4SHeiner Kallweit 
419325e992a4SHeiner Kallweit 		case htons(ETH_P_IPV6):
419425e992a4SHeiner Kallweit 			opts[1] |= TD1_IPv6_CS;
419525e992a4SHeiner Kallweit 			ip_protocol = ipv6_hdr(skb)->nexthdr;
419625e992a4SHeiner Kallweit 			break;
419725e992a4SHeiner Kallweit 
419825e992a4SHeiner Kallweit 		default:
419925e992a4SHeiner Kallweit 			ip_protocol = IPPROTO_RAW;
420025e992a4SHeiner Kallweit 			break;
420125e992a4SHeiner Kallweit 		}
420225e992a4SHeiner Kallweit 
420325e992a4SHeiner Kallweit 		if (ip_protocol == IPPROTO_TCP)
420425e992a4SHeiner Kallweit 			opts[1] |= TD1_TCP_CS;
420525e992a4SHeiner Kallweit 		else if (ip_protocol == IPPROTO_UDP)
420625e992a4SHeiner Kallweit 			opts[1] |= TD1_UDP_CS;
420725e992a4SHeiner Kallweit 		else
420825e992a4SHeiner Kallweit 			WARN_ON_ONCE(1);
420925e992a4SHeiner Kallweit 
4210faa4e04eSHeiner Kallweit 		opts[1] |= skb_transport_offset(skb) << TCPHO_SHIFT;
421125e992a4SHeiner Kallweit 	} else {
42128d520b4dSHeiner Kallweit 		unsigned int padto = rtl_quirk_packet_padto(tp, skb);
42138d520b4dSHeiner Kallweit 
42148d520b4dSHeiner Kallweit 		/* skb_padto would free the skb on error */
42158d520b4dSHeiner Kallweit 		return !__skb_put_padto(skb, padto, false);
421625e992a4SHeiner Kallweit 	}
421725e992a4SHeiner Kallweit 
421825e992a4SHeiner Kallweit 	return true;
421925e992a4SHeiner Kallweit }
422025e992a4SHeiner Kallweit 
rtl_tx_slots_avail(struct rtl8169_private * tp)42218624e9bbSHeiner Kallweit static unsigned int rtl_tx_slots_avail(struct rtl8169_private *tp)
422225e992a4SHeiner Kallweit {
42238624e9bbSHeiner Kallweit 	return READ_ONCE(tp->dirty_tx) + NUM_TX_DESC - READ_ONCE(tp->cur_tx);
422425e992a4SHeiner Kallweit }
422525e992a4SHeiner Kallweit 
422625e992a4SHeiner Kallweit /* Versions RTL8102e and from RTL8168c onwards support csum_v2 */
rtl_chip_supports_csum_v2(struct rtl8169_private * tp)422725e992a4SHeiner Kallweit static bool rtl_chip_supports_csum_v2(struct rtl8169_private *tp)
422825e992a4SHeiner Kallweit {
422925e992a4SHeiner Kallweit 	switch (tp->mac_version) {
423025e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
423125e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_10 ... RTL_GIGA_MAC_VER_17:
423225e992a4SHeiner Kallweit 		return false;
423325e992a4SHeiner Kallweit 	default:
423425e992a4SHeiner Kallweit 		return true;
423525e992a4SHeiner Kallweit 	}
423625e992a4SHeiner Kallweit }
423725e992a4SHeiner Kallweit 
rtl8169_doorbell(struct rtl8169_private * tp)4238f1bce4adSHeiner Kallweit static void rtl8169_doorbell(struct rtl8169_private *tp)
4239f1bce4adSHeiner Kallweit {
4240f1bce4adSHeiner Kallweit 	if (rtl_is_8125(tp))
4241f1bce4adSHeiner Kallweit 		RTL_W16(tp, TxPoll_8125, BIT(0));
4242f1bce4adSHeiner Kallweit 	else
4243f1bce4adSHeiner Kallweit 		RTL_W8(tp, TxPoll, NPQ);
4244f1bce4adSHeiner Kallweit }
4245f1bce4adSHeiner Kallweit 
rtl8169_start_xmit(struct sk_buff * skb,struct net_device * dev)424625e992a4SHeiner Kallweit static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
424725e992a4SHeiner Kallweit 				      struct net_device *dev)
424825e992a4SHeiner Kallweit {
424925e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
425025e992a4SHeiner Kallweit 	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
4251b8447abcSHeiner Kallweit 	struct TxDesc *txd_first, *txd_last;
4252b8447abcSHeiner Kallweit 	bool stop_queue, door_bell;
425368222d7bSKen Milmore 	unsigned int frags;
4254b8447abcSHeiner Kallweit 	u32 opts[2];
4255b8447abcSHeiner Kallweit 
425683c317d7SHeiner Kallweit 	if (unlikely(!rtl_tx_slots_avail(tp))) {
425793882c6fSHeiner Kallweit 		if (net_ratelimit())
425893882c6fSHeiner Kallweit 			netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
425925e992a4SHeiner Kallweit 		goto err_stop_0;
426025e992a4SHeiner Kallweit 	}
426125e992a4SHeiner Kallweit 
4262355f948aSHeiner Kallweit 	opts[1] = rtl8169_tx_vlan_tag(skb);
4263b8447abcSHeiner Kallweit 	opts[0] = 0;
426425e992a4SHeiner Kallweit 
4265b8447abcSHeiner Kallweit 	if (!rtl_chip_supports_csum_v2(tp))
426625e992a4SHeiner Kallweit 		rtl8169_tso_csum_v1(skb, opts);
4267b8447abcSHeiner Kallweit 	else if (!rtl8169_tso_csum_v2(tp, skb, opts))
426825e992a4SHeiner Kallweit 		goto err_dma_0;
426925e992a4SHeiner Kallweit 
4270b8447abcSHeiner Kallweit 	if (unlikely(rtl8169_tx_map(tp, opts, skb_headlen(skb), skb->data,
4271b8447abcSHeiner Kallweit 				    entry, false)))
4272b8447abcSHeiner Kallweit 		goto err_dma_0;
427325e992a4SHeiner Kallweit 
4274bd4bdeb4SHeiner Kallweit 	txd_first = tp->TxDescArray + entry;
4275bd4bdeb4SHeiner Kallweit 
427668222d7bSKen Milmore 	frags = skb_shinfo(skb)->nr_frags;
4277b8447abcSHeiner Kallweit 	if (frags) {
4278b8447abcSHeiner Kallweit 		if (rtl8169_xmit_frags(tp, skb, opts, entry))
42799020845fSHeiner Kallweit 			goto err_dma_1;
4280b8447abcSHeiner Kallweit 		entry = (entry + frags) % NUM_TX_DESC;
428125e992a4SHeiner Kallweit 	}
428225e992a4SHeiner Kallweit 
4283b8447abcSHeiner Kallweit 	txd_last = tp->TxDescArray + entry;
4284b8447abcSHeiner Kallweit 	txd_last->opts1 |= cpu_to_le32(LastFrag);
4285b8447abcSHeiner Kallweit 	tp->tx_skb[entry].skb = skb;
428625e992a4SHeiner Kallweit 
428725e992a4SHeiner Kallweit 	skb_tx_timestamp(skb);
428825e992a4SHeiner Kallweit 
428925e992a4SHeiner Kallweit 	/* Force memory writes to complete before releasing descriptor */
429025e992a4SHeiner Kallweit 	dma_wmb();
429125e992a4SHeiner Kallweit 
4292ef143585SHeiner Kallweit 	door_bell = __netdev_sent_queue(dev, skb->len, netdev_xmit_more());
4293ef143585SHeiner Kallweit 
4294b8447abcSHeiner Kallweit 	txd_first->opts1 |= cpu_to_le32(DescOwn | FirstFrag);
429525e992a4SHeiner Kallweit 
4296794867eeSHeiner Kallweit 	/* rtl_tx needs to see descriptor changes before updated tp->cur_tx */
4297794867eeSHeiner Kallweit 	smp_wmb();
429825e992a4SHeiner Kallweit 
429941294e6aSHeiner Kallweit 	WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1);
430025e992a4SHeiner Kallweit 
43018624e9bbSHeiner Kallweit 	stop_queue = !netif_subqueue_maybe_stop(dev, 0, rtl_tx_slots_avail(tp),
43028624e9bbSHeiner Kallweit 						R8169_TX_STOP_THRS,
43038624e9bbSHeiner Kallweit 						R8169_TX_START_THRS);
43048624e9bbSHeiner Kallweit 	if (door_bell || stop_queue)
430541294e6aSHeiner Kallweit 		rtl8169_doorbell(tp);
430641294e6aSHeiner Kallweit 
430725e992a4SHeiner Kallweit 	return NETDEV_TX_OK;
430825e992a4SHeiner Kallweit 
430925e992a4SHeiner Kallweit err_dma_1:
431022d352c5SHeiner Kallweit 	rtl8169_unmap_tx_skb(tp, entry);
431125e992a4SHeiner Kallweit err_dma_0:
431225e992a4SHeiner Kallweit 	dev_kfree_skb_any(skb);
431325e992a4SHeiner Kallweit 	dev->stats.tx_dropped++;
431425e992a4SHeiner Kallweit 	return NETDEV_TX_OK;
431525e992a4SHeiner Kallweit 
431625e992a4SHeiner Kallweit err_stop_0:
431725e992a4SHeiner Kallweit 	netif_stop_queue(dev);
431825e992a4SHeiner Kallweit 	dev->stats.tx_dropped++;
431925e992a4SHeiner Kallweit 	return NETDEV_TX_BUSY;
432025e992a4SHeiner Kallweit }
432125e992a4SHeiner Kallweit 
rtl_last_frag_len(struct sk_buff * skb)4322773235f4SHeiner Kallweit static unsigned int rtl_last_frag_len(struct sk_buff *skb)
4323773235f4SHeiner Kallweit {
4324773235f4SHeiner Kallweit 	struct skb_shared_info *info = skb_shinfo(skb);
4325773235f4SHeiner Kallweit 	unsigned int nr_frags = info->nr_frags;
4326773235f4SHeiner Kallweit 
4327773235f4SHeiner Kallweit 	if (!nr_frags)
4328773235f4SHeiner Kallweit 		return UINT_MAX;
4329773235f4SHeiner Kallweit 
4330773235f4SHeiner Kallweit 	return skb_frag_size(info->frags + nr_frags - 1);
4331773235f4SHeiner Kallweit }
4332773235f4SHeiner Kallweit 
4333773235f4SHeiner Kallweit /* Workaround for hw issues with TSO on RTL8168evl */
rtl8168evl_fix_tso(struct sk_buff * skb,netdev_features_t features)4334773235f4SHeiner Kallweit static netdev_features_t rtl8168evl_fix_tso(struct sk_buff *skb,
4335773235f4SHeiner Kallweit 					    netdev_features_t features)
4336773235f4SHeiner Kallweit {
4337773235f4SHeiner Kallweit 	/* IPv4 header has options field */
4338773235f4SHeiner Kallweit 	if (vlan_get_protocol(skb) == htons(ETH_P_IP) &&
4339773235f4SHeiner Kallweit 	    ip_hdrlen(skb) > sizeof(struct iphdr))
4340773235f4SHeiner Kallweit 		features &= ~NETIF_F_ALL_TSO;
4341773235f4SHeiner Kallweit 
4342773235f4SHeiner Kallweit 	/* IPv4 TCP header has options field */
4343773235f4SHeiner Kallweit 	else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 &&
4344773235f4SHeiner Kallweit 		 tcp_hdrlen(skb) > sizeof(struct tcphdr))
4345773235f4SHeiner Kallweit 		features &= ~NETIF_F_ALL_TSO;
4346773235f4SHeiner Kallweit 
4347773235f4SHeiner Kallweit 	else if (rtl_last_frag_len(skb) <= 6)
4348773235f4SHeiner Kallweit 		features &= ~NETIF_F_ALL_TSO;
4349773235f4SHeiner Kallweit 
4350773235f4SHeiner Kallweit 	return features;
4351773235f4SHeiner Kallweit }
4352773235f4SHeiner Kallweit 
rtl8169_features_check(struct sk_buff * skb,struct net_device * dev,netdev_features_t features)4353e64e0c89SHeiner Kallweit static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
4354e64e0c89SHeiner Kallweit 						struct net_device *dev,
4355e64e0c89SHeiner Kallweit 						netdev_features_t features)
4356e64e0c89SHeiner Kallweit {
4357e64e0c89SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
4358e64e0c89SHeiner Kallweit 
4359e64e0c89SHeiner Kallweit 	if (skb_is_gso(skb)) {
4360773235f4SHeiner Kallweit 		if (tp->mac_version == RTL_GIGA_MAC_VER_34)
4361773235f4SHeiner Kallweit 			features = rtl8168evl_fix_tso(skb, features);
4362773235f4SHeiner Kallweit 
4363faa4e04eSHeiner Kallweit 		if (skb_transport_offset(skb) > GTTCPHO_MAX &&
4364e64e0c89SHeiner Kallweit 		    rtl_chip_supports_csum_v2(tp))
4365e64e0c89SHeiner Kallweit 			features &= ~NETIF_F_ALL_TSO;
4366e64e0c89SHeiner Kallweit 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
4367847f0a2bSHeiner Kallweit 		/* work around hw bug on some chip versions */
4368847f0a2bSHeiner Kallweit 		if (skb->len < ETH_ZLEN)
4369e64e0c89SHeiner Kallweit 			features &= ~NETIF_F_CSUM_MASK;
4370e64e0c89SHeiner Kallweit 
43718d520b4dSHeiner Kallweit 		if (rtl_quirk_packet_padto(tp, skb))
43728d520b4dSHeiner Kallweit 			features &= ~NETIF_F_CSUM_MASK;
43738d520b4dSHeiner Kallweit 
4374faa4e04eSHeiner Kallweit 		if (skb_transport_offset(skb) > TCPHO_MAX &&
4375e64e0c89SHeiner Kallweit 		    rtl_chip_supports_csum_v2(tp))
4376e64e0c89SHeiner Kallweit 			features &= ~NETIF_F_CSUM_MASK;
4377e64e0c89SHeiner Kallweit 	}
4378e64e0c89SHeiner Kallweit 
4379e64e0c89SHeiner Kallweit 	return vlan_features_check(skb, features);
4380e64e0c89SHeiner Kallweit }
4381e64e0c89SHeiner Kallweit 
rtl8169_pcierr_interrupt(struct net_device * dev)438225e992a4SHeiner Kallweit static void rtl8169_pcierr_interrupt(struct net_device *dev)
438325e992a4SHeiner Kallweit {
438425e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
438525e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
43862864a883SHeiner Kallweit 	int pci_status_errs;
43872864a883SHeiner Kallweit 	u16 pci_cmd;
438825e992a4SHeiner Kallweit 
438925e992a4SHeiner Kallweit 	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
439025e992a4SHeiner Kallweit 
43912864a883SHeiner Kallweit 	pci_status_errs = pci_status_get_and_clear_errors(pdev);
43922864a883SHeiner Kallweit 
439393882c6fSHeiner Kallweit 	if (net_ratelimit())
439493882c6fSHeiner Kallweit 		netdev_err(dev, "PCI error (cmd = 0x%04x, status_errs = 0x%04x)\n",
43952864a883SHeiner Kallweit 			   pci_cmd, pci_status_errs);
439625e992a4SHeiner Kallweit 
439725e992a4SHeiner Kallweit 	rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
439825e992a4SHeiner Kallweit }
439925e992a4SHeiner Kallweit 
rtl_tx(struct net_device * dev,struct rtl8169_private * tp,int budget)440025e992a4SHeiner Kallweit static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,
440125e992a4SHeiner Kallweit 		   int budget)
440225e992a4SHeiner Kallweit {
4403ca1ab89cSHeiner Kallweit 	unsigned int dirty_tx, bytes_compl = 0, pkts_compl = 0;
440494d8a98eSHeiner Kallweit 	struct sk_buff *skb;
440525e992a4SHeiner Kallweit 
440625e992a4SHeiner Kallweit 	dirty_tx = tp->dirty_tx;
440725e992a4SHeiner Kallweit 
4408ca1ab89cSHeiner Kallweit 	while (READ_ONCE(tp->cur_tx) != dirty_tx) {
440925e992a4SHeiner Kallweit 		unsigned int entry = dirty_tx % NUM_TX_DESC;
441025e992a4SHeiner Kallweit 		u32 status;
441125e992a4SHeiner Kallweit 
4412dcf75a0fSMirsad Goran Todorovac 		status = le32_to_cpu(READ_ONCE(tp->TxDescArray[entry].opts1));
441325e992a4SHeiner Kallweit 		if (status & DescOwn)
441425e992a4SHeiner Kallweit 			break;
441525e992a4SHeiner Kallweit 
441694d8a98eSHeiner Kallweit 		skb = tp->tx_skb[entry].skb;
441722d352c5SHeiner Kallweit 		rtl8169_unmap_tx_skb(tp, entry);
441822d352c5SHeiner Kallweit 
44196a41f2b2SHeiner Kallweit 		if (skb) {
442025e992a4SHeiner Kallweit 			pkts_compl++;
44216a41f2b2SHeiner Kallweit 			bytes_compl += skb->len;
44226a41f2b2SHeiner Kallweit 			napi_consume_skb(skb, budget);
442325e992a4SHeiner Kallweit 		}
442425e992a4SHeiner Kallweit 		dirty_tx++;
442525e992a4SHeiner Kallweit 	}
442625e992a4SHeiner Kallweit 
442725e992a4SHeiner Kallweit 	if (tp->dirty_tx != dirty_tx) {
44285e4cb480SHeiner Kallweit 		dev_sw_netstats_tx_add(dev, pkts_compl, bytes_compl);
44291a31ae00SHeiner Kallweit 		WRITE_ONCE(tp->dirty_tx, dirty_tx);
443025e992a4SHeiner Kallweit 
44311a31ae00SHeiner Kallweit 		netif_subqueue_completed_wake(dev, 0, pkts_compl, bytes_compl,
44321a31ae00SHeiner Kallweit 					      rtl_tx_slots_avail(tp),
44331a31ae00SHeiner Kallweit 					      R8169_TX_START_THRS);
443425e992a4SHeiner Kallweit 		/*
443525e992a4SHeiner Kallweit 		 * 8168 hack: TxPoll requests are lost when the Tx packets are
443625e992a4SHeiner Kallweit 		 * too close. Let's kick an extra TxPoll request when a burst
443725e992a4SHeiner Kallweit 		 * of start_xmit activity is detected (if it is not detected,
443825e992a4SHeiner Kallweit 		 * it is slow enough). -- FR
443994d8a98eSHeiner Kallweit 		 * If skb is NULL then we come here again once a tx irq is
444094d8a98eSHeiner Kallweit 		 * triggered after the last fragment is marked transmitted.
444125e992a4SHeiner Kallweit 		 */
4442c1c0ce31SMirsad Goran Todorovac 		if (READ_ONCE(tp->cur_tx) != dirty_tx && skb)
4443f1bce4adSHeiner Kallweit 			rtl8169_doorbell(tp);
444425e992a4SHeiner Kallweit 	}
444525e992a4SHeiner Kallweit }
444625e992a4SHeiner Kallweit 
rtl8169_fragmented_frame(u32 status)444725e992a4SHeiner Kallweit static inline int rtl8169_fragmented_frame(u32 status)
444825e992a4SHeiner Kallweit {
444925e992a4SHeiner Kallweit 	return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
445025e992a4SHeiner Kallweit }
445125e992a4SHeiner Kallweit 
rtl8169_rx_csum(struct sk_buff * skb,u32 opts1)445225e992a4SHeiner Kallweit static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
445325e992a4SHeiner Kallweit {
4454206a75e0SHeiner Kallweit 	u32 status = opts1 & (RxProtoMask | RxCSFailMask);
445525e992a4SHeiner Kallweit 
4456206a75e0SHeiner Kallweit 	if (status == RxProtoTCP || status == RxProtoUDP)
445725e992a4SHeiner Kallweit 		skb->ip_summed = CHECKSUM_UNNECESSARY;
445825e992a4SHeiner Kallweit 	else
445925e992a4SHeiner Kallweit 		skb_checksum_none_assert(skb);
446025e992a4SHeiner Kallweit }
446125e992a4SHeiner Kallweit 
rtl_rx(struct net_device * dev,struct rtl8169_private * tp,int budget)44622f53e9d7SHeiner Kallweit static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int budget)
446325e992a4SHeiner Kallweit {
4464588c7e5cSHeiner Kallweit 	struct device *d = tp_to_dev(tp);
44652f53e9d7SHeiner Kallweit 	int count;
446625e992a4SHeiner Kallweit 
44672f53e9d7SHeiner Kallweit 	for (count = 0; count < budget; count++, tp->cur_rx++) {
44682f53e9d7SHeiner Kallweit 		unsigned int pkt_size, entry = tp->cur_rx % NUM_RX_DESC;
446925e992a4SHeiner Kallweit 		struct RxDesc *desc = tp->RxDescArray + entry;
4470588c7e5cSHeiner Kallweit 		struct sk_buff *skb;
4471588c7e5cSHeiner Kallweit 		const void *rx_buf;
4472588c7e5cSHeiner Kallweit 		dma_addr_t addr;
447325e992a4SHeiner Kallweit 		u32 status;
447425e992a4SHeiner Kallweit 
4475f97eee48SMirsad Goran Todorovac 		status = le32_to_cpu(READ_ONCE(desc->opts1));
447625e992a4SHeiner Kallweit 		if (status & DescOwn)
447725e992a4SHeiner Kallweit 			break;
447825e992a4SHeiner Kallweit 
447925e992a4SHeiner Kallweit 		/* This barrier is needed to keep us from reading
448025e992a4SHeiner Kallweit 		 * any other fields out of the Rx descriptor until
448125e992a4SHeiner Kallweit 		 * we know the status of DescOwn
448225e992a4SHeiner Kallweit 		 */
448325e992a4SHeiner Kallweit 		dma_rmb();
448425e992a4SHeiner Kallweit 
448525e992a4SHeiner Kallweit 		if (unlikely(status & RxRES)) {
448693882c6fSHeiner Kallweit 			if (net_ratelimit())
448793882c6fSHeiner Kallweit 				netdev_warn(dev, "Rx ERROR. status = %08x\n",
448825e992a4SHeiner Kallweit 					    status);
448925e992a4SHeiner Kallweit 			dev->stats.rx_errors++;
449025e992a4SHeiner Kallweit 			if (status & (RxRWT | RxRUNT))
449125e992a4SHeiner Kallweit 				dev->stats.rx_length_errors++;
449225e992a4SHeiner Kallweit 			if (status & RxCRC)
449325e992a4SHeiner Kallweit 				dev->stats.rx_crc_errors++;
449425e992a4SHeiner Kallweit 
4495588c7e5cSHeiner Kallweit 			if (!(dev->features & NETIF_F_RXALL))
4496588c7e5cSHeiner Kallweit 				goto release_descriptor;
4497588c7e5cSHeiner Kallweit 			else if (status & RxRWT || !(status & (RxRUNT | RxCRC)))
4498588c7e5cSHeiner Kallweit 				goto release_descriptor;
4499588c7e5cSHeiner Kallweit 		}
4500588c7e5cSHeiner Kallweit 
4501fcd4e608SHeiner Kallweit 		pkt_size = status & GENMASK(13, 0);
450225e992a4SHeiner Kallweit 		if (likely(!(dev->features & NETIF_F_RXFCS)))
4503fcd4e608SHeiner Kallweit 			pkt_size -= ETH_FCS_LEN;
4504588c7e5cSHeiner Kallweit 
4505588c7e5cSHeiner Kallweit 		/* The driver does not support incoming fragmented frames.
4506588c7e5cSHeiner Kallweit 		 * They are seen as a symptom of over-mtu sized frames.
450725e992a4SHeiner Kallweit 		 */
450825e992a4SHeiner Kallweit 		if (unlikely(rtl8169_fragmented_frame(status))) {
450925e992a4SHeiner Kallweit 			dev->stats.rx_dropped++;
451025e992a4SHeiner Kallweit 			dev->stats.rx_length_errors++;
451125e992a4SHeiner Kallweit 			goto release_descriptor;
451225e992a4SHeiner Kallweit 		}
451325e992a4SHeiner Kallweit 
4514fcd4e608SHeiner Kallweit 		skb = napi_alloc_skb(&tp->napi, pkt_size);
4515fcd4e608SHeiner Kallweit 		if (unlikely(!skb)) {
451625e992a4SHeiner Kallweit 			dev->stats.rx_dropped++;
451725e992a4SHeiner Kallweit 			goto release_descriptor;
451825e992a4SHeiner Kallweit 		}
451925e992a4SHeiner Kallweit 
4520588c7e5cSHeiner Kallweit 		addr = le64_to_cpu(desc->addr);
4521588c7e5cSHeiner Kallweit 		rx_buf = page_address(tp->Rx_databuff[entry]);
4522588c7e5cSHeiner Kallweit 
4523588c7e5cSHeiner Kallweit 		dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
452432879f00SHeiner Kallweit 		prefetch(rx_buf);
452532879f00SHeiner Kallweit 		skb_copy_to_linear_data(skb, rx_buf, pkt_size);
4526fcd4e608SHeiner Kallweit 		skb->tail += pkt_size;
4527fcd4e608SHeiner Kallweit 		skb->len = pkt_size;
4528588c7e5cSHeiner Kallweit 		dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
4529d4ed7463SHeiner Kallweit 
453025e992a4SHeiner Kallweit 		rtl8169_rx_csum(skb, status);
453125e992a4SHeiner Kallweit 		skb->protocol = eth_type_trans(skb, dev);
453225e992a4SHeiner Kallweit 
453325e992a4SHeiner Kallweit 		rtl8169_rx_vlan_tag(desc, skb);
453425e992a4SHeiner Kallweit 
453525e992a4SHeiner Kallweit 		if (skb->pkt_type == PACKET_MULTICAST)
453625e992a4SHeiner Kallweit 			dev->stats.multicast++;
453725e992a4SHeiner Kallweit 
453825e992a4SHeiner Kallweit 		napi_gro_receive(&tp->napi, skb);
453925e992a4SHeiner Kallweit 
45405e4cb480SHeiner Kallweit 		dev_sw_netstats_rx_add(dev, pkt_size);
454125e992a4SHeiner Kallweit release_descriptor:
454225e992a4SHeiner Kallweit 		rtl8169_mark_to_asic(desc);
454325e992a4SHeiner Kallweit 	}
454425e992a4SHeiner Kallweit 
454525e992a4SHeiner Kallweit 	return count;
454625e992a4SHeiner Kallweit }
454725e992a4SHeiner Kallweit 
rtl8169_interrupt(int irq,void * dev_instance)454825e992a4SHeiner Kallweit static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
454925e992a4SHeiner Kallweit {
455025e992a4SHeiner Kallweit 	struct rtl8169_private *tp = dev_instance;
4551c1d532d2SHeiner Kallweit 	u32 status = rtl_get_events(tp);
455225e992a4SHeiner Kallweit 
45539e89d719SHeiner Kallweit 	if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask))
455425e992a4SHeiner Kallweit 		return IRQ_NONE;
455525e992a4SHeiner Kallweit 
455625e992a4SHeiner Kallweit 	if (unlikely(status & SYSErr)) {
455725e992a4SHeiner Kallweit 		rtl8169_pcierr_interrupt(tp->dev);
455825e992a4SHeiner Kallweit 		goto out;
455925e992a4SHeiner Kallweit 	}
456025e992a4SHeiner Kallweit 
456125e992a4SHeiner Kallweit 	if (status & LinkChg)
456225e992a4SHeiner Kallweit 		phy_mac_interrupt(tp->phydev);
456325e992a4SHeiner Kallweit 
456425e992a4SHeiner Kallweit 	if (unlikely(status & RxFIFOOver &&
456525e992a4SHeiner Kallweit 	    tp->mac_version == RTL_GIGA_MAC_VER_11)) {
456625e992a4SHeiner Kallweit 		netif_stop_queue(tp->dev);
45676b02e407SHeiner Kallweit 		rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
456825e992a4SHeiner Kallweit 	}
456925e992a4SHeiner Kallweit 
457025e992a4SHeiner Kallweit 	rtl_irq_disable(tp);
4571766e3bacSHeiner Kallweit 	napi_schedule(&tp->napi);
457225e992a4SHeiner Kallweit out:
457325e992a4SHeiner Kallweit 	rtl_ack_events(tp, status);
457425e992a4SHeiner Kallweit 
457525e992a4SHeiner Kallweit 	return IRQ_HANDLED;
457625e992a4SHeiner Kallweit }
457725e992a4SHeiner Kallweit 
rtl_task(struct work_struct * work)457825e992a4SHeiner Kallweit static void rtl_task(struct work_struct *work)
457925e992a4SHeiner Kallweit {
458025e992a4SHeiner Kallweit 	struct rtl8169_private *tp =
458125e992a4SHeiner Kallweit 		container_of(work, struct rtl8169_private, wk.work);
458280c0576eSHeiner Kallweit 	int ret;
458325e992a4SHeiner Kallweit 
4584abe5fc42SHeiner Kallweit 	rtnl_lock();
458525e992a4SHeiner Kallweit 
4586e18958c6SHeiner Kallweit 	if (!netif_running(tp->dev) ||
458725e992a4SHeiner Kallweit 	    !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
458825e992a4SHeiner Kallweit 		goto out_unlock;
458925e992a4SHeiner Kallweit 
459080c0576eSHeiner Kallweit 	if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
4591ce870af3SHeiner Kallweit 		/* if chip isn't accessible, reset bus to revive it */
4592ce870af3SHeiner Kallweit 		if (RTL_R32(tp, TxConfig) == ~0) {
4593ce870af3SHeiner Kallweit 			ret = pci_reset_bus(tp->pci_dev);
4594ce870af3SHeiner Kallweit 			if (ret < 0) {
4595ce870af3SHeiner Kallweit 				netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n");
4596ce870af3SHeiner Kallweit 				netif_device_detach(tp->dev);
4597ce870af3SHeiner Kallweit 				goto out_unlock;
4598ce870af3SHeiner Kallweit 			}
4599ce870af3SHeiner Kallweit 		}
4600ce870af3SHeiner Kallweit 
460180c0576eSHeiner Kallweit 		/* ASPM compatibility issues are a typical reason for tx timeouts */
460280c0576eSHeiner Kallweit 		ret = pci_disable_link_state(tp->pci_dev, PCIE_LINK_STATE_L1 |
460380c0576eSHeiner Kallweit 							  PCIE_LINK_STATE_L0S);
460480c0576eSHeiner Kallweit 		if (!ret)
460580c0576eSHeiner Kallweit 			netdev_warn_once(tp->dev, "ASPM disabled on Tx timeout\n");
460680c0576eSHeiner Kallweit 		goto reset;
460780c0576eSHeiner Kallweit 	}
460880c0576eSHeiner Kallweit 
4609476c4f5dSHeiner Kallweit 	if (test_and_clear_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags)) {
461080c0576eSHeiner Kallweit reset:
4611e18958c6SHeiner Kallweit 		rtl_reset_work(tp);
4612476c4f5dSHeiner Kallweit 		netif_wake_queue(tp->dev);
4613fbe43b7fSHeiner Kallweit 	} else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) {
4614fbe43b7fSHeiner Kallweit 		rtl_reset_work(tp);
4615476c4f5dSHeiner Kallweit 	}
461625e992a4SHeiner Kallweit out_unlock:
4617abe5fc42SHeiner Kallweit 	rtnl_unlock();
461825e992a4SHeiner Kallweit }
461925e992a4SHeiner Kallweit 
rtl8169_poll(struct napi_struct * napi,int budget)462025e992a4SHeiner Kallweit static int rtl8169_poll(struct napi_struct *napi, int budget)
462125e992a4SHeiner Kallweit {
462225e992a4SHeiner Kallweit 	struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
462325e992a4SHeiner Kallweit 	struct net_device *dev = tp->dev;
462425e992a4SHeiner Kallweit 	int work_done;
462525e992a4SHeiner Kallweit 
462625e992a4SHeiner Kallweit 	rtl_tx(dev, tp, budget);
462725e992a4SHeiner Kallweit 
46289fbb4a7aSHeiner Kallweit 	work_done = rtl_rx(dev, tp, budget);
46299fbb4a7aSHeiner Kallweit 
4630e31a9fedSHeiner Kallweit 	if (work_done < budget && napi_complete_done(napi, work_done))
463125e992a4SHeiner Kallweit 		rtl_irq_enable(tp);
463225e992a4SHeiner Kallweit 
463325e992a4SHeiner Kallweit 	return work_done;
463425e992a4SHeiner Kallweit }
463525e992a4SHeiner Kallweit 
r8169_phylink_handler(struct net_device * ndev)463625e992a4SHeiner Kallweit static void r8169_phylink_handler(struct net_device *ndev)
463725e992a4SHeiner Kallweit {
463825e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(ndev);
46394b6c6065SJuhee Kang 	struct device *d = tp_to_dev(tp);
464025e992a4SHeiner Kallweit 
464125e992a4SHeiner Kallweit 	if (netif_carrier_ok(ndev)) {
464225e992a4SHeiner Kallweit 		rtl_link_chg_patch(tp);
46434b6c6065SJuhee Kang 		pm_request_resume(d);
46440fbeb803SHeiner Kallweit 		netif_wake_queue(tp->dev);
464525e992a4SHeiner Kallweit 	} else {
46460fbeb803SHeiner Kallweit 		/* In few cases rx is broken after link-down otherwise */
46470fbeb803SHeiner Kallweit 		if (rtl_is_8125(tp))
4648fbe43b7fSHeiner Kallweit 			rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE);
46494b6c6065SJuhee Kang 		pm_runtime_idle(d);
465025e992a4SHeiner Kallweit 	}
465125e992a4SHeiner Kallweit 
465225e992a4SHeiner Kallweit 	phy_print_status(tp->phydev);
465325e992a4SHeiner Kallweit }
465425e992a4SHeiner Kallweit 
r8169_phy_connect(struct rtl8169_private * tp)465525e992a4SHeiner Kallweit static int r8169_phy_connect(struct rtl8169_private *tp)
465625e992a4SHeiner Kallweit {
465725e992a4SHeiner Kallweit 	struct phy_device *phydev = tp->phydev;
465825e992a4SHeiner Kallweit 	phy_interface_t phy_mode;
465925e992a4SHeiner Kallweit 	int ret;
466025e992a4SHeiner Kallweit 
466125e992a4SHeiner Kallweit 	phy_mode = tp->supports_gmii ? PHY_INTERFACE_MODE_GMII :
466225e992a4SHeiner Kallweit 		   PHY_INTERFACE_MODE_MII;
466325e992a4SHeiner Kallweit 
466425e992a4SHeiner Kallweit 	ret = phy_connect_direct(tp->dev, phydev, r8169_phylink_handler,
466525e992a4SHeiner Kallweit 				 phy_mode);
466625e992a4SHeiner Kallweit 	if (ret)
466725e992a4SHeiner Kallweit 		return ret;
466825e992a4SHeiner Kallweit 
466966058b1cSHeiner Kallweit 	if (!tp->supports_gmii)
467025e992a4SHeiner Kallweit 		phy_set_max_speed(phydev, SPEED_100);
467125e992a4SHeiner Kallweit 
467225e992a4SHeiner Kallweit 	phy_attached_info(phydev);
467325e992a4SHeiner Kallweit 
467425e992a4SHeiner Kallweit 	return 0;
467525e992a4SHeiner Kallweit }
467625e992a4SHeiner Kallweit 
rtl8169_down(struct rtl8169_private * tp)46778ac8e8c6SHeiner Kallweit static void rtl8169_down(struct rtl8169_private *tp)
467825e992a4SHeiner Kallweit {
46798ac8e8c6SHeiner Kallweit 	/* Clear all task flags */
46808ac8e8c6SHeiner Kallweit 	bitmap_zero(tp->wk.flags, RTL_FLAG_MAX);
468125e992a4SHeiner Kallweit 
468225e992a4SHeiner Kallweit 	phy_stop(tp->phydev);
468325e992a4SHeiner Kallweit 
4684a2ee8472SHeiner Kallweit 	rtl8169_update_counters(tp);
4685a2ee8472SHeiner Kallweit 
4686f658b909SHeiner Kallweit 	pci_clear_master(tp->pci_dev);
4687f658b909SHeiner Kallweit 	rtl_pci_commit(tp);
4688f658b909SHeiner Kallweit 
4689bb41c13cSChunhao Lin 	rtl8169_cleanup(tp);
4690d192181cSHeiner Kallweit 	rtl_disable_exit_l1(tp);
46917257c977SHeiner Kallweit 	rtl_prepare_power_down(tp);
4692a5126096SChunHao Lin 
4693a5126096SChunHao Lin 	if (tp->dash_type != RTL_DASH_NONE)
4694a5126096SChunHao Lin 		rtl8168_driver_stop(tp);
469525e992a4SHeiner Kallweit }
469625e992a4SHeiner Kallweit 
rtl8169_up(struct rtl8169_private * tp)4697567ca57fSHeiner Kallweit static void rtl8169_up(struct rtl8169_private *tp)
4698567ca57fSHeiner Kallweit {
4699a5126096SChunHao Lin 	if (tp->dash_type != RTL_DASH_NONE)
4700a5126096SChunHao Lin 		rtl8168_driver_start(tp);
4701a5126096SChunHao Lin 
4702f658b909SHeiner Kallweit 	pci_set_master(tp->pci_dev);
47035c2280fcSHeiner Kallweit 	phy_init_hw(tp->phydev);
47047257c977SHeiner Kallweit 	phy_resume(tp->phydev);
4705567ca57fSHeiner Kallweit 	rtl8169_init_phy(tp);
4706567ca57fSHeiner Kallweit 	napi_enable(&tp->napi);
4707567ca57fSHeiner Kallweit 	set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
4708567ca57fSHeiner Kallweit 	rtl_reset_work(tp);
4709567ca57fSHeiner Kallweit 
4710567ca57fSHeiner Kallweit 	phy_start(tp->phydev);
4711567ca57fSHeiner Kallweit }
4712567ca57fSHeiner Kallweit 
rtl8169_close(struct net_device * dev)471325e992a4SHeiner Kallweit static int rtl8169_close(struct net_device *dev)
471425e992a4SHeiner Kallweit {
471525e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
471625e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
471725e992a4SHeiner Kallweit 
471825e992a4SHeiner Kallweit 	pm_runtime_get_sync(&pdev->dev);
471925e992a4SHeiner Kallweit 
47208ac8e8c6SHeiner Kallweit 	netif_stop_queue(dev);
47218ac8e8c6SHeiner Kallweit 	rtl8169_down(tp);
47228ac8e8c6SHeiner Kallweit 	rtl8169_rx_clear(tp);
472325e992a4SHeiner Kallweit 
4724a9ef8976SHeiner Kallweit 	cancel_work(&tp->wk.work);
472525e992a4SHeiner Kallweit 
47261bd32771SThomas Gleixner 	free_irq(tp->irq, tp);
472725e992a4SHeiner Kallweit 
4728cc9f07a8SHeiner Kallweit 	phy_disconnect(tp->phydev);
4729cc9f07a8SHeiner Kallweit 
473025e992a4SHeiner Kallweit 	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
473125e992a4SHeiner Kallweit 			  tp->RxPhyAddr);
473225e992a4SHeiner Kallweit 	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
473325e992a4SHeiner Kallweit 			  tp->TxPhyAddr);
473425e992a4SHeiner Kallweit 	tp->TxDescArray = NULL;
473525e992a4SHeiner Kallweit 	tp->RxDescArray = NULL;
473625e992a4SHeiner Kallweit 
473725e992a4SHeiner Kallweit 	pm_runtime_put_sync(&pdev->dev);
473825e992a4SHeiner Kallweit 
473925e992a4SHeiner Kallweit 	return 0;
474025e992a4SHeiner Kallweit }
474125e992a4SHeiner Kallweit 
474225e992a4SHeiner Kallweit #ifdef CONFIG_NET_POLL_CONTROLLER
rtl8169_netpoll(struct net_device * dev)474325e992a4SHeiner Kallweit static void rtl8169_netpoll(struct net_device *dev)
474425e992a4SHeiner Kallweit {
474525e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
474625e992a4SHeiner Kallweit 
47471bd32771SThomas Gleixner 	rtl8169_interrupt(tp->irq, tp);
474825e992a4SHeiner Kallweit }
474925e992a4SHeiner Kallweit #endif
475025e992a4SHeiner Kallweit 
rtl_open(struct net_device * dev)475125e992a4SHeiner Kallweit static int rtl_open(struct net_device *dev)
475225e992a4SHeiner Kallweit {
475325e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
475425e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
4755870f531eSHeiner Kallweit 	unsigned long irqflags;
475625e992a4SHeiner Kallweit 	int retval = -ENOMEM;
475725e992a4SHeiner Kallweit 
475825e992a4SHeiner Kallweit 	pm_runtime_get_sync(&pdev->dev);
475925e992a4SHeiner Kallweit 
476025e992a4SHeiner Kallweit 	/*
476125e992a4SHeiner Kallweit 	 * Rx and Tx descriptors needs 256 bytes alignment.
476225e992a4SHeiner Kallweit 	 * dma_alloc_coherent provides more.
476325e992a4SHeiner Kallweit 	 */
476425e992a4SHeiner Kallweit 	tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
476525e992a4SHeiner Kallweit 					     &tp->TxPhyAddr, GFP_KERNEL);
476625e992a4SHeiner Kallweit 	if (!tp->TxDescArray)
47671c470b53SHeiner Kallweit 		goto out;
476825e992a4SHeiner Kallweit 
476925e992a4SHeiner Kallweit 	tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
477025e992a4SHeiner Kallweit 					     &tp->RxPhyAddr, GFP_KERNEL);
477125e992a4SHeiner Kallweit 	if (!tp->RxDescArray)
477225e992a4SHeiner Kallweit 		goto err_free_tx_0;
477325e992a4SHeiner Kallweit 
477425e992a4SHeiner Kallweit 	retval = rtl8169_init_ring(tp);
477525e992a4SHeiner Kallweit 	if (retval < 0)
477625e992a4SHeiner Kallweit 		goto err_free_rx_1;
477725e992a4SHeiner Kallweit 
477825e992a4SHeiner Kallweit 	rtl_request_firmware(tp);
477925e992a4SHeiner Kallweit 
4780870f531eSHeiner Kallweit 	irqflags = pci_dev_msi_enabled(pdev) ? IRQF_NO_THREAD : IRQF_SHARED;
47811bd32771SThomas Gleixner 	retval = request_irq(tp->irq, rtl8169_interrupt, irqflags, dev->name, tp);
478225e992a4SHeiner Kallweit 	if (retval < 0)
478325e992a4SHeiner Kallweit 		goto err_release_fw_2;
478425e992a4SHeiner Kallweit 
478525e992a4SHeiner Kallweit 	retval = r8169_phy_connect(tp);
478625e992a4SHeiner Kallweit 	if (retval)
478725e992a4SHeiner Kallweit 		goto err_free_irq;
478825e992a4SHeiner Kallweit 
4789567ca57fSHeiner Kallweit 	rtl8169_up(tp);
4790d56f58ceSHeiner Kallweit 	rtl8169_init_counter_offsets(tp);
479125e992a4SHeiner Kallweit 	netif_start_queue(dev);
479225e992a4SHeiner Kallweit out:
47931c470b53SHeiner Kallweit 	pm_runtime_put_sync(&pdev->dev);
47941c470b53SHeiner Kallweit 
479525e992a4SHeiner Kallweit 	return retval;
479625e992a4SHeiner Kallweit 
479725e992a4SHeiner Kallweit err_free_irq:
47981bd32771SThomas Gleixner 	free_irq(tp->irq, tp);
479925e992a4SHeiner Kallweit err_release_fw_2:
480025e992a4SHeiner Kallweit 	rtl_release_firmware(tp);
480125e992a4SHeiner Kallweit 	rtl8169_rx_clear(tp);
480225e992a4SHeiner Kallweit err_free_rx_1:
480325e992a4SHeiner Kallweit 	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
480425e992a4SHeiner Kallweit 			  tp->RxPhyAddr);
480525e992a4SHeiner Kallweit 	tp->RxDescArray = NULL;
480625e992a4SHeiner Kallweit err_free_tx_0:
480725e992a4SHeiner Kallweit 	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
480825e992a4SHeiner Kallweit 			  tp->TxPhyAddr);
480925e992a4SHeiner Kallweit 	tp->TxDescArray = NULL;
481025e992a4SHeiner Kallweit 	goto out;
481125e992a4SHeiner Kallweit }
481225e992a4SHeiner Kallweit 
481325e992a4SHeiner Kallweit static void
rtl8169_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * stats)481425e992a4SHeiner Kallweit rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
481525e992a4SHeiner Kallweit {
481625e992a4SHeiner Kallweit 	struct rtl8169_private *tp = netdev_priv(dev);
481725e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
481825e992a4SHeiner Kallweit 	struct rtl8169_counters *counters = tp->counters;
481925e992a4SHeiner Kallweit 
482025e992a4SHeiner Kallweit 	pm_runtime_get_noresume(&pdev->dev);
482125e992a4SHeiner Kallweit 
4822314a9cbbSHeiner Kallweit 	netdev_stats_to_stats64(stats, &dev->stats);
48235e4cb480SHeiner Kallweit 	dev_fetch_sw_netstats(stats, dev->tstats);
482425e992a4SHeiner Kallweit 
482525e992a4SHeiner Kallweit 	/*
4826ed72a9bbSCorentin Musard 	 * Fetch additional counter values missing in stats collected by driver
482725e992a4SHeiner Kallweit 	 * from tally counters.
482825e992a4SHeiner Kallweit 	 */
482925e992a4SHeiner Kallweit 	if (pm_runtime_active(&pdev->dev))
483025e992a4SHeiner Kallweit 		rtl8169_update_counters(tp);
483125e992a4SHeiner Kallweit 
483225e992a4SHeiner Kallweit 	/*
483325e992a4SHeiner Kallweit 	 * Subtract values fetched during initalization.
483425e992a4SHeiner Kallweit 	 * See rtl8169_init_counter_offsets for a description why we do that.
483525e992a4SHeiner Kallweit 	 */
483625e992a4SHeiner Kallweit 	stats->tx_errors = le64_to_cpu(counters->tx_errors) -
483725e992a4SHeiner Kallweit 		le64_to_cpu(tp->tc_offset.tx_errors);
483825e992a4SHeiner Kallweit 	stats->collisions = le32_to_cpu(counters->tx_multi_collision) -
483925e992a4SHeiner Kallweit 		le32_to_cpu(tp->tc_offset.tx_multi_collision);
484025e992a4SHeiner Kallweit 	stats->tx_aborted_errors = le16_to_cpu(counters->tx_aborted) -
484125e992a4SHeiner Kallweit 		le16_to_cpu(tp->tc_offset.tx_aborted);
48420da3359aSHeiner Kallweit 	stats->rx_missed_errors = le16_to_cpu(counters->rx_missed) -
48430da3359aSHeiner Kallweit 		le16_to_cpu(tp->tc_offset.rx_missed);
484425e992a4SHeiner Kallweit 
484525e992a4SHeiner Kallweit 	pm_runtime_put_noidle(&pdev->dev);
484625e992a4SHeiner Kallweit }
484725e992a4SHeiner Kallweit 
rtl8169_net_suspend(struct rtl8169_private * tp)484827dc36aeSHeiner Kallweit static void rtl8169_net_suspend(struct rtl8169_private *tp)
484925e992a4SHeiner Kallweit {
485027dc36aeSHeiner Kallweit 	netif_device_detach(tp->dev);
4851476c4f5dSHeiner Kallweit 
4852476c4f5dSHeiner Kallweit 	if (netif_running(tp->dev))
48538ac8e8c6SHeiner Kallweit 		rtl8169_down(tp);
485425e992a4SHeiner Kallweit }
485525e992a4SHeiner Kallweit 
rtl8169_runtime_resume(struct device * dev)485606e56697SHeiner Kallweit static int rtl8169_runtime_resume(struct device *dev)
485725e992a4SHeiner Kallweit {
485806e56697SHeiner Kallweit 	struct rtl8169_private *tp = dev_get_drvdata(dev);
485906e56697SHeiner Kallweit 
486027dc36aeSHeiner Kallweit 	rtl_rar_set(tp, tp->dev->dev_addr);
486106e56697SHeiner Kallweit 	__rtl8169_set_wol(tp, tp->saved_wolopts);
486225e992a4SHeiner Kallweit 
4863288302daSHeiner Kallweit 	if (tp->TxDescArray)
4864567ca57fSHeiner Kallweit 		rtl8169_up(tp);
486525e992a4SHeiner Kallweit 
4866476c4f5dSHeiner Kallweit 	netif_device_attach(tp->dev);
4867476c4f5dSHeiner Kallweit 
486825e992a4SHeiner Kallweit 	return 0;
486925e992a4SHeiner Kallweit }
487025e992a4SHeiner Kallweit 
rtl8169_suspend(struct device * device)48718fe6e670SHeiner Kallweit static int rtl8169_suspend(struct device *device)
4872bb13a800SHeiner Kallweit {
4873bb13a800SHeiner Kallweit 	struct rtl8169_private *tp = dev_get_drvdata(device);
4874bb13a800SHeiner Kallweit 
4875bb13a800SHeiner Kallweit 	rtnl_lock();
4876bb13a800SHeiner Kallweit 	rtl8169_net_suspend(tp);
4877bb13a800SHeiner Kallweit 	if (!device_may_wakeup(tp_to_dev(tp)))
4878bb13a800SHeiner Kallweit 		clk_disable_unprepare(tp->clk);
4879bb13a800SHeiner Kallweit 	rtnl_unlock();
4880bb13a800SHeiner Kallweit 
4881bb13a800SHeiner Kallweit 	return 0;
4882bb13a800SHeiner Kallweit }
4883bb13a800SHeiner Kallweit 
rtl8169_resume(struct device * device)48848fe6e670SHeiner Kallweit static int rtl8169_resume(struct device *device)
4885bb13a800SHeiner Kallweit {
4886bb13a800SHeiner Kallweit 	struct rtl8169_private *tp = dev_get_drvdata(device);
4887bb13a800SHeiner Kallweit 
4888bb13a800SHeiner Kallweit 	if (!device_may_wakeup(tp_to_dev(tp)))
4889bb13a800SHeiner Kallweit 		clk_prepare_enable(tp->clk);
4890bb13a800SHeiner Kallweit 
4891ef9da46dSHeiner Kallweit 	/* Reportedly at least Asus X453MA truncates packets otherwise */
4892ef9da46dSHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_37)
4893ef9da46dSHeiner Kallweit 		rtl_init_rxcfg(tp);
4894ef9da46dSHeiner Kallweit 
489506e56697SHeiner Kallweit 	return rtl8169_runtime_resume(device);
4896bb13a800SHeiner Kallweit }
4897bb13a800SHeiner Kallweit 
rtl8169_runtime_suspend(struct device * device)489825e992a4SHeiner Kallweit static int rtl8169_runtime_suspend(struct device *device)
489925e992a4SHeiner Kallweit {
490027dc36aeSHeiner Kallweit 	struct rtl8169_private *tp = dev_get_drvdata(device);
490125e992a4SHeiner Kallweit 
4902476c4f5dSHeiner Kallweit 	if (!tp->TxDescArray) {
4903476c4f5dSHeiner Kallweit 		netif_device_detach(tp->dev);
490425e992a4SHeiner Kallweit 		return 0;
4905476c4f5dSHeiner Kallweit 	}
490625e992a4SHeiner Kallweit 
4907abe5fc42SHeiner Kallweit 	rtnl_lock();
490801bd753dSHeiner Kallweit 	__rtl8169_set_wol(tp, WAKE_PHY);
490927dc36aeSHeiner Kallweit 	rtl8169_net_suspend(tp);
4910abe5fc42SHeiner Kallweit 	rtnl_unlock();
491125e992a4SHeiner Kallweit 
491225e992a4SHeiner Kallweit 	return 0;
491325e992a4SHeiner Kallweit }
491425e992a4SHeiner Kallweit 
rtl8169_runtime_idle(struct device * device)491525e992a4SHeiner Kallweit static int rtl8169_runtime_idle(struct device *device)
491625e992a4SHeiner Kallweit {
491727dc36aeSHeiner Kallweit 	struct rtl8169_private *tp = dev_get_drvdata(device);
491825e992a4SHeiner Kallweit 
4919c61d525fSChunHao Lin 	if (tp->dash_enabled)
492054744510SHeiner Kallweit 		return -EBUSY;
492154744510SHeiner Kallweit 
492227dc36aeSHeiner Kallweit 	if (!netif_running(tp->dev) || !netif_carrier_ok(tp->dev))
492325e992a4SHeiner Kallweit 		pm_schedule_suspend(device, 10000);
492425e992a4SHeiner Kallweit 
492525e992a4SHeiner Kallweit 	return -EBUSY;
492625e992a4SHeiner Kallweit }
492725e992a4SHeiner Kallweit 
492825e992a4SHeiner Kallweit static const struct dev_pm_ops rtl8169_pm_ops = {
49298fe6e670SHeiner Kallweit 	SYSTEM_SLEEP_PM_OPS(rtl8169_suspend, rtl8169_resume)
49308fe6e670SHeiner Kallweit 	RUNTIME_PM_OPS(rtl8169_runtime_suspend, rtl8169_runtime_resume,
493167ee63efSHeiner Kallweit 		       rtl8169_runtime_idle)
493225e992a4SHeiner Kallweit };
493325e992a4SHeiner Kallweit 
rtl_shutdown(struct pci_dev * pdev)493425e992a4SHeiner Kallweit static void rtl_shutdown(struct pci_dev *pdev)
493525e992a4SHeiner Kallweit {
493627dc36aeSHeiner Kallweit 	struct rtl8169_private *tp = pci_get_drvdata(pdev);
493725e992a4SHeiner Kallweit 
4938abe5fc42SHeiner Kallweit 	rtnl_lock();
493927dc36aeSHeiner Kallweit 	rtl8169_net_suspend(tp);
4940abe5fc42SHeiner Kallweit 	rtnl_unlock();
494125e992a4SHeiner Kallweit 
494225e992a4SHeiner Kallweit 	/* Restore original MAC address */
494327dc36aeSHeiner Kallweit 	rtl_rar_set(tp, tp->dev->perm_addr);
494425e992a4SHeiner Kallweit 
4945c61d525fSChunHao Lin 	if (system_state == SYSTEM_POWER_OFF && !tp->dash_enabled) {
4946bb703e57SHeiner Kallweit 		pci_wake_from_d3(pdev, tp->saved_wolopts);
494725e992a4SHeiner Kallweit 		pci_set_power_state(pdev, PCI_D3hot);
494825e992a4SHeiner Kallweit 	}
494925e992a4SHeiner Kallweit }
495025e992a4SHeiner Kallweit 
rtl_remove_one(struct pci_dev * pdev)495125e992a4SHeiner Kallweit static void rtl_remove_one(struct pci_dev *pdev)
495225e992a4SHeiner Kallweit {
495327dc36aeSHeiner Kallweit 	struct rtl8169_private *tp = pci_get_drvdata(pdev);
495425e992a4SHeiner Kallweit 
495512b1bc75SHeiner Kallweit 	if (pci_dev_run_wake(pdev))
495612b1bc75SHeiner Kallweit 		pm_runtime_get_noresume(&pdev->dev);
495725e992a4SHeiner Kallweit 
4958a9ef8976SHeiner Kallweit 	cancel_work_sync(&tp->wk.work);
4959a9ef8976SHeiner Kallweit 
496027dc36aeSHeiner Kallweit 	unregister_netdev(tp->dev);
496125e992a4SHeiner Kallweit 
4962e0d38b58SHeiner Kallweit 	if (tp->dash_type != RTL_DASH_NONE)
496312b1bc75SHeiner Kallweit 		rtl8168_driver_stop(tp);
496425e992a4SHeiner Kallweit 
496512b1bc75SHeiner Kallweit 	rtl_release_firmware(tp);
496625e992a4SHeiner Kallweit 
496725e992a4SHeiner Kallweit 	/* restore original MAC address */
496827dc36aeSHeiner Kallweit 	rtl_rar_set(tp, tp->dev->perm_addr);
496925e992a4SHeiner Kallweit }
497025e992a4SHeiner Kallweit 
497125e992a4SHeiner Kallweit static const struct net_device_ops rtl_netdev_ops = {
497225e992a4SHeiner Kallweit 	.ndo_open		= rtl_open,
497325e992a4SHeiner Kallweit 	.ndo_stop		= rtl8169_close,
497425e992a4SHeiner Kallweit 	.ndo_get_stats64	= rtl8169_get_stats64,
497525e992a4SHeiner Kallweit 	.ndo_start_xmit		= rtl8169_start_xmit,
4976e64e0c89SHeiner Kallweit 	.ndo_features_check	= rtl8169_features_check,
497725e992a4SHeiner Kallweit 	.ndo_tx_timeout		= rtl8169_tx_timeout,
497825e992a4SHeiner Kallweit 	.ndo_validate_addr	= eth_validate_addr,
497925e992a4SHeiner Kallweit 	.ndo_change_mtu		= rtl8169_change_mtu,
498025e992a4SHeiner Kallweit 	.ndo_fix_features	= rtl8169_fix_features,
498125e992a4SHeiner Kallweit 	.ndo_set_features	= rtl8169_set_features,
498225e992a4SHeiner Kallweit 	.ndo_set_mac_address	= rtl_set_mac_address,
4983a7605370SArnd Bergmann 	.ndo_eth_ioctl		= phy_do_ioctl_running,
498425e992a4SHeiner Kallweit 	.ndo_set_rx_mode	= rtl_set_rx_mode,
498525e992a4SHeiner Kallweit #ifdef CONFIG_NET_POLL_CONTROLLER
498625e992a4SHeiner Kallweit 	.ndo_poll_controller	= rtl8169_netpoll,
498725e992a4SHeiner Kallweit #endif
498825e992a4SHeiner Kallweit 
498925e992a4SHeiner Kallweit };
499025e992a4SHeiner Kallweit 
rtl_set_irq_mask(struct rtl8169_private * tp)4991ec9a4088SHeiner Kallweit static void rtl_set_irq_mask(struct rtl8169_private *tp)
4992ec9a4088SHeiner Kallweit {
49932045e158SHeiner Kallweit 	tp->irq_mask = RxOK | RxErr | TxOK | TxErr | LinkChg;
4994ec9a4088SHeiner Kallweit 
4995ec9a4088SHeiner Kallweit 	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
4996ec9a4088SHeiner Kallweit 		tp->irq_mask |= SYSErr | RxOverflow | RxFIFOOver;
4997ec9a4088SHeiner Kallweit 	else if (tp->mac_version == RTL_GIGA_MAC_VER_11)
4998ec9a4088SHeiner Kallweit 		/* special workaround needed */
4999ec9a4088SHeiner Kallweit 		tp->irq_mask |= RxFIFOOver;
5000ec9a4088SHeiner Kallweit 	else
5001ec9a4088SHeiner Kallweit 		tp->irq_mask |= RxOverflow;
5002ec9a4088SHeiner Kallweit }
5003ec9a4088SHeiner Kallweit 
rtl_alloc_irq(struct rtl8169_private * tp)500425e992a4SHeiner Kallweit static int rtl_alloc_irq(struct rtl8169_private *tp)
500525e992a4SHeiner Kallweit {
500625e992a4SHeiner Kallweit 	unsigned int flags;
500725e992a4SHeiner Kallweit 
5008003bd5b4SHeiner Kallweit 	switch (tp->mac_version) {
5009003bd5b4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
501025e992a4SHeiner Kallweit 		rtl_unlock_config_regs(tp);
501125e992a4SHeiner Kallweit 		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
501225e992a4SHeiner Kallweit 		rtl_lock_config_regs(tp);
5013df561f66SGustavo A. R. Silva 		fallthrough;
5014f13bc681SHeiner Kallweit 	case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_17:
501525e992a4SHeiner Kallweit 		flags = PCI_IRQ_LEGACY;
5016003bd5b4SHeiner Kallweit 		break;
5017003bd5b4SHeiner Kallweit 	default:
501825e992a4SHeiner Kallweit 		flags = PCI_IRQ_ALL_TYPES;
5019003bd5b4SHeiner Kallweit 		break;
502025e992a4SHeiner Kallweit 	}
502125e992a4SHeiner Kallweit 
502225e992a4SHeiner Kallweit 	return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
502325e992a4SHeiner Kallweit }
502425e992a4SHeiner Kallweit 
rtl_read_mac_address(struct rtl8169_private * tp,u8 mac_addr[ETH_ALEN])502525e992a4SHeiner Kallweit static void rtl_read_mac_address(struct rtl8169_private *tp,
502625e992a4SHeiner Kallweit 				 u8 mac_addr[ETH_ALEN])
502725e992a4SHeiner Kallweit {
502825e992a4SHeiner Kallweit 	/* Get MAC address */
50299e9f33baSHeiner Kallweit 	if (rtl_is_8168evl_up(tp) && tp->mac_version != RTL_GIGA_MAC_VER_34) {
5030ae1e82c6SHeiner Kallweit 		u32 value;
50319e9f33baSHeiner Kallweit 
5032ae1e82c6SHeiner Kallweit 		value = rtl_eri_read(tp, 0xe0);
5033ae1e82c6SHeiner Kallweit 		put_unaligned_le32(value, mac_addr);
503425e992a4SHeiner Kallweit 		value = rtl_eri_read(tp, 0xe4);
5035ae1e82c6SHeiner Kallweit 		put_unaligned_le16(value, mac_addr + 4);
5036f1bce4adSHeiner Kallweit 	} else if (rtl_is_8125(tp)) {
5037f1bce4adSHeiner Kallweit 		rtl_read_mac_from_reg(tp, mac_addr, MAC0_BKP);
503825e992a4SHeiner Kallweit 	}
503925e992a4SHeiner Kallweit }
504025e992a4SHeiner Kallweit 
DECLARE_RTL_COND(rtl_link_list_ready_cond)504125e992a4SHeiner Kallweit DECLARE_RTL_COND(rtl_link_list_ready_cond)
504225e992a4SHeiner Kallweit {
504325e992a4SHeiner Kallweit 	return RTL_R8(tp, MCU) & LINK_LIST_RDY;
504425e992a4SHeiner Kallweit }
504525e992a4SHeiner Kallweit 
r8168g_wait_ll_share_fifo_ready(struct rtl8169_private * tp)5046e031ce80SHeiner Kallweit static void r8168g_wait_ll_share_fifo_ready(struct rtl8169_private *tp)
5047e031ce80SHeiner Kallweit {
5048e031ce80SHeiner Kallweit 	rtl_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42);
5049e031ce80SHeiner Kallweit }
5050e031ce80SHeiner Kallweit 
r8169_mdio_read_reg(struct mii_bus * mii_bus,int phyaddr,int phyreg)505125e992a4SHeiner Kallweit static int r8169_mdio_read_reg(struct mii_bus *mii_bus, int phyaddr, int phyreg)
505225e992a4SHeiner Kallweit {
505325e992a4SHeiner Kallweit 	struct rtl8169_private *tp = mii_bus->priv;
505425e992a4SHeiner Kallweit 
505525e992a4SHeiner Kallweit 	if (phyaddr > 0)
505625e992a4SHeiner Kallweit 		return -ENODEV;
505725e992a4SHeiner Kallweit 
505825e992a4SHeiner Kallweit 	return rtl_readphy(tp, phyreg);
505925e992a4SHeiner Kallweit }
506025e992a4SHeiner Kallweit 
r8169_mdio_write_reg(struct mii_bus * mii_bus,int phyaddr,int phyreg,u16 val)506125e992a4SHeiner Kallweit static int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr,
506225e992a4SHeiner Kallweit 				int phyreg, u16 val)
506325e992a4SHeiner Kallweit {
506425e992a4SHeiner Kallweit 	struct rtl8169_private *tp = mii_bus->priv;
506525e992a4SHeiner Kallweit 
506625e992a4SHeiner Kallweit 	if (phyaddr > 0)
506725e992a4SHeiner Kallweit 		return -ENODEV;
506825e992a4SHeiner Kallweit 
506925e992a4SHeiner Kallweit 	rtl_writephy(tp, phyreg, val);
507025e992a4SHeiner Kallweit 
507125e992a4SHeiner Kallweit 	return 0;
507225e992a4SHeiner Kallweit }
507325e992a4SHeiner Kallweit 
r8169_mdio_register(struct rtl8169_private * tp)507425e992a4SHeiner Kallweit static int r8169_mdio_register(struct rtl8169_private *tp)
507525e992a4SHeiner Kallweit {
507625e992a4SHeiner Kallweit 	struct pci_dev *pdev = tp->pci_dev;
507725e992a4SHeiner Kallweit 	struct mii_bus *new_bus;
507825e992a4SHeiner Kallweit 	int ret;
507925e992a4SHeiner Kallweit 
5080b9906101SHeiner Kallweit 	/* On some boards with this chip version the BIOS is buggy and misses
5081b9906101SHeiner Kallweit 	 * to reset the PHY page selector. This results in the PHY ID read
5082b9906101SHeiner Kallweit 	 * accessing registers on a different page, returning a more or
5083b9906101SHeiner Kallweit 	 * less random value. Fix this by resetting the page selector first.
5084b9906101SHeiner Kallweit 	 */
5085b9906101SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_25 ||
5086b9906101SHeiner Kallweit 	    tp->mac_version == RTL_GIGA_MAC_VER_26)
5087b9906101SHeiner Kallweit 		r8169_mdio_write(tp, 0x1f, 0);
5088b9906101SHeiner Kallweit 
508925e992a4SHeiner Kallweit 	new_bus = devm_mdiobus_alloc(&pdev->dev);
509025e992a4SHeiner Kallweit 	if (!new_bus)
509125e992a4SHeiner Kallweit 		return -ENOMEM;
509225e992a4SHeiner Kallweit 
509325e992a4SHeiner Kallweit 	new_bus->name = "r8169";
509425e992a4SHeiner Kallweit 	new_bus->priv = tp;
509525e992a4SHeiner Kallweit 	new_bus->parent = &pdev->dev;
509693e8990cSHeiner Kallweit 	new_bus->irq[0] = PHY_MAC_INTERRUPT;
5097e9a72f87SSayanta Pattanayak 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x",
5098e9a72f87SSayanta Pattanayak 		 pci_domain_nr(pdev->bus), pci_dev_id(pdev));
509925e992a4SHeiner Kallweit 
510025e992a4SHeiner Kallweit 	new_bus->read = r8169_mdio_read_reg;
510125e992a4SHeiner Kallweit 	new_bus->write = r8169_mdio_write_reg;
510225e992a4SHeiner Kallweit 
5103ac3a68d5SBartosz Golaszewski 	ret = devm_mdiobus_register(&pdev->dev, new_bus);
510425e992a4SHeiner Kallweit 	if (ret)
510525e992a4SHeiner Kallweit 		return ret;
510625e992a4SHeiner Kallweit 
510725e992a4SHeiner Kallweit 	tp->phydev = mdiobus_get_phy(new_bus, 0);
510825e992a4SHeiner Kallweit 	if (!tp->phydev) {
510925e992a4SHeiner Kallweit 		return -ENODEV;
51102e8c339bSHeiner Kallweit 	} else if (!tp->phydev->drv) {
51112e8c339bSHeiner Kallweit 		/* Most chip versions fail with the genphy driver.
51122e8c339bSHeiner Kallweit 		 * Therefore ensure that the dedicated PHY driver is loaded.
51132e8c339bSHeiner Kallweit 		 */
51140c2006b2SHeiner Kallweit 		dev_err(&pdev->dev, "no dedicated PHY driver found for PHY ID 0x%08x, maybe realtek.ko needs to be added to initramfs?\n",
51150c2006b2SHeiner Kallweit 			tp->phydev->phy_id);
51162e8c339bSHeiner Kallweit 		return -EUNATCH;
511725e992a4SHeiner Kallweit 	}
511825e992a4SHeiner Kallweit 
5119eca485d2SDenis Kirjanov 	tp->phydev->mac_managed_pm = true;
51205c2280fcSHeiner Kallweit 
512111ac4e66SHeiner Kallweit 	phy_support_asym_pause(tp->phydev);
512211ac4e66SHeiner Kallweit 
512325e992a4SHeiner Kallweit 	/* PHY will be woken up in rtl_open() */
512425e992a4SHeiner Kallweit 	phy_suspend(tp->phydev);
512525e992a4SHeiner Kallweit 
512625e992a4SHeiner Kallweit 	return 0;
512725e992a4SHeiner Kallweit }
512825e992a4SHeiner Kallweit 
rtl_hw_init_8168g(struct rtl8169_private * tp)512925e992a4SHeiner Kallweit static void rtl_hw_init_8168g(struct rtl8169_private *tp)
513025e992a4SHeiner Kallweit {
51319617886fSHeiner Kallweit 	rtl_enable_rxdvgate(tp);
513225e992a4SHeiner Kallweit 
513325e992a4SHeiner Kallweit 	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
513425e992a4SHeiner Kallweit 	msleep(1);
513525e992a4SHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
513625e992a4SHeiner Kallweit 
5137ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
5138e031ce80SHeiner Kallweit 	r8168g_wait_ll_share_fifo_ready(tp);
513925e992a4SHeiner Kallweit 
5140ef712edeSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe8de, 0, BIT(15));
5141e031ce80SHeiner Kallweit 	r8168g_wait_ll_share_fifo_ready(tp);
514225e992a4SHeiner Kallweit }
514325e992a4SHeiner Kallweit 
rtl_hw_init_8125(struct rtl8169_private * tp)5144f1bce4adSHeiner Kallweit static void rtl_hw_init_8125(struct rtl8169_private *tp)
5145f1bce4adSHeiner Kallweit {
51469617886fSHeiner Kallweit 	rtl_enable_rxdvgate(tp);
5147f1bce4adSHeiner Kallweit 
5148f1bce4adSHeiner Kallweit 	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
5149f1bce4adSHeiner Kallweit 	msleep(1);
5150f1bce4adSHeiner Kallweit 	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
5151f1bce4adSHeiner Kallweit 
5152f1bce4adSHeiner Kallweit 	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
5153e031ce80SHeiner Kallweit 	r8168g_wait_ll_share_fifo_ready(tp);
5154f1bce4adSHeiner Kallweit 
5155f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc0aa, 0x07d0);
5156f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc0a6, 0x0150);
5157f1bce4adSHeiner Kallweit 	r8168_mac_ocp_write(tp, 0xc01e, 0x5555);
5158e031ce80SHeiner Kallweit 	r8168g_wait_ll_share_fifo_ready(tp);
5159f1bce4adSHeiner Kallweit }
5160f1bce4adSHeiner Kallweit 
rtl_hw_initialize(struct rtl8169_private * tp)516125e992a4SHeiner Kallweit static void rtl_hw_initialize(struct rtl8169_private *tp)
516225e992a4SHeiner Kallweit {
516325e992a4SHeiner Kallweit 	switch (tp->mac_version) {
5164133706a9SHeiner Kallweit 	case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
516525e992a4SHeiner Kallweit 		rtl8168ep_stop_cmac(tp);
5166df561f66SGustavo A. R. Silva 		fallthrough;
516725e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
516825e992a4SHeiner Kallweit 		rtl_hw_init_8168g(tp);
516925e992a4SHeiner Kallweit 		break;
5170efc37109SHeiner Kallweit 	case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
5171f1bce4adSHeiner Kallweit 		rtl_hw_init_8125(tp);
5172f1bce4adSHeiner Kallweit 		break;
517325e992a4SHeiner Kallweit 	default:
517425e992a4SHeiner Kallweit 		break;
517525e992a4SHeiner Kallweit 	}
517625e992a4SHeiner Kallweit }
517725e992a4SHeiner Kallweit 
rtl_jumbo_max(struct rtl8169_private * tp)517825e992a4SHeiner Kallweit static int rtl_jumbo_max(struct rtl8169_private *tp)
517925e992a4SHeiner Kallweit {
518025e992a4SHeiner Kallweit 	/* Non-GBit versions don't support jumbo frames */
518125e992a4SHeiner Kallweit 	if (!tp->supports_gmii)
5182a8ec173aSHeiner Kallweit 		return 0;
518325e992a4SHeiner Kallweit 
518425e992a4SHeiner Kallweit 	switch (tp->mac_version) {
518525e992a4SHeiner Kallweit 	/* RTL8169 */
518625e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
518725e992a4SHeiner Kallweit 		return JUMBO_7K;
518825e992a4SHeiner Kallweit 	/* RTL8168b */
518925e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_11:
519025e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_17:
519125e992a4SHeiner Kallweit 		return JUMBO_4K;
519225e992a4SHeiner Kallweit 	/* RTL8168c */
519325e992a4SHeiner Kallweit 	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24:
519425e992a4SHeiner Kallweit 		return JUMBO_6K;
519525e992a4SHeiner Kallweit 	default:
519625e992a4SHeiner Kallweit 		return JUMBO_9K;
519725e992a4SHeiner Kallweit 	}
519825e992a4SHeiner Kallweit }
519925e992a4SHeiner Kallweit 
rtl_init_mac_address(struct rtl8169_private * tp)5200c782e204SHeiner Kallweit static void rtl_init_mac_address(struct rtl8169_private *tp)
5201c782e204SHeiner Kallweit {
5202c75a9ad4SHeiner Kallweit 	u8 mac_addr[ETH_ALEN] __aligned(2) = {};
5203c782e204SHeiner Kallweit 	struct net_device *dev = tp->dev;
5204ce37115eSHeiner Kallweit 	int rc;
5205c782e204SHeiner Kallweit 
5206c782e204SHeiner Kallweit 	rc = eth_platform_get_mac_address(tp_to_dev(tp), mac_addr);
5207c782e204SHeiner Kallweit 	if (!rc)
5208c782e204SHeiner Kallweit 		goto done;
5209c782e204SHeiner Kallweit 
5210c782e204SHeiner Kallweit 	rtl_read_mac_address(tp, mac_addr);
5211c782e204SHeiner Kallweit 	if (is_valid_ether_addr(mac_addr))
5212c782e204SHeiner Kallweit 		goto done;
5213c782e204SHeiner Kallweit 
5214ce37115eSHeiner Kallweit 	rtl_read_mac_from_reg(tp, mac_addr, MAC0);
5215c782e204SHeiner Kallweit 	if (is_valid_ether_addr(mac_addr))
5216c782e204SHeiner Kallweit 		goto done;
5217c782e204SHeiner Kallweit 
5218c75a9ad4SHeiner Kallweit 	eth_random_addr(mac_addr);
5219c75a9ad4SHeiner Kallweit 	dev->addr_assign_type = NET_ADDR_RANDOM;
5220c782e204SHeiner Kallweit 	dev_warn(tp_to_dev(tp), "can't read MAC address, setting random one\n");
5221c782e204SHeiner Kallweit done:
52221c5d09d5SJakub Kicinski 	eth_hw_addr_set(dev, mac_addr);
5223c782e204SHeiner Kallweit 	rtl_rar_set(tp, mac_addr);
5224c782e204SHeiner Kallweit }
5225c782e204SHeiner Kallweit 
5226cf2ffdeaSHeiner Kallweit /* register is set if system vendor successfully tested ASPM 1.2 */
rtl_aspm_is_safe(struct rtl8169_private * tp)5227cf2ffdeaSHeiner Kallweit static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
5228cf2ffdeaSHeiner Kallweit {
5229cf2ffdeaSHeiner Kallweit 	if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
5230cf2ffdeaSHeiner Kallweit 	    r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
5231cf2ffdeaSHeiner Kallweit 		return true;
5232cf2ffdeaSHeiner Kallweit 
5233cf2ffdeaSHeiner Kallweit 	return false;
5234cf2ffdeaSHeiner Kallweit }
5235cf2ffdeaSHeiner Kallweit 
rtl_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)523625e992a4SHeiner Kallweit static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
523725e992a4SHeiner Kallweit {
523825e992a4SHeiner Kallweit 	struct rtl8169_private *tp;
5239f1f9ca28SHeiner Kallweit 	int jumbo_max, region, rc;
5240f1f9ca28SHeiner Kallweit 	enum mac_version chipset;
524125e992a4SHeiner Kallweit 	struct net_device *dev;
5242bc590b47SHeiner Kallweit 	u32 txconfig;
5243f1f9ca28SHeiner Kallweit 	u16 xid;
524425e992a4SHeiner Kallweit 
524525e992a4SHeiner Kallweit 	dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
524625e992a4SHeiner Kallweit 	if (!dev)
524725e992a4SHeiner Kallweit 		return -ENOMEM;
524825e992a4SHeiner Kallweit 
524925e992a4SHeiner Kallweit 	SET_NETDEV_DEV(dev, &pdev->dev);
525025e992a4SHeiner Kallweit 	dev->netdev_ops = &rtl_netdev_ops;
525125e992a4SHeiner Kallweit 	tp = netdev_priv(dev);
525225e992a4SHeiner Kallweit 	tp->dev = dev;
525325e992a4SHeiner Kallweit 	tp->pci_dev = pdev;
5254145a40e8SHeiner Kallweit 	tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
52557ec3f872SHeiner Kallweit 	tp->eee_adv = -1;
52560360c046SHeiner Kallweit 	tp->ocp_base = OCP_STD_PHY_BASE;
525725e992a4SHeiner Kallweit 
5258d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_init(&tp->cfg9346_usage_lock);
5259d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_init(&tp->config25_lock);
5260d6c36cbcSSebastian Andrzej Siewior 	raw_spin_lock_init(&tp->mac_ocp_lock);
526191c86435SHeiner Kallweit 
52625e4cb480SHeiner Kallweit 	dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
52635e4cb480SHeiner Kallweit 						   struct pcpu_sw_netstats);
52645e4cb480SHeiner Kallweit 	if (!dev->tstats)
52655e4cb480SHeiner Kallweit 		return -ENOMEM;
52665e4cb480SHeiner Kallweit 
526725e992a4SHeiner Kallweit 	/* Get the *optional* external "ether_clk" used on some boards */
5268599566c1SHeiner Kallweit 	tp->clk = devm_clk_get_optional_enabled(&pdev->dev, "ether_clk");
5269599566c1SHeiner Kallweit 	if (IS_ERR(tp->clk))
5270599566c1SHeiner Kallweit 		return dev_err_probe(&pdev->dev, PTR_ERR(tp->clk), "failed to get ether_clk\n");
527125e992a4SHeiner Kallweit 
527225e992a4SHeiner Kallweit 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
527325e992a4SHeiner Kallweit 	rc = pcim_enable_device(pdev);
5274733b3e27SHeiner Kallweit 	if (rc < 0)
5275733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, rc, "enable failure\n");
527625e992a4SHeiner Kallweit 
527725e992a4SHeiner Kallweit 	if (pcim_set_mwi(pdev) < 0)
527825e992a4SHeiner Kallweit 		dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n");
527925e992a4SHeiner Kallweit 
528025e992a4SHeiner Kallweit 	/* use first MMIO region */
528125e992a4SHeiner Kallweit 	region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
5282733b3e27SHeiner Kallweit 	if (region < 0)
5283733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n");
528425e992a4SHeiner Kallweit 
52857cb7541aSHeiner Kallweit 	rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME);
5286733b3e27SHeiner Kallweit 	if (rc < 0)
5287733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n");
528825e992a4SHeiner Kallweit 
528925e992a4SHeiner Kallweit 	tp->mmio_addr = pcim_iomap_table(pdev)[region];
529025e992a4SHeiner Kallweit 
5291bc590b47SHeiner Kallweit 	txconfig = RTL_R32(tp, TxConfig);
5292733b3e27SHeiner Kallweit 	if (txconfig == ~0U)
5293733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n");
5294bc590b47SHeiner Kallweit 
5295bc590b47SHeiner Kallweit 	xid = (txconfig >> 20) & 0xfcf;
5296f1f9ca28SHeiner Kallweit 
529725e992a4SHeiner Kallweit 	/* Identify chip attached to board */
5298f1f9ca28SHeiner Kallweit 	chipset = rtl8169_get_mac_version(xid, tp->supports_gmii);
5299733b3e27SHeiner Kallweit 	if (chipset == RTL_GIGA_MAC_NONE)
5300733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, -ENODEV,
5301733b3e27SHeiner Kallweit 				     "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n",
5302733b3e27SHeiner Kallweit 				     xid);
5303f1f9ca28SHeiner Kallweit 	tp->mac_version = chipset;
530425e992a4SHeiner Kallweit 
5305cf2ffdeaSHeiner Kallweit 	/* Disable ASPM L1 as that cause random device stop working
5306cf2ffdeaSHeiner Kallweit 	 * problems as well as full system hangs for some PCIe devices users.
5307cf2ffdeaSHeiner Kallweit 	 */
5308cf2ffdeaSHeiner Kallweit 	if (rtl_aspm_is_safe(tp))
5309cf2ffdeaSHeiner Kallweit 		rc = 0;
5310cf2ffdeaSHeiner Kallweit 	else
5311cf2ffdeaSHeiner Kallweit 		rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
5312cf2ffdeaSHeiner Kallweit 	tp->aspm_manageable = !rc;
5313cf2ffdeaSHeiner Kallweit 
5314c61d525fSChunHao Lin 	tp->dash_type = rtl_get_dash_type(tp);
5315c61d525fSChunHao Lin 	tp->dash_enabled = rtl_dash_is_enabled(tp);
5316e0d38b58SHeiner Kallweit 
5317975e8505SHeiner Kallweit 	tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
531825e992a4SHeiner Kallweit 
531925e992a4SHeiner Kallweit 	if (sizeof(dma_addr_t) > 4 && tp->mac_version >= RTL_GIGA_MAC_VER_18 &&
53203c18cbe3SHeiner Kallweit 	    !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
532125e992a4SHeiner Kallweit 		dev->features |= NETIF_F_HIGHDMA;
532225e992a4SHeiner Kallweit 
532325e992a4SHeiner Kallweit 	rtl_init_rxcfg(tp);
532425e992a4SHeiner Kallweit 
532525e992a4SHeiner Kallweit 	rtl8169_irq_mask_and_ack(tp);
532625e992a4SHeiner Kallweit 
532725e992a4SHeiner Kallweit 	rtl_hw_initialize(tp);
532825e992a4SHeiner Kallweit 
532925e992a4SHeiner Kallweit 	rtl_hw_reset(tp);
533025e992a4SHeiner Kallweit 
533125e992a4SHeiner Kallweit 	rc = rtl_alloc_irq(tp);
5332733b3e27SHeiner Kallweit 	if (rc < 0)
5333733b3e27SHeiner Kallweit 		return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n");
5334733b3e27SHeiner Kallweit 
53351bd32771SThomas Gleixner 	tp->irq = pci_irq_vector(pdev, 0);
533625e992a4SHeiner Kallweit 
533725e992a4SHeiner Kallweit 	INIT_WORK(&tp->wk.work, rtl_task);
533825e992a4SHeiner Kallweit 
5339c782e204SHeiner Kallweit 	rtl_init_mac_address(tp);
534025e992a4SHeiner Kallweit 
534125e992a4SHeiner Kallweit 	dev->ethtool_ops = &rtl8169_ethtool_ops;
534225e992a4SHeiner Kallweit 
5343b48b89f9SJakub Kicinski 	netif_napi_add(dev, &tp->napi, rtl8169_poll);
534425e992a4SHeiner Kallweit 
534595099c56SHeiner Kallweit 	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
534695099c56SHeiner Kallweit 			   NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
5347a9b3d568SHeiner Kallweit 	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
534825e992a4SHeiner Kallweit 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
534925e992a4SHeiner Kallweit 
535025e992a4SHeiner Kallweit 	/*
535125e992a4SHeiner Kallweit 	 * Pretend we are using VLANs; This bypasses a nasty bug where
535225e992a4SHeiner Kallweit 	 * Interrupts stop flowing on high load on 8110SCd controllers.
535325e992a4SHeiner Kallweit 	 */
535425e992a4SHeiner Kallweit 	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
535525e992a4SHeiner Kallweit 		/* Disallow toggling */
535625e992a4SHeiner Kallweit 		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
535725e992a4SHeiner Kallweit 
535895099c56SHeiner Kallweit 	if (rtl_chip_supports_csum_v2(tp))
535995099c56SHeiner Kallweit 		dev->hw_features |= NETIF_F_IPV6_CSUM;
536095099c56SHeiner Kallweit 
536195099c56SHeiner Kallweit 	dev->features |= dev->hw_features;
536295099c56SHeiner Kallweit 
536395099c56SHeiner Kallweit 	/* There has been a number of reports that using SG/TSO results in
536495099c56SHeiner Kallweit 	 * tx timeouts. However for a lot of people SG/TSO works fine.
536595099c56SHeiner Kallweit 	 * Therefore disable both features by default, but allow users to
536695099c56SHeiner Kallweit 	 * enable them. Use at own risk!
536795099c56SHeiner Kallweit 	 */
53680170d594SHeiner Kallweit 	if (rtl_chip_supports_csum_v2(tp)) {
536995099c56SHeiner Kallweit 		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
5370ee8b7a11SJakub Kicinski 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
5371ee8b7a11SJakub Kicinski 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V2);
53720170d594SHeiner Kallweit 	} else {
537395099c56SHeiner Kallweit 		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO;
5374ee8b7a11SJakub Kicinski 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V1);
5375ee8b7a11SJakub Kicinski 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1);
53760170d594SHeiner Kallweit 	}
537725e992a4SHeiner Kallweit 
537825e992a4SHeiner Kallweit 	dev->hw_features |= NETIF_F_RXALL;
537925e992a4SHeiner Kallweit 	dev->hw_features |= NETIF_F_RXFCS;
538025e992a4SHeiner Kallweit 
538142f66a44SHeiner Kallweit 	netdev_sw_irq_coalesce_default_on(dev);
538242f66a44SHeiner Kallweit 
5383145192f8SHeiner Kallweit 	/* configure chip for default features */
5384145192f8SHeiner Kallweit 	rtl8169_set_features(dev, dev->features);
5385145192f8SHeiner Kallweit 
5386c61d525fSChunHao Lin 	if (!tp->dash_enabled) {
5387128735a1SHeiner Kallweit 		rtl_set_d3_pll_down(tp, true);
538854744510SHeiner Kallweit 	} else {
538954744510SHeiner Kallweit 		rtl_set_d3_pll_down(tp, false);
539054744510SHeiner Kallweit 		dev->wol_enabled = 1;
539154744510SHeiner Kallweit 	}
5392128735a1SHeiner Kallweit 
539325e992a4SHeiner Kallweit 	jumbo_max = rtl_jumbo_max(tp);
5394a8ec173aSHeiner Kallweit 	if (jumbo_max)
539525e992a4SHeiner Kallweit 		dev->max_mtu = jumbo_max;
539625e992a4SHeiner Kallweit 
5397ec9a4088SHeiner Kallweit 	rtl_set_irq_mask(tp);
53989fa0a8e1SHeiner Kallweit 
539925e992a4SHeiner Kallweit 	tp->fw_name = rtl_chip_infos[chipset].fw_name;
540025e992a4SHeiner Kallweit 
540125e992a4SHeiner Kallweit 	tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters),
540225e992a4SHeiner Kallweit 					    &tp->counters_phys_addr,
540325e992a4SHeiner Kallweit 					    GFP_KERNEL);
540425e992a4SHeiner Kallweit 	if (!tp->counters)
540525e992a4SHeiner Kallweit 		return -ENOMEM;
540625e992a4SHeiner Kallweit 
540727dc36aeSHeiner Kallweit 	pci_set_drvdata(pdev, tp);
540825e992a4SHeiner Kallweit 
540925e992a4SHeiner Kallweit 	rc = r8169_mdio_register(tp);
541025e992a4SHeiner Kallweit 	if (rc)
541125e992a4SHeiner Kallweit 		return rc;
541225e992a4SHeiner Kallweit 
541325e992a4SHeiner Kallweit 	rc = register_netdev(dev);
541425e992a4SHeiner Kallweit 	if (rc)
54150785dad4SHeiner Kallweit 		return rc;
541625e992a4SHeiner Kallweit 
541793882c6fSHeiner Kallweit 	netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
54181bd32771SThomas Gleixner 		    rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
541925e992a4SHeiner Kallweit 
5420a8ec173aSHeiner Kallweit 	if (jumbo_max)
542193882c6fSHeiner Kallweit 		netdev_info(dev, "jumbo features [frames: %d bytes, tx checksumming: %s]\n",
542225e992a4SHeiner Kallweit 			    jumbo_max, tp->mac_version <= RTL_GIGA_MAC_VER_06 ?
542325e992a4SHeiner Kallweit 			    "ok" : "ko");
542425e992a4SHeiner Kallweit 
5425e0d38b58SHeiner Kallweit 	if (tp->dash_type != RTL_DASH_NONE) {
5426c61d525fSChunHao Lin 		netdev_info(dev, "DASH %s\n",
5427c61d525fSChunHao Lin 			    tp->dash_enabled ? "enabled" : "disabled");
542825e992a4SHeiner Kallweit 		rtl8168_driver_start(tp);
5429a38b7fbfSHeiner Kallweit 	}
543025e992a4SHeiner Kallweit 
543125e992a4SHeiner Kallweit 	if (pci_dev_run_wake(pdev))
543225e992a4SHeiner Kallweit 		pm_runtime_put_sync(&pdev->dev);
543325e992a4SHeiner Kallweit 
543425e992a4SHeiner Kallweit 	return 0;
543525e992a4SHeiner Kallweit }
543625e992a4SHeiner Kallweit 
543725e992a4SHeiner Kallweit static struct pci_driver rtl8169_pci_driver = {
54387cb7541aSHeiner Kallweit 	.name		= KBUILD_MODNAME,
543925e992a4SHeiner Kallweit 	.id_table	= rtl8169_pci_tbl,
544025e992a4SHeiner Kallweit 	.probe		= rtl_init_one,
544125e992a4SHeiner Kallweit 	.remove		= rtl_remove_one,
544225e992a4SHeiner Kallweit 	.shutdown	= rtl_shutdown,
54438fe6e670SHeiner Kallweit 	.driver.pm	= pm_ptr(&rtl8169_pm_ops),
544425e992a4SHeiner Kallweit };
544525e992a4SHeiner Kallweit 
544625e992a4SHeiner Kallweit module_pci_driver(rtl8169_pci_driver);
5447