xref: /OK3568_Linux_fs/kernel/drivers/net/usb/r8152.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Copyright (c) 2014 Realtek Semiconductor Corp. All rights reserved.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/signal.h>
7*4882a593Smuzhiyun #include <linux/slab.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/netdevice.h>
10*4882a593Smuzhiyun #include <linux/etherdevice.h>
11*4882a593Smuzhiyun #include <linux/mii.h>
12*4882a593Smuzhiyun #include <linux/ethtool.h>
13*4882a593Smuzhiyun #include <linux/usb.h>
14*4882a593Smuzhiyun #include <linux/crc32.h>
15*4882a593Smuzhiyun #include <linux/if_vlan.h>
16*4882a593Smuzhiyun #include <linux/uaccess.h>
17*4882a593Smuzhiyun #include <linux/list.h>
18*4882a593Smuzhiyun #include <linux/ip.h>
19*4882a593Smuzhiyun #include <linux/ipv6.h>
20*4882a593Smuzhiyun #include <net/ip6_checksum.h>
21*4882a593Smuzhiyun #include <uapi/linux/mdio.h>
22*4882a593Smuzhiyun #include <linux/mdio.h>
23*4882a593Smuzhiyun #include <linux/usb/cdc.h>
24*4882a593Smuzhiyun #include <linux/suspend.h>
25*4882a593Smuzhiyun #include <linux/atomic.h>
26*4882a593Smuzhiyun #include <linux/acpi.h>
27*4882a593Smuzhiyun #include <linux/firmware.h>
28*4882a593Smuzhiyun #include <crypto/hash.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* Information for net-next */
31*4882a593Smuzhiyun #define NETNEXT_VERSION		"11"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* Information for net */
34*4882a593Smuzhiyun #define NET_VERSION		"11"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define DRIVER_VERSION		"v1." NETNEXT_VERSION "." NET_VERSION
37*4882a593Smuzhiyun #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
38*4882a593Smuzhiyun #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
39*4882a593Smuzhiyun #define MODULENAME "r8152"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define R8152_PHY_ID		32
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define PLA_IDR			0xc000
44*4882a593Smuzhiyun #define PLA_RCR			0xc010
45*4882a593Smuzhiyun #define PLA_RMS			0xc016
46*4882a593Smuzhiyun #define PLA_RXFIFO_CTRL0	0xc0a0
47*4882a593Smuzhiyun #define PLA_RXFIFO_CTRL1	0xc0a4
48*4882a593Smuzhiyun #define PLA_RXFIFO_CTRL2	0xc0a8
49*4882a593Smuzhiyun #define PLA_DMY_REG0		0xc0b0
50*4882a593Smuzhiyun #define PLA_FMC			0xc0b4
51*4882a593Smuzhiyun #define PLA_CFG_WOL		0xc0b6
52*4882a593Smuzhiyun #define PLA_TEREDO_CFG		0xc0bc
53*4882a593Smuzhiyun #define PLA_TEREDO_WAKE_BASE	0xc0c4
54*4882a593Smuzhiyun #define PLA_MAR			0xcd00
55*4882a593Smuzhiyun #define PLA_BACKUP		0xd000
56*4882a593Smuzhiyun #define PLA_BDC_CR		0xd1a0
57*4882a593Smuzhiyun #define PLA_TEREDO_TIMER	0xd2cc
58*4882a593Smuzhiyun #define PLA_REALWOW_TIMER	0xd2e8
59*4882a593Smuzhiyun #define PLA_UPHY_TIMER		0xd388
60*4882a593Smuzhiyun #define PLA_SUSPEND_FLAG	0xd38a
61*4882a593Smuzhiyun #define PLA_INDICATE_FALG	0xd38c
62*4882a593Smuzhiyun #define PLA_MACDBG_PRE		0xd38c	/* RTL_VER_04 only */
63*4882a593Smuzhiyun #define PLA_MACDBG_POST		0xd38e	/* RTL_VER_04 only */
64*4882a593Smuzhiyun #define PLA_EXTRA_STATUS	0xd398
65*4882a593Smuzhiyun #define PLA_EFUSE_DATA		0xdd00
66*4882a593Smuzhiyun #define PLA_EFUSE_CMD		0xdd02
67*4882a593Smuzhiyun #define PLA_LEDSEL		0xdd90
68*4882a593Smuzhiyun #define PLA_LED_FEATURE		0xdd92
69*4882a593Smuzhiyun #define PLA_PHYAR		0xde00
70*4882a593Smuzhiyun #define PLA_BOOT_CTRL		0xe004
71*4882a593Smuzhiyun #define PLA_LWAKE_CTRL_REG	0xe007
72*4882a593Smuzhiyun #define PLA_GPHY_INTR_IMR	0xe022
73*4882a593Smuzhiyun #define PLA_EEE_CR		0xe040
74*4882a593Smuzhiyun #define PLA_EEEP_CR		0xe080
75*4882a593Smuzhiyun #define PLA_MAC_PWR_CTRL	0xe0c0
76*4882a593Smuzhiyun #define PLA_MAC_PWR_CTRL2	0xe0ca
77*4882a593Smuzhiyun #define PLA_MAC_PWR_CTRL3	0xe0cc
78*4882a593Smuzhiyun #define PLA_MAC_PWR_CTRL4	0xe0ce
79*4882a593Smuzhiyun #define PLA_WDT6_CTRL		0xe428
80*4882a593Smuzhiyun #define PLA_TCR0		0xe610
81*4882a593Smuzhiyun #define PLA_TCR1		0xe612
82*4882a593Smuzhiyun #define PLA_MTPS		0xe615
83*4882a593Smuzhiyun #define PLA_TXFIFO_CTRL		0xe618
84*4882a593Smuzhiyun #define PLA_RSTTALLY		0xe800
85*4882a593Smuzhiyun #define PLA_CR			0xe813
86*4882a593Smuzhiyun #define PLA_CRWECR		0xe81c
87*4882a593Smuzhiyun #define PLA_CONFIG12		0xe81e	/* CONFIG1, CONFIG2 */
88*4882a593Smuzhiyun #define PLA_CONFIG34		0xe820	/* CONFIG3, CONFIG4 */
89*4882a593Smuzhiyun #define PLA_CONFIG5		0xe822
90*4882a593Smuzhiyun #define PLA_PHY_PWR		0xe84c
91*4882a593Smuzhiyun #define PLA_OOB_CTRL		0xe84f
92*4882a593Smuzhiyun #define PLA_CPCR		0xe854
93*4882a593Smuzhiyun #define PLA_MISC_0		0xe858
94*4882a593Smuzhiyun #define PLA_MISC_1		0xe85a
95*4882a593Smuzhiyun #define PLA_OCP_GPHY_BASE	0xe86c
96*4882a593Smuzhiyun #define PLA_TALLYCNT		0xe890
97*4882a593Smuzhiyun #define PLA_SFF_STS_7		0xe8de
98*4882a593Smuzhiyun #define PLA_PHYSTATUS		0xe908
99*4882a593Smuzhiyun #define PLA_CONFIG6		0xe90a /* CONFIG6 */
100*4882a593Smuzhiyun #define PLA_BP_BA		0xfc26
101*4882a593Smuzhiyun #define PLA_BP_0		0xfc28
102*4882a593Smuzhiyun #define PLA_BP_1		0xfc2a
103*4882a593Smuzhiyun #define PLA_BP_2		0xfc2c
104*4882a593Smuzhiyun #define PLA_BP_3		0xfc2e
105*4882a593Smuzhiyun #define PLA_BP_4		0xfc30
106*4882a593Smuzhiyun #define PLA_BP_5		0xfc32
107*4882a593Smuzhiyun #define PLA_BP_6		0xfc34
108*4882a593Smuzhiyun #define PLA_BP_7		0xfc36
109*4882a593Smuzhiyun #define PLA_BP_EN		0xfc38
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define USB_USB2PHY		0xb41e
112*4882a593Smuzhiyun #define USB_SSPHYLINK1		0xb426
113*4882a593Smuzhiyun #define USB_SSPHYLINK2		0xb428
114*4882a593Smuzhiyun #define USB_U2P3_CTRL		0xb460
115*4882a593Smuzhiyun #define USB_CSR_DUMMY1		0xb464
116*4882a593Smuzhiyun #define USB_CSR_DUMMY2		0xb466
117*4882a593Smuzhiyun #define USB_DEV_STAT		0xb808
118*4882a593Smuzhiyun #define USB_CONNECT_TIMER	0xcbf8
119*4882a593Smuzhiyun #define USB_MSC_TIMER		0xcbfc
120*4882a593Smuzhiyun #define USB_BURST_SIZE		0xcfc0
121*4882a593Smuzhiyun #define USB_FW_FIX_EN0		0xcfca
122*4882a593Smuzhiyun #define USB_FW_FIX_EN1		0xcfcc
123*4882a593Smuzhiyun #define USB_LPM_CONFIG		0xcfd8
124*4882a593Smuzhiyun #define USB_CSTMR		0xcfef	/* RTL8153A */
125*4882a593Smuzhiyun #define USB_FW_CTRL		0xd334	/* RTL8153B */
126*4882a593Smuzhiyun #define USB_FC_TIMER		0xd340
127*4882a593Smuzhiyun #define USB_USB_CTRL		0xd406
128*4882a593Smuzhiyun #define USB_PHY_CTRL		0xd408
129*4882a593Smuzhiyun #define USB_TX_AGG		0xd40a
130*4882a593Smuzhiyun #define USB_RX_BUF_TH		0xd40c
131*4882a593Smuzhiyun #define USB_USB_TIMER		0xd428
132*4882a593Smuzhiyun #define USB_RX_EARLY_TIMEOUT	0xd42c
133*4882a593Smuzhiyun #define USB_RX_EARLY_SIZE	0xd42e
134*4882a593Smuzhiyun #define USB_PM_CTRL_STATUS	0xd432	/* RTL8153A */
135*4882a593Smuzhiyun #define USB_RX_EXTRA_AGGR_TMR	0xd432	/* RTL8153B */
136*4882a593Smuzhiyun #define USB_TX_DMA		0xd434
137*4882a593Smuzhiyun #define USB_UPT_RXDMA_OWN	0xd437
138*4882a593Smuzhiyun #define USB_TOLERANCE		0xd490
139*4882a593Smuzhiyun #define USB_LPM_CTRL		0xd41a
140*4882a593Smuzhiyun #define USB_BMU_RESET		0xd4b0
141*4882a593Smuzhiyun #define USB_U1U2_TIMER		0xd4da
142*4882a593Smuzhiyun #define USB_FW_TASK		0xd4e8	/* RTL8153B */
143*4882a593Smuzhiyun #define USB_UPS_CTRL		0xd800
144*4882a593Smuzhiyun #define USB_POWER_CUT		0xd80a
145*4882a593Smuzhiyun #define USB_MISC_0		0xd81a
146*4882a593Smuzhiyun #define USB_MISC_1		0xd81f
147*4882a593Smuzhiyun #define USB_AFE_CTRL2		0xd824
148*4882a593Smuzhiyun #define USB_UPS_CFG		0xd842
149*4882a593Smuzhiyun #define USB_UPS_FLAGS		0xd848
150*4882a593Smuzhiyun #define USB_WDT1_CTRL		0xe404
151*4882a593Smuzhiyun #define USB_WDT11_CTRL		0xe43c
152*4882a593Smuzhiyun #define USB_BP_BA		PLA_BP_BA
153*4882a593Smuzhiyun #define USB_BP_0		PLA_BP_0
154*4882a593Smuzhiyun #define USB_BP_1		PLA_BP_1
155*4882a593Smuzhiyun #define USB_BP_2		PLA_BP_2
156*4882a593Smuzhiyun #define USB_BP_3		PLA_BP_3
157*4882a593Smuzhiyun #define USB_BP_4		PLA_BP_4
158*4882a593Smuzhiyun #define USB_BP_5		PLA_BP_5
159*4882a593Smuzhiyun #define USB_BP_6		PLA_BP_6
160*4882a593Smuzhiyun #define USB_BP_7		PLA_BP_7
161*4882a593Smuzhiyun #define USB_BP_EN		PLA_BP_EN	/* RTL8153A */
162*4882a593Smuzhiyun #define USB_BP_8		0xfc38		/* RTL8153B */
163*4882a593Smuzhiyun #define USB_BP_9		0xfc3a
164*4882a593Smuzhiyun #define USB_BP_10		0xfc3c
165*4882a593Smuzhiyun #define USB_BP_11		0xfc3e
166*4882a593Smuzhiyun #define USB_BP_12		0xfc40
167*4882a593Smuzhiyun #define USB_BP_13		0xfc42
168*4882a593Smuzhiyun #define USB_BP_14		0xfc44
169*4882a593Smuzhiyun #define USB_BP_15		0xfc46
170*4882a593Smuzhiyun #define USB_BP2_EN		0xfc48
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun /* OCP Registers */
173*4882a593Smuzhiyun #define OCP_ALDPS_CONFIG	0x2010
174*4882a593Smuzhiyun #define OCP_EEE_CONFIG1		0x2080
175*4882a593Smuzhiyun #define OCP_EEE_CONFIG2		0x2092
176*4882a593Smuzhiyun #define OCP_EEE_CONFIG3		0x2094
177*4882a593Smuzhiyun #define OCP_BASE_MII		0xa400
178*4882a593Smuzhiyun #define OCP_EEE_AR		0xa41a
179*4882a593Smuzhiyun #define OCP_EEE_DATA		0xa41c
180*4882a593Smuzhiyun #define OCP_PHY_STATUS		0xa420
181*4882a593Smuzhiyun #define OCP_NCTL_CFG		0xa42c
182*4882a593Smuzhiyun #define OCP_POWER_CFG		0xa430
183*4882a593Smuzhiyun #define OCP_EEE_CFG		0xa432
184*4882a593Smuzhiyun #define OCP_SRAM_ADDR		0xa436
185*4882a593Smuzhiyun #define OCP_SRAM_DATA		0xa438
186*4882a593Smuzhiyun #define OCP_DOWN_SPEED		0xa442
187*4882a593Smuzhiyun #define OCP_EEE_ABLE		0xa5c4
188*4882a593Smuzhiyun #define OCP_EEE_ADV		0xa5d0
189*4882a593Smuzhiyun #define OCP_EEE_LPABLE		0xa5d2
190*4882a593Smuzhiyun #define OCP_PHY_STATE		0xa708		/* nway state for 8153 */
191*4882a593Smuzhiyun #define OCP_PHY_PATCH_STAT	0xb800
192*4882a593Smuzhiyun #define OCP_PHY_PATCH_CMD	0xb820
193*4882a593Smuzhiyun #define OCP_PHY_LOCK		0xb82e
194*4882a593Smuzhiyun #define OCP_ADC_IOFFSET		0xbcfc
195*4882a593Smuzhiyun #define OCP_ADC_CFG		0xbc06
196*4882a593Smuzhiyun #define OCP_SYSCLK_CFG		0xc416
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /* SRAM Register */
199*4882a593Smuzhiyun #define SRAM_GREEN_CFG		0x8011
200*4882a593Smuzhiyun #define SRAM_LPF_CFG		0x8012
201*4882a593Smuzhiyun #define SRAM_10M_AMP1		0x8080
202*4882a593Smuzhiyun #define SRAM_10M_AMP2		0x8082
203*4882a593Smuzhiyun #define SRAM_IMPEDANCE		0x8084
204*4882a593Smuzhiyun #define SRAM_PHY_LOCK		0xb82e
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun /* PLA_RCR */
207*4882a593Smuzhiyun #define RCR_AAP			0x00000001
208*4882a593Smuzhiyun #define RCR_APM			0x00000002
209*4882a593Smuzhiyun #define RCR_AM			0x00000004
210*4882a593Smuzhiyun #define RCR_AB			0x00000008
211*4882a593Smuzhiyun #define RCR_ACPT_ALL		(RCR_AAP | RCR_APM | RCR_AM | RCR_AB)
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun /* PLA_RXFIFO_CTRL0 */
214*4882a593Smuzhiyun #define RXFIFO_THR1_NORMAL	0x00080002
215*4882a593Smuzhiyun #define RXFIFO_THR1_OOB		0x01800003
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun /* PLA_RXFIFO_CTRL1 */
218*4882a593Smuzhiyun #define RXFIFO_THR2_FULL	0x00000060
219*4882a593Smuzhiyun #define RXFIFO_THR2_HIGH	0x00000038
220*4882a593Smuzhiyun #define RXFIFO_THR2_OOB		0x0000004a
221*4882a593Smuzhiyun #define RXFIFO_THR2_NORMAL	0x00a0
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /* PLA_RXFIFO_CTRL2 */
224*4882a593Smuzhiyun #define RXFIFO_THR3_FULL	0x00000078
225*4882a593Smuzhiyun #define RXFIFO_THR3_HIGH	0x00000048
226*4882a593Smuzhiyun #define RXFIFO_THR3_OOB		0x0000005a
227*4882a593Smuzhiyun #define RXFIFO_THR3_NORMAL	0x0110
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun /* PLA_TXFIFO_CTRL */
230*4882a593Smuzhiyun #define TXFIFO_THR_NORMAL	0x00400008
231*4882a593Smuzhiyun #define TXFIFO_THR_NORMAL2	0x01000008
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /* PLA_DMY_REG0 */
234*4882a593Smuzhiyun #define ECM_ALDPS		0x0002
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /* PLA_FMC */
237*4882a593Smuzhiyun #define FMC_FCR_MCU_EN		0x0001
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /* PLA_EEEP_CR */
240*4882a593Smuzhiyun #define EEEP_CR_EEEP_TX		0x0002
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun /* PLA_WDT6_CTRL */
243*4882a593Smuzhiyun #define WDT6_SET_MODE		0x0010
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun /* PLA_TCR0 */
246*4882a593Smuzhiyun #define TCR0_TX_EMPTY		0x0800
247*4882a593Smuzhiyun #define TCR0_AUTO_FIFO		0x0080
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun /* PLA_TCR1 */
250*4882a593Smuzhiyun #define VERSION_MASK		0x7cf0
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun /* PLA_MTPS */
253*4882a593Smuzhiyun #define MTPS_JUMBO		(12 * 1024 / 64)
254*4882a593Smuzhiyun #define MTPS_DEFAULT		(6 * 1024 / 64)
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /* PLA_RSTTALLY */
257*4882a593Smuzhiyun #define TALLY_RESET		0x0001
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun /* PLA_CR */
260*4882a593Smuzhiyun #define CR_RST			0x10
261*4882a593Smuzhiyun #define CR_RE			0x08
262*4882a593Smuzhiyun #define CR_TE			0x04
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun /* PLA_CRWECR */
265*4882a593Smuzhiyun #define CRWECR_NORAML		0x00
266*4882a593Smuzhiyun #define CRWECR_CONFIG		0xc0
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /* PLA_OOB_CTRL */
269*4882a593Smuzhiyun #define NOW_IS_OOB		0x80
270*4882a593Smuzhiyun #define TXFIFO_EMPTY		0x20
271*4882a593Smuzhiyun #define RXFIFO_EMPTY		0x10
272*4882a593Smuzhiyun #define LINK_LIST_READY		0x02
273*4882a593Smuzhiyun #define DIS_MCU_CLROOB		0x01
274*4882a593Smuzhiyun #define FIFO_EMPTY		(TXFIFO_EMPTY | RXFIFO_EMPTY)
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun /* PLA_MISC_1 */
277*4882a593Smuzhiyun #define RXDY_GATED_EN		0x0008
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun /* PLA_SFF_STS_7 */
280*4882a593Smuzhiyun #define RE_INIT_LL		0x8000
281*4882a593Smuzhiyun #define MCU_BORW_EN		0x4000
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun /* PLA_CPCR */
284*4882a593Smuzhiyun #define CPCR_RX_VLAN		0x0040
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* PLA_CFG_WOL */
287*4882a593Smuzhiyun #define MAGIC_EN		0x0001
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun /* PLA_TEREDO_CFG */
290*4882a593Smuzhiyun #define TEREDO_SEL		0x8000
291*4882a593Smuzhiyun #define TEREDO_WAKE_MASK	0x7f00
292*4882a593Smuzhiyun #define TEREDO_RS_EVENT_MASK	0x00fe
293*4882a593Smuzhiyun #define OOB_TEREDO_EN		0x0001
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun /* PLA_BDC_CR */
296*4882a593Smuzhiyun #define ALDPS_PROXY_MODE	0x0001
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun /* PLA_EFUSE_CMD */
299*4882a593Smuzhiyun #define EFUSE_READ_CMD		BIT(15)
300*4882a593Smuzhiyun #define EFUSE_DATA_BIT16	BIT(7)
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun /* PLA_CONFIG34 */
303*4882a593Smuzhiyun #define LINK_ON_WAKE_EN		0x0010
304*4882a593Smuzhiyun #define LINK_OFF_WAKE_EN	0x0008
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun /* PLA_CONFIG6 */
307*4882a593Smuzhiyun #define LANWAKE_CLR_EN		BIT(0)
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun /* PLA_CONFIG5 */
310*4882a593Smuzhiyun #define BWF_EN			0x0040
311*4882a593Smuzhiyun #define MWF_EN			0x0020
312*4882a593Smuzhiyun #define UWF_EN			0x0010
313*4882a593Smuzhiyun #define LAN_WAKE_EN		0x0002
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun /* PLA_LED_FEATURE */
316*4882a593Smuzhiyun #define LED_MODE_MASK		0x0700
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /* PLA_PHY_PWR */
319*4882a593Smuzhiyun #define TX_10M_IDLE_EN		0x0080
320*4882a593Smuzhiyun #define PFM_PWM_SWITCH		0x0040
321*4882a593Smuzhiyun #define TEST_IO_OFF		BIT(4)
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun /* PLA_MAC_PWR_CTRL */
324*4882a593Smuzhiyun #define D3_CLK_GATED_EN		0x00004000
325*4882a593Smuzhiyun #define MCU_CLK_RATIO		0x07010f07
326*4882a593Smuzhiyun #define MCU_CLK_RATIO_MASK	0x0f0f0f0f
327*4882a593Smuzhiyun #define ALDPS_SPDWN_RATIO	0x0f87
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun /* PLA_MAC_PWR_CTRL2 */
330*4882a593Smuzhiyun #define EEE_SPDWN_RATIO		0x8007
331*4882a593Smuzhiyun #define MAC_CLK_SPDWN_EN	BIT(15)
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun /* PLA_MAC_PWR_CTRL3 */
334*4882a593Smuzhiyun #define PLA_MCU_SPDWN_EN	BIT(14)
335*4882a593Smuzhiyun #define PKT_AVAIL_SPDWN_EN	0x0100
336*4882a593Smuzhiyun #define SUSPEND_SPDWN_EN	0x0004
337*4882a593Smuzhiyun #define U1U2_SPDWN_EN		0x0002
338*4882a593Smuzhiyun #define L1_SPDWN_EN		0x0001
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun /* PLA_MAC_PWR_CTRL4 */
341*4882a593Smuzhiyun #define PWRSAVE_SPDWN_EN	0x1000
342*4882a593Smuzhiyun #define RXDV_SPDWN_EN		0x0800
343*4882a593Smuzhiyun #define TX10MIDLE_EN		0x0100
344*4882a593Smuzhiyun #define TP100_SPDWN_EN		0x0020
345*4882a593Smuzhiyun #define TP500_SPDWN_EN		0x0010
346*4882a593Smuzhiyun #define TP1000_SPDWN_EN		0x0008
347*4882a593Smuzhiyun #define EEE_SPDWN_EN		0x0001
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun /* PLA_GPHY_INTR_IMR */
350*4882a593Smuzhiyun #define GPHY_STS_MSK		0x0001
351*4882a593Smuzhiyun #define SPEED_DOWN_MSK		0x0002
352*4882a593Smuzhiyun #define SPDWN_RXDV_MSK		0x0004
353*4882a593Smuzhiyun #define SPDWN_LINKCHG_MSK	0x0008
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun /* PLA_PHYAR */
356*4882a593Smuzhiyun #define PHYAR_FLAG		0x80000000
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun /* PLA_EEE_CR */
359*4882a593Smuzhiyun #define EEE_RX_EN		0x0001
360*4882a593Smuzhiyun #define EEE_TX_EN		0x0002
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun /* PLA_BOOT_CTRL */
363*4882a593Smuzhiyun #define AUTOLOAD_DONE		0x0002
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun /* PLA_LWAKE_CTRL_REG */
366*4882a593Smuzhiyun #define LANWAKE_PIN		BIT(7)
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun /* PLA_SUSPEND_FLAG */
369*4882a593Smuzhiyun #define LINK_CHG_EVENT		BIT(0)
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun /* PLA_INDICATE_FALG */
372*4882a593Smuzhiyun #define UPCOMING_RUNTIME_D3	BIT(0)
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun /* PLA_MACDBG_PRE and PLA_MACDBG_POST */
375*4882a593Smuzhiyun #define DEBUG_OE		BIT(0)
376*4882a593Smuzhiyun #define DEBUG_LTSSM		0x0082
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun /* PLA_EXTRA_STATUS */
379*4882a593Smuzhiyun #define CUR_LINK_OK		BIT(15)
380*4882a593Smuzhiyun #define U3P3_CHECK_EN		BIT(7)	/* RTL_VER_05 only */
381*4882a593Smuzhiyun #define LINK_CHANGE_FLAG	BIT(8)
382*4882a593Smuzhiyun #define POLL_LINK_CHG		BIT(0)
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun /* USB_USB2PHY */
385*4882a593Smuzhiyun #define USB2PHY_SUSPEND		0x0001
386*4882a593Smuzhiyun #define USB2PHY_L1		0x0002
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun /* USB_SSPHYLINK1 */
389*4882a593Smuzhiyun #define DELAY_PHY_PWR_CHG	BIT(1)
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun /* USB_SSPHYLINK2 */
392*4882a593Smuzhiyun #define pwd_dn_scale_mask	0x3ffe
393*4882a593Smuzhiyun #define pwd_dn_scale(x)		((x) << 1)
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun /* USB_CSR_DUMMY1 */
396*4882a593Smuzhiyun #define DYNAMIC_BURST		0x0001
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun /* USB_CSR_DUMMY2 */
399*4882a593Smuzhiyun #define EP4_FULL_FC		0x0001
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun /* USB_DEV_STAT */
402*4882a593Smuzhiyun #define STAT_SPEED_MASK		0x0006
403*4882a593Smuzhiyun #define STAT_SPEED_HIGH		0x0000
404*4882a593Smuzhiyun #define STAT_SPEED_FULL		0x0002
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun /* USB_FW_FIX_EN0 */
407*4882a593Smuzhiyun #define FW_FIX_SUSPEND		BIT(14)
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun /* USB_FW_FIX_EN1 */
410*4882a593Smuzhiyun #define FW_IP_RESET_EN		BIT(9)
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun /* USB_LPM_CONFIG */
413*4882a593Smuzhiyun #define LPM_U1U2_EN		BIT(0)
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun /* USB_TX_AGG */
416*4882a593Smuzhiyun #define TX_AGG_MAX_THRESHOLD	0x03
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun /* USB_RX_BUF_TH */
419*4882a593Smuzhiyun #define RX_THR_SUPPER		0x0c350180
420*4882a593Smuzhiyun #define RX_THR_HIGH		0x7a120180
421*4882a593Smuzhiyun #define RX_THR_SLOW		0xffff0180
422*4882a593Smuzhiyun #define RX_THR_B		0x00010001
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun /* USB_TX_DMA */
425*4882a593Smuzhiyun #define TEST_MODE_DISABLE	0x00000001
426*4882a593Smuzhiyun #define TX_SIZE_ADJUST1		0x00000100
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun /* USB_BMU_RESET */
429*4882a593Smuzhiyun #define BMU_RESET_EP_IN		0x01
430*4882a593Smuzhiyun #define BMU_RESET_EP_OUT	0x02
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun /* USB_UPT_RXDMA_OWN */
433*4882a593Smuzhiyun #define OWN_UPDATE		BIT(0)
434*4882a593Smuzhiyun #define OWN_CLEAR		BIT(1)
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun /* USB_FW_TASK */
437*4882a593Smuzhiyun #define FC_PATCH_TASK		BIT(1)
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun /* USB_UPS_CTRL */
440*4882a593Smuzhiyun #define POWER_CUT		0x0100
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun /* USB_PM_CTRL_STATUS */
443*4882a593Smuzhiyun #define RESUME_INDICATE		0x0001
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun /* USB_CSTMR */
446*4882a593Smuzhiyun #define FORCE_SUPER		BIT(0)
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun /* USB_FW_CTRL */
449*4882a593Smuzhiyun #define FLOW_CTRL_PATCH_OPT	BIT(1)
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun /* USB_FC_TIMER */
452*4882a593Smuzhiyun #define CTRL_TIMER_EN		BIT(15)
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun /* USB_USB_CTRL */
455*4882a593Smuzhiyun #define RX_AGG_DISABLE		0x0010
456*4882a593Smuzhiyun #define RX_ZERO_EN		0x0080
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun /* USB_U2P3_CTRL */
459*4882a593Smuzhiyun #define U2P3_ENABLE		0x0001
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /* USB_POWER_CUT */
462*4882a593Smuzhiyun #define PWR_EN			0x0001
463*4882a593Smuzhiyun #define PHASE2_EN		0x0008
464*4882a593Smuzhiyun #define UPS_EN			BIT(4)
465*4882a593Smuzhiyun #define USP_PREWAKE		BIT(5)
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun /* USB_MISC_0 */
468*4882a593Smuzhiyun #define PCUT_STATUS		0x0001
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun /* USB_RX_EARLY_TIMEOUT */
471*4882a593Smuzhiyun #define COALESCE_SUPER		 85000U
472*4882a593Smuzhiyun #define COALESCE_HIGH		250000U
473*4882a593Smuzhiyun #define COALESCE_SLOW		524280U
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun /* USB_WDT1_CTRL */
476*4882a593Smuzhiyun #define WTD1_EN			BIT(0)
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun /* USB_WDT11_CTRL */
479*4882a593Smuzhiyun #define TIMER11_EN		0x0001
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun /* USB_LPM_CTRL */
482*4882a593Smuzhiyun /* bit 4 ~ 5: fifo empty boundary */
483*4882a593Smuzhiyun #define FIFO_EMPTY_1FB		0x30	/* 0x1fb * 64 = 32448 bytes */
484*4882a593Smuzhiyun /* bit 2 ~ 3: LMP timer */
485*4882a593Smuzhiyun #define LPM_TIMER_MASK		0x0c
486*4882a593Smuzhiyun #define LPM_TIMER_500MS		0x04	/* 500 ms */
487*4882a593Smuzhiyun #define LPM_TIMER_500US		0x0c	/* 500 us */
488*4882a593Smuzhiyun #define ROK_EXIT_LPM		0x02
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun /* USB_AFE_CTRL2 */
491*4882a593Smuzhiyun #define SEN_VAL_MASK		0xf800
492*4882a593Smuzhiyun #define SEN_VAL_NORMAL		0xa000
493*4882a593Smuzhiyun #define SEL_RXIDLE		0x0100
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun /* USB_UPS_CFG */
496*4882a593Smuzhiyun #define SAW_CNT_1MS_MASK	0x0fff
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun /* USB_UPS_FLAGS */
499*4882a593Smuzhiyun #define UPS_FLAGS_R_TUNE		BIT(0)
500*4882a593Smuzhiyun #define UPS_FLAGS_EN_10M_CKDIV		BIT(1)
501*4882a593Smuzhiyun #define UPS_FLAGS_250M_CKDIV		BIT(2)
502*4882a593Smuzhiyun #define UPS_FLAGS_EN_ALDPS		BIT(3)
503*4882a593Smuzhiyun #define UPS_FLAGS_CTAP_SHORT_DIS	BIT(4)
504*4882a593Smuzhiyun #define ups_flags_speed(x)		((x) << 16)
505*4882a593Smuzhiyun #define UPS_FLAGS_EN_EEE		BIT(20)
506*4882a593Smuzhiyun #define UPS_FLAGS_EN_500M_EEE		BIT(21)
507*4882a593Smuzhiyun #define UPS_FLAGS_EN_EEE_CKDIV		BIT(22)
508*4882a593Smuzhiyun #define UPS_FLAGS_EEE_PLLOFF_100	BIT(23)
509*4882a593Smuzhiyun #define UPS_FLAGS_EEE_PLLOFF_GIGA	BIT(24)
510*4882a593Smuzhiyun #define UPS_FLAGS_EEE_CMOD_LV_EN	BIT(25)
511*4882a593Smuzhiyun #define UPS_FLAGS_EN_GREEN		BIT(26)
512*4882a593Smuzhiyun #define UPS_FLAGS_EN_FLOW_CTR		BIT(27)
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun enum spd_duplex {
515*4882a593Smuzhiyun 	NWAY_10M_HALF,
516*4882a593Smuzhiyun 	NWAY_10M_FULL,
517*4882a593Smuzhiyun 	NWAY_100M_HALF,
518*4882a593Smuzhiyun 	NWAY_100M_FULL,
519*4882a593Smuzhiyun 	NWAY_1000M_FULL,
520*4882a593Smuzhiyun 	FORCE_10M_HALF,
521*4882a593Smuzhiyun 	FORCE_10M_FULL,
522*4882a593Smuzhiyun 	FORCE_100M_HALF,
523*4882a593Smuzhiyun 	FORCE_100M_FULL,
524*4882a593Smuzhiyun };
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun /* OCP_ALDPS_CONFIG */
527*4882a593Smuzhiyun #define ENPWRSAVE		0x8000
528*4882a593Smuzhiyun #define ENPDNPS			0x0200
529*4882a593Smuzhiyun #define LINKENA			0x0100
530*4882a593Smuzhiyun #define DIS_SDSAVE		0x0010
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun /* OCP_PHY_STATUS */
533*4882a593Smuzhiyun #define PHY_STAT_MASK		0x0007
534*4882a593Smuzhiyun #define PHY_STAT_EXT_INIT	2
535*4882a593Smuzhiyun #define PHY_STAT_LAN_ON		3
536*4882a593Smuzhiyun #define PHY_STAT_PWRDN		5
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun /* OCP_NCTL_CFG */
539*4882a593Smuzhiyun #define PGA_RETURN_EN		BIT(1)
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun /* OCP_POWER_CFG */
542*4882a593Smuzhiyun #define EEE_CLKDIV_EN		0x8000
543*4882a593Smuzhiyun #define EN_ALDPS		0x0004
544*4882a593Smuzhiyun #define EN_10M_PLLOFF		0x0001
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /* OCP_EEE_CONFIG1 */
547*4882a593Smuzhiyun #define RG_TXLPI_MSK_HFDUP	0x8000
548*4882a593Smuzhiyun #define RG_MATCLR_EN		0x4000
549*4882a593Smuzhiyun #define EEE_10_CAP		0x2000
550*4882a593Smuzhiyun #define EEE_NWAY_EN		0x1000
551*4882a593Smuzhiyun #define TX_QUIET_EN		0x0200
552*4882a593Smuzhiyun #define RX_QUIET_EN		0x0100
553*4882a593Smuzhiyun #define sd_rise_time_mask	0x0070
554*4882a593Smuzhiyun #define sd_rise_time(x)		(min(x, 7) << 4)	/* bit 4 ~ 6 */
555*4882a593Smuzhiyun #define RG_RXLPI_MSK_HFDUP	0x0008
556*4882a593Smuzhiyun #define SDFALLTIME		0x0007	/* bit 0 ~ 2 */
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun /* OCP_EEE_CONFIG2 */
559*4882a593Smuzhiyun #define RG_LPIHYS_NUM		0x7000	/* bit 12 ~ 15 */
560*4882a593Smuzhiyun #define RG_DACQUIET_EN		0x0400
561*4882a593Smuzhiyun #define RG_LDVQUIET_EN		0x0200
562*4882a593Smuzhiyun #define RG_CKRSEL		0x0020
563*4882a593Smuzhiyun #define RG_EEEPRG_EN		0x0010
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun /* OCP_EEE_CONFIG3 */
566*4882a593Smuzhiyun #define fast_snr_mask		0xff80
567*4882a593Smuzhiyun #define fast_snr(x)		(min(x, 0x1ff) << 7)	/* bit 7 ~ 15 */
568*4882a593Smuzhiyun #define RG_LFS_SEL		0x0060	/* bit 6 ~ 5 */
569*4882a593Smuzhiyun #define MSK_PH			0x0006	/* bit 0 ~ 3 */
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun /* OCP_EEE_AR */
572*4882a593Smuzhiyun /* bit[15:14] function */
573*4882a593Smuzhiyun #define FUN_ADDR		0x0000
574*4882a593Smuzhiyun #define FUN_DATA		0x4000
575*4882a593Smuzhiyun /* bit[4:0] device addr */
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun /* OCP_EEE_CFG */
578*4882a593Smuzhiyun #define CTAP_SHORT_EN		0x0040
579*4882a593Smuzhiyun #define EEE10_EN		0x0010
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun /* OCP_DOWN_SPEED */
582*4882a593Smuzhiyun #define EN_EEE_CMODE		BIT(14)
583*4882a593Smuzhiyun #define EN_EEE_1000		BIT(13)
584*4882a593Smuzhiyun #define EN_EEE_100		BIT(12)
585*4882a593Smuzhiyun #define EN_10M_CLKDIV		BIT(11)
586*4882a593Smuzhiyun #define EN_10M_BGOFF		0x0080
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun /* OCP_PHY_STATE */
589*4882a593Smuzhiyun #define TXDIS_STATE		0x01
590*4882a593Smuzhiyun #define ABD_STATE		0x02
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun /* OCP_PHY_PATCH_STAT */
593*4882a593Smuzhiyun #define PATCH_READY		BIT(6)
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun /* OCP_PHY_PATCH_CMD */
596*4882a593Smuzhiyun #define PATCH_REQUEST		BIT(4)
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun /* OCP_PHY_LOCK */
599*4882a593Smuzhiyun #define PATCH_LOCK		BIT(0)
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun /* OCP_ADC_CFG */
602*4882a593Smuzhiyun #define CKADSEL_L		0x0100
603*4882a593Smuzhiyun #define ADC_EN			0x0080
604*4882a593Smuzhiyun #define EN_EMI_L		0x0040
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun /* OCP_SYSCLK_CFG */
607*4882a593Smuzhiyun #define clk_div_expo(x)		(min(x, 5) << 8)
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun /* SRAM_GREEN_CFG */
610*4882a593Smuzhiyun #define GREEN_ETH_EN		BIT(15)
611*4882a593Smuzhiyun #define R_TUNE_EN		BIT(11)
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun /* SRAM_LPF_CFG */
614*4882a593Smuzhiyun #define LPF_AUTO_TUNE		0x8000
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun /* SRAM_10M_AMP1 */
617*4882a593Smuzhiyun #define GDAC_IB_UPALL		0x0008
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun /* SRAM_10M_AMP2 */
620*4882a593Smuzhiyun #define AMP_DN			0x0200
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun /* SRAM_IMPEDANCE */
623*4882a593Smuzhiyun #define RX_DRIVING_MASK		0x6000
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun /* SRAM_PHY_LOCK */
626*4882a593Smuzhiyun #define PHY_PATCH_LOCK		0x0001
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun /* MAC PASSTHRU */
629*4882a593Smuzhiyun #define AD_MASK			0xfee0
630*4882a593Smuzhiyun #define BND_MASK		0x0004
631*4882a593Smuzhiyun #define BD_MASK			0x0001
632*4882a593Smuzhiyun #define EFUSE			0xcfdb
633*4882a593Smuzhiyun #define PASS_THRU_MASK		0x1
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun #define BP4_SUPER_ONLY		0x1578	/* RTL_VER_04 only */
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun enum rtl_register_content {
638*4882a593Smuzhiyun 	_1000bps	= 0x10,
639*4882a593Smuzhiyun 	_100bps		= 0x08,
640*4882a593Smuzhiyun 	_10bps		= 0x04,
641*4882a593Smuzhiyun 	LINK_STATUS	= 0x02,
642*4882a593Smuzhiyun 	FULL_DUP	= 0x01,
643*4882a593Smuzhiyun };
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun #define RTL8152_MAX_TX		4
646*4882a593Smuzhiyun #define RTL8152_MAX_RX		10
647*4882a593Smuzhiyun #define INTBUFSIZE		2
648*4882a593Smuzhiyun #define TX_ALIGN		4
649*4882a593Smuzhiyun #define RX_ALIGN		8
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun #define RTL8152_RX_MAX_PENDING	4096
652*4882a593Smuzhiyun #define RTL8152_RXFG_HEADSZ	256
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun #define INTR_LINK		0x0004
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun #define RTL8152_REQT_READ	0xc0
657*4882a593Smuzhiyun #define RTL8152_REQT_WRITE	0x40
658*4882a593Smuzhiyun #define RTL8152_REQ_GET_REGS	0x05
659*4882a593Smuzhiyun #define RTL8152_REQ_SET_REGS	0x05
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun #define BYTE_EN_DWORD		0xff
662*4882a593Smuzhiyun #define BYTE_EN_WORD		0x33
663*4882a593Smuzhiyun #define BYTE_EN_BYTE		0x11
664*4882a593Smuzhiyun #define BYTE_EN_SIX_BYTES	0x3f
665*4882a593Smuzhiyun #define BYTE_EN_START_MASK	0x0f
666*4882a593Smuzhiyun #define BYTE_EN_END_MASK	0xf0
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun #define RTL8153_MAX_PACKET	9216 /* 9K */
669*4882a593Smuzhiyun #define RTL8153_MAX_MTU		(RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \
670*4882a593Smuzhiyun 				 ETH_FCS_LEN)
671*4882a593Smuzhiyun #define RTL8152_RMS		(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
672*4882a593Smuzhiyun #define RTL8153_RMS		RTL8153_MAX_PACKET
673*4882a593Smuzhiyun #define RTL8152_TX_TIMEOUT	(5 * HZ)
674*4882a593Smuzhiyun #define RTL8152_NAPI_WEIGHT	64
675*4882a593Smuzhiyun #define rx_reserved_size(x)	((x) + VLAN_ETH_HLEN + ETH_FCS_LEN + \
676*4882a593Smuzhiyun 				 sizeof(struct rx_desc) + RX_ALIGN)
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun /* rtl8152 flags */
679*4882a593Smuzhiyun enum rtl8152_flags {
680*4882a593Smuzhiyun 	RTL8152_UNPLUG = 0,
681*4882a593Smuzhiyun 	RTL8152_SET_RX_MODE,
682*4882a593Smuzhiyun 	WORK_ENABLE,
683*4882a593Smuzhiyun 	RTL8152_LINK_CHG,
684*4882a593Smuzhiyun 	SELECTIVE_SUSPEND,
685*4882a593Smuzhiyun 	PHY_RESET,
686*4882a593Smuzhiyun 	SCHEDULE_TASKLET,
687*4882a593Smuzhiyun 	GREEN_ETHERNET,
688*4882a593Smuzhiyun 	DELL_TB_RX_AGG_BUG,
689*4882a593Smuzhiyun 	LENOVO_MACPASSTHRU,
690*4882a593Smuzhiyun };
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun /* Define these values to match your device */
693*4882a593Smuzhiyun #define VENDOR_ID_REALTEK		0x0bda
694*4882a593Smuzhiyun #define VENDOR_ID_MICROSOFT		0x045e
695*4882a593Smuzhiyun #define VENDOR_ID_SAMSUNG		0x04e8
696*4882a593Smuzhiyun #define VENDOR_ID_LENOVO		0x17ef
697*4882a593Smuzhiyun #define VENDOR_ID_LINKSYS		0x13b1
698*4882a593Smuzhiyun #define VENDOR_ID_NVIDIA		0x0955
699*4882a593Smuzhiyun #define VENDOR_ID_TPLINK		0x2357
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2	0x3082
702*4882a593Smuzhiyun #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2		0xa387
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun #define MCU_TYPE_PLA			0x0100
705*4882a593Smuzhiyun #define MCU_TYPE_USB			0x0000
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun struct tally_counter {
708*4882a593Smuzhiyun 	__le64	tx_packets;
709*4882a593Smuzhiyun 	__le64	rx_packets;
710*4882a593Smuzhiyun 	__le64	tx_errors;
711*4882a593Smuzhiyun 	__le32	rx_errors;
712*4882a593Smuzhiyun 	__le16	rx_missed;
713*4882a593Smuzhiyun 	__le16	align_errors;
714*4882a593Smuzhiyun 	__le32	tx_one_collision;
715*4882a593Smuzhiyun 	__le32	tx_multi_collision;
716*4882a593Smuzhiyun 	__le64	rx_unicast;
717*4882a593Smuzhiyun 	__le64	rx_broadcast;
718*4882a593Smuzhiyun 	__le32	rx_multicast;
719*4882a593Smuzhiyun 	__le16	tx_aborted;
720*4882a593Smuzhiyun 	__le16	tx_underrun;
721*4882a593Smuzhiyun };
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun struct rx_desc {
724*4882a593Smuzhiyun 	__le32 opts1;
725*4882a593Smuzhiyun #define RX_LEN_MASK			0x7fff
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	__le32 opts2;
728*4882a593Smuzhiyun #define RD_UDP_CS			BIT(23)
729*4882a593Smuzhiyun #define RD_TCP_CS			BIT(22)
730*4882a593Smuzhiyun #define RD_IPV6_CS			BIT(20)
731*4882a593Smuzhiyun #define RD_IPV4_CS			BIT(19)
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	__le32 opts3;
734*4882a593Smuzhiyun #define IPF				BIT(23) /* IP checksum fail */
735*4882a593Smuzhiyun #define UDPF				BIT(22) /* UDP checksum fail */
736*4882a593Smuzhiyun #define TCPF				BIT(21) /* TCP checksum fail */
737*4882a593Smuzhiyun #define RX_VLAN_TAG			BIT(16)
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	__le32 opts4;
740*4882a593Smuzhiyun 	__le32 opts5;
741*4882a593Smuzhiyun 	__le32 opts6;
742*4882a593Smuzhiyun };
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun struct tx_desc {
745*4882a593Smuzhiyun 	__le32 opts1;
746*4882a593Smuzhiyun #define TX_FS			BIT(31) /* First segment of a packet */
747*4882a593Smuzhiyun #define TX_LS			BIT(30) /* Final segment of a packet */
748*4882a593Smuzhiyun #define GTSENDV4		BIT(28)
749*4882a593Smuzhiyun #define GTSENDV6		BIT(27)
750*4882a593Smuzhiyun #define GTTCPHO_SHIFT		18
751*4882a593Smuzhiyun #define GTTCPHO_MAX		0x7fU
752*4882a593Smuzhiyun #define TX_LEN_MAX		0x3ffffU
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	__le32 opts2;
755*4882a593Smuzhiyun #define UDP_CS			BIT(31) /* Calculate UDP/IP checksum */
756*4882a593Smuzhiyun #define TCP_CS			BIT(30) /* Calculate TCP/IP checksum */
757*4882a593Smuzhiyun #define IPV4_CS			BIT(29) /* Calculate IPv4 checksum */
758*4882a593Smuzhiyun #define IPV6_CS			BIT(28) /* Calculate IPv6 checksum */
759*4882a593Smuzhiyun #define MSS_SHIFT		17
760*4882a593Smuzhiyun #define MSS_MAX			0x7ffU
761*4882a593Smuzhiyun #define TCPHO_SHIFT		17
762*4882a593Smuzhiyun #define TCPHO_MAX		0x7ffU
763*4882a593Smuzhiyun #define TX_VLAN_TAG		BIT(16)
764*4882a593Smuzhiyun };
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun struct r8152;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun struct rx_agg {
769*4882a593Smuzhiyun 	struct list_head list, info_list;
770*4882a593Smuzhiyun 	struct urb *urb;
771*4882a593Smuzhiyun 	struct r8152 *context;
772*4882a593Smuzhiyun 	struct page *page;
773*4882a593Smuzhiyun 	void *buffer;
774*4882a593Smuzhiyun };
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun struct tx_agg {
777*4882a593Smuzhiyun 	struct list_head list;
778*4882a593Smuzhiyun 	struct urb *urb;
779*4882a593Smuzhiyun 	struct r8152 *context;
780*4882a593Smuzhiyun 	void *buffer;
781*4882a593Smuzhiyun 	void *head;
782*4882a593Smuzhiyun 	u32 skb_num;
783*4882a593Smuzhiyun 	u32 skb_len;
784*4882a593Smuzhiyun };
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun struct r8152 {
787*4882a593Smuzhiyun 	unsigned long flags;
788*4882a593Smuzhiyun 	struct usb_device *udev;
789*4882a593Smuzhiyun 	struct napi_struct napi;
790*4882a593Smuzhiyun 	struct usb_interface *intf;
791*4882a593Smuzhiyun 	struct net_device *netdev;
792*4882a593Smuzhiyun 	struct urb *intr_urb;
793*4882a593Smuzhiyun 	struct tx_agg tx_info[RTL8152_MAX_TX];
794*4882a593Smuzhiyun 	struct list_head rx_info, rx_used;
795*4882a593Smuzhiyun 	struct list_head rx_done, tx_free;
796*4882a593Smuzhiyun 	struct sk_buff_head tx_queue, rx_queue;
797*4882a593Smuzhiyun 	spinlock_t rx_lock, tx_lock;
798*4882a593Smuzhiyun 	struct delayed_work schedule, hw_phy_work;
799*4882a593Smuzhiyun 	struct mii_if_info mii;
800*4882a593Smuzhiyun 	struct mutex control;	/* use for hw setting */
801*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
802*4882a593Smuzhiyun 	struct notifier_block pm_notifier;
803*4882a593Smuzhiyun #endif
804*4882a593Smuzhiyun 	struct tasklet_struct tx_tl;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	struct rtl_ops {
807*4882a593Smuzhiyun 		void (*init)(struct r8152 *tp);
808*4882a593Smuzhiyun 		int (*enable)(struct r8152 *tp);
809*4882a593Smuzhiyun 		void (*disable)(struct r8152 *tp);
810*4882a593Smuzhiyun 		void (*up)(struct r8152 *tp);
811*4882a593Smuzhiyun 		void (*down)(struct r8152 *tp);
812*4882a593Smuzhiyun 		void (*unload)(struct r8152 *tp);
813*4882a593Smuzhiyun 		int (*eee_get)(struct r8152 *tp, struct ethtool_eee *eee);
814*4882a593Smuzhiyun 		int (*eee_set)(struct r8152 *tp, struct ethtool_eee *eee);
815*4882a593Smuzhiyun 		bool (*in_nway)(struct r8152 *tp);
816*4882a593Smuzhiyun 		void (*hw_phy_cfg)(struct r8152 *tp);
817*4882a593Smuzhiyun 		void (*autosuspend_en)(struct r8152 *tp, bool enable);
818*4882a593Smuzhiyun 	} rtl_ops;
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	struct ups_info {
821*4882a593Smuzhiyun 		u32 _10m_ckdiv:1;
822*4882a593Smuzhiyun 		u32 _250m_ckdiv:1;
823*4882a593Smuzhiyun 		u32 aldps:1;
824*4882a593Smuzhiyun 		u32 lite_mode:2;
825*4882a593Smuzhiyun 		u32 speed_duplex:4;
826*4882a593Smuzhiyun 		u32 eee:1;
827*4882a593Smuzhiyun 		u32 eee_lite:1;
828*4882a593Smuzhiyun 		u32 eee_ckdiv:1;
829*4882a593Smuzhiyun 		u32 eee_plloff_100:1;
830*4882a593Smuzhiyun 		u32 eee_plloff_giga:1;
831*4882a593Smuzhiyun 		u32 eee_cmod_lv:1;
832*4882a593Smuzhiyun 		u32 green:1;
833*4882a593Smuzhiyun 		u32 flow_control:1;
834*4882a593Smuzhiyun 		u32 ctap_short_off:1;
835*4882a593Smuzhiyun 	} ups_info;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun #define RTL_VER_SIZE		32
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	struct rtl_fw {
840*4882a593Smuzhiyun 		const char *fw_name;
841*4882a593Smuzhiyun 		const struct firmware *fw;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 		char version[RTL_VER_SIZE];
844*4882a593Smuzhiyun 		int (*pre_fw)(struct r8152 *tp);
845*4882a593Smuzhiyun 		int (*post_fw)(struct r8152 *tp);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		bool retry;
848*4882a593Smuzhiyun 	} rtl_fw;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	atomic_t rx_count;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	bool eee_en;
853*4882a593Smuzhiyun 	int intr_interval;
854*4882a593Smuzhiyun 	u32 saved_wolopts;
855*4882a593Smuzhiyun 	u32 msg_enable;
856*4882a593Smuzhiyun 	u32 tx_qlen;
857*4882a593Smuzhiyun 	u32 coalesce;
858*4882a593Smuzhiyun 	u32 advertising;
859*4882a593Smuzhiyun 	u32 rx_buf_sz;
860*4882a593Smuzhiyun 	u32 rx_copybreak;
861*4882a593Smuzhiyun 	u32 rx_pending;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	u16 ocp_base;
864*4882a593Smuzhiyun 	u16 speed;
865*4882a593Smuzhiyun 	u16 eee_adv;
866*4882a593Smuzhiyun 	u8 *intr_buff;
867*4882a593Smuzhiyun 	u8 version;
868*4882a593Smuzhiyun 	u8 duplex;
869*4882a593Smuzhiyun 	u8 autoneg;
870*4882a593Smuzhiyun };
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun /**
873*4882a593Smuzhiyun  * struct fw_block - block type and total length
874*4882a593Smuzhiyun  * @type: type of the current block, such as RTL_FW_END, RTL_FW_PLA,
875*4882a593Smuzhiyun  *	RTL_FW_USB and so on.
876*4882a593Smuzhiyun  * @length: total length of the current block.
877*4882a593Smuzhiyun  */
878*4882a593Smuzhiyun struct fw_block {
879*4882a593Smuzhiyun 	__le32 type;
880*4882a593Smuzhiyun 	__le32 length;
881*4882a593Smuzhiyun } __packed;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun /**
884*4882a593Smuzhiyun  * struct fw_header - header of the firmware file
885*4882a593Smuzhiyun  * @checksum: checksum of sha256 which is calculated from the whole file
886*4882a593Smuzhiyun  *	except the checksum field of the file. That is, calculate sha256
887*4882a593Smuzhiyun  *	from the version field to the end of the file.
888*4882a593Smuzhiyun  * @version: version of this firmware.
889*4882a593Smuzhiyun  * @blocks: the first firmware block of the file
890*4882a593Smuzhiyun  */
891*4882a593Smuzhiyun struct fw_header {
892*4882a593Smuzhiyun 	u8 checksum[32];
893*4882a593Smuzhiyun 	char version[RTL_VER_SIZE];
894*4882a593Smuzhiyun 	struct fw_block blocks[];
895*4882a593Smuzhiyun } __packed;
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun /**
898*4882a593Smuzhiyun  * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB.
899*4882a593Smuzhiyun  *	The layout of the firmware block is:
900*4882a593Smuzhiyun  *	<struct fw_mac> + <info> + <firmware data>.
901*4882a593Smuzhiyun  * @fw_offset: offset of the firmware binary data. The start address of
902*4882a593Smuzhiyun  *	the data would be the address of struct fw_mac + @fw_offset.
903*4882a593Smuzhiyun  * @fw_reg: the register to load the firmware. Depends on chip.
904*4882a593Smuzhiyun  * @bp_ba_addr: the register to write break point base address. Depends on
905*4882a593Smuzhiyun  *	chip.
906*4882a593Smuzhiyun  * @bp_ba_value: break point base address. Depends on chip.
907*4882a593Smuzhiyun  * @bp_en_addr: the register to write break point enabled mask. Depends
908*4882a593Smuzhiyun  *	on chip.
909*4882a593Smuzhiyun  * @bp_en_value: break point enabled mask. Depends on the firmware.
910*4882a593Smuzhiyun  * @bp_start: the start register of break points. Depends on chip.
911*4882a593Smuzhiyun  * @bp_num: the break point number which needs to be set for this firmware.
912*4882a593Smuzhiyun  *	Depends on the firmware.
913*4882a593Smuzhiyun  * @bp: break points. Depends on firmware.
914*4882a593Smuzhiyun  * @fw_ver_reg: the register to store the fw version.
915*4882a593Smuzhiyun  * @fw_ver_data: the firmware version of the current type.
916*4882a593Smuzhiyun  * @info: additional information for debugging, and is followed by the
917*4882a593Smuzhiyun  *	binary data of firmware.
918*4882a593Smuzhiyun  */
919*4882a593Smuzhiyun struct fw_mac {
920*4882a593Smuzhiyun 	struct fw_block blk_hdr;
921*4882a593Smuzhiyun 	__le16 fw_offset;
922*4882a593Smuzhiyun 	__le16 fw_reg;
923*4882a593Smuzhiyun 	__le16 bp_ba_addr;
924*4882a593Smuzhiyun 	__le16 bp_ba_value;
925*4882a593Smuzhiyun 	__le16 bp_en_addr;
926*4882a593Smuzhiyun 	__le16 bp_en_value;
927*4882a593Smuzhiyun 	__le16 bp_start;
928*4882a593Smuzhiyun 	__le16 bp_num;
929*4882a593Smuzhiyun 	__le16 bp[16]; /* any value determined by firmware */
930*4882a593Smuzhiyun 	__le32 reserved;
931*4882a593Smuzhiyun 	__le16 fw_ver_reg;
932*4882a593Smuzhiyun 	u8 fw_ver_data;
933*4882a593Smuzhiyun 	char info[];
934*4882a593Smuzhiyun } __packed;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun /**
937*4882a593Smuzhiyun  * struct fw_phy_patch_key - a firmware block used by RTL_FW_PHY_START.
938*4882a593Smuzhiyun  *	This is used to set patch key when loading the firmware of PHY.
939*4882a593Smuzhiyun  * @key_reg: the register to write the patch key.
940*4882a593Smuzhiyun  * @key_data: patch key.
941*4882a593Smuzhiyun  */
942*4882a593Smuzhiyun struct fw_phy_patch_key {
943*4882a593Smuzhiyun 	struct fw_block blk_hdr;
944*4882a593Smuzhiyun 	__le16 key_reg;
945*4882a593Smuzhiyun 	__le16 key_data;
946*4882a593Smuzhiyun 	__le32 reserved;
947*4882a593Smuzhiyun } __packed;
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun /**
950*4882a593Smuzhiyun  * struct fw_phy_nc - a firmware block used by RTL_FW_PHY_NC.
951*4882a593Smuzhiyun  *	The layout of the firmware block is:
952*4882a593Smuzhiyun  *	<struct fw_phy_nc> + <info> + <firmware data>.
953*4882a593Smuzhiyun  * @fw_offset: offset of the firmware binary data. The start address of
954*4882a593Smuzhiyun  *	the data would be the address of struct fw_phy_nc + @fw_offset.
955*4882a593Smuzhiyun  * @fw_reg: the register to load the firmware. Depends on chip.
956*4882a593Smuzhiyun  * @ba_reg: the register to write the base address. Depends on chip.
957*4882a593Smuzhiyun  * @ba_data: base address. Depends on chip.
958*4882a593Smuzhiyun  * @patch_en_addr: the register of enabling patch mode. Depends on chip.
959*4882a593Smuzhiyun  * @patch_en_value: patch mode enabled mask. Depends on the firmware.
960*4882a593Smuzhiyun  * @mode_reg: the regitster of switching the mode.
961*4882a593Smuzhiyun  * @mod_pre: the mode needing to be set before loading the firmware.
962*4882a593Smuzhiyun  * @mod_post: the mode to be set when finishing to load the firmware.
963*4882a593Smuzhiyun  * @bp_start: the start register of break points. Depends on chip.
964*4882a593Smuzhiyun  * @bp_num: the break point number which needs to be set for this firmware.
965*4882a593Smuzhiyun  *	Depends on the firmware.
966*4882a593Smuzhiyun  * @bp: break points. Depends on firmware.
967*4882a593Smuzhiyun  * @info: additional information for debugging, and is followed by the
968*4882a593Smuzhiyun  *	binary data of firmware.
969*4882a593Smuzhiyun  */
970*4882a593Smuzhiyun struct fw_phy_nc {
971*4882a593Smuzhiyun 	struct fw_block blk_hdr;
972*4882a593Smuzhiyun 	__le16 fw_offset;
973*4882a593Smuzhiyun 	__le16 fw_reg;
974*4882a593Smuzhiyun 	__le16 ba_reg;
975*4882a593Smuzhiyun 	__le16 ba_data;
976*4882a593Smuzhiyun 	__le16 patch_en_addr;
977*4882a593Smuzhiyun 	__le16 patch_en_value;
978*4882a593Smuzhiyun 	__le16 mode_reg;
979*4882a593Smuzhiyun 	__le16 mode_pre;
980*4882a593Smuzhiyun 	__le16 mode_post;
981*4882a593Smuzhiyun 	__le16 reserved;
982*4882a593Smuzhiyun 	__le16 bp_start;
983*4882a593Smuzhiyun 	__le16 bp_num;
984*4882a593Smuzhiyun 	__le16 bp[4];
985*4882a593Smuzhiyun 	char info[];
986*4882a593Smuzhiyun } __packed;
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun enum rtl_fw_type {
989*4882a593Smuzhiyun 	RTL_FW_END = 0,
990*4882a593Smuzhiyun 	RTL_FW_PLA,
991*4882a593Smuzhiyun 	RTL_FW_USB,
992*4882a593Smuzhiyun 	RTL_FW_PHY_START,
993*4882a593Smuzhiyun 	RTL_FW_PHY_STOP,
994*4882a593Smuzhiyun 	RTL_FW_PHY_NC,
995*4882a593Smuzhiyun };
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun enum rtl_version {
998*4882a593Smuzhiyun 	RTL_VER_UNKNOWN = 0,
999*4882a593Smuzhiyun 	RTL_VER_01,
1000*4882a593Smuzhiyun 	RTL_VER_02,
1001*4882a593Smuzhiyun 	RTL_VER_03,
1002*4882a593Smuzhiyun 	RTL_VER_04,
1003*4882a593Smuzhiyun 	RTL_VER_05,
1004*4882a593Smuzhiyun 	RTL_VER_06,
1005*4882a593Smuzhiyun 	RTL_VER_07,
1006*4882a593Smuzhiyun 	RTL_VER_08,
1007*4882a593Smuzhiyun 	RTL_VER_09,
1008*4882a593Smuzhiyun 	RTL_VER_MAX
1009*4882a593Smuzhiyun };
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun enum tx_csum_stat {
1012*4882a593Smuzhiyun 	TX_CSUM_SUCCESS = 0,
1013*4882a593Smuzhiyun 	TX_CSUM_TSO,
1014*4882a593Smuzhiyun 	TX_CSUM_NONE
1015*4882a593Smuzhiyun };
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun #define RTL_ADVERTISED_10_HALF			BIT(0)
1018*4882a593Smuzhiyun #define RTL_ADVERTISED_10_FULL			BIT(1)
1019*4882a593Smuzhiyun #define RTL_ADVERTISED_100_HALF			BIT(2)
1020*4882a593Smuzhiyun #define RTL_ADVERTISED_100_FULL			BIT(3)
1021*4882a593Smuzhiyun #define RTL_ADVERTISED_1000_HALF		BIT(4)
1022*4882a593Smuzhiyun #define RTL_ADVERTISED_1000_FULL		BIT(5)
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
1025*4882a593Smuzhiyun  * The RTL chips use a 64 element hash table based on the Ethernet CRC.
1026*4882a593Smuzhiyun  */
1027*4882a593Smuzhiyun static const int multicast_filter_limit = 32;
1028*4882a593Smuzhiyun static unsigned int agg_buf_sz = 16384;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun #define RTL_LIMITED_TSO_SIZE	(agg_buf_sz - sizeof(struct tx_desc) - \
1031*4882a593Smuzhiyun 				 VLAN_ETH_HLEN - ETH_FCS_LEN)
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun static
get_registers(struct r8152 * tp,u16 value,u16 index,u16 size,void * data)1034*4882a593Smuzhiyun int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
1035*4882a593Smuzhiyun {
1036*4882a593Smuzhiyun 	int ret;
1037*4882a593Smuzhiyun 	void *tmp;
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	tmp = kmalloc(size, GFP_KERNEL);
1040*4882a593Smuzhiyun 	if (!tmp)
1041*4882a593Smuzhiyun 		return -ENOMEM;
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
1044*4882a593Smuzhiyun 			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
1045*4882a593Smuzhiyun 			      value, index, tmp, size, 500);
1046*4882a593Smuzhiyun 	if (ret < 0)
1047*4882a593Smuzhiyun 		memset(data, 0xff, size);
1048*4882a593Smuzhiyun 	else
1049*4882a593Smuzhiyun 		memcpy(data, tmp, size);
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	kfree(tmp);
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	return ret;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun static
set_registers(struct r8152 * tp,u16 value,u16 index,u16 size,void * data)1057*4882a593Smuzhiyun int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
1058*4882a593Smuzhiyun {
1059*4882a593Smuzhiyun 	int ret;
1060*4882a593Smuzhiyun 	void *tmp;
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	tmp = kmemdup(data, size, GFP_KERNEL);
1063*4882a593Smuzhiyun 	if (!tmp)
1064*4882a593Smuzhiyun 		return -ENOMEM;
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun 	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
1067*4882a593Smuzhiyun 			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
1068*4882a593Smuzhiyun 			      value, index, tmp, size, 500);
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	kfree(tmp);
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	return ret;
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun 
rtl_set_unplug(struct r8152 * tp)1075*4882a593Smuzhiyun static void rtl_set_unplug(struct r8152 *tp)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun 	if (tp->udev->state == USB_STATE_NOTATTACHED) {
1078*4882a593Smuzhiyun 		set_bit(RTL8152_UNPLUG, &tp->flags);
1079*4882a593Smuzhiyun 		smp_mb__after_atomic();
1080*4882a593Smuzhiyun 	}
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
generic_ocp_read(struct r8152 * tp,u16 index,u16 size,void * data,u16 type)1083*4882a593Smuzhiyun static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
1084*4882a593Smuzhiyun 			    void *data, u16 type)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun 	u16 limit = 64;
1087*4882a593Smuzhiyun 	int ret = 0;
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1090*4882a593Smuzhiyun 		return -ENODEV;
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	/* both size and indix must be 4 bytes align */
1093*4882a593Smuzhiyun 	if ((size & 3) || !size || (index & 3) || !data)
1094*4882a593Smuzhiyun 		return -EPERM;
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 	if ((u32)index + (u32)size > 0xffff)
1097*4882a593Smuzhiyun 		return -EPERM;
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	while (size) {
1100*4882a593Smuzhiyun 		if (size > limit) {
1101*4882a593Smuzhiyun 			ret = get_registers(tp, index, type, limit, data);
1102*4882a593Smuzhiyun 			if (ret < 0)
1103*4882a593Smuzhiyun 				break;
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun 			index += limit;
1106*4882a593Smuzhiyun 			data += limit;
1107*4882a593Smuzhiyun 			size -= limit;
1108*4882a593Smuzhiyun 		} else {
1109*4882a593Smuzhiyun 			ret = get_registers(tp, index, type, size, data);
1110*4882a593Smuzhiyun 			if (ret < 0)
1111*4882a593Smuzhiyun 				break;
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 			index += size;
1114*4882a593Smuzhiyun 			data += size;
1115*4882a593Smuzhiyun 			size = 0;
1116*4882a593Smuzhiyun 			break;
1117*4882a593Smuzhiyun 		}
1118*4882a593Smuzhiyun 	}
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	if (ret == -ENODEV)
1121*4882a593Smuzhiyun 		rtl_set_unplug(tp);
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 	return ret;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun 
generic_ocp_write(struct r8152 * tp,u16 index,u16 byteen,u16 size,void * data,u16 type)1126*4882a593Smuzhiyun static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
1127*4882a593Smuzhiyun 			     u16 size, void *data, u16 type)
1128*4882a593Smuzhiyun {
1129*4882a593Smuzhiyun 	int ret;
1130*4882a593Smuzhiyun 	u16 byteen_start, byteen_end, byen;
1131*4882a593Smuzhiyun 	u16 limit = 512;
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1134*4882a593Smuzhiyun 		return -ENODEV;
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 	/* both size and indix must be 4 bytes align */
1137*4882a593Smuzhiyun 	if ((size & 3) || !size || (index & 3) || !data)
1138*4882a593Smuzhiyun 		return -EPERM;
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 	if ((u32)index + (u32)size > 0xffff)
1141*4882a593Smuzhiyun 		return -EPERM;
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	byteen_start = byteen & BYTE_EN_START_MASK;
1144*4882a593Smuzhiyun 	byteen_end = byteen & BYTE_EN_END_MASK;
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun 	byen = byteen_start | (byteen_start << 4);
1147*4882a593Smuzhiyun 	ret = set_registers(tp, index, type | byen, 4, data);
1148*4882a593Smuzhiyun 	if (ret < 0)
1149*4882a593Smuzhiyun 		goto error1;
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 	index += 4;
1152*4882a593Smuzhiyun 	data += 4;
1153*4882a593Smuzhiyun 	size -= 4;
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 	if (size) {
1156*4882a593Smuzhiyun 		size -= 4;
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 		while (size) {
1159*4882a593Smuzhiyun 			if (size > limit) {
1160*4882a593Smuzhiyun 				ret = set_registers(tp, index,
1161*4882a593Smuzhiyun 						    type | BYTE_EN_DWORD,
1162*4882a593Smuzhiyun 						    limit, data);
1163*4882a593Smuzhiyun 				if (ret < 0)
1164*4882a593Smuzhiyun 					goto error1;
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 				index += limit;
1167*4882a593Smuzhiyun 				data += limit;
1168*4882a593Smuzhiyun 				size -= limit;
1169*4882a593Smuzhiyun 			} else {
1170*4882a593Smuzhiyun 				ret = set_registers(tp, index,
1171*4882a593Smuzhiyun 						    type | BYTE_EN_DWORD,
1172*4882a593Smuzhiyun 						    size, data);
1173*4882a593Smuzhiyun 				if (ret < 0)
1174*4882a593Smuzhiyun 					goto error1;
1175*4882a593Smuzhiyun 
1176*4882a593Smuzhiyun 				index += size;
1177*4882a593Smuzhiyun 				data += size;
1178*4882a593Smuzhiyun 				size = 0;
1179*4882a593Smuzhiyun 				break;
1180*4882a593Smuzhiyun 			}
1181*4882a593Smuzhiyun 		}
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 		byen = byteen_end | (byteen_end >> 4);
1184*4882a593Smuzhiyun 		ret = set_registers(tp, index, type | byen, 4, data);
1185*4882a593Smuzhiyun 		if (ret < 0)
1186*4882a593Smuzhiyun 			goto error1;
1187*4882a593Smuzhiyun 	}
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun error1:
1190*4882a593Smuzhiyun 	if (ret == -ENODEV)
1191*4882a593Smuzhiyun 		rtl_set_unplug(tp);
1192*4882a593Smuzhiyun 
1193*4882a593Smuzhiyun 	return ret;
1194*4882a593Smuzhiyun }
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun static inline
pla_ocp_read(struct r8152 * tp,u16 index,u16 size,void * data)1197*4882a593Smuzhiyun int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
1198*4882a593Smuzhiyun {
1199*4882a593Smuzhiyun 	return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
1200*4882a593Smuzhiyun }
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun static inline
pla_ocp_write(struct r8152 * tp,u16 index,u16 byteen,u16 size,void * data)1203*4882a593Smuzhiyun int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
1204*4882a593Smuzhiyun {
1205*4882a593Smuzhiyun 	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA);
1206*4882a593Smuzhiyun }
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun static inline
usb_ocp_write(struct r8152 * tp,u16 index,u16 byteen,u16 size,void * data)1209*4882a593Smuzhiyun int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
1210*4882a593Smuzhiyun {
1211*4882a593Smuzhiyun 	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB);
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun 
ocp_read_dword(struct r8152 * tp,u16 type,u16 index)1214*4882a593Smuzhiyun static u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index)
1215*4882a593Smuzhiyun {
1216*4882a593Smuzhiyun 	__le32 data;
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 	generic_ocp_read(tp, index, sizeof(data), &data, type);
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	return __le32_to_cpu(data);
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun 
ocp_write_dword(struct r8152 * tp,u16 type,u16 index,u32 data)1223*4882a593Smuzhiyun static void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun 	__le32 tmp = __cpu_to_le32(data);
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun 	generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type);
1228*4882a593Smuzhiyun }
1229*4882a593Smuzhiyun 
ocp_read_word(struct r8152 * tp,u16 type,u16 index)1230*4882a593Smuzhiyun static u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index)
1231*4882a593Smuzhiyun {
1232*4882a593Smuzhiyun 	u32 data;
1233*4882a593Smuzhiyun 	__le32 tmp;
1234*4882a593Smuzhiyun 	u16 byen = BYTE_EN_WORD;
1235*4882a593Smuzhiyun 	u8 shift = index & 2;
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	index &= ~3;
1238*4882a593Smuzhiyun 	byen <<= shift;
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type | byen);
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun 	data = __le32_to_cpu(tmp);
1243*4882a593Smuzhiyun 	data >>= (shift * 8);
1244*4882a593Smuzhiyun 	data &= 0xffff;
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 	return (u16)data;
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun 
ocp_write_word(struct r8152 * tp,u16 type,u16 index,u32 data)1249*4882a593Smuzhiyun static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
1250*4882a593Smuzhiyun {
1251*4882a593Smuzhiyun 	u32 mask = 0xffff;
1252*4882a593Smuzhiyun 	__le32 tmp;
1253*4882a593Smuzhiyun 	u16 byen = BYTE_EN_WORD;
1254*4882a593Smuzhiyun 	u8 shift = index & 2;
1255*4882a593Smuzhiyun 
1256*4882a593Smuzhiyun 	data &= mask;
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun 	if (index & 2) {
1259*4882a593Smuzhiyun 		byen <<= shift;
1260*4882a593Smuzhiyun 		mask <<= (shift * 8);
1261*4882a593Smuzhiyun 		data <<= (shift * 8);
1262*4882a593Smuzhiyun 		index &= ~3;
1263*4882a593Smuzhiyun 	}
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun 	tmp = __cpu_to_le32(data);
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun 
ocp_read_byte(struct r8152 * tp,u16 type,u16 index)1270*4882a593Smuzhiyun static u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index)
1271*4882a593Smuzhiyun {
1272*4882a593Smuzhiyun 	u32 data;
1273*4882a593Smuzhiyun 	__le32 tmp;
1274*4882a593Smuzhiyun 	u8 shift = index & 3;
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun 	index &= ~3;
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
1279*4882a593Smuzhiyun 
1280*4882a593Smuzhiyun 	data = __le32_to_cpu(tmp);
1281*4882a593Smuzhiyun 	data >>= (shift * 8);
1282*4882a593Smuzhiyun 	data &= 0xff;
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	return (u8)data;
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun 
ocp_write_byte(struct r8152 * tp,u16 type,u16 index,u32 data)1287*4882a593Smuzhiyun static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
1288*4882a593Smuzhiyun {
1289*4882a593Smuzhiyun 	u32 mask = 0xff;
1290*4882a593Smuzhiyun 	__le32 tmp;
1291*4882a593Smuzhiyun 	u16 byen = BYTE_EN_BYTE;
1292*4882a593Smuzhiyun 	u8 shift = index & 3;
1293*4882a593Smuzhiyun 
1294*4882a593Smuzhiyun 	data &= mask;
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun 	if (index & 3) {
1297*4882a593Smuzhiyun 		byen <<= shift;
1298*4882a593Smuzhiyun 		mask <<= (shift * 8);
1299*4882a593Smuzhiyun 		data <<= (shift * 8);
1300*4882a593Smuzhiyun 		index &= ~3;
1301*4882a593Smuzhiyun 	}
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	tmp = __cpu_to_le32(data);
1304*4882a593Smuzhiyun 
1305*4882a593Smuzhiyun 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
1306*4882a593Smuzhiyun }
1307*4882a593Smuzhiyun 
ocp_reg_read(struct r8152 * tp,u16 addr)1308*4882a593Smuzhiyun static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
1309*4882a593Smuzhiyun {
1310*4882a593Smuzhiyun 	u16 ocp_base, ocp_index;
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	ocp_base = addr & 0xf000;
1313*4882a593Smuzhiyun 	if (ocp_base != tp->ocp_base) {
1314*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
1315*4882a593Smuzhiyun 		tp->ocp_base = ocp_base;
1316*4882a593Smuzhiyun 	}
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	ocp_index = (addr & 0x0fff) | 0xb000;
1319*4882a593Smuzhiyun 	return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun 
ocp_reg_write(struct r8152 * tp,u16 addr,u16 data)1322*4882a593Smuzhiyun static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun 	u16 ocp_base, ocp_index;
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	ocp_base = addr & 0xf000;
1327*4882a593Smuzhiyun 	if (ocp_base != tp->ocp_base) {
1328*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
1329*4882a593Smuzhiyun 		tp->ocp_base = ocp_base;
1330*4882a593Smuzhiyun 	}
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 	ocp_index = (addr & 0x0fff) | 0xb000;
1333*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun 
r8152_mdio_write(struct r8152 * tp,u32 reg_addr,u32 value)1336*4882a593Smuzhiyun static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
1337*4882a593Smuzhiyun {
1338*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
1339*4882a593Smuzhiyun }
1340*4882a593Smuzhiyun 
r8152_mdio_read(struct r8152 * tp,u32 reg_addr)1341*4882a593Smuzhiyun static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
1342*4882a593Smuzhiyun {
1343*4882a593Smuzhiyun 	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun 
sram_write(struct r8152 * tp,u16 addr,u16 data)1346*4882a593Smuzhiyun static void sram_write(struct r8152 *tp, u16 addr, u16 data)
1347*4882a593Smuzhiyun {
1348*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
1349*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_SRAM_DATA, data);
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun 
sram_read(struct r8152 * tp,u16 addr)1352*4882a593Smuzhiyun static u16 sram_read(struct r8152 *tp, u16 addr)
1353*4882a593Smuzhiyun {
1354*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
1355*4882a593Smuzhiyun 	return ocp_reg_read(tp, OCP_SRAM_DATA);
1356*4882a593Smuzhiyun }
1357*4882a593Smuzhiyun 
read_mii_word(struct net_device * netdev,int phy_id,int reg)1358*4882a593Smuzhiyun static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
1359*4882a593Smuzhiyun {
1360*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
1361*4882a593Smuzhiyun 	int ret;
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1364*4882a593Smuzhiyun 		return -ENODEV;
1365*4882a593Smuzhiyun 
1366*4882a593Smuzhiyun 	if (phy_id != R8152_PHY_ID)
1367*4882a593Smuzhiyun 		return -EINVAL;
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun 	ret = r8152_mdio_read(tp, reg);
1370*4882a593Smuzhiyun 
1371*4882a593Smuzhiyun 	return ret;
1372*4882a593Smuzhiyun }
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun static
write_mii_word(struct net_device * netdev,int phy_id,int reg,int val)1375*4882a593Smuzhiyun void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
1376*4882a593Smuzhiyun {
1377*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1380*4882a593Smuzhiyun 		return;
1381*4882a593Smuzhiyun 
1382*4882a593Smuzhiyun 	if (phy_id != R8152_PHY_ID)
1383*4882a593Smuzhiyun 		return;
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun 	r8152_mdio_write(tp, reg, val);
1386*4882a593Smuzhiyun }
1387*4882a593Smuzhiyun 
1388*4882a593Smuzhiyun static int
1389*4882a593Smuzhiyun r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
1390*4882a593Smuzhiyun 
rtl8152_set_mac_address(struct net_device * netdev,void * p)1391*4882a593Smuzhiyun static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
1392*4882a593Smuzhiyun {
1393*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
1394*4882a593Smuzhiyun 	struct sockaddr *addr = p;
1395*4882a593Smuzhiyun 	int ret = -EADDRNOTAVAIL;
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 	if (!is_valid_ether_addr(addr->sa_data))
1398*4882a593Smuzhiyun 		goto out1;
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
1401*4882a593Smuzhiyun 	if (ret < 0)
1402*4882a593Smuzhiyun 		goto out1;
1403*4882a593Smuzhiyun 
1404*4882a593Smuzhiyun 	mutex_lock(&tp->control);
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
1407*4882a593Smuzhiyun 
1408*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
1409*4882a593Smuzhiyun 	pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data);
1410*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
1415*4882a593Smuzhiyun out1:
1416*4882a593Smuzhiyun 	return ret;
1417*4882a593Smuzhiyun }
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun /* Devices containing proper chips can support a persistent
1420*4882a593Smuzhiyun  * host system provided MAC address.
1421*4882a593Smuzhiyun  * Examples of this are Dell TB15 and Dell WD15 docks
1422*4882a593Smuzhiyun  */
vendor_mac_passthru_addr_read(struct r8152 * tp,struct sockaddr * sa)1423*4882a593Smuzhiyun static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa)
1424*4882a593Smuzhiyun {
1425*4882a593Smuzhiyun 	acpi_status status;
1426*4882a593Smuzhiyun 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1427*4882a593Smuzhiyun 	union acpi_object *obj;
1428*4882a593Smuzhiyun 	int ret = -EINVAL;
1429*4882a593Smuzhiyun 	u32 ocp_data;
1430*4882a593Smuzhiyun 	unsigned char buf[6];
1431*4882a593Smuzhiyun 	char *mac_obj_name;
1432*4882a593Smuzhiyun 	acpi_object_type mac_obj_type;
1433*4882a593Smuzhiyun 	int mac_strlen;
1434*4882a593Smuzhiyun 
1435*4882a593Smuzhiyun 	if (test_bit(LENOVO_MACPASSTHRU, &tp->flags)) {
1436*4882a593Smuzhiyun 		mac_obj_name = "\\MACA";
1437*4882a593Smuzhiyun 		mac_obj_type = ACPI_TYPE_STRING;
1438*4882a593Smuzhiyun 		mac_strlen = 0x16;
1439*4882a593Smuzhiyun 	} else {
1440*4882a593Smuzhiyun 		/* test for -AD variant of RTL8153 */
1441*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
1442*4882a593Smuzhiyun 		if ((ocp_data & AD_MASK) == 0x1000) {
1443*4882a593Smuzhiyun 			/* test for MAC address pass-through bit */
1444*4882a593Smuzhiyun 			ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, EFUSE);
1445*4882a593Smuzhiyun 			if ((ocp_data & PASS_THRU_MASK) != 1) {
1446*4882a593Smuzhiyun 				netif_dbg(tp, probe, tp->netdev,
1447*4882a593Smuzhiyun 						"No efuse for RTL8153-AD MAC pass through\n");
1448*4882a593Smuzhiyun 				return -ENODEV;
1449*4882a593Smuzhiyun 			}
1450*4882a593Smuzhiyun 		} else {
1451*4882a593Smuzhiyun 			/* test for RTL8153-BND and RTL8153-BD */
1452*4882a593Smuzhiyun 			ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
1453*4882a593Smuzhiyun 			if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) {
1454*4882a593Smuzhiyun 				netif_dbg(tp, probe, tp->netdev,
1455*4882a593Smuzhiyun 						"Invalid variant for MAC pass through\n");
1456*4882a593Smuzhiyun 				return -ENODEV;
1457*4882a593Smuzhiyun 			}
1458*4882a593Smuzhiyun 		}
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 		mac_obj_name = "\\_SB.AMAC";
1461*4882a593Smuzhiyun 		mac_obj_type = ACPI_TYPE_BUFFER;
1462*4882a593Smuzhiyun 		mac_strlen = 0x17;
1463*4882a593Smuzhiyun 	}
1464*4882a593Smuzhiyun 
1465*4882a593Smuzhiyun 	/* returns _AUXMAC_#AABBCCDDEEFF# */
1466*4882a593Smuzhiyun 	status = acpi_evaluate_object(NULL, mac_obj_name, NULL, &buffer);
1467*4882a593Smuzhiyun 	obj = (union acpi_object *)buffer.pointer;
1468*4882a593Smuzhiyun 	if (!ACPI_SUCCESS(status))
1469*4882a593Smuzhiyun 		return -ENODEV;
1470*4882a593Smuzhiyun 	if (obj->type != mac_obj_type || obj->string.length != mac_strlen) {
1471*4882a593Smuzhiyun 		netif_warn(tp, probe, tp->netdev,
1472*4882a593Smuzhiyun 			   "Invalid buffer for pass-thru MAC addr: (%d, %d)\n",
1473*4882a593Smuzhiyun 			   obj->type, obj->string.length);
1474*4882a593Smuzhiyun 		goto amacout;
1475*4882a593Smuzhiyun 	}
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun 	if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0 ||
1478*4882a593Smuzhiyun 	    strncmp(obj->string.pointer + 0x15, "#", 1) != 0) {
1479*4882a593Smuzhiyun 		netif_warn(tp, probe, tp->netdev,
1480*4882a593Smuzhiyun 			   "Invalid header when reading pass-thru MAC addr\n");
1481*4882a593Smuzhiyun 		goto amacout;
1482*4882a593Smuzhiyun 	}
1483*4882a593Smuzhiyun 	ret = hex2bin(buf, obj->string.pointer + 9, 6);
1484*4882a593Smuzhiyun 	if (!(ret == 0 && is_valid_ether_addr(buf))) {
1485*4882a593Smuzhiyun 		netif_warn(tp, probe, tp->netdev,
1486*4882a593Smuzhiyun 			   "Invalid MAC for pass-thru MAC addr: %d, %pM\n",
1487*4882a593Smuzhiyun 			   ret, buf);
1488*4882a593Smuzhiyun 		ret = -EINVAL;
1489*4882a593Smuzhiyun 		goto amacout;
1490*4882a593Smuzhiyun 	}
1491*4882a593Smuzhiyun 	memcpy(sa->sa_data, buf, 6);
1492*4882a593Smuzhiyun 	netif_info(tp, probe, tp->netdev,
1493*4882a593Smuzhiyun 		   "Using pass-thru MAC addr %pM\n", sa->sa_data);
1494*4882a593Smuzhiyun 
1495*4882a593Smuzhiyun amacout:
1496*4882a593Smuzhiyun 	kfree(obj);
1497*4882a593Smuzhiyun 	return ret;
1498*4882a593Smuzhiyun }
1499*4882a593Smuzhiyun 
determine_ethernet_addr(struct r8152 * tp,struct sockaddr * sa)1500*4882a593Smuzhiyun static int determine_ethernet_addr(struct r8152 *tp, struct sockaddr *sa)
1501*4882a593Smuzhiyun {
1502*4882a593Smuzhiyun 	struct net_device *dev = tp->netdev;
1503*4882a593Smuzhiyun 	int ret;
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	sa->sa_family = dev->type;
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun 	ret = eth_platform_get_mac_address(&tp->udev->dev, sa->sa_data);
1508*4882a593Smuzhiyun 	if (ret < 0) {
1509*4882a593Smuzhiyun 		if (tp->version == RTL_VER_01) {
1510*4882a593Smuzhiyun 			ret = pla_ocp_read(tp, PLA_IDR, 8, sa->sa_data);
1511*4882a593Smuzhiyun 		} else {
1512*4882a593Smuzhiyun 			/* if device doesn't support MAC pass through this will
1513*4882a593Smuzhiyun 			 * be expected to be non-zero
1514*4882a593Smuzhiyun 			 */
1515*4882a593Smuzhiyun 			ret = vendor_mac_passthru_addr_read(tp, sa);
1516*4882a593Smuzhiyun 			if (ret < 0)
1517*4882a593Smuzhiyun 				ret = pla_ocp_read(tp, PLA_BACKUP, 8,
1518*4882a593Smuzhiyun 						   sa->sa_data);
1519*4882a593Smuzhiyun 		}
1520*4882a593Smuzhiyun 	}
1521*4882a593Smuzhiyun 
1522*4882a593Smuzhiyun 	if (ret < 0) {
1523*4882a593Smuzhiyun 		netif_err(tp, probe, dev, "Get ether addr fail\n");
1524*4882a593Smuzhiyun 	} else if (!is_valid_ether_addr(sa->sa_data)) {
1525*4882a593Smuzhiyun 		netif_err(tp, probe, dev, "Invalid ether addr %pM\n",
1526*4882a593Smuzhiyun 			  sa->sa_data);
1527*4882a593Smuzhiyun 		eth_hw_addr_random(dev);
1528*4882a593Smuzhiyun 		ether_addr_copy(sa->sa_data, dev->dev_addr);
1529*4882a593Smuzhiyun 		netif_info(tp, probe, dev, "Random ether addr %pM\n",
1530*4882a593Smuzhiyun 			   sa->sa_data);
1531*4882a593Smuzhiyun 		return 0;
1532*4882a593Smuzhiyun 	}
1533*4882a593Smuzhiyun 
1534*4882a593Smuzhiyun 	return ret;
1535*4882a593Smuzhiyun }
1536*4882a593Smuzhiyun 
set_ethernet_addr(struct r8152 * tp)1537*4882a593Smuzhiyun static int set_ethernet_addr(struct r8152 *tp)
1538*4882a593Smuzhiyun {
1539*4882a593Smuzhiyun 	struct net_device *dev = tp->netdev;
1540*4882a593Smuzhiyun 	struct sockaddr sa;
1541*4882a593Smuzhiyun 	int ret;
1542*4882a593Smuzhiyun 
1543*4882a593Smuzhiyun 	ret = determine_ethernet_addr(tp, &sa);
1544*4882a593Smuzhiyun 	if (ret < 0)
1545*4882a593Smuzhiyun 		return ret;
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 	if (tp->version == RTL_VER_01)
1548*4882a593Smuzhiyun 		ether_addr_copy(dev->dev_addr, sa.sa_data);
1549*4882a593Smuzhiyun 	else
1550*4882a593Smuzhiyun 		ret = rtl8152_set_mac_address(dev, &sa);
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun 	return ret;
1553*4882a593Smuzhiyun }
1554*4882a593Smuzhiyun 
read_bulk_callback(struct urb * urb)1555*4882a593Smuzhiyun static void read_bulk_callback(struct urb *urb)
1556*4882a593Smuzhiyun {
1557*4882a593Smuzhiyun 	struct net_device *netdev;
1558*4882a593Smuzhiyun 	int status = urb->status;
1559*4882a593Smuzhiyun 	struct rx_agg *agg;
1560*4882a593Smuzhiyun 	struct r8152 *tp;
1561*4882a593Smuzhiyun 	unsigned long flags;
1562*4882a593Smuzhiyun 
1563*4882a593Smuzhiyun 	agg = urb->context;
1564*4882a593Smuzhiyun 	if (!agg)
1565*4882a593Smuzhiyun 		return;
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	tp = agg->context;
1568*4882a593Smuzhiyun 	if (!tp)
1569*4882a593Smuzhiyun 		return;
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1572*4882a593Smuzhiyun 		return;
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun 	if (!test_bit(WORK_ENABLE, &tp->flags))
1575*4882a593Smuzhiyun 		return;
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun 	netdev = tp->netdev;
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun 	/* When link down, the driver would cancel all bulks. */
1580*4882a593Smuzhiyun 	/* This avoid the re-submitting bulk */
1581*4882a593Smuzhiyun 	if (!netif_carrier_ok(netdev))
1582*4882a593Smuzhiyun 		return;
1583*4882a593Smuzhiyun 
1584*4882a593Smuzhiyun 	usb_mark_last_busy(tp->udev);
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun 	switch (status) {
1587*4882a593Smuzhiyun 	case 0:
1588*4882a593Smuzhiyun 		if (urb->actual_length < ETH_ZLEN)
1589*4882a593Smuzhiyun 			break;
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun 		spin_lock_irqsave(&tp->rx_lock, flags);
1592*4882a593Smuzhiyun 		list_add_tail(&agg->list, &tp->rx_done);
1593*4882a593Smuzhiyun 		spin_unlock_irqrestore(&tp->rx_lock, flags);
1594*4882a593Smuzhiyun 		napi_schedule(&tp->napi);
1595*4882a593Smuzhiyun 		return;
1596*4882a593Smuzhiyun 	case -ESHUTDOWN:
1597*4882a593Smuzhiyun 		rtl_set_unplug(tp);
1598*4882a593Smuzhiyun 		netif_device_detach(tp->netdev);
1599*4882a593Smuzhiyun 		return;
1600*4882a593Smuzhiyun 	case -ENOENT:
1601*4882a593Smuzhiyun 		return;	/* the urb is in unlink state */
1602*4882a593Smuzhiyun 	case -ETIME:
1603*4882a593Smuzhiyun 		if (net_ratelimit())
1604*4882a593Smuzhiyun 			netdev_warn(netdev, "maybe reset is needed?\n");
1605*4882a593Smuzhiyun 		break;
1606*4882a593Smuzhiyun 	default:
1607*4882a593Smuzhiyun 		if (net_ratelimit())
1608*4882a593Smuzhiyun 			netdev_warn(netdev, "Rx status %d\n", status);
1609*4882a593Smuzhiyun 		break;
1610*4882a593Smuzhiyun 	}
1611*4882a593Smuzhiyun 
1612*4882a593Smuzhiyun 	r8152_submit_rx(tp, agg, GFP_ATOMIC);
1613*4882a593Smuzhiyun }
1614*4882a593Smuzhiyun 
write_bulk_callback(struct urb * urb)1615*4882a593Smuzhiyun static void write_bulk_callback(struct urb *urb)
1616*4882a593Smuzhiyun {
1617*4882a593Smuzhiyun 	struct net_device_stats *stats;
1618*4882a593Smuzhiyun 	struct net_device *netdev;
1619*4882a593Smuzhiyun 	struct tx_agg *agg;
1620*4882a593Smuzhiyun 	struct r8152 *tp;
1621*4882a593Smuzhiyun 	unsigned long flags;
1622*4882a593Smuzhiyun 	int status = urb->status;
1623*4882a593Smuzhiyun 
1624*4882a593Smuzhiyun 	agg = urb->context;
1625*4882a593Smuzhiyun 	if (!agg)
1626*4882a593Smuzhiyun 		return;
1627*4882a593Smuzhiyun 
1628*4882a593Smuzhiyun 	tp = agg->context;
1629*4882a593Smuzhiyun 	if (!tp)
1630*4882a593Smuzhiyun 		return;
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun 	netdev = tp->netdev;
1633*4882a593Smuzhiyun 	stats = &netdev->stats;
1634*4882a593Smuzhiyun 	if (status) {
1635*4882a593Smuzhiyun 		if (net_ratelimit())
1636*4882a593Smuzhiyun 			netdev_warn(netdev, "Tx status %d\n", status);
1637*4882a593Smuzhiyun 		stats->tx_errors += agg->skb_num;
1638*4882a593Smuzhiyun 	} else {
1639*4882a593Smuzhiyun 		stats->tx_packets += agg->skb_num;
1640*4882a593Smuzhiyun 		stats->tx_bytes += agg->skb_len;
1641*4882a593Smuzhiyun 	}
1642*4882a593Smuzhiyun 
1643*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->tx_lock, flags);
1644*4882a593Smuzhiyun 	list_add_tail(&agg->list, &tp->tx_free);
1645*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->tx_lock, flags);
1646*4882a593Smuzhiyun 
1647*4882a593Smuzhiyun 	usb_autopm_put_interface_async(tp->intf);
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 	if (!netif_carrier_ok(netdev))
1650*4882a593Smuzhiyun 		return;
1651*4882a593Smuzhiyun 
1652*4882a593Smuzhiyun 	if (!test_bit(WORK_ENABLE, &tp->flags))
1653*4882a593Smuzhiyun 		return;
1654*4882a593Smuzhiyun 
1655*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1656*4882a593Smuzhiyun 		return;
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 	if (!skb_queue_empty(&tp->tx_queue))
1659*4882a593Smuzhiyun 		tasklet_schedule(&tp->tx_tl);
1660*4882a593Smuzhiyun }
1661*4882a593Smuzhiyun 
intr_callback(struct urb * urb)1662*4882a593Smuzhiyun static void intr_callback(struct urb *urb)
1663*4882a593Smuzhiyun {
1664*4882a593Smuzhiyun 	struct r8152 *tp;
1665*4882a593Smuzhiyun 	__le16 *d;
1666*4882a593Smuzhiyun 	int status = urb->status;
1667*4882a593Smuzhiyun 	int res;
1668*4882a593Smuzhiyun 
1669*4882a593Smuzhiyun 	tp = urb->context;
1670*4882a593Smuzhiyun 	if (!tp)
1671*4882a593Smuzhiyun 		return;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	if (!test_bit(WORK_ENABLE, &tp->flags))
1674*4882a593Smuzhiyun 		return;
1675*4882a593Smuzhiyun 
1676*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
1677*4882a593Smuzhiyun 		return;
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 	switch (status) {
1680*4882a593Smuzhiyun 	case 0:			/* success */
1681*4882a593Smuzhiyun 		break;
1682*4882a593Smuzhiyun 	case -ECONNRESET:	/* unlink */
1683*4882a593Smuzhiyun 	case -ESHUTDOWN:
1684*4882a593Smuzhiyun 		netif_device_detach(tp->netdev);
1685*4882a593Smuzhiyun 		fallthrough;
1686*4882a593Smuzhiyun 	case -ENOENT:
1687*4882a593Smuzhiyun 	case -EPROTO:
1688*4882a593Smuzhiyun 		netif_info(tp, intr, tp->netdev,
1689*4882a593Smuzhiyun 			   "Stop submitting intr, status %d\n", status);
1690*4882a593Smuzhiyun 		return;
1691*4882a593Smuzhiyun 	case -EOVERFLOW:
1692*4882a593Smuzhiyun 		if (net_ratelimit())
1693*4882a593Smuzhiyun 			netif_info(tp, intr, tp->netdev,
1694*4882a593Smuzhiyun 				   "intr status -EOVERFLOW\n");
1695*4882a593Smuzhiyun 		goto resubmit;
1696*4882a593Smuzhiyun 	/* -EPIPE:  should clear the halt */
1697*4882a593Smuzhiyun 	default:
1698*4882a593Smuzhiyun 		netif_info(tp, intr, tp->netdev, "intr status %d\n", status);
1699*4882a593Smuzhiyun 		goto resubmit;
1700*4882a593Smuzhiyun 	}
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 	d = urb->transfer_buffer;
1703*4882a593Smuzhiyun 	if (INTR_LINK & __le16_to_cpu(d[0])) {
1704*4882a593Smuzhiyun 		if (!netif_carrier_ok(tp->netdev)) {
1705*4882a593Smuzhiyun 			set_bit(RTL8152_LINK_CHG, &tp->flags);
1706*4882a593Smuzhiyun 			schedule_delayed_work(&tp->schedule, 0);
1707*4882a593Smuzhiyun 		}
1708*4882a593Smuzhiyun 	} else {
1709*4882a593Smuzhiyun 		if (netif_carrier_ok(tp->netdev)) {
1710*4882a593Smuzhiyun 			netif_stop_queue(tp->netdev);
1711*4882a593Smuzhiyun 			set_bit(RTL8152_LINK_CHG, &tp->flags);
1712*4882a593Smuzhiyun 			schedule_delayed_work(&tp->schedule, 0);
1713*4882a593Smuzhiyun 		}
1714*4882a593Smuzhiyun 	}
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun resubmit:
1717*4882a593Smuzhiyun 	res = usb_submit_urb(urb, GFP_ATOMIC);
1718*4882a593Smuzhiyun 	if (res == -ENODEV) {
1719*4882a593Smuzhiyun 		rtl_set_unplug(tp);
1720*4882a593Smuzhiyun 		netif_device_detach(tp->netdev);
1721*4882a593Smuzhiyun 	} else if (res) {
1722*4882a593Smuzhiyun 		netif_err(tp, intr, tp->netdev,
1723*4882a593Smuzhiyun 			  "can't resubmit intr, status %d\n", res);
1724*4882a593Smuzhiyun 	}
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun 
rx_agg_align(void * data)1727*4882a593Smuzhiyun static inline void *rx_agg_align(void *data)
1728*4882a593Smuzhiyun {
1729*4882a593Smuzhiyun 	return (void *)ALIGN((uintptr_t)data, RX_ALIGN);
1730*4882a593Smuzhiyun }
1731*4882a593Smuzhiyun 
tx_agg_align(void * data)1732*4882a593Smuzhiyun static inline void *tx_agg_align(void *data)
1733*4882a593Smuzhiyun {
1734*4882a593Smuzhiyun 	return (void *)ALIGN((uintptr_t)data, TX_ALIGN);
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun 
free_rx_agg(struct r8152 * tp,struct rx_agg * agg)1737*4882a593Smuzhiyun static void free_rx_agg(struct r8152 *tp, struct rx_agg *agg)
1738*4882a593Smuzhiyun {
1739*4882a593Smuzhiyun 	list_del(&agg->info_list);
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	usb_free_urb(agg->urb);
1742*4882a593Smuzhiyun 	put_page(agg->page);
1743*4882a593Smuzhiyun 	kfree(agg);
1744*4882a593Smuzhiyun 
1745*4882a593Smuzhiyun 	atomic_dec(&tp->rx_count);
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun 
alloc_rx_agg(struct r8152 * tp,gfp_t mflags)1748*4882a593Smuzhiyun static struct rx_agg *alloc_rx_agg(struct r8152 *tp, gfp_t mflags)
1749*4882a593Smuzhiyun {
1750*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
1751*4882a593Smuzhiyun 	int node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1;
1752*4882a593Smuzhiyun 	unsigned int order = get_order(tp->rx_buf_sz);
1753*4882a593Smuzhiyun 	struct rx_agg *rx_agg;
1754*4882a593Smuzhiyun 	unsigned long flags;
1755*4882a593Smuzhiyun 
1756*4882a593Smuzhiyun 	rx_agg = kmalloc_node(sizeof(*rx_agg), mflags, node);
1757*4882a593Smuzhiyun 	if (!rx_agg)
1758*4882a593Smuzhiyun 		return NULL;
1759*4882a593Smuzhiyun 
1760*4882a593Smuzhiyun 	rx_agg->page = alloc_pages(mflags | __GFP_COMP, order);
1761*4882a593Smuzhiyun 	if (!rx_agg->page)
1762*4882a593Smuzhiyun 		goto free_rx;
1763*4882a593Smuzhiyun 
1764*4882a593Smuzhiyun 	rx_agg->buffer = page_address(rx_agg->page);
1765*4882a593Smuzhiyun 
1766*4882a593Smuzhiyun 	rx_agg->urb = usb_alloc_urb(0, mflags);
1767*4882a593Smuzhiyun 	if (!rx_agg->urb)
1768*4882a593Smuzhiyun 		goto free_buf;
1769*4882a593Smuzhiyun 
1770*4882a593Smuzhiyun 	rx_agg->context = tp;
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun 	INIT_LIST_HEAD(&rx_agg->list);
1773*4882a593Smuzhiyun 	INIT_LIST_HEAD(&rx_agg->info_list);
1774*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
1775*4882a593Smuzhiyun 	list_add_tail(&rx_agg->info_list, &tp->rx_info);
1776*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
1777*4882a593Smuzhiyun 
1778*4882a593Smuzhiyun 	atomic_inc(&tp->rx_count);
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun 	return rx_agg;
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun free_buf:
1783*4882a593Smuzhiyun 	__free_pages(rx_agg->page, order);
1784*4882a593Smuzhiyun free_rx:
1785*4882a593Smuzhiyun 	kfree(rx_agg);
1786*4882a593Smuzhiyun 	return NULL;
1787*4882a593Smuzhiyun }
1788*4882a593Smuzhiyun 
free_all_mem(struct r8152 * tp)1789*4882a593Smuzhiyun static void free_all_mem(struct r8152 *tp)
1790*4882a593Smuzhiyun {
1791*4882a593Smuzhiyun 	struct rx_agg *agg, *agg_next;
1792*4882a593Smuzhiyun 	unsigned long flags;
1793*4882a593Smuzhiyun 	int i;
1794*4882a593Smuzhiyun 
1795*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun 	list_for_each_entry_safe(agg, agg_next, &tp->rx_info, info_list)
1798*4882a593Smuzhiyun 		free_rx_agg(tp, agg);
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun 	WARN_ON(atomic_read(&tp->rx_count));
1803*4882a593Smuzhiyun 
1804*4882a593Smuzhiyun 	for (i = 0; i < RTL8152_MAX_TX; i++) {
1805*4882a593Smuzhiyun 		usb_free_urb(tp->tx_info[i].urb);
1806*4882a593Smuzhiyun 		tp->tx_info[i].urb = NULL;
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun 		kfree(tp->tx_info[i].buffer);
1809*4882a593Smuzhiyun 		tp->tx_info[i].buffer = NULL;
1810*4882a593Smuzhiyun 		tp->tx_info[i].head = NULL;
1811*4882a593Smuzhiyun 	}
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun 	usb_free_urb(tp->intr_urb);
1814*4882a593Smuzhiyun 	tp->intr_urb = NULL;
1815*4882a593Smuzhiyun 
1816*4882a593Smuzhiyun 	kfree(tp->intr_buff);
1817*4882a593Smuzhiyun 	tp->intr_buff = NULL;
1818*4882a593Smuzhiyun }
1819*4882a593Smuzhiyun 
alloc_all_mem(struct r8152 * tp)1820*4882a593Smuzhiyun static int alloc_all_mem(struct r8152 *tp)
1821*4882a593Smuzhiyun {
1822*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
1823*4882a593Smuzhiyun 	struct usb_interface *intf = tp->intf;
1824*4882a593Smuzhiyun 	struct usb_host_interface *alt = intf->cur_altsetting;
1825*4882a593Smuzhiyun 	struct usb_host_endpoint *ep_intr = alt->endpoint + 2;
1826*4882a593Smuzhiyun 	int node, i;
1827*4882a593Smuzhiyun 
1828*4882a593Smuzhiyun 	node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1;
1829*4882a593Smuzhiyun 
1830*4882a593Smuzhiyun 	spin_lock_init(&tp->rx_lock);
1831*4882a593Smuzhiyun 	spin_lock_init(&tp->tx_lock);
1832*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tp->rx_info);
1833*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tp->tx_free);
1834*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tp->rx_done);
1835*4882a593Smuzhiyun 	skb_queue_head_init(&tp->tx_queue);
1836*4882a593Smuzhiyun 	skb_queue_head_init(&tp->rx_queue);
1837*4882a593Smuzhiyun 	atomic_set(&tp->rx_count, 0);
1838*4882a593Smuzhiyun 
1839*4882a593Smuzhiyun 	for (i = 0; i < RTL8152_MAX_RX; i++) {
1840*4882a593Smuzhiyun 		if (!alloc_rx_agg(tp, GFP_KERNEL))
1841*4882a593Smuzhiyun 			goto err1;
1842*4882a593Smuzhiyun 	}
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 	for (i = 0; i < RTL8152_MAX_TX; i++) {
1845*4882a593Smuzhiyun 		struct urb *urb;
1846*4882a593Smuzhiyun 		u8 *buf;
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun 		buf = kmalloc_node(agg_buf_sz, GFP_KERNEL, node);
1849*4882a593Smuzhiyun 		if (!buf)
1850*4882a593Smuzhiyun 			goto err1;
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun 		if (buf != tx_agg_align(buf)) {
1853*4882a593Smuzhiyun 			kfree(buf);
1854*4882a593Smuzhiyun 			buf = kmalloc_node(agg_buf_sz + TX_ALIGN, GFP_KERNEL,
1855*4882a593Smuzhiyun 					   node);
1856*4882a593Smuzhiyun 			if (!buf)
1857*4882a593Smuzhiyun 				goto err1;
1858*4882a593Smuzhiyun 		}
1859*4882a593Smuzhiyun 
1860*4882a593Smuzhiyun 		urb = usb_alloc_urb(0, GFP_KERNEL);
1861*4882a593Smuzhiyun 		if (!urb) {
1862*4882a593Smuzhiyun 			kfree(buf);
1863*4882a593Smuzhiyun 			goto err1;
1864*4882a593Smuzhiyun 		}
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun 		INIT_LIST_HEAD(&tp->tx_info[i].list);
1867*4882a593Smuzhiyun 		tp->tx_info[i].context = tp;
1868*4882a593Smuzhiyun 		tp->tx_info[i].urb = urb;
1869*4882a593Smuzhiyun 		tp->tx_info[i].buffer = buf;
1870*4882a593Smuzhiyun 		tp->tx_info[i].head = tx_agg_align(buf);
1871*4882a593Smuzhiyun 
1872*4882a593Smuzhiyun 		list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
1873*4882a593Smuzhiyun 	}
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun 	tp->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
1876*4882a593Smuzhiyun 	if (!tp->intr_urb)
1877*4882a593Smuzhiyun 		goto err1;
1878*4882a593Smuzhiyun 
1879*4882a593Smuzhiyun 	tp->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
1880*4882a593Smuzhiyun 	if (!tp->intr_buff)
1881*4882a593Smuzhiyun 		goto err1;
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun 	tp->intr_interval = (int)ep_intr->desc.bInterval;
1884*4882a593Smuzhiyun 	usb_fill_int_urb(tp->intr_urb, tp->udev, usb_rcvintpipe(tp->udev, 3),
1885*4882a593Smuzhiyun 			 tp->intr_buff, INTBUFSIZE, intr_callback,
1886*4882a593Smuzhiyun 			 tp, tp->intr_interval);
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun 	return 0;
1889*4882a593Smuzhiyun 
1890*4882a593Smuzhiyun err1:
1891*4882a593Smuzhiyun 	free_all_mem(tp);
1892*4882a593Smuzhiyun 	return -ENOMEM;
1893*4882a593Smuzhiyun }
1894*4882a593Smuzhiyun 
r8152_get_tx_agg(struct r8152 * tp)1895*4882a593Smuzhiyun static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
1896*4882a593Smuzhiyun {
1897*4882a593Smuzhiyun 	struct tx_agg *agg = NULL;
1898*4882a593Smuzhiyun 	unsigned long flags;
1899*4882a593Smuzhiyun 
1900*4882a593Smuzhiyun 	if (list_empty(&tp->tx_free))
1901*4882a593Smuzhiyun 		return NULL;
1902*4882a593Smuzhiyun 
1903*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->tx_lock, flags);
1904*4882a593Smuzhiyun 	if (!list_empty(&tp->tx_free)) {
1905*4882a593Smuzhiyun 		struct list_head *cursor;
1906*4882a593Smuzhiyun 
1907*4882a593Smuzhiyun 		cursor = tp->tx_free.next;
1908*4882a593Smuzhiyun 		list_del_init(cursor);
1909*4882a593Smuzhiyun 		agg = list_entry(cursor, struct tx_agg, list);
1910*4882a593Smuzhiyun 	}
1911*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->tx_lock, flags);
1912*4882a593Smuzhiyun 
1913*4882a593Smuzhiyun 	return agg;
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun /* r8152_csum_workaround()
1917*4882a593Smuzhiyun  * The hw limits the value of the transport offset. When the offset is out of
1918*4882a593Smuzhiyun  * range, calculate the checksum by sw.
1919*4882a593Smuzhiyun  */
r8152_csum_workaround(struct r8152 * tp,struct sk_buff * skb,struct sk_buff_head * list)1920*4882a593Smuzhiyun static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
1921*4882a593Smuzhiyun 				  struct sk_buff_head *list)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun 	if (skb_shinfo(skb)->gso_size) {
1924*4882a593Smuzhiyun 		netdev_features_t features = tp->netdev->features;
1925*4882a593Smuzhiyun 		struct sk_buff *segs, *seg, *next;
1926*4882a593Smuzhiyun 		struct sk_buff_head seg_list;
1927*4882a593Smuzhiyun 
1928*4882a593Smuzhiyun 		features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
1929*4882a593Smuzhiyun 		segs = skb_gso_segment(skb, features);
1930*4882a593Smuzhiyun 		if (IS_ERR(segs) || !segs)
1931*4882a593Smuzhiyun 			goto drop;
1932*4882a593Smuzhiyun 
1933*4882a593Smuzhiyun 		__skb_queue_head_init(&seg_list);
1934*4882a593Smuzhiyun 
1935*4882a593Smuzhiyun 		skb_list_walk_safe(segs, seg, next) {
1936*4882a593Smuzhiyun 			skb_mark_not_on_list(seg);
1937*4882a593Smuzhiyun 			__skb_queue_tail(&seg_list, seg);
1938*4882a593Smuzhiyun 		}
1939*4882a593Smuzhiyun 
1940*4882a593Smuzhiyun 		skb_queue_splice(&seg_list, list);
1941*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1942*4882a593Smuzhiyun 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
1943*4882a593Smuzhiyun 		if (skb_checksum_help(skb) < 0)
1944*4882a593Smuzhiyun 			goto drop;
1945*4882a593Smuzhiyun 
1946*4882a593Smuzhiyun 		__skb_queue_head(list, skb);
1947*4882a593Smuzhiyun 	} else {
1948*4882a593Smuzhiyun 		struct net_device_stats *stats;
1949*4882a593Smuzhiyun 
1950*4882a593Smuzhiyun drop:
1951*4882a593Smuzhiyun 		stats = &tp->netdev->stats;
1952*4882a593Smuzhiyun 		stats->tx_dropped++;
1953*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1954*4882a593Smuzhiyun 	}
1955*4882a593Smuzhiyun }
1956*4882a593Smuzhiyun 
rtl_tx_vlan_tag(struct tx_desc * desc,struct sk_buff * skb)1957*4882a593Smuzhiyun static inline void rtl_tx_vlan_tag(struct tx_desc *desc, struct sk_buff *skb)
1958*4882a593Smuzhiyun {
1959*4882a593Smuzhiyun 	if (skb_vlan_tag_present(skb)) {
1960*4882a593Smuzhiyun 		u32 opts2;
1961*4882a593Smuzhiyun 
1962*4882a593Smuzhiyun 		opts2 = TX_VLAN_TAG | swab16(skb_vlan_tag_get(skb));
1963*4882a593Smuzhiyun 		desc->opts2 |= cpu_to_le32(opts2);
1964*4882a593Smuzhiyun 	}
1965*4882a593Smuzhiyun }
1966*4882a593Smuzhiyun 
rtl_rx_vlan_tag(struct rx_desc * desc,struct sk_buff * skb)1967*4882a593Smuzhiyun static inline void rtl_rx_vlan_tag(struct rx_desc *desc, struct sk_buff *skb)
1968*4882a593Smuzhiyun {
1969*4882a593Smuzhiyun 	u32 opts2 = le32_to_cpu(desc->opts2);
1970*4882a593Smuzhiyun 
1971*4882a593Smuzhiyun 	if (opts2 & RX_VLAN_TAG)
1972*4882a593Smuzhiyun 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
1973*4882a593Smuzhiyun 				       swab16(opts2 & 0xffff));
1974*4882a593Smuzhiyun }
1975*4882a593Smuzhiyun 
r8152_tx_csum(struct r8152 * tp,struct tx_desc * desc,struct sk_buff * skb,u32 len,u32 transport_offset)1976*4882a593Smuzhiyun static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
1977*4882a593Smuzhiyun 			 struct sk_buff *skb, u32 len, u32 transport_offset)
1978*4882a593Smuzhiyun {
1979*4882a593Smuzhiyun 	u32 mss = skb_shinfo(skb)->gso_size;
1980*4882a593Smuzhiyun 	u32 opts1, opts2 = 0;
1981*4882a593Smuzhiyun 	int ret = TX_CSUM_SUCCESS;
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 	WARN_ON_ONCE(len > TX_LEN_MAX);
1984*4882a593Smuzhiyun 
1985*4882a593Smuzhiyun 	opts1 = len | TX_FS | TX_LS;
1986*4882a593Smuzhiyun 
1987*4882a593Smuzhiyun 	if (mss) {
1988*4882a593Smuzhiyun 		if (transport_offset > GTTCPHO_MAX) {
1989*4882a593Smuzhiyun 			netif_warn(tp, tx_err, tp->netdev,
1990*4882a593Smuzhiyun 				   "Invalid transport offset 0x%x for TSO\n",
1991*4882a593Smuzhiyun 				   transport_offset);
1992*4882a593Smuzhiyun 			ret = TX_CSUM_TSO;
1993*4882a593Smuzhiyun 			goto unavailable;
1994*4882a593Smuzhiyun 		}
1995*4882a593Smuzhiyun 
1996*4882a593Smuzhiyun 		switch (vlan_get_protocol(skb)) {
1997*4882a593Smuzhiyun 		case htons(ETH_P_IP):
1998*4882a593Smuzhiyun 			opts1 |= GTSENDV4;
1999*4882a593Smuzhiyun 			break;
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun 		case htons(ETH_P_IPV6):
2002*4882a593Smuzhiyun 			if (skb_cow_head(skb, 0)) {
2003*4882a593Smuzhiyun 				ret = TX_CSUM_TSO;
2004*4882a593Smuzhiyun 				goto unavailable;
2005*4882a593Smuzhiyun 			}
2006*4882a593Smuzhiyun 			tcp_v6_gso_csum_prep(skb);
2007*4882a593Smuzhiyun 			opts1 |= GTSENDV6;
2008*4882a593Smuzhiyun 			break;
2009*4882a593Smuzhiyun 
2010*4882a593Smuzhiyun 		default:
2011*4882a593Smuzhiyun 			WARN_ON_ONCE(1);
2012*4882a593Smuzhiyun 			break;
2013*4882a593Smuzhiyun 		}
2014*4882a593Smuzhiyun 
2015*4882a593Smuzhiyun 		opts1 |= transport_offset << GTTCPHO_SHIFT;
2016*4882a593Smuzhiyun 		opts2 |= min(mss, MSS_MAX) << MSS_SHIFT;
2017*4882a593Smuzhiyun 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
2018*4882a593Smuzhiyun 		u8 ip_protocol;
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun 		if (transport_offset > TCPHO_MAX) {
2021*4882a593Smuzhiyun 			netif_warn(tp, tx_err, tp->netdev,
2022*4882a593Smuzhiyun 				   "Invalid transport offset 0x%x\n",
2023*4882a593Smuzhiyun 				   transport_offset);
2024*4882a593Smuzhiyun 			ret = TX_CSUM_NONE;
2025*4882a593Smuzhiyun 			goto unavailable;
2026*4882a593Smuzhiyun 		}
2027*4882a593Smuzhiyun 
2028*4882a593Smuzhiyun 		switch (vlan_get_protocol(skb)) {
2029*4882a593Smuzhiyun 		case htons(ETH_P_IP):
2030*4882a593Smuzhiyun 			opts2 |= IPV4_CS;
2031*4882a593Smuzhiyun 			ip_protocol = ip_hdr(skb)->protocol;
2032*4882a593Smuzhiyun 			break;
2033*4882a593Smuzhiyun 
2034*4882a593Smuzhiyun 		case htons(ETH_P_IPV6):
2035*4882a593Smuzhiyun 			opts2 |= IPV6_CS;
2036*4882a593Smuzhiyun 			ip_protocol = ipv6_hdr(skb)->nexthdr;
2037*4882a593Smuzhiyun 			break;
2038*4882a593Smuzhiyun 
2039*4882a593Smuzhiyun 		default:
2040*4882a593Smuzhiyun 			ip_protocol = IPPROTO_RAW;
2041*4882a593Smuzhiyun 			break;
2042*4882a593Smuzhiyun 		}
2043*4882a593Smuzhiyun 
2044*4882a593Smuzhiyun 		if (ip_protocol == IPPROTO_TCP)
2045*4882a593Smuzhiyun 			opts2 |= TCP_CS;
2046*4882a593Smuzhiyun 		else if (ip_protocol == IPPROTO_UDP)
2047*4882a593Smuzhiyun 			opts2 |= UDP_CS;
2048*4882a593Smuzhiyun 		else
2049*4882a593Smuzhiyun 			WARN_ON_ONCE(1);
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun 		opts2 |= transport_offset << TCPHO_SHIFT;
2052*4882a593Smuzhiyun 	}
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	desc->opts2 = cpu_to_le32(opts2);
2055*4882a593Smuzhiyun 	desc->opts1 = cpu_to_le32(opts1);
2056*4882a593Smuzhiyun 
2057*4882a593Smuzhiyun unavailable:
2058*4882a593Smuzhiyun 	return ret;
2059*4882a593Smuzhiyun }
2060*4882a593Smuzhiyun 
r8152_tx_agg_fill(struct r8152 * tp,struct tx_agg * agg)2061*4882a593Smuzhiyun static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
2062*4882a593Smuzhiyun {
2063*4882a593Smuzhiyun 	struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
2064*4882a593Smuzhiyun 	int remain, ret;
2065*4882a593Smuzhiyun 	u8 *tx_data;
2066*4882a593Smuzhiyun 
2067*4882a593Smuzhiyun 	__skb_queue_head_init(&skb_head);
2068*4882a593Smuzhiyun 	spin_lock(&tx_queue->lock);
2069*4882a593Smuzhiyun 	skb_queue_splice_init(tx_queue, &skb_head);
2070*4882a593Smuzhiyun 	spin_unlock(&tx_queue->lock);
2071*4882a593Smuzhiyun 
2072*4882a593Smuzhiyun 	tx_data = agg->head;
2073*4882a593Smuzhiyun 	agg->skb_num = 0;
2074*4882a593Smuzhiyun 	agg->skb_len = 0;
2075*4882a593Smuzhiyun 	remain = agg_buf_sz;
2076*4882a593Smuzhiyun 
2077*4882a593Smuzhiyun 	while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
2078*4882a593Smuzhiyun 		struct tx_desc *tx_desc;
2079*4882a593Smuzhiyun 		struct sk_buff *skb;
2080*4882a593Smuzhiyun 		unsigned int len;
2081*4882a593Smuzhiyun 		u32 offset;
2082*4882a593Smuzhiyun 
2083*4882a593Smuzhiyun 		skb = __skb_dequeue(&skb_head);
2084*4882a593Smuzhiyun 		if (!skb)
2085*4882a593Smuzhiyun 			break;
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun 		len = skb->len + sizeof(*tx_desc);
2088*4882a593Smuzhiyun 
2089*4882a593Smuzhiyun 		if (len > remain) {
2090*4882a593Smuzhiyun 			__skb_queue_head(&skb_head, skb);
2091*4882a593Smuzhiyun 			break;
2092*4882a593Smuzhiyun 		}
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun 		tx_data = tx_agg_align(tx_data);
2095*4882a593Smuzhiyun 		tx_desc = (struct tx_desc *)tx_data;
2096*4882a593Smuzhiyun 
2097*4882a593Smuzhiyun 		offset = (u32)skb_transport_offset(skb);
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 		if (r8152_tx_csum(tp, tx_desc, skb, skb->len, offset)) {
2100*4882a593Smuzhiyun 			r8152_csum_workaround(tp, skb, &skb_head);
2101*4882a593Smuzhiyun 			continue;
2102*4882a593Smuzhiyun 		}
2103*4882a593Smuzhiyun 
2104*4882a593Smuzhiyun 		rtl_tx_vlan_tag(tx_desc, skb);
2105*4882a593Smuzhiyun 
2106*4882a593Smuzhiyun 		tx_data += sizeof(*tx_desc);
2107*4882a593Smuzhiyun 
2108*4882a593Smuzhiyun 		len = skb->len;
2109*4882a593Smuzhiyun 		if (skb_copy_bits(skb, 0, tx_data, len) < 0) {
2110*4882a593Smuzhiyun 			struct net_device_stats *stats = &tp->netdev->stats;
2111*4882a593Smuzhiyun 
2112*4882a593Smuzhiyun 			stats->tx_dropped++;
2113*4882a593Smuzhiyun 			dev_kfree_skb_any(skb);
2114*4882a593Smuzhiyun 			tx_data -= sizeof(*tx_desc);
2115*4882a593Smuzhiyun 			continue;
2116*4882a593Smuzhiyun 		}
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 		tx_data += len;
2119*4882a593Smuzhiyun 		agg->skb_len += len;
2120*4882a593Smuzhiyun 		agg->skb_num += skb_shinfo(skb)->gso_segs ?: 1;
2121*4882a593Smuzhiyun 
2122*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun 		remain = agg_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
2125*4882a593Smuzhiyun 
2126*4882a593Smuzhiyun 		if (test_bit(DELL_TB_RX_AGG_BUG, &tp->flags))
2127*4882a593Smuzhiyun 			break;
2128*4882a593Smuzhiyun 	}
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun 	if (!skb_queue_empty(&skb_head)) {
2131*4882a593Smuzhiyun 		spin_lock(&tx_queue->lock);
2132*4882a593Smuzhiyun 		skb_queue_splice(&skb_head, tx_queue);
2133*4882a593Smuzhiyun 		spin_unlock(&tx_queue->lock);
2134*4882a593Smuzhiyun 	}
2135*4882a593Smuzhiyun 
2136*4882a593Smuzhiyun 	netif_tx_lock(tp->netdev);
2137*4882a593Smuzhiyun 
2138*4882a593Smuzhiyun 	if (netif_queue_stopped(tp->netdev) &&
2139*4882a593Smuzhiyun 	    skb_queue_len(&tp->tx_queue) < tp->tx_qlen)
2140*4882a593Smuzhiyun 		netif_wake_queue(tp->netdev);
2141*4882a593Smuzhiyun 
2142*4882a593Smuzhiyun 	netif_tx_unlock(tp->netdev);
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun 	ret = usb_autopm_get_interface_async(tp->intf);
2145*4882a593Smuzhiyun 	if (ret < 0)
2146*4882a593Smuzhiyun 		goto out_tx_fill;
2147*4882a593Smuzhiyun 
2148*4882a593Smuzhiyun 	usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
2149*4882a593Smuzhiyun 			  agg->head, (int)(tx_data - (u8 *)agg->head),
2150*4882a593Smuzhiyun 			  (usb_complete_t)write_bulk_callback, agg);
2151*4882a593Smuzhiyun 
2152*4882a593Smuzhiyun 	ret = usb_submit_urb(agg->urb, GFP_ATOMIC);
2153*4882a593Smuzhiyun 	if (ret < 0)
2154*4882a593Smuzhiyun 		usb_autopm_put_interface_async(tp->intf);
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun out_tx_fill:
2157*4882a593Smuzhiyun 	return ret;
2158*4882a593Smuzhiyun }
2159*4882a593Smuzhiyun 
r8152_rx_csum(struct r8152 * tp,struct rx_desc * rx_desc)2160*4882a593Smuzhiyun static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
2161*4882a593Smuzhiyun {
2162*4882a593Smuzhiyun 	u8 checksum = CHECKSUM_NONE;
2163*4882a593Smuzhiyun 	u32 opts2, opts3;
2164*4882a593Smuzhiyun 
2165*4882a593Smuzhiyun 	if (!(tp->netdev->features & NETIF_F_RXCSUM))
2166*4882a593Smuzhiyun 		goto return_result;
2167*4882a593Smuzhiyun 
2168*4882a593Smuzhiyun 	opts2 = le32_to_cpu(rx_desc->opts2);
2169*4882a593Smuzhiyun 	opts3 = le32_to_cpu(rx_desc->opts3);
2170*4882a593Smuzhiyun 
2171*4882a593Smuzhiyun 	if (opts2 & RD_IPV4_CS) {
2172*4882a593Smuzhiyun 		if (opts3 & IPF)
2173*4882a593Smuzhiyun 			checksum = CHECKSUM_NONE;
2174*4882a593Smuzhiyun 		else if ((opts2 & RD_UDP_CS) && !(opts3 & UDPF))
2175*4882a593Smuzhiyun 			checksum = CHECKSUM_UNNECESSARY;
2176*4882a593Smuzhiyun 		else if ((opts2 & RD_TCP_CS) && !(opts3 & TCPF))
2177*4882a593Smuzhiyun 			checksum = CHECKSUM_UNNECESSARY;
2178*4882a593Smuzhiyun 	} else if (opts2 & RD_IPV6_CS) {
2179*4882a593Smuzhiyun 		if ((opts2 & RD_UDP_CS) && !(opts3 & UDPF))
2180*4882a593Smuzhiyun 			checksum = CHECKSUM_UNNECESSARY;
2181*4882a593Smuzhiyun 		else if ((opts2 & RD_TCP_CS) && !(opts3 & TCPF))
2182*4882a593Smuzhiyun 			checksum = CHECKSUM_UNNECESSARY;
2183*4882a593Smuzhiyun 	}
2184*4882a593Smuzhiyun 
2185*4882a593Smuzhiyun return_result:
2186*4882a593Smuzhiyun 	return checksum;
2187*4882a593Smuzhiyun }
2188*4882a593Smuzhiyun 
rx_count_exceed(struct r8152 * tp)2189*4882a593Smuzhiyun static inline bool rx_count_exceed(struct r8152 *tp)
2190*4882a593Smuzhiyun {
2191*4882a593Smuzhiyun 	return atomic_read(&tp->rx_count) > RTL8152_MAX_RX;
2192*4882a593Smuzhiyun }
2193*4882a593Smuzhiyun 
agg_offset(struct rx_agg * agg,void * addr)2194*4882a593Smuzhiyun static inline int agg_offset(struct rx_agg *agg, void *addr)
2195*4882a593Smuzhiyun {
2196*4882a593Smuzhiyun 	return (int)(addr - agg->buffer);
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun 
rtl_get_free_rx(struct r8152 * tp,gfp_t mflags)2199*4882a593Smuzhiyun static struct rx_agg *rtl_get_free_rx(struct r8152 *tp, gfp_t mflags)
2200*4882a593Smuzhiyun {
2201*4882a593Smuzhiyun 	struct rx_agg *agg, *agg_next, *agg_free = NULL;
2202*4882a593Smuzhiyun 	unsigned long flags;
2203*4882a593Smuzhiyun 
2204*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2205*4882a593Smuzhiyun 
2206*4882a593Smuzhiyun 	list_for_each_entry_safe(agg, agg_next, &tp->rx_used, list) {
2207*4882a593Smuzhiyun 		if (page_count(agg->page) == 1) {
2208*4882a593Smuzhiyun 			if (!agg_free) {
2209*4882a593Smuzhiyun 				list_del_init(&agg->list);
2210*4882a593Smuzhiyun 				agg_free = agg;
2211*4882a593Smuzhiyun 				continue;
2212*4882a593Smuzhiyun 			}
2213*4882a593Smuzhiyun 			if (rx_count_exceed(tp)) {
2214*4882a593Smuzhiyun 				list_del_init(&agg->list);
2215*4882a593Smuzhiyun 				free_rx_agg(tp, agg);
2216*4882a593Smuzhiyun 			}
2217*4882a593Smuzhiyun 			break;
2218*4882a593Smuzhiyun 		}
2219*4882a593Smuzhiyun 	}
2220*4882a593Smuzhiyun 
2221*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2222*4882a593Smuzhiyun 
2223*4882a593Smuzhiyun 	if (!agg_free && atomic_read(&tp->rx_count) < tp->rx_pending)
2224*4882a593Smuzhiyun 		agg_free = alloc_rx_agg(tp, mflags);
2225*4882a593Smuzhiyun 
2226*4882a593Smuzhiyun 	return agg_free;
2227*4882a593Smuzhiyun }
2228*4882a593Smuzhiyun 
rx_bottom(struct r8152 * tp,int budget)2229*4882a593Smuzhiyun static int rx_bottom(struct r8152 *tp, int budget)
2230*4882a593Smuzhiyun {
2231*4882a593Smuzhiyun 	unsigned long flags;
2232*4882a593Smuzhiyun 	struct list_head *cursor, *next, rx_queue;
2233*4882a593Smuzhiyun 	int ret = 0, work_done = 0;
2234*4882a593Smuzhiyun 	struct napi_struct *napi = &tp->napi;
2235*4882a593Smuzhiyun 
2236*4882a593Smuzhiyun 	if (!skb_queue_empty(&tp->rx_queue)) {
2237*4882a593Smuzhiyun 		while (work_done < budget) {
2238*4882a593Smuzhiyun 			struct sk_buff *skb = __skb_dequeue(&tp->rx_queue);
2239*4882a593Smuzhiyun 			struct net_device *netdev = tp->netdev;
2240*4882a593Smuzhiyun 			struct net_device_stats *stats = &netdev->stats;
2241*4882a593Smuzhiyun 			unsigned int pkt_len;
2242*4882a593Smuzhiyun 
2243*4882a593Smuzhiyun 			if (!skb)
2244*4882a593Smuzhiyun 				break;
2245*4882a593Smuzhiyun 
2246*4882a593Smuzhiyun 			pkt_len = skb->len;
2247*4882a593Smuzhiyun 			napi_gro_receive(napi, skb);
2248*4882a593Smuzhiyun 			work_done++;
2249*4882a593Smuzhiyun 			stats->rx_packets++;
2250*4882a593Smuzhiyun 			stats->rx_bytes += pkt_len;
2251*4882a593Smuzhiyun 		}
2252*4882a593Smuzhiyun 	}
2253*4882a593Smuzhiyun 
2254*4882a593Smuzhiyun 	if (list_empty(&tp->rx_done))
2255*4882a593Smuzhiyun 		goto out1;
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun 	INIT_LIST_HEAD(&rx_queue);
2258*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2259*4882a593Smuzhiyun 	list_splice_init(&tp->rx_done, &rx_queue);
2260*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 	list_for_each_safe(cursor, next, &rx_queue) {
2263*4882a593Smuzhiyun 		struct rx_desc *rx_desc;
2264*4882a593Smuzhiyun 		struct rx_agg *agg, *agg_free;
2265*4882a593Smuzhiyun 		int len_used = 0;
2266*4882a593Smuzhiyun 		struct urb *urb;
2267*4882a593Smuzhiyun 		u8 *rx_data;
2268*4882a593Smuzhiyun 
2269*4882a593Smuzhiyun 		list_del_init(cursor);
2270*4882a593Smuzhiyun 
2271*4882a593Smuzhiyun 		agg = list_entry(cursor, struct rx_agg, list);
2272*4882a593Smuzhiyun 		urb = agg->urb;
2273*4882a593Smuzhiyun 		if (urb->actual_length < ETH_ZLEN)
2274*4882a593Smuzhiyun 			goto submit;
2275*4882a593Smuzhiyun 
2276*4882a593Smuzhiyun 		agg_free = rtl_get_free_rx(tp, GFP_ATOMIC);
2277*4882a593Smuzhiyun 
2278*4882a593Smuzhiyun 		rx_desc = agg->buffer;
2279*4882a593Smuzhiyun 		rx_data = agg->buffer;
2280*4882a593Smuzhiyun 		len_used += sizeof(struct rx_desc);
2281*4882a593Smuzhiyun 
2282*4882a593Smuzhiyun 		while (urb->actual_length > len_used) {
2283*4882a593Smuzhiyun 			struct net_device *netdev = tp->netdev;
2284*4882a593Smuzhiyun 			struct net_device_stats *stats = &netdev->stats;
2285*4882a593Smuzhiyun 			unsigned int pkt_len, rx_frag_head_sz;
2286*4882a593Smuzhiyun 			struct sk_buff *skb;
2287*4882a593Smuzhiyun 
2288*4882a593Smuzhiyun 			/* limite the skb numbers for rx_queue */
2289*4882a593Smuzhiyun 			if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000))
2290*4882a593Smuzhiyun 				break;
2291*4882a593Smuzhiyun 
2292*4882a593Smuzhiyun 			pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
2293*4882a593Smuzhiyun 			if (pkt_len < ETH_ZLEN)
2294*4882a593Smuzhiyun 				break;
2295*4882a593Smuzhiyun 
2296*4882a593Smuzhiyun 			len_used += pkt_len;
2297*4882a593Smuzhiyun 			if (urb->actual_length < len_used)
2298*4882a593Smuzhiyun 				break;
2299*4882a593Smuzhiyun 
2300*4882a593Smuzhiyun 			pkt_len -= ETH_FCS_LEN;
2301*4882a593Smuzhiyun 			rx_data += sizeof(struct rx_desc);
2302*4882a593Smuzhiyun 
2303*4882a593Smuzhiyun 			if (!agg_free || tp->rx_copybreak > pkt_len)
2304*4882a593Smuzhiyun 				rx_frag_head_sz = pkt_len;
2305*4882a593Smuzhiyun 			else
2306*4882a593Smuzhiyun 				rx_frag_head_sz = tp->rx_copybreak;
2307*4882a593Smuzhiyun 
2308*4882a593Smuzhiyun 			skb = napi_alloc_skb(napi, rx_frag_head_sz);
2309*4882a593Smuzhiyun 			if (!skb) {
2310*4882a593Smuzhiyun 				stats->rx_dropped++;
2311*4882a593Smuzhiyun 				goto find_next_rx;
2312*4882a593Smuzhiyun 			}
2313*4882a593Smuzhiyun 
2314*4882a593Smuzhiyun 			skb->ip_summed = r8152_rx_csum(tp, rx_desc);
2315*4882a593Smuzhiyun 			memcpy(skb->data, rx_data, rx_frag_head_sz);
2316*4882a593Smuzhiyun 			skb_put(skb, rx_frag_head_sz);
2317*4882a593Smuzhiyun 			pkt_len -= rx_frag_head_sz;
2318*4882a593Smuzhiyun 			rx_data += rx_frag_head_sz;
2319*4882a593Smuzhiyun 			if (pkt_len) {
2320*4882a593Smuzhiyun 				skb_add_rx_frag(skb, 0, agg->page,
2321*4882a593Smuzhiyun 						agg_offset(agg, rx_data),
2322*4882a593Smuzhiyun 						pkt_len,
2323*4882a593Smuzhiyun 						SKB_DATA_ALIGN(pkt_len));
2324*4882a593Smuzhiyun 				get_page(agg->page);
2325*4882a593Smuzhiyun 			}
2326*4882a593Smuzhiyun 
2327*4882a593Smuzhiyun 			skb->protocol = eth_type_trans(skb, netdev);
2328*4882a593Smuzhiyun 			rtl_rx_vlan_tag(rx_desc, skb);
2329*4882a593Smuzhiyun 			if (work_done < budget) {
2330*4882a593Smuzhiyun 				work_done++;
2331*4882a593Smuzhiyun 				stats->rx_packets++;
2332*4882a593Smuzhiyun 				stats->rx_bytes += skb->len;
2333*4882a593Smuzhiyun 				napi_gro_receive(napi, skb);
2334*4882a593Smuzhiyun 			} else {
2335*4882a593Smuzhiyun 				__skb_queue_tail(&tp->rx_queue, skb);
2336*4882a593Smuzhiyun 			}
2337*4882a593Smuzhiyun 
2338*4882a593Smuzhiyun find_next_rx:
2339*4882a593Smuzhiyun 			rx_data = rx_agg_align(rx_data + pkt_len + ETH_FCS_LEN);
2340*4882a593Smuzhiyun 			rx_desc = (struct rx_desc *)rx_data;
2341*4882a593Smuzhiyun 			len_used = agg_offset(agg, rx_data);
2342*4882a593Smuzhiyun 			len_used += sizeof(struct rx_desc);
2343*4882a593Smuzhiyun 		}
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun 		WARN_ON(!agg_free && page_count(agg->page) > 1);
2346*4882a593Smuzhiyun 
2347*4882a593Smuzhiyun 		if (agg_free) {
2348*4882a593Smuzhiyun 			spin_lock_irqsave(&tp->rx_lock, flags);
2349*4882a593Smuzhiyun 			if (page_count(agg->page) == 1) {
2350*4882a593Smuzhiyun 				list_add(&agg_free->list, &tp->rx_used);
2351*4882a593Smuzhiyun 			} else {
2352*4882a593Smuzhiyun 				list_add_tail(&agg->list, &tp->rx_used);
2353*4882a593Smuzhiyun 				agg = agg_free;
2354*4882a593Smuzhiyun 				urb = agg->urb;
2355*4882a593Smuzhiyun 			}
2356*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tp->rx_lock, flags);
2357*4882a593Smuzhiyun 		}
2358*4882a593Smuzhiyun 
2359*4882a593Smuzhiyun submit:
2360*4882a593Smuzhiyun 		if (!ret) {
2361*4882a593Smuzhiyun 			ret = r8152_submit_rx(tp, agg, GFP_ATOMIC);
2362*4882a593Smuzhiyun 		} else {
2363*4882a593Smuzhiyun 			urb->actual_length = 0;
2364*4882a593Smuzhiyun 			list_add_tail(&agg->list, next);
2365*4882a593Smuzhiyun 		}
2366*4882a593Smuzhiyun 	}
2367*4882a593Smuzhiyun 
2368*4882a593Smuzhiyun 	if (!list_empty(&rx_queue)) {
2369*4882a593Smuzhiyun 		spin_lock_irqsave(&tp->rx_lock, flags);
2370*4882a593Smuzhiyun 		list_splice_tail(&rx_queue, &tp->rx_done);
2371*4882a593Smuzhiyun 		spin_unlock_irqrestore(&tp->rx_lock, flags);
2372*4882a593Smuzhiyun 	}
2373*4882a593Smuzhiyun 
2374*4882a593Smuzhiyun out1:
2375*4882a593Smuzhiyun 	return work_done;
2376*4882a593Smuzhiyun }
2377*4882a593Smuzhiyun 
tx_bottom(struct r8152 * tp)2378*4882a593Smuzhiyun static void tx_bottom(struct r8152 *tp)
2379*4882a593Smuzhiyun {
2380*4882a593Smuzhiyun 	int res;
2381*4882a593Smuzhiyun 
2382*4882a593Smuzhiyun 	do {
2383*4882a593Smuzhiyun 		struct net_device *netdev = tp->netdev;
2384*4882a593Smuzhiyun 		struct tx_agg *agg;
2385*4882a593Smuzhiyun 
2386*4882a593Smuzhiyun 		if (skb_queue_empty(&tp->tx_queue))
2387*4882a593Smuzhiyun 			break;
2388*4882a593Smuzhiyun 
2389*4882a593Smuzhiyun 		agg = r8152_get_tx_agg(tp);
2390*4882a593Smuzhiyun 		if (!agg)
2391*4882a593Smuzhiyun 			break;
2392*4882a593Smuzhiyun 
2393*4882a593Smuzhiyun 		res = r8152_tx_agg_fill(tp, agg);
2394*4882a593Smuzhiyun 		if (!res)
2395*4882a593Smuzhiyun 			continue;
2396*4882a593Smuzhiyun 
2397*4882a593Smuzhiyun 		if (res == -ENODEV) {
2398*4882a593Smuzhiyun 			rtl_set_unplug(tp);
2399*4882a593Smuzhiyun 			netif_device_detach(netdev);
2400*4882a593Smuzhiyun 		} else {
2401*4882a593Smuzhiyun 			struct net_device_stats *stats = &netdev->stats;
2402*4882a593Smuzhiyun 			unsigned long flags;
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 			netif_warn(tp, tx_err, netdev,
2405*4882a593Smuzhiyun 				   "failed tx_urb %d\n", res);
2406*4882a593Smuzhiyun 			stats->tx_dropped += agg->skb_num;
2407*4882a593Smuzhiyun 
2408*4882a593Smuzhiyun 			spin_lock_irqsave(&tp->tx_lock, flags);
2409*4882a593Smuzhiyun 			list_add_tail(&agg->list, &tp->tx_free);
2410*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tp->tx_lock, flags);
2411*4882a593Smuzhiyun 		}
2412*4882a593Smuzhiyun 	} while (res == 0);
2413*4882a593Smuzhiyun }
2414*4882a593Smuzhiyun 
bottom_half(unsigned long data)2415*4882a593Smuzhiyun static void bottom_half(unsigned long data)
2416*4882a593Smuzhiyun {
2417*4882a593Smuzhiyun 	struct r8152 *tp;
2418*4882a593Smuzhiyun 
2419*4882a593Smuzhiyun 	tp = (struct r8152 *)data;
2420*4882a593Smuzhiyun 
2421*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
2422*4882a593Smuzhiyun 		return;
2423*4882a593Smuzhiyun 
2424*4882a593Smuzhiyun 	if (!test_bit(WORK_ENABLE, &tp->flags))
2425*4882a593Smuzhiyun 		return;
2426*4882a593Smuzhiyun 
2427*4882a593Smuzhiyun 	/* When link down, the driver would cancel all bulks. */
2428*4882a593Smuzhiyun 	/* This avoid the re-submitting bulk */
2429*4882a593Smuzhiyun 	if (!netif_carrier_ok(tp->netdev))
2430*4882a593Smuzhiyun 		return;
2431*4882a593Smuzhiyun 
2432*4882a593Smuzhiyun 	clear_bit(SCHEDULE_TASKLET, &tp->flags);
2433*4882a593Smuzhiyun 
2434*4882a593Smuzhiyun 	tx_bottom(tp);
2435*4882a593Smuzhiyun }
2436*4882a593Smuzhiyun 
r8152_poll(struct napi_struct * napi,int budget)2437*4882a593Smuzhiyun static int r8152_poll(struct napi_struct *napi, int budget)
2438*4882a593Smuzhiyun {
2439*4882a593Smuzhiyun 	struct r8152 *tp = container_of(napi, struct r8152, napi);
2440*4882a593Smuzhiyun 	int work_done;
2441*4882a593Smuzhiyun 
2442*4882a593Smuzhiyun 	work_done = rx_bottom(tp, budget);
2443*4882a593Smuzhiyun 
2444*4882a593Smuzhiyun 	if (work_done < budget) {
2445*4882a593Smuzhiyun 		if (!napi_complete_done(napi, work_done))
2446*4882a593Smuzhiyun 			goto out;
2447*4882a593Smuzhiyun 		if (!list_empty(&tp->rx_done))
2448*4882a593Smuzhiyun 			napi_schedule(napi);
2449*4882a593Smuzhiyun 	}
2450*4882a593Smuzhiyun 
2451*4882a593Smuzhiyun out:
2452*4882a593Smuzhiyun 	return work_done;
2453*4882a593Smuzhiyun }
2454*4882a593Smuzhiyun 
2455*4882a593Smuzhiyun static
r8152_submit_rx(struct r8152 * tp,struct rx_agg * agg,gfp_t mem_flags)2456*4882a593Smuzhiyun int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags)
2457*4882a593Smuzhiyun {
2458*4882a593Smuzhiyun 	int ret;
2459*4882a593Smuzhiyun 
2460*4882a593Smuzhiyun 	/* The rx would be stopped, so skip submitting */
2461*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags) ||
2462*4882a593Smuzhiyun 	    !test_bit(WORK_ENABLE, &tp->flags) || !netif_carrier_ok(tp->netdev))
2463*4882a593Smuzhiyun 		return 0;
2464*4882a593Smuzhiyun 
2465*4882a593Smuzhiyun 	usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
2466*4882a593Smuzhiyun 			  agg->buffer, tp->rx_buf_sz,
2467*4882a593Smuzhiyun 			  (usb_complete_t)read_bulk_callback, agg);
2468*4882a593Smuzhiyun 
2469*4882a593Smuzhiyun 	ret = usb_submit_urb(agg->urb, mem_flags);
2470*4882a593Smuzhiyun 	if (ret == -ENODEV) {
2471*4882a593Smuzhiyun 		rtl_set_unplug(tp);
2472*4882a593Smuzhiyun 		netif_device_detach(tp->netdev);
2473*4882a593Smuzhiyun 	} else if (ret) {
2474*4882a593Smuzhiyun 		struct urb *urb = agg->urb;
2475*4882a593Smuzhiyun 		unsigned long flags;
2476*4882a593Smuzhiyun 
2477*4882a593Smuzhiyun 		urb->actual_length = 0;
2478*4882a593Smuzhiyun 		spin_lock_irqsave(&tp->rx_lock, flags);
2479*4882a593Smuzhiyun 		list_add_tail(&agg->list, &tp->rx_done);
2480*4882a593Smuzhiyun 		spin_unlock_irqrestore(&tp->rx_lock, flags);
2481*4882a593Smuzhiyun 
2482*4882a593Smuzhiyun 		netif_err(tp, rx_err, tp->netdev,
2483*4882a593Smuzhiyun 			  "Couldn't submit rx[%p], ret = %d\n", agg, ret);
2484*4882a593Smuzhiyun 
2485*4882a593Smuzhiyun 		napi_schedule(&tp->napi);
2486*4882a593Smuzhiyun 	}
2487*4882a593Smuzhiyun 
2488*4882a593Smuzhiyun 	return ret;
2489*4882a593Smuzhiyun }
2490*4882a593Smuzhiyun 
rtl_drop_queued_tx(struct r8152 * tp)2491*4882a593Smuzhiyun static void rtl_drop_queued_tx(struct r8152 *tp)
2492*4882a593Smuzhiyun {
2493*4882a593Smuzhiyun 	struct net_device_stats *stats = &tp->netdev->stats;
2494*4882a593Smuzhiyun 	struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
2495*4882a593Smuzhiyun 	struct sk_buff *skb;
2496*4882a593Smuzhiyun 
2497*4882a593Smuzhiyun 	if (skb_queue_empty(tx_queue))
2498*4882a593Smuzhiyun 		return;
2499*4882a593Smuzhiyun 
2500*4882a593Smuzhiyun 	__skb_queue_head_init(&skb_head);
2501*4882a593Smuzhiyun 	spin_lock_bh(&tx_queue->lock);
2502*4882a593Smuzhiyun 	skb_queue_splice_init(tx_queue, &skb_head);
2503*4882a593Smuzhiyun 	spin_unlock_bh(&tx_queue->lock);
2504*4882a593Smuzhiyun 
2505*4882a593Smuzhiyun 	while ((skb = __skb_dequeue(&skb_head))) {
2506*4882a593Smuzhiyun 		dev_kfree_skb(skb);
2507*4882a593Smuzhiyun 		stats->tx_dropped++;
2508*4882a593Smuzhiyun 	}
2509*4882a593Smuzhiyun }
2510*4882a593Smuzhiyun 
rtl8152_tx_timeout(struct net_device * netdev,unsigned int txqueue)2511*4882a593Smuzhiyun static void rtl8152_tx_timeout(struct net_device *netdev, unsigned int txqueue)
2512*4882a593Smuzhiyun {
2513*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
2514*4882a593Smuzhiyun 
2515*4882a593Smuzhiyun 	netif_warn(tp, tx_err, netdev, "Tx timeout\n");
2516*4882a593Smuzhiyun 
2517*4882a593Smuzhiyun 	usb_queue_reset_device(tp->intf);
2518*4882a593Smuzhiyun }
2519*4882a593Smuzhiyun 
rtl8152_set_rx_mode(struct net_device * netdev)2520*4882a593Smuzhiyun static void rtl8152_set_rx_mode(struct net_device *netdev)
2521*4882a593Smuzhiyun {
2522*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
2523*4882a593Smuzhiyun 
2524*4882a593Smuzhiyun 	if (netif_carrier_ok(netdev)) {
2525*4882a593Smuzhiyun 		set_bit(RTL8152_SET_RX_MODE, &tp->flags);
2526*4882a593Smuzhiyun 		schedule_delayed_work(&tp->schedule, 0);
2527*4882a593Smuzhiyun 	}
2528*4882a593Smuzhiyun }
2529*4882a593Smuzhiyun 
_rtl8152_set_rx_mode(struct net_device * netdev)2530*4882a593Smuzhiyun static void _rtl8152_set_rx_mode(struct net_device *netdev)
2531*4882a593Smuzhiyun {
2532*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
2533*4882a593Smuzhiyun 	u32 mc_filter[2];	/* Multicast hash filter */
2534*4882a593Smuzhiyun 	__le32 tmp[2];
2535*4882a593Smuzhiyun 	u32 ocp_data;
2536*4882a593Smuzhiyun 
2537*4882a593Smuzhiyun 	netif_stop_queue(netdev);
2538*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
2539*4882a593Smuzhiyun 	ocp_data &= ~RCR_ACPT_ALL;
2540*4882a593Smuzhiyun 	ocp_data |= RCR_AB | RCR_APM;
2541*4882a593Smuzhiyun 
2542*4882a593Smuzhiyun 	if (netdev->flags & IFF_PROMISC) {
2543*4882a593Smuzhiyun 		/* Unconditionally log net taps. */
2544*4882a593Smuzhiyun 		netif_notice(tp, link, netdev, "Promiscuous mode enabled\n");
2545*4882a593Smuzhiyun 		ocp_data |= RCR_AM | RCR_AAP;
2546*4882a593Smuzhiyun 		mc_filter[1] = 0xffffffff;
2547*4882a593Smuzhiyun 		mc_filter[0] = 0xffffffff;
2548*4882a593Smuzhiyun 	} else if ((netdev_mc_count(netdev) > multicast_filter_limit) ||
2549*4882a593Smuzhiyun 		   (netdev->flags & IFF_ALLMULTI)) {
2550*4882a593Smuzhiyun 		/* Too many to filter perfectly -- accept all multicasts. */
2551*4882a593Smuzhiyun 		ocp_data |= RCR_AM;
2552*4882a593Smuzhiyun 		mc_filter[1] = 0xffffffff;
2553*4882a593Smuzhiyun 		mc_filter[0] = 0xffffffff;
2554*4882a593Smuzhiyun 	} else {
2555*4882a593Smuzhiyun 		struct netdev_hw_addr *ha;
2556*4882a593Smuzhiyun 
2557*4882a593Smuzhiyun 		mc_filter[1] = 0;
2558*4882a593Smuzhiyun 		mc_filter[0] = 0;
2559*4882a593Smuzhiyun 		netdev_for_each_mc_addr(ha, netdev) {
2560*4882a593Smuzhiyun 			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
2561*4882a593Smuzhiyun 
2562*4882a593Smuzhiyun 			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
2563*4882a593Smuzhiyun 			ocp_data |= RCR_AM;
2564*4882a593Smuzhiyun 		}
2565*4882a593Smuzhiyun 	}
2566*4882a593Smuzhiyun 
2567*4882a593Smuzhiyun 	tmp[0] = __cpu_to_le32(swab32(mc_filter[1]));
2568*4882a593Smuzhiyun 	tmp[1] = __cpu_to_le32(swab32(mc_filter[0]));
2569*4882a593Smuzhiyun 
2570*4882a593Smuzhiyun 	pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp);
2571*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
2572*4882a593Smuzhiyun 	netif_wake_queue(netdev);
2573*4882a593Smuzhiyun }
2574*4882a593Smuzhiyun 
2575*4882a593Smuzhiyun static netdev_features_t
rtl8152_features_check(struct sk_buff * skb,struct net_device * dev,netdev_features_t features)2576*4882a593Smuzhiyun rtl8152_features_check(struct sk_buff *skb, struct net_device *dev,
2577*4882a593Smuzhiyun 		       netdev_features_t features)
2578*4882a593Smuzhiyun {
2579*4882a593Smuzhiyun 	u32 mss = skb_shinfo(skb)->gso_size;
2580*4882a593Smuzhiyun 	int max_offset = mss ? GTTCPHO_MAX : TCPHO_MAX;
2581*4882a593Smuzhiyun 	int offset = skb_transport_offset(skb);
2582*4882a593Smuzhiyun 
2583*4882a593Smuzhiyun 	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) && offset > max_offset)
2584*4882a593Smuzhiyun 		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
2585*4882a593Smuzhiyun 	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
2586*4882a593Smuzhiyun 		features &= ~NETIF_F_GSO_MASK;
2587*4882a593Smuzhiyun 
2588*4882a593Smuzhiyun 	return features;
2589*4882a593Smuzhiyun }
2590*4882a593Smuzhiyun 
rtl8152_start_xmit(struct sk_buff * skb,struct net_device * netdev)2591*4882a593Smuzhiyun static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
2592*4882a593Smuzhiyun 				      struct net_device *netdev)
2593*4882a593Smuzhiyun {
2594*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
2595*4882a593Smuzhiyun 
2596*4882a593Smuzhiyun 	skb_tx_timestamp(skb);
2597*4882a593Smuzhiyun 
2598*4882a593Smuzhiyun 	skb_queue_tail(&tp->tx_queue, skb);
2599*4882a593Smuzhiyun 
2600*4882a593Smuzhiyun 	if (!list_empty(&tp->tx_free)) {
2601*4882a593Smuzhiyun 		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
2602*4882a593Smuzhiyun 			set_bit(SCHEDULE_TASKLET, &tp->flags);
2603*4882a593Smuzhiyun 			schedule_delayed_work(&tp->schedule, 0);
2604*4882a593Smuzhiyun 		} else {
2605*4882a593Smuzhiyun 			usb_mark_last_busy(tp->udev);
2606*4882a593Smuzhiyun 			tasklet_schedule(&tp->tx_tl);
2607*4882a593Smuzhiyun 		}
2608*4882a593Smuzhiyun 	} else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen) {
2609*4882a593Smuzhiyun 		netif_stop_queue(netdev);
2610*4882a593Smuzhiyun 	}
2611*4882a593Smuzhiyun 
2612*4882a593Smuzhiyun 	return NETDEV_TX_OK;
2613*4882a593Smuzhiyun }
2614*4882a593Smuzhiyun 
r8152b_reset_packet_filter(struct r8152 * tp)2615*4882a593Smuzhiyun static void r8152b_reset_packet_filter(struct r8152 *tp)
2616*4882a593Smuzhiyun {
2617*4882a593Smuzhiyun 	u32	ocp_data;
2618*4882a593Smuzhiyun 
2619*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC);
2620*4882a593Smuzhiyun 	ocp_data &= ~FMC_FCR_MCU_EN;
2621*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
2622*4882a593Smuzhiyun 	ocp_data |= FMC_FCR_MCU_EN;
2623*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
2624*4882a593Smuzhiyun }
2625*4882a593Smuzhiyun 
rtl8152_nic_reset(struct r8152 * tp)2626*4882a593Smuzhiyun static void rtl8152_nic_reset(struct r8152 *tp)
2627*4882a593Smuzhiyun {
2628*4882a593Smuzhiyun 	int	i;
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
2631*4882a593Smuzhiyun 
2632*4882a593Smuzhiyun 	for (i = 0; i < 1000; i++) {
2633*4882a593Smuzhiyun 		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
2634*4882a593Smuzhiyun 			break;
2635*4882a593Smuzhiyun 		usleep_range(100, 400);
2636*4882a593Smuzhiyun 	}
2637*4882a593Smuzhiyun }
2638*4882a593Smuzhiyun 
set_tx_qlen(struct r8152 * tp)2639*4882a593Smuzhiyun static void set_tx_qlen(struct r8152 *tp)
2640*4882a593Smuzhiyun {
2641*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
2642*4882a593Smuzhiyun 
2643*4882a593Smuzhiyun 	tp->tx_qlen = agg_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN +
2644*4882a593Smuzhiyun 				    sizeof(struct tx_desc));
2645*4882a593Smuzhiyun }
2646*4882a593Smuzhiyun 
rtl8152_get_speed(struct r8152 * tp)2647*4882a593Smuzhiyun static inline u8 rtl8152_get_speed(struct r8152 *tp)
2648*4882a593Smuzhiyun {
2649*4882a593Smuzhiyun 	return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
2650*4882a593Smuzhiyun }
2651*4882a593Smuzhiyun 
rtl_set_eee_plus(struct r8152 * tp)2652*4882a593Smuzhiyun static void rtl_set_eee_plus(struct r8152 *tp)
2653*4882a593Smuzhiyun {
2654*4882a593Smuzhiyun 	u32 ocp_data;
2655*4882a593Smuzhiyun 	u8 speed;
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun 	speed = rtl8152_get_speed(tp);
2658*4882a593Smuzhiyun 	if (speed & _10bps) {
2659*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
2660*4882a593Smuzhiyun 		ocp_data |= EEEP_CR_EEEP_TX;
2661*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
2662*4882a593Smuzhiyun 	} else {
2663*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
2664*4882a593Smuzhiyun 		ocp_data &= ~EEEP_CR_EEEP_TX;
2665*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
2666*4882a593Smuzhiyun 	}
2667*4882a593Smuzhiyun }
2668*4882a593Smuzhiyun 
rxdy_gated_en(struct r8152 * tp,bool enable)2669*4882a593Smuzhiyun static void rxdy_gated_en(struct r8152 *tp, bool enable)
2670*4882a593Smuzhiyun {
2671*4882a593Smuzhiyun 	u32 ocp_data;
2672*4882a593Smuzhiyun 
2673*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
2674*4882a593Smuzhiyun 	if (enable)
2675*4882a593Smuzhiyun 		ocp_data |= RXDY_GATED_EN;
2676*4882a593Smuzhiyun 	else
2677*4882a593Smuzhiyun 		ocp_data &= ~RXDY_GATED_EN;
2678*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
2679*4882a593Smuzhiyun }
2680*4882a593Smuzhiyun 
rtl_start_rx(struct r8152 * tp)2681*4882a593Smuzhiyun static int rtl_start_rx(struct r8152 *tp)
2682*4882a593Smuzhiyun {
2683*4882a593Smuzhiyun 	struct rx_agg *agg, *agg_next;
2684*4882a593Smuzhiyun 	struct list_head tmp_list;
2685*4882a593Smuzhiyun 	unsigned long flags;
2686*4882a593Smuzhiyun 	int ret = 0, i = 0;
2687*4882a593Smuzhiyun 
2688*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tmp_list);
2689*4882a593Smuzhiyun 
2690*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2691*4882a593Smuzhiyun 
2692*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tp->rx_done);
2693*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tp->rx_used);
2694*4882a593Smuzhiyun 
2695*4882a593Smuzhiyun 	list_splice_init(&tp->rx_info, &tmp_list);
2696*4882a593Smuzhiyun 
2697*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2698*4882a593Smuzhiyun 
2699*4882a593Smuzhiyun 	list_for_each_entry_safe(agg, agg_next, &tmp_list, info_list) {
2700*4882a593Smuzhiyun 		INIT_LIST_HEAD(&agg->list);
2701*4882a593Smuzhiyun 
2702*4882a593Smuzhiyun 		/* Only RTL8152_MAX_RX rx_agg need to be submitted. */
2703*4882a593Smuzhiyun 		if (++i > RTL8152_MAX_RX) {
2704*4882a593Smuzhiyun 			spin_lock_irqsave(&tp->rx_lock, flags);
2705*4882a593Smuzhiyun 			list_add_tail(&agg->list, &tp->rx_used);
2706*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tp->rx_lock, flags);
2707*4882a593Smuzhiyun 		} else if (unlikely(ret < 0)) {
2708*4882a593Smuzhiyun 			spin_lock_irqsave(&tp->rx_lock, flags);
2709*4882a593Smuzhiyun 			list_add_tail(&agg->list, &tp->rx_done);
2710*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tp->rx_lock, flags);
2711*4882a593Smuzhiyun 		} else {
2712*4882a593Smuzhiyun 			ret = r8152_submit_rx(tp, agg, GFP_KERNEL);
2713*4882a593Smuzhiyun 		}
2714*4882a593Smuzhiyun 	}
2715*4882a593Smuzhiyun 
2716*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2717*4882a593Smuzhiyun 	WARN_ON(!list_empty(&tp->rx_info));
2718*4882a593Smuzhiyun 	list_splice(&tmp_list, &tp->rx_info);
2719*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2720*4882a593Smuzhiyun 
2721*4882a593Smuzhiyun 	return ret;
2722*4882a593Smuzhiyun }
2723*4882a593Smuzhiyun 
rtl_stop_rx(struct r8152 * tp)2724*4882a593Smuzhiyun static int rtl_stop_rx(struct r8152 *tp)
2725*4882a593Smuzhiyun {
2726*4882a593Smuzhiyun 	struct rx_agg *agg, *agg_next;
2727*4882a593Smuzhiyun 	struct list_head tmp_list;
2728*4882a593Smuzhiyun 	unsigned long flags;
2729*4882a593Smuzhiyun 
2730*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tmp_list);
2731*4882a593Smuzhiyun 
2732*4882a593Smuzhiyun 	/* The usb_kill_urb() couldn't be used in atomic.
2733*4882a593Smuzhiyun 	 * Therefore, move the list of rx_info to a tmp one.
2734*4882a593Smuzhiyun 	 * Then, list_for_each_entry_safe could be used without
2735*4882a593Smuzhiyun 	 * spin lock.
2736*4882a593Smuzhiyun 	 */
2737*4882a593Smuzhiyun 
2738*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2739*4882a593Smuzhiyun 	list_splice_init(&tp->rx_info, &tmp_list);
2740*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2741*4882a593Smuzhiyun 
2742*4882a593Smuzhiyun 	list_for_each_entry_safe(agg, agg_next, &tmp_list, info_list) {
2743*4882a593Smuzhiyun 		/* At least RTL8152_MAX_RX rx_agg have the page_count being
2744*4882a593Smuzhiyun 		 * equal to 1, so the other ones could be freed safely.
2745*4882a593Smuzhiyun 		 */
2746*4882a593Smuzhiyun 		if (page_count(agg->page) > 1)
2747*4882a593Smuzhiyun 			free_rx_agg(tp, agg);
2748*4882a593Smuzhiyun 		else
2749*4882a593Smuzhiyun 			usb_kill_urb(agg->urb);
2750*4882a593Smuzhiyun 	}
2751*4882a593Smuzhiyun 
2752*4882a593Smuzhiyun 	/* Move back the list of temp to the rx_info */
2753*4882a593Smuzhiyun 	spin_lock_irqsave(&tp->rx_lock, flags);
2754*4882a593Smuzhiyun 	WARN_ON(!list_empty(&tp->rx_info));
2755*4882a593Smuzhiyun 	list_splice(&tmp_list, &tp->rx_info);
2756*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tp->rx_lock, flags);
2757*4882a593Smuzhiyun 
2758*4882a593Smuzhiyun 	while (!skb_queue_empty(&tp->rx_queue))
2759*4882a593Smuzhiyun 		dev_kfree_skb(__skb_dequeue(&tp->rx_queue));
2760*4882a593Smuzhiyun 
2761*4882a593Smuzhiyun 	return 0;
2762*4882a593Smuzhiyun }
2763*4882a593Smuzhiyun 
r8153b_rx_agg_chg_indicate(struct r8152 * tp)2764*4882a593Smuzhiyun static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp)
2765*4882a593Smuzhiyun {
2766*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN,
2767*4882a593Smuzhiyun 		       OWN_UPDATE | OWN_CLEAR);
2768*4882a593Smuzhiyun }
2769*4882a593Smuzhiyun 
rtl_enable(struct r8152 * tp)2770*4882a593Smuzhiyun static int rtl_enable(struct r8152 *tp)
2771*4882a593Smuzhiyun {
2772*4882a593Smuzhiyun 	u32 ocp_data;
2773*4882a593Smuzhiyun 
2774*4882a593Smuzhiyun 	r8152b_reset_packet_filter(tp);
2775*4882a593Smuzhiyun 
2776*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR);
2777*4882a593Smuzhiyun 	ocp_data |= CR_RE | CR_TE;
2778*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data);
2779*4882a593Smuzhiyun 
2780*4882a593Smuzhiyun 	switch (tp->version) {
2781*4882a593Smuzhiyun 	case RTL_VER_08:
2782*4882a593Smuzhiyun 	case RTL_VER_09:
2783*4882a593Smuzhiyun 		r8153b_rx_agg_chg_indicate(tp);
2784*4882a593Smuzhiyun 		break;
2785*4882a593Smuzhiyun 	default:
2786*4882a593Smuzhiyun 		break;
2787*4882a593Smuzhiyun 	}
2788*4882a593Smuzhiyun 
2789*4882a593Smuzhiyun 	rxdy_gated_en(tp, false);
2790*4882a593Smuzhiyun 
2791*4882a593Smuzhiyun 	return 0;
2792*4882a593Smuzhiyun }
2793*4882a593Smuzhiyun 
rtl8152_enable(struct r8152 * tp)2794*4882a593Smuzhiyun static int rtl8152_enable(struct r8152 *tp)
2795*4882a593Smuzhiyun {
2796*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
2797*4882a593Smuzhiyun 		return -ENODEV;
2798*4882a593Smuzhiyun 
2799*4882a593Smuzhiyun 	set_tx_qlen(tp);
2800*4882a593Smuzhiyun 	rtl_set_eee_plus(tp);
2801*4882a593Smuzhiyun 
2802*4882a593Smuzhiyun 	return rtl_enable(tp);
2803*4882a593Smuzhiyun }
2804*4882a593Smuzhiyun 
r8153_set_rx_early_timeout(struct r8152 * tp)2805*4882a593Smuzhiyun static void r8153_set_rx_early_timeout(struct r8152 *tp)
2806*4882a593Smuzhiyun {
2807*4882a593Smuzhiyun 	u32 ocp_data = tp->coalesce / 8;
2808*4882a593Smuzhiyun 
2809*4882a593Smuzhiyun 	switch (tp->version) {
2810*4882a593Smuzhiyun 	case RTL_VER_03:
2811*4882a593Smuzhiyun 	case RTL_VER_04:
2812*4882a593Smuzhiyun 	case RTL_VER_05:
2813*4882a593Smuzhiyun 	case RTL_VER_06:
2814*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
2815*4882a593Smuzhiyun 			       ocp_data);
2816*4882a593Smuzhiyun 		break;
2817*4882a593Smuzhiyun 
2818*4882a593Smuzhiyun 	case RTL_VER_08:
2819*4882a593Smuzhiyun 	case RTL_VER_09:
2820*4882a593Smuzhiyun 		/* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout
2821*4882a593Smuzhiyun 		 * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns.
2822*4882a593Smuzhiyun 		 */
2823*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
2824*4882a593Smuzhiyun 			       128 / 8);
2825*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR,
2826*4882a593Smuzhiyun 			       ocp_data);
2827*4882a593Smuzhiyun 		break;
2828*4882a593Smuzhiyun 
2829*4882a593Smuzhiyun 	default:
2830*4882a593Smuzhiyun 		break;
2831*4882a593Smuzhiyun 	}
2832*4882a593Smuzhiyun }
2833*4882a593Smuzhiyun 
r8153_set_rx_early_size(struct r8152 * tp)2834*4882a593Smuzhiyun static void r8153_set_rx_early_size(struct r8152 *tp)
2835*4882a593Smuzhiyun {
2836*4882a593Smuzhiyun 	u32 ocp_data = tp->rx_buf_sz - rx_reserved_size(tp->netdev->mtu);
2837*4882a593Smuzhiyun 
2838*4882a593Smuzhiyun 	switch (tp->version) {
2839*4882a593Smuzhiyun 	case RTL_VER_03:
2840*4882a593Smuzhiyun 	case RTL_VER_04:
2841*4882a593Smuzhiyun 	case RTL_VER_05:
2842*4882a593Smuzhiyun 	case RTL_VER_06:
2843*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
2844*4882a593Smuzhiyun 			       ocp_data / 4);
2845*4882a593Smuzhiyun 		break;
2846*4882a593Smuzhiyun 	case RTL_VER_08:
2847*4882a593Smuzhiyun 	case RTL_VER_09:
2848*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
2849*4882a593Smuzhiyun 			       ocp_data / 8);
2850*4882a593Smuzhiyun 		break;
2851*4882a593Smuzhiyun 	default:
2852*4882a593Smuzhiyun 		WARN_ON_ONCE(1);
2853*4882a593Smuzhiyun 		break;
2854*4882a593Smuzhiyun 	}
2855*4882a593Smuzhiyun }
2856*4882a593Smuzhiyun 
rtl8153_enable(struct r8152 * tp)2857*4882a593Smuzhiyun static int rtl8153_enable(struct r8152 *tp)
2858*4882a593Smuzhiyun {
2859*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
2860*4882a593Smuzhiyun 		return -ENODEV;
2861*4882a593Smuzhiyun 
2862*4882a593Smuzhiyun 	set_tx_qlen(tp);
2863*4882a593Smuzhiyun 	rtl_set_eee_plus(tp);
2864*4882a593Smuzhiyun 	r8153_set_rx_early_timeout(tp);
2865*4882a593Smuzhiyun 	r8153_set_rx_early_size(tp);
2866*4882a593Smuzhiyun 
2867*4882a593Smuzhiyun 	if (tp->version == RTL_VER_09) {
2868*4882a593Smuzhiyun 		u32 ocp_data;
2869*4882a593Smuzhiyun 
2870*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
2871*4882a593Smuzhiyun 		ocp_data &= ~FC_PATCH_TASK;
2872*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
2873*4882a593Smuzhiyun 		usleep_range(1000, 2000);
2874*4882a593Smuzhiyun 		ocp_data |= FC_PATCH_TASK;
2875*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
2876*4882a593Smuzhiyun 	}
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun 	return rtl_enable(tp);
2879*4882a593Smuzhiyun }
2880*4882a593Smuzhiyun 
rtl_disable(struct r8152 * tp)2881*4882a593Smuzhiyun static void rtl_disable(struct r8152 *tp)
2882*4882a593Smuzhiyun {
2883*4882a593Smuzhiyun 	u32 ocp_data;
2884*4882a593Smuzhiyun 	int i;
2885*4882a593Smuzhiyun 
2886*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
2887*4882a593Smuzhiyun 		rtl_drop_queued_tx(tp);
2888*4882a593Smuzhiyun 		return;
2889*4882a593Smuzhiyun 	}
2890*4882a593Smuzhiyun 
2891*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
2892*4882a593Smuzhiyun 	ocp_data &= ~RCR_ACPT_ALL;
2893*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
2894*4882a593Smuzhiyun 
2895*4882a593Smuzhiyun 	rtl_drop_queued_tx(tp);
2896*4882a593Smuzhiyun 
2897*4882a593Smuzhiyun 	for (i = 0; i < RTL8152_MAX_TX; i++)
2898*4882a593Smuzhiyun 		usb_kill_urb(tp->tx_info[i].urb);
2899*4882a593Smuzhiyun 
2900*4882a593Smuzhiyun 	rxdy_gated_en(tp, true);
2901*4882a593Smuzhiyun 
2902*4882a593Smuzhiyun 	for (i = 0; i < 1000; i++) {
2903*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
2904*4882a593Smuzhiyun 		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
2905*4882a593Smuzhiyun 			break;
2906*4882a593Smuzhiyun 		usleep_range(1000, 2000);
2907*4882a593Smuzhiyun 	}
2908*4882a593Smuzhiyun 
2909*4882a593Smuzhiyun 	for (i = 0; i < 1000; i++) {
2910*4882a593Smuzhiyun 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
2911*4882a593Smuzhiyun 			break;
2912*4882a593Smuzhiyun 		usleep_range(1000, 2000);
2913*4882a593Smuzhiyun 	}
2914*4882a593Smuzhiyun 
2915*4882a593Smuzhiyun 	rtl_stop_rx(tp);
2916*4882a593Smuzhiyun 
2917*4882a593Smuzhiyun 	rtl8152_nic_reset(tp);
2918*4882a593Smuzhiyun }
2919*4882a593Smuzhiyun 
r8152_power_cut_en(struct r8152 * tp,bool enable)2920*4882a593Smuzhiyun static void r8152_power_cut_en(struct r8152 *tp, bool enable)
2921*4882a593Smuzhiyun {
2922*4882a593Smuzhiyun 	u32 ocp_data;
2923*4882a593Smuzhiyun 
2924*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
2925*4882a593Smuzhiyun 	if (enable)
2926*4882a593Smuzhiyun 		ocp_data |= POWER_CUT;
2927*4882a593Smuzhiyun 	else
2928*4882a593Smuzhiyun 		ocp_data &= ~POWER_CUT;
2929*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
2930*4882a593Smuzhiyun 
2931*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
2932*4882a593Smuzhiyun 	ocp_data &= ~RESUME_INDICATE;
2933*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
2934*4882a593Smuzhiyun }
2935*4882a593Smuzhiyun 
rtl_rx_vlan_en(struct r8152 * tp,bool enable)2936*4882a593Smuzhiyun static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
2937*4882a593Smuzhiyun {
2938*4882a593Smuzhiyun 	u32 ocp_data;
2939*4882a593Smuzhiyun 
2940*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
2941*4882a593Smuzhiyun 	if (enable)
2942*4882a593Smuzhiyun 		ocp_data |= CPCR_RX_VLAN;
2943*4882a593Smuzhiyun 	else
2944*4882a593Smuzhiyun 		ocp_data &= ~CPCR_RX_VLAN;
2945*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
2946*4882a593Smuzhiyun }
2947*4882a593Smuzhiyun 
rtl8152_set_features(struct net_device * dev,netdev_features_t features)2948*4882a593Smuzhiyun static int rtl8152_set_features(struct net_device *dev,
2949*4882a593Smuzhiyun 				netdev_features_t features)
2950*4882a593Smuzhiyun {
2951*4882a593Smuzhiyun 	netdev_features_t changed = features ^ dev->features;
2952*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
2953*4882a593Smuzhiyun 	int ret;
2954*4882a593Smuzhiyun 
2955*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
2956*4882a593Smuzhiyun 	if (ret < 0)
2957*4882a593Smuzhiyun 		goto out;
2958*4882a593Smuzhiyun 
2959*4882a593Smuzhiyun 	mutex_lock(&tp->control);
2960*4882a593Smuzhiyun 
2961*4882a593Smuzhiyun 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
2962*4882a593Smuzhiyun 		if (features & NETIF_F_HW_VLAN_CTAG_RX)
2963*4882a593Smuzhiyun 			rtl_rx_vlan_en(tp, true);
2964*4882a593Smuzhiyun 		else
2965*4882a593Smuzhiyun 			rtl_rx_vlan_en(tp, false);
2966*4882a593Smuzhiyun 	}
2967*4882a593Smuzhiyun 
2968*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
2969*4882a593Smuzhiyun 
2970*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
2971*4882a593Smuzhiyun 
2972*4882a593Smuzhiyun out:
2973*4882a593Smuzhiyun 	return ret;
2974*4882a593Smuzhiyun }
2975*4882a593Smuzhiyun 
2976*4882a593Smuzhiyun #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
2977*4882a593Smuzhiyun 
__rtl_get_wol(struct r8152 * tp)2978*4882a593Smuzhiyun static u32 __rtl_get_wol(struct r8152 *tp)
2979*4882a593Smuzhiyun {
2980*4882a593Smuzhiyun 	u32 ocp_data;
2981*4882a593Smuzhiyun 	u32 wolopts = 0;
2982*4882a593Smuzhiyun 
2983*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
2984*4882a593Smuzhiyun 	if (ocp_data & LINK_ON_WAKE_EN)
2985*4882a593Smuzhiyun 		wolopts |= WAKE_PHY;
2986*4882a593Smuzhiyun 
2987*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
2988*4882a593Smuzhiyun 	if (ocp_data & UWF_EN)
2989*4882a593Smuzhiyun 		wolopts |= WAKE_UCAST;
2990*4882a593Smuzhiyun 	if (ocp_data & BWF_EN)
2991*4882a593Smuzhiyun 		wolopts |= WAKE_BCAST;
2992*4882a593Smuzhiyun 	if (ocp_data & MWF_EN)
2993*4882a593Smuzhiyun 		wolopts |= WAKE_MCAST;
2994*4882a593Smuzhiyun 
2995*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
2996*4882a593Smuzhiyun 	if (ocp_data & MAGIC_EN)
2997*4882a593Smuzhiyun 		wolopts |= WAKE_MAGIC;
2998*4882a593Smuzhiyun 
2999*4882a593Smuzhiyun 	return wolopts;
3000*4882a593Smuzhiyun }
3001*4882a593Smuzhiyun 
__rtl_set_wol(struct r8152 * tp,u32 wolopts)3002*4882a593Smuzhiyun static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
3003*4882a593Smuzhiyun {
3004*4882a593Smuzhiyun 	u32 ocp_data;
3005*4882a593Smuzhiyun 
3006*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
3007*4882a593Smuzhiyun 
3008*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
3009*4882a593Smuzhiyun 	ocp_data &= ~LINK_ON_WAKE_EN;
3010*4882a593Smuzhiyun 	if (wolopts & WAKE_PHY)
3011*4882a593Smuzhiyun 		ocp_data |= LINK_ON_WAKE_EN;
3012*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
3013*4882a593Smuzhiyun 
3014*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
3015*4882a593Smuzhiyun 	ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN);
3016*4882a593Smuzhiyun 	if (wolopts & WAKE_UCAST)
3017*4882a593Smuzhiyun 		ocp_data |= UWF_EN;
3018*4882a593Smuzhiyun 	if (wolopts & WAKE_BCAST)
3019*4882a593Smuzhiyun 		ocp_data |= BWF_EN;
3020*4882a593Smuzhiyun 	if (wolopts & WAKE_MCAST)
3021*4882a593Smuzhiyun 		ocp_data |= MWF_EN;
3022*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data);
3023*4882a593Smuzhiyun 
3024*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
3025*4882a593Smuzhiyun 
3026*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
3027*4882a593Smuzhiyun 	ocp_data &= ~MAGIC_EN;
3028*4882a593Smuzhiyun 	if (wolopts & WAKE_MAGIC)
3029*4882a593Smuzhiyun 		ocp_data |= MAGIC_EN;
3030*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
3031*4882a593Smuzhiyun 
3032*4882a593Smuzhiyun 	if (wolopts & WAKE_ANY)
3033*4882a593Smuzhiyun 		device_set_wakeup_enable(&tp->udev->dev, true);
3034*4882a593Smuzhiyun 	else
3035*4882a593Smuzhiyun 		device_set_wakeup_enable(&tp->udev->dev, false);
3036*4882a593Smuzhiyun }
3037*4882a593Smuzhiyun 
r8153_u1u2en(struct r8152 * tp,bool enable)3038*4882a593Smuzhiyun static void r8153_u1u2en(struct r8152 *tp, bool enable)
3039*4882a593Smuzhiyun {
3040*4882a593Smuzhiyun 	u8 u1u2[8];
3041*4882a593Smuzhiyun 
3042*4882a593Smuzhiyun 	if (enable)
3043*4882a593Smuzhiyun 		memset(u1u2, 0xff, sizeof(u1u2));
3044*4882a593Smuzhiyun 	else
3045*4882a593Smuzhiyun 		memset(u1u2, 0x00, sizeof(u1u2));
3046*4882a593Smuzhiyun 
3047*4882a593Smuzhiyun 	usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
3048*4882a593Smuzhiyun }
3049*4882a593Smuzhiyun 
r8153b_u1u2en(struct r8152 * tp,bool enable)3050*4882a593Smuzhiyun static void r8153b_u1u2en(struct r8152 *tp, bool enable)
3051*4882a593Smuzhiyun {
3052*4882a593Smuzhiyun 	u32 ocp_data;
3053*4882a593Smuzhiyun 
3054*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG);
3055*4882a593Smuzhiyun 	if (enable)
3056*4882a593Smuzhiyun 		ocp_data |= LPM_U1U2_EN;
3057*4882a593Smuzhiyun 	else
3058*4882a593Smuzhiyun 		ocp_data &= ~LPM_U1U2_EN;
3059*4882a593Smuzhiyun 
3060*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG, ocp_data);
3061*4882a593Smuzhiyun }
3062*4882a593Smuzhiyun 
r8153_u2p3en(struct r8152 * tp,bool enable)3063*4882a593Smuzhiyun static void r8153_u2p3en(struct r8152 *tp, bool enable)
3064*4882a593Smuzhiyun {
3065*4882a593Smuzhiyun 	u32 ocp_data;
3066*4882a593Smuzhiyun 
3067*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
3068*4882a593Smuzhiyun 	if (enable)
3069*4882a593Smuzhiyun 		ocp_data |= U2P3_ENABLE;
3070*4882a593Smuzhiyun 	else
3071*4882a593Smuzhiyun 		ocp_data &= ~U2P3_ENABLE;
3072*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
3073*4882a593Smuzhiyun }
3074*4882a593Smuzhiyun 
r8153b_ups_flags(struct r8152 * tp)3075*4882a593Smuzhiyun static void r8153b_ups_flags(struct r8152 *tp)
3076*4882a593Smuzhiyun {
3077*4882a593Smuzhiyun 	u32 ups_flags = 0;
3078*4882a593Smuzhiyun 
3079*4882a593Smuzhiyun 	if (tp->ups_info.green)
3080*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_GREEN;
3081*4882a593Smuzhiyun 
3082*4882a593Smuzhiyun 	if (tp->ups_info.aldps)
3083*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_ALDPS;
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun 	if (tp->ups_info.eee)
3086*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_EEE;
3087*4882a593Smuzhiyun 
3088*4882a593Smuzhiyun 	if (tp->ups_info.flow_control)
3089*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_FLOW_CTR;
3090*4882a593Smuzhiyun 
3091*4882a593Smuzhiyun 	if (tp->ups_info.eee_ckdiv)
3092*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_EEE_CKDIV;
3093*4882a593Smuzhiyun 
3094*4882a593Smuzhiyun 	if (tp->ups_info.eee_cmod_lv)
3095*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN;
3096*4882a593Smuzhiyun 
3097*4882a593Smuzhiyun 	if (tp->ups_info._10m_ckdiv)
3098*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EN_10M_CKDIV;
3099*4882a593Smuzhiyun 
3100*4882a593Smuzhiyun 	if (tp->ups_info.eee_plloff_100)
3101*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EEE_PLLOFF_100;
3102*4882a593Smuzhiyun 
3103*4882a593Smuzhiyun 	if (tp->ups_info.eee_plloff_giga)
3104*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_EEE_PLLOFF_GIGA;
3105*4882a593Smuzhiyun 
3106*4882a593Smuzhiyun 	if (tp->ups_info._250m_ckdiv)
3107*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_250M_CKDIV;
3108*4882a593Smuzhiyun 
3109*4882a593Smuzhiyun 	if (tp->ups_info.ctap_short_off)
3110*4882a593Smuzhiyun 		ups_flags |= UPS_FLAGS_CTAP_SHORT_DIS;
3111*4882a593Smuzhiyun 
3112*4882a593Smuzhiyun 	switch (tp->ups_info.speed_duplex) {
3113*4882a593Smuzhiyun 	case NWAY_10M_HALF:
3114*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(1);
3115*4882a593Smuzhiyun 		break;
3116*4882a593Smuzhiyun 	case NWAY_10M_FULL:
3117*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(2);
3118*4882a593Smuzhiyun 		break;
3119*4882a593Smuzhiyun 	case NWAY_100M_HALF:
3120*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(3);
3121*4882a593Smuzhiyun 		break;
3122*4882a593Smuzhiyun 	case NWAY_100M_FULL:
3123*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(4);
3124*4882a593Smuzhiyun 		break;
3125*4882a593Smuzhiyun 	case NWAY_1000M_FULL:
3126*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(5);
3127*4882a593Smuzhiyun 		break;
3128*4882a593Smuzhiyun 	case FORCE_10M_HALF:
3129*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(6);
3130*4882a593Smuzhiyun 		break;
3131*4882a593Smuzhiyun 	case FORCE_10M_FULL:
3132*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(7);
3133*4882a593Smuzhiyun 		break;
3134*4882a593Smuzhiyun 	case FORCE_100M_HALF:
3135*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(8);
3136*4882a593Smuzhiyun 		break;
3137*4882a593Smuzhiyun 	case FORCE_100M_FULL:
3138*4882a593Smuzhiyun 		ups_flags |= ups_flags_speed(9);
3139*4882a593Smuzhiyun 		break;
3140*4882a593Smuzhiyun 	default:
3141*4882a593Smuzhiyun 		break;
3142*4882a593Smuzhiyun 	}
3143*4882a593Smuzhiyun 
3144*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags);
3145*4882a593Smuzhiyun }
3146*4882a593Smuzhiyun 
r8153b_green_en(struct r8152 * tp,bool enable)3147*4882a593Smuzhiyun static void r8153b_green_en(struct r8152 *tp, bool enable)
3148*4882a593Smuzhiyun {
3149*4882a593Smuzhiyun 	u16 data;
3150*4882a593Smuzhiyun 
3151*4882a593Smuzhiyun 	if (enable) {
3152*4882a593Smuzhiyun 		sram_write(tp, 0x8045, 0);	/* 10M abiq&ldvbias */
3153*4882a593Smuzhiyun 		sram_write(tp, 0x804d, 0x1222);	/* 100M short abiq&ldvbias */
3154*4882a593Smuzhiyun 		sram_write(tp, 0x805d, 0x0022);	/* 1000M short abiq&ldvbias */
3155*4882a593Smuzhiyun 	} else {
3156*4882a593Smuzhiyun 		sram_write(tp, 0x8045, 0x2444);	/* 10M abiq&ldvbias */
3157*4882a593Smuzhiyun 		sram_write(tp, 0x804d, 0x2444);	/* 100M short abiq&ldvbias */
3158*4882a593Smuzhiyun 		sram_write(tp, 0x805d, 0x2444);	/* 1000M short abiq&ldvbias */
3159*4882a593Smuzhiyun 	}
3160*4882a593Smuzhiyun 
3161*4882a593Smuzhiyun 	data = sram_read(tp, SRAM_GREEN_CFG);
3162*4882a593Smuzhiyun 	data |= GREEN_ETH_EN;
3163*4882a593Smuzhiyun 	sram_write(tp, SRAM_GREEN_CFG, data);
3164*4882a593Smuzhiyun 
3165*4882a593Smuzhiyun 	tp->ups_info.green = enable;
3166*4882a593Smuzhiyun }
3167*4882a593Smuzhiyun 
r8153_phy_status(struct r8152 * tp,u16 desired)3168*4882a593Smuzhiyun static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
3169*4882a593Smuzhiyun {
3170*4882a593Smuzhiyun 	u16 data;
3171*4882a593Smuzhiyun 	int i;
3172*4882a593Smuzhiyun 
3173*4882a593Smuzhiyun 	for (i = 0; i < 500; i++) {
3174*4882a593Smuzhiyun 		data = ocp_reg_read(tp, OCP_PHY_STATUS);
3175*4882a593Smuzhiyun 		data &= PHY_STAT_MASK;
3176*4882a593Smuzhiyun 		if (desired) {
3177*4882a593Smuzhiyun 			if (data == desired)
3178*4882a593Smuzhiyun 				break;
3179*4882a593Smuzhiyun 		} else if (data == PHY_STAT_LAN_ON || data == PHY_STAT_PWRDN ||
3180*4882a593Smuzhiyun 			   data == PHY_STAT_EXT_INIT) {
3181*4882a593Smuzhiyun 			break;
3182*4882a593Smuzhiyun 		}
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun 		msleep(20);
3185*4882a593Smuzhiyun 		if (test_bit(RTL8152_UNPLUG, &tp->flags))
3186*4882a593Smuzhiyun 			break;
3187*4882a593Smuzhiyun 	}
3188*4882a593Smuzhiyun 
3189*4882a593Smuzhiyun 	return data;
3190*4882a593Smuzhiyun }
3191*4882a593Smuzhiyun 
r8153b_ups_en(struct r8152 * tp,bool enable)3192*4882a593Smuzhiyun static void r8153b_ups_en(struct r8152 *tp, bool enable)
3193*4882a593Smuzhiyun {
3194*4882a593Smuzhiyun 	u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT);
3195*4882a593Smuzhiyun 
3196*4882a593Smuzhiyun 	if (enable) {
3197*4882a593Smuzhiyun 		r8153b_ups_flags(tp);
3198*4882a593Smuzhiyun 
3199*4882a593Smuzhiyun 		ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN;
3200*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
3201*4882a593Smuzhiyun 
3202*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff);
3203*4882a593Smuzhiyun 		ocp_data |= BIT(0);
3204*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data);
3205*4882a593Smuzhiyun 	} else {
3206*4882a593Smuzhiyun 		u16 data;
3207*4882a593Smuzhiyun 
3208*4882a593Smuzhiyun 		ocp_data &= ~(UPS_EN | USP_PREWAKE);
3209*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
3210*4882a593Smuzhiyun 
3211*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff);
3212*4882a593Smuzhiyun 		ocp_data &= ~BIT(0);
3213*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data);
3214*4882a593Smuzhiyun 
3215*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
3216*4882a593Smuzhiyun 		ocp_data &= ~PCUT_STATUS;
3217*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
3218*4882a593Smuzhiyun 
3219*4882a593Smuzhiyun 		data = r8153_phy_status(tp, 0);
3220*4882a593Smuzhiyun 
3221*4882a593Smuzhiyun 		switch (data) {
3222*4882a593Smuzhiyun 		case PHY_STAT_PWRDN:
3223*4882a593Smuzhiyun 		case PHY_STAT_EXT_INIT:
3224*4882a593Smuzhiyun 			r8153b_green_en(tp,
3225*4882a593Smuzhiyun 					test_bit(GREEN_ETHERNET, &tp->flags));
3226*4882a593Smuzhiyun 
3227*4882a593Smuzhiyun 			data = r8152_mdio_read(tp, MII_BMCR);
3228*4882a593Smuzhiyun 			data &= ~BMCR_PDOWN;
3229*4882a593Smuzhiyun 			data |= BMCR_RESET;
3230*4882a593Smuzhiyun 			r8152_mdio_write(tp, MII_BMCR, data);
3231*4882a593Smuzhiyun 
3232*4882a593Smuzhiyun 			data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
3233*4882a593Smuzhiyun 			fallthrough;
3234*4882a593Smuzhiyun 
3235*4882a593Smuzhiyun 		default:
3236*4882a593Smuzhiyun 			if (data != PHY_STAT_LAN_ON)
3237*4882a593Smuzhiyun 				netif_warn(tp, link, tp->netdev,
3238*4882a593Smuzhiyun 					   "PHY not ready");
3239*4882a593Smuzhiyun 			break;
3240*4882a593Smuzhiyun 		}
3241*4882a593Smuzhiyun 	}
3242*4882a593Smuzhiyun }
3243*4882a593Smuzhiyun 
r8153_power_cut_en(struct r8152 * tp,bool enable)3244*4882a593Smuzhiyun static void r8153_power_cut_en(struct r8152 *tp, bool enable)
3245*4882a593Smuzhiyun {
3246*4882a593Smuzhiyun 	u32 ocp_data;
3247*4882a593Smuzhiyun 
3248*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
3249*4882a593Smuzhiyun 	if (enable)
3250*4882a593Smuzhiyun 		ocp_data |= PWR_EN | PHASE2_EN;
3251*4882a593Smuzhiyun 	else
3252*4882a593Smuzhiyun 		ocp_data &= ~(PWR_EN | PHASE2_EN);
3253*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
3254*4882a593Smuzhiyun 
3255*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
3256*4882a593Smuzhiyun 	ocp_data &= ~PCUT_STATUS;
3257*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
3258*4882a593Smuzhiyun }
3259*4882a593Smuzhiyun 
r8153b_power_cut_en(struct r8152 * tp,bool enable)3260*4882a593Smuzhiyun static void r8153b_power_cut_en(struct r8152 *tp, bool enable)
3261*4882a593Smuzhiyun {
3262*4882a593Smuzhiyun 	u32 ocp_data;
3263*4882a593Smuzhiyun 
3264*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
3265*4882a593Smuzhiyun 	if (enable)
3266*4882a593Smuzhiyun 		ocp_data |= PWR_EN | PHASE2_EN;
3267*4882a593Smuzhiyun 	else
3268*4882a593Smuzhiyun 		ocp_data &= ~PWR_EN;
3269*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
3270*4882a593Smuzhiyun 
3271*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
3272*4882a593Smuzhiyun 	ocp_data &= ~PCUT_STATUS;
3273*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
3274*4882a593Smuzhiyun }
3275*4882a593Smuzhiyun 
r8153_queue_wake(struct r8152 * tp,bool enable)3276*4882a593Smuzhiyun static void r8153_queue_wake(struct r8152 *tp, bool enable)
3277*4882a593Smuzhiyun {
3278*4882a593Smuzhiyun 	u32 ocp_data;
3279*4882a593Smuzhiyun 
3280*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG);
3281*4882a593Smuzhiyun 	if (enable)
3282*4882a593Smuzhiyun 		ocp_data |= UPCOMING_RUNTIME_D3;
3283*4882a593Smuzhiyun 	else
3284*4882a593Smuzhiyun 		ocp_data &= ~UPCOMING_RUNTIME_D3;
3285*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_INDICATE_FALG, ocp_data);
3286*4882a593Smuzhiyun 
3287*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_SUSPEND_FLAG);
3288*4882a593Smuzhiyun 	ocp_data &= ~LINK_CHG_EVENT;
3289*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_SUSPEND_FLAG, ocp_data);
3290*4882a593Smuzhiyun 
3291*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
3292*4882a593Smuzhiyun 	ocp_data &= ~LINK_CHANGE_FLAG;
3293*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
3294*4882a593Smuzhiyun }
3295*4882a593Smuzhiyun 
rtl_can_wakeup(struct r8152 * tp)3296*4882a593Smuzhiyun static bool rtl_can_wakeup(struct r8152 *tp)
3297*4882a593Smuzhiyun {
3298*4882a593Smuzhiyun 	struct usb_device *udev = tp->udev;
3299*4882a593Smuzhiyun 
3300*4882a593Smuzhiyun 	return (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP);
3301*4882a593Smuzhiyun }
3302*4882a593Smuzhiyun 
rtl_runtime_suspend_enable(struct r8152 * tp,bool enable)3303*4882a593Smuzhiyun static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable)
3304*4882a593Smuzhiyun {
3305*4882a593Smuzhiyun 	if (enable) {
3306*4882a593Smuzhiyun 		u32 ocp_data;
3307*4882a593Smuzhiyun 
3308*4882a593Smuzhiyun 		__rtl_set_wol(tp, WAKE_ANY);
3309*4882a593Smuzhiyun 
3310*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
3311*4882a593Smuzhiyun 
3312*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
3313*4882a593Smuzhiyun 		ocp_data |= LINK_OFF_WAKE_EN;
3314*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
3315*4882a593Smuzhiyun 
3316*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
3317*4882a593Smuzhiyun 	} else {
3318*4882a593Smuzhiyun 		u32 ocp_data;
3319*4882a593Smuzhiyun 
3320*4882a593Smuzhiyun 		__rtl_set_wol(tp, tp->saved_wolopts);
3321*4882a593Smuzhiyun 
3322*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
3323*4882a593Smuzhiyun 
3324*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
3325*4882a593Smuzhiyun 		ocp_data &= ~LINK_OFF_WAKE_EN;
3326*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
3327*4882a593Smuzhiyun 
3328*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
3329*4882a593Smuzhiyun 	}
3330*4882a593Smuzhiyun }
3331*4882a593Smuzhiyun 
rtl8153_runtime_enable(struct r8152 * tp,bool enable)3332*4882a593Smuzhiyun static void rtl8153_runtime_enable(struct r8152 *tp, bool enable)
3333*4882a593Smuzhiyun {
3334*4882a593Smuzhiyun 	if (enable) {
3335*4882a593Smuzhiyun 		r8153_u1u2en(tp, false);
3336*4882a593Smuzhiyun 		r8153_u2p3en(tp, false);
3337*4882a593Smuzhiyun 		rtl_runtime_suspend_enable(tp, true);
3338*4882a593Smuzhiyun 	} else {
3339*4882a593Smuzhiyun 		rtl_runtime_suspend_enable(tp, false);
3340*4882a593Smuzhiyun 
3341*4882a593Smuzhiyun 		switch (tp->version) {
3342*4882a593Smuzhiyun 		case RTL_VER_03:
3343*4882a593Smuzhiyun 		case RTL_VER_04:
3344*4882a593Smuzhiyun 			break;
3345*4882a593Smuzhiyun 		case RTL_VER_05:
3346*4882a593Smuzhiyun 		case RTL_VER_06:
3347*4882a593Smuzhiyun 		default:
3348*4882a593Smuzhiyun 			r8153_u2p3en(tp, true);
3349*4882a593Smuzhiyun 			break;
3350*4882a593Smuzhiyun 		}
3351*4882a593Smuzhiyun 
3352*4882a593Smuzhiyun 		r8153_u1u2en(tp, true);
3353*4882a593Smuzhiyun 	}
3354*4882a593Smuzhiyun }
3355*4882a593Smuzhiyun 
rtl8153b_runtime_enable(struct r8152 * tp,bool enable)3356*4882a593Smuzhiyun static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable)
3357*4882a593Smuzhiyun {
3358*4882a593Smuzhiyun 	if (enable) {
3359*4882a593Smuzhiyun 		r8153_queue_wake(tp, true);
3360*4882a593Smuzhiyun 		r8153b_u1u2en(tp, false);
3361*4882a593Smuzhiyun 		r8153_u2p3en(tp, false);
3362*4882a593Smuzhiyun 		rtl_runtime_suspend_enable(tp, true);
3363*4882a593Smuzhiyun 		r8153b_ups_en(tp, true);
3364*4882a593Smuzhiyun 	} else {
3365*4882a593Smuzhiyun 		r8153b_ups_en(tp, false);
3366*4882a593Smuzhiyun 		r8153_queue_wake(tp, false);
3367*4882a593Smuzhiyun 		rtl_runtime_suspend_enable(tp, false);
3368*4882a593Smuzhiyun 		if (tp->udev->speed != USB_SPEED_HIGH)
3369*4882a593Smuzhiyun 			r8153b_u1u2en(tp, true);
3370*4882a593Smuzhiyun 	}
3371*4882a593Smuzhiyun }
3372*4882a593Smuzhiyun 
r8153_teredo_off(struct r8152 * tp)3373*4882a593Smuzhiyun static void r8153_teredo_off(struct r8152 *tp)
3374*4882a593Smuzhiyun {
3375*4882a593Smuzhiyun 	u32 ocp_data;
3376*4882a593Smuzhiyun 
3377*4882a593Smuzhiyun 	switch (tp->version) {
3378*4882a593Smuzhiyun 	case RTL_VER_01:
3379*4882a593Smuzhiyun 	case RTL_VER_02:
3380*4882a593Smuzhiyun 	case RTL_VER_03:
3381*4882a593Smuzhiyun 	case RTL_VER_04:
3382*4882a593Smuzhiyun 	case RTL_VER_05:
3383*4882a593Smuzhiyun 	case RTL_VER_06:
3384*4882a593Smuzhiyun 	case RTL_VER_07:
3385*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
3386*4882a593Smuzhiyun 		ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK |
3387*4882a593Smuzhiyun 			      OOB_TEREDO_EN);
3388*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
3389*4882a593Smuzhiyun 		break;
3390*4882a593Smuzhiyun 
3391*4882a593Smuzhiyun 	case RTL_VER_08:
3392*4882a593Smuzhiyun 	case RTL_VER_09:
3393*4882a593Smuzhiyun 		/* The bit 0 ~ 7 are relative with teredo settings. They are
3394*4882a593Smuzhiyun 		 * W1C (write 1 to clear), so set all 1 to disable it.
3395*4882a593Smuzhiyun 		 */
3396*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, 0xff);
3397*4882a593Smuzhiyun 		break;
3398*4882a593Smuzhiyun 
3399*4882a593Smuzhiyun 	default:
3400*4882a593Smuzhiyun 		break;
3401*4882a593Smuzhiyun 	}
3402*4882a593Smuzhiyun 
3403*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
3404*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
3405*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
3406*4882a593Smuzhiyun }
3407*4882a593Smuzhiyun 
rtl_reset_bmu(struct r8152 * tp)3408*4882a593Smuzhiyun static void rtl_reset_bmu(struct r8152 *tp)
3409*4882a593Smuzhiyun {
3410*4882a593Smuzhiyun 	u32 ocp_data;
3411*4882a593Smuzhiyun 
3412*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_RESET);
3413*4882a593Smuzhiyun 	ocp_data &= ~(BMU_RESET_EP_IN | BMU_RESET_EP_OUT);
3414*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data);
3415*4882a593Smuzhiyun 	ocp_data |= BMU_RESET_EP_IN | BMU_RESET_EP_OUT;
3416*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data);
3417*4882a593Smuzhiyun }
3418*4882a593Smuzhiyun 
3419*4882a593Smuzhiyun /* Clear the bp to stop the firmware before loading a new one */
rtl_clear_bp(struct r8152 * tp,u16 type)3420*4882a593Smuzhiyun static void rtl_clear_bp(struct r8152 *tp, u16 type)
3421*4882a593Smuzhiyun {
3422*4882a593Smuzhiyun 	switch (tp->version) {
3423*4882a593Smuzhiyun 	case RTL_VER_01:
3424*4882a593Smuzhiyun 	case RTL_VER_02:
3425*4882a593Smuzhiyun 	case RTL_VER_07:
3426*4882a593Smuzhiyun 		break;
3427*4882a593Smuzhiyun 	case RTL_VER_03:
3428*4882a593Smuzhiyun 	case RTL_VER_04:
3429*4882a593Smuzhiyun 	case RTL_VER_05:
3430*4882a593Smuzhiyun 	case RTL_VER_06:
3431*4882a593Smuzhiyun 		ocp_write_byte(tp, type, PLA_BP_EN, 0);
3432*4882a593Smuzhiyun 		break;
3433*4882a593Smuzhiyun 	case RTL_VER_08:
3434*4882a593Smuzhiyun 	case RTL_VER_09:
3435*4882a593Smuzhiyun 	default:
3436*4882a593Smuzhiyun 		if (type == MCU_TYPE_USB) {
3437*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
3438*4882a593Smuzhiyun 
3439*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0);
3440*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0);
3441*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0);
3442*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0);
3443*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0);
3444*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0);
3445*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0);
3446*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0);
3447*4882a593Smuzhiyun 		} else {
3448*4882a593Smuzhiyun 			ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
3449*4882a593Smuzhiyun 		}
3450*4882a593Smuzhiyun 		break;
3451*4882a593Smuzhiyun 	}
3452*4882a593Smuzhiyun 
3453*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_0, 0);
3454*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_1, 0);
3455*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_2, 0);
3456*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_3, 0);
3457*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_4, 0);
3458*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_5, 0);
3459*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_6, 0);
3460*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_7, 0);
3461*4882a593Smuzhiyun 
3462*4882a593Smuzhiyun 	/* wait 3 ms to make sure the firmware is stopped */
3463*4882a593Smuzhiyun 	usleep_range(3000, 6000);
3464*4882a593Smuzhiyun 	ocp_write_word(tp, type, PLA_BP_BA, 0);
3465*4882a593Smuzhiyun }
3466*4882a593Smuzhiyun 
r8153_patch_request(struct r8152 * tp,bool request)3467*4882a593Smuzhiyun static int r8153_patch_request(struct r8152 *tp, bool request)
3468*4882a593Smuzhiyun {
3469*4882a593Smuzhiyun 	u16 data;
3470*4882a593Smuzhiyun 	int i;
3471*4882a593Smuzhiyun 
3472*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD);
3473*4882a593Smuzhiyun 	if (request)
3474*4882a593Smuzhiyun 		data |= PATCH_REQUEST;
3475*4882a593Smuzhiyun 	else
3476*4882a593Smuzhiyun 		data &= ~PATCH_REQUEST;
3477*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data);
3478*4882a593Smuzhiyun 
3479*4882a593Smuzhiyun 	for (i = 0; request && i < 5000; i++) {
3480*4882a593Smuzhiyun 		usleep_range(1000, 2000);
3481*4882a593Smuzhiyun 		if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)
3482*4882a593Smuzhiyun 			break;
3483*4882a593Smuzhiyun 	}
3484*4882a593Smuzhiyun 
3485*4882a593Smuzhiyun 	if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) {
3486*4882a593Smuzhiyun 		netif_err(tp, drv, tp->netdev, "patch request fail\n");
3487*4882a593Smuzhiyun 		r8153_patch_request(tp, false);
3488*4882a593Smuzhiyun 		return -ETIME;
3489*4882a593Smuzhiyun 	} else {
3490*4882a593Smuzhiyun 		return 0;
3491*4882a593Smuzhiyun 	}
3492*4882a593Smuzhiyun }
3493*4882a593Smuzhiyun 
r8153_pre_ram_code(struct r8152 * tp,u16 key_addr,u16 patch_key)3494*4882a593Smuzhiyun static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key)
3495*4882a593Smuzhiyun {
3496*4882a593Smuzhiyun 	if (r8153_patch_request(tp, true)) {
3497*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "patch request fail\n");
3498*4882a593Smuzhiyun 		return -ETIME;
3499*4882a593Smuzhiyun 	}
3500*4882a593Smuzhiyun 
3501*4882a593Smuzhiyun 	sram_write(tp, key_addr, patch_key);
3502*4882a593Smuzhiyun 	sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK);
3503*4882a593Smuzhiyun 
3504*4882a593Smuzhiyun 	return 0;
3505*4882a593Smuzhiyun }
3506*4882a593Smuzhiyun 
r8153_post_ram_code(struct r8152 * tp,u16 key_addr)3507*4882a593Smuzhiyun static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr)
3508*4882a593Smuzhiyun {
3509*4882a593Smuzhiyun 	u16 data;
3510*4882a593Smuzhiyun 
3511*4882a593Smuzhiyun 	sram_write(tp, 0x0000, 0x0000);
3512*4882a593Smuzhiyun 
3513*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_PHY_LOCK);
3514*4882a593Smuzhiyun 	data &= ~PATCH_LOCK;
3515*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_PHY_LOCK, data);
3516*4882a593Smuzhiyun 
3517*4882a593Smuzhiyun 	sram_write(tp, key_addr, 0x0000);
3518*4882a593Smuzhiyun 
3519*4882a593Smuzhiyun 	r8153_patch_request(tp, false);
3520*4882a593Smuzhiyun 
3521*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base);
3522*4882a593Smuzhiyun 
3523*4882a593Smuzhiyun 	return 0;
3524*4882a593Smuzhiyun }
3525*4882a593Smuzhiyun 
rtl8152_is_fw_phy_nc_ok(struct r8152 * tp,struct fw_phy_nc * phy)3526*4882a593Smuzhiyun static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy)
3527*4882a593Smuzhiyun {
3528*4882a593Smuzhiyun 	u32 length;
3529*4882a593Smuzhiyun 	u16 fw_offset, fw_reg, ba_reg, patch_en_addr, mode_reg, bp_start;
3530*4882a593Smuzhiyun 	bool rc = false;
3531*4882a593Smuzhiyun 
3532*4882a593Smuzhiyun 	switch (tp->version) {
3533*4882a593Smuzhiyun 	case RTL_VER_04:
3534*4882a593Smuzhiyun 	case RTL_VER_05:
3535*4882a593Smuzhiyun 	case RTL_VER_06:
3536*4882a593Smuzhiyun 		fw_reg = 0xa014;
3537*4882a593Smuzhiyun 		ba_reg = 0xa012;
3538*4882a593Smuzhiyun 		patch_en_addr = 0xa01a;
3539*4882a593Smuzhiyun 		mode_reg = 0xb820;
3540*4882a593Smuzhiyun 		bp_start = 0xa000;
3541*4882a593Smuzhiyun 		break;
3542*4882a593Smuzhiyun 	default:
3543*4882a593Smuzhiyun 		goto out;
3544*4882a593Smuzhiyun 	}
3545*4882a593Smuzhiyun 
3546*4882a593Smuzhiyun 	fw_offset = __le16_to_cpu(phy->fw_offset);
3547*4882a593Smuzhiyun 	if (fw_offset < sizeof(*phy)) {
3548*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "fw_offset too small\n");
3549*4882a593Smuzhiyun 		goto out;
3550*4882a593Smuzhiyun 	}
3551*4882a593Smuzhiyun 
3552*4882a593Smuzhiyun 	length = __le32_to_cpu(phy->blk_hdr.length);
3553*4882a593Smuzhiyun 	if (length < fw_offset) {
3554*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid fw_offset\n");
3555*4882a593Smuzhiyun 		goto out;
3556*4882a593Smuzhiyun 	}
3557*4882a593Smuzhiyun 
3558*4882a593Smuzhiyun 	length -= __le16_to_cpu(phy->fw_offset);
3559*4882a593Smuzhiyun 	if (!length || (length & 1)) {
3560*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid block length\n");
3561*4882a593Smuzhiyun 		goto out;
3562*4882a593Smuzhiyun 	}
3563*4882a593Smuzhiyun 
3564*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->fw_reg) != fw_reg) {
3565*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid register to load firmware\n");
3566*4882a593Smuzhiyun 		goto out;
3567*4882a593Smuzhiyun 	}
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->ba_reg) != ba_reg) {
3570*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid base address register\n");
3571*4882a593Smuzhiyun 		goto out;
3572*4882a593Smuzhiyun 	}
3573*4882a593Smuzhiyun 
3574*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->patch_en_addr) != patch_en_addr) {
3575*4882a593Smuzhiyun 		dev_err(&tp->intf->dev,
3576*4882a593Smuzhiyun 			"invalid patch mode enabled register\n");
3577*4882a593Smuzhiyun 		goto out;
3578*4882a593Smuzhiyun 	}
3579*4882a593Smuzhiyun 
3580*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->mode_reg) != mode_reg) {
3581*4882a593Smuzhiyun 		dev_err(&tp->intf->dev,
3582*4882a593Smuzhiyun 			"invalid register to switch the mode\n");
3583*4882a593Smuzhiyun 		goto out;
3584*4882a593Smuzhiyun 	}
3585*4882a593Smuzhiyun 
3586*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->bp_start) != bp_start) {
3587*4882a593Smuzhiyun 		dev_err(&tp->intf->dev,
3588*4882a593Smuzhiyun 			"invalid start register of break point\n");
3589*4882a593Smuzhiyun 		goto out;
3590*4882a593Smuzhiyun 	}
3591*4882a593Smuzhiyun 
3592*4882a593Smuzhiyun 	if (__le16_to_cpu(phy->bp_num) > 4) {
3593*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid break point number\n");
3594*4882a593Smuzhiyun 		goto out;
3595*4882a593Smuzhiyun 	}
3596*4882a593Smuzhiyun 
3597*4882a593Smuzhiyun 	rc = true;
3598*4882a593Smuzhiyun out:
3599*4882a593Smuzhiyun 	return rc;
3600*4882a593Smuzhiyun }
3601*4882a593Smuzhiyun 
rtl8152_is_fw_mac_ok(struct r8152 * tp,struct fw_mac * mac)3602*4882a593Smuzhiyun static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
3603*4882a593Smuzhiyun {
3604*4882a593Smuzhiyun 	u16 fw_reg, bp_ba_addr, bp_en_addr, bp_start, fw_offset;
3605*4882a593Smuzhiyun 	bool rc = false;
3606*4882a593Smuzhiyun 	u32 length, type;
3607*4882a593Smuzhiyun 	int i, max_bp;
3608*4882a593Smuzhiyun 
3609*4882a593Smuzhiyun 	type = __le32_to_cpu(mac->blk_hdr.type);
3610*4882a593Smuzhiyun 	if (type == RTL_FW_PLA) {
3611*4882a593Smuzhiyun 		switch (tp->version) {
3612*4882a593Smuzhiyun 		case RTL_VER_01:
3613*4882a593Smuzhiyun 		case RTL_VER_02:
3614*4882a593Smuzhiyun 		case RTL_VER_07:
3615*4882a593Smuzhiyun 			fw_reg = 0xf800;
3616*4882a593Smuzhiyun 			bp_ba_addr = PLA_BP_BA;
3617*4882a593Smuzhiyun 			bp_en_addr = 0;
3618*4882a593Smuzhiyun 			bp_start = PLA_BP_0;
3619*4882a593Smuzhiyun 			max_bp = 8;
3620*4882a593Smuzhiyun 			break;
3621*4882a593Smuzhiyun 		case RTL_VER_03:
3622*4882a593Smuzhiyun 		case RTL_VER_04:
3623*4882a593Smuzhiyun 		case RTL_VER_05:
3624*4882a593Smuzhiyun 		case RTL_VER_06:
3625*4882a593Smuzhiyun 		case RTL_VER_08:
3626*4882a593Smuzhiyun 		case RTL_VER_09:
3627*4882a593Smuzhiyun 			fw_reg = 0xf800;
3628*4882a593Smuzhiyun 			bp_ba_addr = PLA_BP_BA;
3629*4882a593Smuzhiyun 			bp_en_addr = PLA_BP_EN;
3630*4882a593Smuzhiyun 			bp_start = PLA_BP_0;
3631*4882a593Smuzhiyun 			max_bp = 8;
3632*4882a593Smuzhiyun 			break;
3633*4882a593Smuzhiyun 		default:
3634*4882a593Smuzhiyun 			goto out;
3635*4882a593Smuzhiyun 		}
3636*4882a593Smuzhiyun 	} else if (type == RTL_FW_USB) {
3637*4882a593Smuzhiyun 		switch (tp->version) {
3638*4882a593Smuzhiyun 		case RTL_VER_03:
3639*4882a593Smuzhiyun 		case RTL_VER_04:
3640*4882a593Smuzhiyun 		case RTL_VER_05:
3641*4882a593Smuzhiyun 		case RTL_VER_06:
3642*4882a593Smuzhiyun 			fw_reg = 0xf800;
3643*4882a593Smuzhiyun 			bp_ba_addr = USB_BP_BA;
3644*4882a593Smuzhiyun 			bp_en_addr = USB_BP_EN;
3645*4882a593Smuzhiyun 			bp_start = USB_BP_0;
3646*4882a593Smuzhiyun 			max_bp = 8;
3647*4882a593Smuzhiyun 			break;
3648*4882a593Smuzhiyun 		case RTL_VER_08:
3649*4882a593Smuzhiyun 		case RTL_VER_09:
3650*4882a593Smuzhiyun 			fw_reg = 0xe600;
3651*4882a593Smuzhiyun 			bp_ba_addr = USB_BP_BA;
3652*4882a593Smuzhiyun 			bp_en_addr = USB_BP2_EN;
3653*4882a593Smuzhiyun 			bp_start = USB_BP_0;
3654*4882a593Smuzhiyun 			max_bp = 16;
3655*4882a593Smuzhiyun 			break;
3656*4882a593Smuzhiyun 		case RTL_VER_01:
3657*4882a593Smuzhiyun 		case RTL_VER_02:
3658*4882a593Smuzhiyun 		case RTL_VER_07:
3659*4882a593Smuzhiyun 		default:
3660*4882a593Smuzhiyun 			goto out;
3661*4882a593Smuzhiyun 		}
3662*4882a593Smuzhiyun 	} else {
3663*4882a593Smuzhiyun 		goto out;
3664*4882a593Smuzhiyun 	}
3665*4882a593Smuzhiyun 
3666*4882a593Smuzhiyun 	fw_offset = __le16_to_cpu(mac->fw_offset);
3667*4882a593Smuzhiyun 	if (fw_offset < sizeof(*mac)) {
3668*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "fw_offset too small\n");
3669*4882a593Smuzhiyun 		goto out;
3670*4882a593Smuzhiyun 	}
3671*4882a593Smuzhiyun 
3672*4882a593Smuzhiyun 	length = __le32_to_cpu(mac->blk_hdr.length);
3673*4882a593Smuzhiyun 	if (length < fw_offset) {
3674*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid fw_offset\n");
3675*4882a593Smuzhiyun 		goto out;
3676*4882a593Smuzhiyun 	}
3677*4882a593Smuzhiyun 
3678*4882a593Smuzhiyun 	length -= fw_offset;
3679*4882a593Smuzhiyun 	if (length < 4 || (length & 3)) {
3680*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid block length\n");
3681*4882a593Smuzhiyun 		goto out;
3682*4882a593Smuzhiyun 	}
3683*4882a593Smuzhiyun 
3684*4882a593Smuzhiyun 	if (__le16_to_cpu(mac->fw_reg) != fw_reg) {
3685*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid register to load firmware\n");
3686*4882a593Smuzhiyun 		goto out;
3687*4882a593Smuzhiyun 	}
3688*4882a593Smuzhiyun 
3689*4882a593Smuzhiyun 	if (__le16_to_cpu(mac->bp_ba_addr) != bp_ba_addr) {
3690*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid base address register\n");
3691*4882a593Smuzhiyun 		goto out;
3692*4882a593Smuzhiyun 	}
3693*4882a593Smuzhiyun 
3694*4882a593Smuzhiyun 	if (__le16_to_cpu(mac->bp_en_addr) != bp_en_addr) {
3695*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid enabled mask register\n");
3696*4882a593Smuzhiyun 		goto out;
3697*4882a593Smuzhiyun 	}
3698*4882a593Smuzhiyun 
3699*4882a593Smuzhiyun 	if (__le16_to_cpu(mac->bp_start) != bp_start) {
3700*4882a593Smuzhiyun 		dev_err(&tp->intf->dev,
3701*4882a593Smuzhiyun 			"invalid start register of break point\n");
3702*4882a593Smuzhiyun 		goto out;
3703*4882a593Smuzhiyun 	}
3704*4882a593Smuzhiyun 
3705*4882a593Smuzhiyun 	if (__le16_to_cpu(mac->bp_num) > max_bp) {
3706*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "invalid break point number\n");
3707*4882a593Smuzhiyun 		goto out;
3708*4882a593Smuzhiyun 	}
3709*4882a593Smuzhiyun 
3710*4882a593Smuzhiyun 	for (i = __le16_to_cpu(mac->bp_num); i < max_bp; i++) {
3711*4882a593Smuzhiyun 		if (mac->bp[i]) {
3712*4882a593Smuzhiyun 			dev_err(&tp->intf->dev, "unused bp%u is not zero\n", i);
3713*4882a593Smuzhiyun 			goto out;
3714*4882a593Smuzhiyun 		}
3715*4882a593Smuzhiyun 	}
3716*4882a593Smuzhiyun 
3717*4882a593Smuzhiyun 	rc = true;
3718*4882a593Smuzhiyun out:
3719*4882a593Smuzhiyun 	return rc;
3720*4882a593Smuzhiyun }
3721*4882a593Smuzhiyun 
3722*4882a593Smuzhiyun /* Verify the checksum for the firmware file. It is calculated from the version
3723*4882a593Smuzhiyun  * field to the end of the file. Compare the result with the checksum field to
3724*4882a593Smuzhiyun  * make sure the file is correct.
3725*4882a593Smuzhiyun  */
rtl8152_fw_verify_checksum(struct r8152 * tp,struct fw_header * fw_hdr,size_t size)3726*4882a593Smuzhiyun static long rtl8152_fw_verify_checksum(struct r8152 *tp,
3727*4882a593Smuzhiyun 				       struct fw_header *fw_hdr, size_t size)
3728*4882a593Smuzhiyun {
3729*4882a593Smuzhiyun 	unsigned char checksum[sizeof(fw_hdr->checksum)];
3730*4882a593Smuzhiyun 	struct crypto_shash *alg;
3731*4882a593Smuzhiyun 	struct shash_desc *sdesc;
3732*4882a593Smuzhiyun 	size_t len;
3733*4882a593Smuzhiyun 	long rc;
3734*4882a593Smuzhiyun 
3735*4882a593Smuzhiyun 	alg = crypto_alloc_shash("sha256", 0, 0);
3736*4882a593Smuzhiyun 	if (IS_ERR(alg)) {
3737*4882a593Smuzhiyun 		rc = PTR_ERR(alg);
3738*4882a593Smuzhiyun 		goto out;
3739*4882a593Smuzhiyun 	}
3740*4882a593Smuzhiyun 
3741*4882a593Smuzhiyun 	if (crypto_shash_digestsize(alg) != sizeof(fw_hdr->checksum)) {
3742*4882a593Smuzhiyun 		rc = -EFAULT;
3743*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "digestsize incorrect (%u)\n",
3744*4882a593Smuzhiyun 			crypto_shash_digestsize(alg));
3745*4882a593Smuzhiyun 		goto free_shash;
3746*4882a593Smuzhiyun 	}
3747*4882a593Smuzhiyun 
3748*4882a593Smuzhiyun 	len = sizeof(*sdesc) + crypto_shash_descsize(alg);
3749*4882a593Smuzhiyun 	sdesc = kmalloc(len, GFP_KERNEL);
3750*4882a593Smuzhiyun 	if (!sdesc) {
3751*4882a593Smuzhiyun 		rc = -ENOMEM;
3752*4882a593Smuzhiyun 		goto free_shash;
3753*4882a593Smuzhiyun 	}
3754*4882a593Smuzhiyun 	sdesc->tfm = alg;
3755*4882a593Smuzhiyun 
3756*4882a593Smuzhiyun 	len = size - sizeof(fw_hdr->checksum);
3757*4882a593Smuzhiyun 	rc = crypto_shash_digest(sdesc, fw_hdr->version, len, checksum);
3758*4882a593Smuzhiyun 	kfree(sdesc);
3759*4882a593Smuzhiyun 	if (rc)
3760*4882a593Smuzhiyun 		goto free_shash;
3761*4882a593Smuzhiyun 
3762*4882a593Smuzhiyun 	if (memcmp(fw_hdr->checksum, checksum, sizeof(fw_hdr->checksum))) {
3763*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "checksum fail\n");
3764*4882a593Smuzhiyun 		rc = -EFAULT;
3765*4882a593Smuzhiyun 	}
3766*4882a593Smuzhiyun 
3767*4882a593Smuzhiyun free_shash:
3768*4882a593Smuzhiyun 	crypto_free_shash(alg);
3769*4882a593Smuzhiyun out:
3770*4882a593Smuzhiyun 	return rc;
3771*4882a593Smuzhiyun }
3772*4882a593Smuzhiyun 
rtl8152_check_firmware(struct r8152 * tp,struct rtl_fw * rtl_fw)3773*4882a593Smuzhiyun static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw)
3774*4882a593Smuzhiyun {
3775*4882a593Smuzhiyun 	const struct firmware *fw = rtl_fw->fw;
3776*4882a593Smuzhiyun 	struct fw_header *fw_hdr = (struct fw_header *)fw->data;
3777*4882a593Smuzhiyun 	struct fw_mac *pla = NULL, *usb = NULL;
3778*4882a593Smuzhiyun 	struct fw_phy_patch_key *start = NULL;
3779*4882a593Smuzhiyun 	struct fw_phy_nc *phy_nc = NULL;
3780*4882a593Smuzhiyun 	struct fw_block *stop = NULL;
3781*4882a593Smuzhiyun 	long ret = -EFAULT;
3782*4882a593Smuzhiyun 	int i;
3783*4882a593Smuzhiyun 
3784*4882a593Smuzhiyun 	if (fw->size < sizeof(*fw_hdr)) {
3785*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "file too small\n");
3786*4882a593Smuzhiyun 		goto fail;
3787*4882a593Smuzhiyun 	}
3788*4882a593Smuzhiyun 
3789*4882a593Smuzhiyun 	ret = rtl8152_fw_verify_checksum(tp, fw_hdr, fw->size);
3790*4882a593Smuzhiyun 	if (ret)
3791*4882a593Smuzhiyun 		goto fail;
3792*4882a593Smuzhiyun 
3793*4882a593Smuzhiyun 	ret = -EFAULT;
3794*4882a593Smuzhiyun 
3795*4882a593Smuzhiyun 	for (i = sizeof(*fw_hdr); i < fw->size;) {
3796*4882a593Smuzhiyun 		struct fw_block *block = (struct fw_block *)&fw->data[i];
3797*4882a593Smuzhiyun 		u32 type;
3798*4882a593Smuzhiyun 
3799*4882a593Smuzhiyun 		if ((i + sizeof(*block)) > fw->size)
3800*4882a593Smuzhiyun 			goto fail;
3801*4882a593Smuzhiyun 
3802*4882a593Smuzhiyun 		type = __le32_to_cpu(block->type);
3803*4882a593Smuzhiyun 		switch (type) {
3804*4882a593Smuzhiyun 		case RTL_FW_END:
3805*4882a593Smuzhiyun 			if (__le32_to_cpu(block->length) != sizeof(*block))
3806*4882a593Smuzhiyun 				goto fail;
3807*4882a593Smuzhiyun 			goto fw_end;
3808*4882a593Smuzhiyun 		case RTL_FW_PLA:
3809*4882a593Smuzhiyun 			if (pla) {
3810*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3811*4882a593Smuzhiyun 					"multiple PLA firmware encountered");
3812*4882a593Smuzhiyun 				goto fail;
3813*4882a593Smuzhiyun 			}
3814*4882a593Smuzhiyun 
3815*4882a593Smuzhiyun 			pla = (struct fw_mac *)block;
3816*4882a593Smuzhiyun 			if (!rtl8152_is_fw_mac_ok(tp, pla)) {
3817*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3818*4882a593Smuzhiyun 					"check PLA firmware failed\n");
3819*4882a593Smuzhiyun 				goto fail;
3820*4882a593Smuzhiyun 			}
3821*4882a593Smuzhiyun 			break;
3822*4882a593Smuzhiyun 		case RTL_FW_USB:
3823*4882a593Smuzhiyun 			if (usb) {
3824*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3825*4882a593Smuzhiyun 					"multiple USB firmware encountered");
3826*4882a593Smuzhiyun 				goto fail;
3827*4882a593Smuzhiyun 			}
3828*4882a593Smuzhiyun 
3829*4882a593Smuzhiyun 			usb = (struct fw_mac *)block;
3830*4882a593Smuzhiyun 			if (!rtl8152_is_fw_mac_ok(tp, usb)) {
3831*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3832*4882a593Smuzhiyun 					"check USB firmware failed\n");
3833*4882a593Smuzhiyun 				goto fail;
3834*4882a593Smuzhiyun 			}
3835*4882a593Smuzhiyun 			break;
3836*4882a593Smuzhiyun 		case RTL_FW_PHY_START:
3837*4882a593Smuzhiyun 			if (start || phy_nc || stop) {
3838*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3839*4882a593Smuzhiyun 					"check PHY_START fail\n");
3840*4882a593Smuzhiyun 				goto fail;
3841*4882a593Smuzhiyun 			}
3842*4882a593Smuzhiyun 
3843*4882a593Smuzhiyun 			if (__le32_to_cpu(block->length) != sizeof(*start)) {
3844*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3845*4882a593Smuzhiyun 					"Invalid length for PHY_START\n");
3846*4882a593Smuzhiyun 				goto fail;
3847*4882a593Smuzhiyun 			}
3848*4882a593Smuzhiyun 
3849*4882a593Smuzhiyun 			start = (struct fw_phy_patch_key *)block;
3850*4882a593Smuzhiyun 			break;
3851*4882a593Smuzhiyun 		case RTL_FW_PHY_STOP:
3852*4882a593Smuzhiyun 			if (stop || !start) {
3853*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3854*4882a593Smuzhiyun 					"Check PHY_STOP fail\n");
3855*4882a593Smuzhiyun 				goto fail;
3856*4882a593Smuzhiyun 			}
3857*4882a593Smuzhiyun 
3858*4882a593Smuzhiyun 			if (__le32_to_cpu(block->length) != sizeof(*block)) {
3859*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3860*4882a593Smuzhiyun 					"Invalid length for PHY_STOP\n");
3861*4882a593Smuzhiyun 				goto fail;
3862*4882a593Smuzhiyun 			}
3863*4882a593Smuzhiyun 
3864*4882a593Smuzhiyun 			stop = block;
3865*4882a593Smuzhiyun 			break;
3866*4882a593Smuzhiyun 		case RTL_FW_PHY_NC:
3867*4882a593Smuzhiyun 			if (!start || stop) {
3868*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3869*4882a593Smuzhiyun 					"check PHY_NC fail\n");
3870*4882a593Smuzhiyun 				goto fail;
3871*4882a593Smuzhiyun 			}
3872*4882a593Smuzhiyun 
3873*4882a593Smuzhiyun 			if (phy_nc) {
3874*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3875*4882a593Smuzhiyun 					"multiple PHY NC encountered\n");
3876*4882a593Smuzhiyun 				goto fail;
3877*4882a593Smuzhiyun 			}
3878*4882a593Smuzhiyun 
3879*4882a593Smuzhiyun 			phy_nc = (struct fw_phy_nc *)block;
3880*4882a593Smuzhiyun 			if (!rtl8152_is_fw_phy_nc_ok(tp, phy_nc)) {
3881*4882a593Smuzhiyun 				dev_err(&tp->intf->dev,
3882*4882a593Smuzhiyun 					"check PHY NC firmware failed\n");
3883*4882a593Smuzhiyun 				goto fail;
3884*4882a593Smuzhiyun 			}
3885*4882a593Smuzhiyun 
3886*4882a593Smuzhiyun 			break;
3887*4882a593Smuzhiyun 		default:
3888*4882a593Smuzhiyun 			dev_warn(&tp->intf->dev, "Unknown type %u is found\n",
3889*4882a593Smuzhiyun 				 type);
3890*4882a593Smuzhiyun 			break;
3891*4882a593Smuzhiyun 		}
3892*4882a593Smuzhiyun 
3893*4882a593Smuzhiyun 		/* next block */
3894*4882a593Smuzhiyun 		i += ALIGN(__le32_to_cpu(block->length), 8);
3895*4882a593Smuzhiyun 	}
3896*4882a593Smuzhiyun 
3897*4882a593Smuzhiyun fw_end:
3898*4882a593Smuzhiyun 	if ((phy_nc || start) && !stop) {
3899*4882a593Smuzhiyun 		dev_err(&tp->intf->dev, "without PHY_STOP\n");
3900*4882a593Smuzhiyun 		goto fail;
3901*4882a593Smuzhiyun 	}
3902*4882a593Smuzhiyun 
3903*4882a593Smuzhiyun 	return 0;
3904*4882a593Smuzhiyun fail:
3905*4882a593Smuzhiyun 	return ret;
3906*4882a593Smuzhiyun }
3907*4882a593Smuzhiyun 
rtl8152_fw_phy_nc_apply(struct r8152 * tp,struct fw_phy_nc * phy)3908*4882a593Smuzhiyun static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy)
3909*4882a593Smuzhiyun {
3910*4882a593Smuzhiyun 	u16 mode_reg, bp_index;
3911*4882a593Smuzhiyun 	u32 length, i, num;
3912*4882a593Smuzhiyun 	__le16 *data;
3913*4882a593Smuzhiyun 
3914*4882a593Smuzhiyun 	mode_reg = __le16_to_cpu(phy->mode_reg);
3915*4882a593Smuzhiyun 	sram_write(tp, mode_reg, __le16_to_cpu(phy->mode_pre));
3916*4882a593Smuzhiyun 	sram_write(tp, __le16_to_cpu(phy->ba_reg),
3917*4882a593Smuzhiyun 		   __le16_to_cpu(phy->ba_data));
3918*4882a593Smuzhiyun 
3919*4882a593Smuzhiyun 	length = __le32_to_cpu(phy->blk_hdr.length);
3920*4882a593Smuzhiyun 	length -= __le16_to_cpu(phy->fw_offset);
3921*4882a593Smuzhiyun 	num = length / 2;
3922*4882a593Smuzhiyun 	data = (__le16 *)((u8 *)phy + __le16_to_cpu(phy->fw_offset));
3923*4882a593Smuzhiyun 
3924*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_SRAM_ADDR, __le16_to_cpu(phy->fw_reg));
3925*4882a593Smuzhiyun 	for (i = 0; i < num; i++)
3926*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_SRAM_DATA, __le16_to_cpu(data[i]));
3927*4882a593Smuzhiyun 
3928*4882a593Smuzhiyun 	sram_write(tp, __le16_to_cpu(phy->patch_en_addr),
3929*4882a593Smuzhiyun 		   __le16_to_cpu(phy->patch_en_value));
3930*4882a593Smuzhiyun 
3931*4882a593Smuzhiyun 	bp_index = __le16_to_cpu(phy->bp_start);
3932*4882a593Smuzhiyun 	num = __le16_to_cpu(phy->bp_num);
3933*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
3934*4882a593Smuzhiyun 		sram_write(tp, bp_index, __le16_to_cpu(phy->bp[i]));
3935*4882a593Smuzhiyun 		bp_index += 2;
3936*4882a593Smuzhiyun 	}
3937*4882a593Smuzhiyun 
3938*4882a593Smuzhiyun 	sram_write(tp, mode_reg, __le16_to_cpu(phy->mode_post));
3939*4882a593Smuzhiyun 
3940*4882a593Smuzhiyun 	dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info);
3941*4882a593Smuzhiyun }
3942*4882a593Smuzhiyun 
rtl8152_fw_mac_apply(struct r8152 * tp,struct fw_mac * mac)3943*4882a593Smuzhiyun static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac)
3944*4882a593Smuzhiyun {
3945*4882a593Smuzhiyun 	u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg;
3946*4882a593Smuzhiyun 	u32 length;
3947*4882a593Smuzhiyun 	u8 *data;
3948*4882a593Smuzhiyun 	int i;
3949*4882a593Smuzhiyun 
3950*4882a593Smuzhiyun 	switch (__le32_to_cpu(mac->blk_hdr.type)) {
3951*4882a593Smuzhiyun 	case RTL_FW_PLA:
3952*4882a593Smuzhiyun 		type = MCU_TYPE_PLA;
3953*4882a593Smuzhiyun 		break;
3954*4882a593Smuzhiyun 	case RTL_FW_USB:
3955*4882a593Smuzhiyun 		type = MCU_TYPE_USB;
3956*4882a593Smuzhiyun 		break;
3957*4882a593Smuzhiyun 	default:
3958*4882a593Smuzhiyun 		return;
3959*4882a593Smuzhiyun 	}
3960*4882a593Smuzhiyun 
3961*4882a593Smuzhiyun 	rtl_clear_bp(tp, type);
3962*4882a593Smuzhiyun 
3963*4882a593Smuzhiyun 	/* Enable backup/restore of MACDBG. This is required after clearing PLA
3964*4882a593Smuzhiyun 	 * break points and before applying the PLA firmware.
3965*4882a593Smuzhiyun 	 */
3966*4882a593Smuzhiyun 	if (tp->version == RTL_VER_04 && type == MCU_TYPE_PLA &&
3967*4882a593Smuzhiyun 	    !(ocp_read_word(tp, MCU_TYPE_PLA, PLA_MACDBG_POST) & DEBUG_OE)) {
3968*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MACDBG_PRE, DEBUG_LTSSM);
3969*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MACDBG_POST, DEBUG_LTSSM);
3970*4882a593Smuzhiyun 	}
3971*4882a593Smuzhiyun 
3972*4882a593Smuzhiyun 	length = __le32_to_cpu(mac->blk_hdr.length);
3973*4882a593Smuzhiyun 	length -= __le16_to_cpu(mac->fw_offset);
3974*4882a593Smuzhiyun 
3975*4882a593Smuzhiyun 	data = (u8 *)mac;
3976*4882a593Smuzhiyun 	data += __le16_to_cpu(mac->fw_offset);
3977*4882a593Smuzhiyun 
3978*4882a593Smuzhiyun 	generic_ocp_write(tp, __le16_to_cpu(mac->fw_reg), 0xff, length, data,
3979*4882a593Smuzhiyun 			  type);
3980*4882a593Smuzhiyun 
3981*4882a593Smuzhiyun 	ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr),
3982*4882a593Smuzhiyun 		       __le16_to_cpu(mac->bp_ba_value));
3983*4882a593Smuzhiyun 
3984*4882a593Smuzhiyun 	bp_index = __le16_to_cpu(mac->bp_start);
3985*4882a593Smuzhiyun 	bp_num = __le16_to_cpu(mac->bp_num);
3986*4882a593Smuzhiyun 	for (i = 0; i < bp_num; i++) {
3987*4882a593Smuzhiyun 		ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i]));
3988*4882a593Smuzhiyun 		bp_index += 2;
3989*4882a593Smuzhiyun 	}
3990*4882a593Smuzhiyun 
3991*4882a593Smuzhiyun 	bp_en_addr = __le16_to_cpu(mac->bp_en_addr);
3992*4882a593Smuzhiyun 	if (bp_en_addr)
3993*4882a593Smuzhiyun 		ocp_write_word(tp, type, bp_en_addr,
3994*4882a593Smuzhiyun 			       __le16_to_cpu(mac->bp_en_value));
3995*4882a593Smuzhiyun 
3996*4882a593Smuzhiyun 	fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg);
3997*4882a593Smuzhiyun 	if (fw_ver_reg)
3998*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, fw_ver_reg,
3999*4882a593Smuzhiyun 			       mac->fw_ver_data);
4000*4882a593Smuzhiyun 
4001*4882a593Smuzhiyun 	dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info);
4002*4882a593Smuzhiyun }
4003*4882a593Smuzhiyun 
rtl8152_apply_firmware(struct r8152 * tp)4004*4882a593Smuzhiyun static void rtl8152_apply_firmware(struct r8152 *tp)
4005*4882a593Smuzhiyun {
4006*4882a593Smuzhiyun 	struct rtl_fw *rtl_fw = &tp->rtl_fw;
4007*4882a593Smuzhiyun 	const struct firmware *fw;
4008*4882a593Smuzhiyun 	struct fw_header *fw_hdr;
4009*4882a593Smuzhiyun 	struct fw_phy_patch_key *key;
4010*4882a593Smuzhiyun 	u16 key_addr = 0;
4011*4882a593Smuzhiyun 	int i;
4012*4882a593Smuzhiyun 
4013*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(rtl_fw->fw))
4014*4882a593Smuzhiyun 		return;
4015*4882a593Smuzhiyun 
4016*4882a593Smuzhiyun 	fw = rtl_fw->fw;
4017*4882a593Smuzhiyun 	fw_hdr = (struct fw_header *)fw->data;
4018*4882a593Smuzhiyun 
4019*4882a593Smuzhiyun 	if (rtl_fw->pre_fw)
4020*4882a593Smuzhiyun 		rtl_fw->pre_fw(tp);
4021*4882a593Smuzhiyun 
4022*4882a593Smuzhiyun 	for (i = offsetof(struct fw_header, blocks); i < fw->size;) {
4023*4882a593Smuzhiyun 		struct fw_block *block = (struct fw_block *)&fw->data[i];
4024*4882a593Smuzhiyun 
4025*4882a593Smuzhiyun 		switch (__le32_to_cpu(block->type)) {
4026*4882a593Smuzhiyun 		case RTL_FW_END:
4027*4882a593Smuzhiyun 			goto post_fw;
4028*4882a593Smuzhiyun 		case RTL_FW_PLA:
4029*4882a593Smuzhiyun 		case RTL_FW_USB:
4030*4882a593Smuzhiyun 			rtl8152_fw_mac_apply(tp, (struct fw_mac *)block);
4031*4882a593Smuzhiyun 			break;
4032*4882a593Smuzhiyun 		case RTL_FW_PHY_START:
4033*4882a593Smuzhiyun 			key = (struct fw_phy_patch_key *)block;
4034*4882a593Smuzhiyun 			key_addr = __le16_to_cpu(key->key_reg);
4035*4882a593Smuzhiyun 			r8153_pre_ram_code(tp, key_addr,
4036*4882a593Smuzhiyun 					   __le16_to_cpu(key->key_data));
4037*4882a593Smuzhiyun 			break;
4038*4882a593Smuzhiyun 		case RTL_FW_PHY_STOP:
4039*4882a593Smuzhiyun 			WARN_ON(!key_addr);
4040*4882a593Smuzhiyun 			r8153_post_ram_code(tp, key_addr);
4041*4882a593Smuzhiyun 			break;
4042*4882a593Smuzhiyun 		case RTL_FW_PHY_NC:
4043*4882a593Smuzhiyun 			rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block);
4044*4882a593Smuzhiyun 			break;
4045*4882a593Smuzhiyun 		default:
4046*4882a593Smuzhiyun 			break;
4047*4882a593Smuzhiyun 		}
4048*4882a593Smuzhiyun 
4049*4882a593Smuzhiyun 		i += ALIGN(__le32_to_cpu(block->length), 8);
4050*4882a593Smuzhiyun 	}
4051*4882a593Smuzhiyun 
4052*4882a593Smuzhiyun post_fw:
4053*4882a593Smuzhiyun 	if (rtl_fw->post_fw)
4054*4882a593Smuzhiyun 		rtl_fw->post_fw(tp);
4055*4882a593Smuzhiyun 
4056*4882a593Smuzhiyun 	strscpy(rtl_fw->version, fw_hdr->version, RTL_VER_SIZE);
4057*4882a593Smuzhiyun 	dev_info(&tp->intf->dev, "load %s successfully\n", rtl_fw->version);
4058*4882a593Smuzhiyun }
4059*4882a593Smuzhiyun 
rtl8152_release_firmware(struct r8152 * tp)4060*4882a593Smuzhiyun static void rtl8152_release_firmware(struct r8152 *tp)
4061*4882a593Smuzhiyun {
4062*4882a593Smuzhiyun 	struct rtl_fw *rtl_fw = &tp->rtl_fw;
4063*4882a593Smuzhiyun 
4064*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(rtl_fw->fw)) {
4065*4882a593Smuzhiyun 		release_firmware(rtl_fw->fw);
4066*4882a593Smuzhiyun 		rtl_fw->fw = NULL;
4067*4882a593Smuzhiyun 	}
4068*4882a593Smuzhiyun }
4069*4882a593Smuzhiyun 
rtl8152_request_firmware(struct r8152 * tp)4070*4882a593Smuzhiyun static int rtl8152_request_firmware(struct r8152 *tp)
4071*4882a593Smuzhiyun {
4072*4882a593Smuzhiyun 	struct rtl_fw *rtl_fw = &tp->rtl_fw;
4073*4882a593Smuzhiyun 	long rc;
4074*4882a593Smuzhiyun 
4075*4882a593Smuzhiyun 	if (rtl_fw->fw || !rtl_fw->fw_name) {
4076*4882a593Smuzhiyun 		dev_info(&tp->intf->dev, "skip request firmware\n");
4077*4882a593Smuzhiyun 		rc = 0;
4078*4882a593Smuzhiyun 		goto result;
4079*4882a593Smuzhiyun 	}
4080*4882a593Smuzhiyun 
4081*4882a593Smuzhiyun 	rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, &tp->intf->dev);
4082*4882a593Smuzhiyun 	if (rc < 0)
4083*4882a593Smuzhiyun 		goto result;
4084*4882a593Smuzhiyun 
4085*4882a593Smuzhiyun 	rc = rtl8152_check_firmware(tp, rtl_fw);
4086*4882a593Smuzhiyun 	if (rc < 0)
4087*4882a593Smuzhiyun 		release_firmware(rtl_fw->fw);
4088*4882a593Smuzhiyun 
4089*4882a593Smuzhiyun result:
4090*4882a593Smuzhiyun 	if (rc) {
4091*4882a593Smuzhiyun 		rtl_fw->fw = ERR_PTR(rc);
4092*4882a593Smuzhiyun 
4093*4882a593Smuzhiyun 		dev_warn(&tp->intf->dev,
4094*4882a593Smuzhiyun 			 "unable to load firmware patch %s (%ld)\n",
4095*4882a593Smuzhiyun 			 rtl_fw->fw_name, rc);
4096*4882a593Smuzhiyun 	}
4097*4882a593Smuzhiyun 
4098*4882a593Smuzhiyun 	return rc;
4099*4882a593Smuzhiyun }
4100*4882a593Smuzhiyun 
r8152_aldps_en(struct r8152 * tp,bool enable)4101*4882a593Smuzhiyun static void r8152_aldps_en(struct r8152 *tp, bool enable)
4102*4882a593Smuzhiyun {
4103*4882a593Smuzhiyun 	if (enable) {
4104*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
4105*4882a593Smuzhiyun 						    LINKENA | DIS_SDSAVE);
4106*4882a593Smuzhiyun 	} else {
4107*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA |
4108*4882a593Smuzhiyun 						    DIS_SDSAVE);
4109*4882a593Smuzhiyun 		msleep(20);
4110*4882a593Smuzhiyun 	}
4111*4882a593Smuzhiyun }
4112*4882a593Smuzhiyun 
r8152_mmd_indirect(struct r8152 * tp,u16 dev,u16 reg)4113*4882a593Smuzhiyun static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg)
4114*4882a593Smuzhiyun {
4115*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_AR, FUN_ADDR | dev);
4116*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_DATA, reg);
4117*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_AR, FUN_DATA | dev);
4118*4882a593Smuzhiyun }
4119*4882a593Smuzhiyun 
r8152_mmd_read(struct r8152 * tp,u16 dev,u16 reg)4120*4882a593Smuzhiyun static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)
4121*4882a593Smuzhiyun {
4122*4882a593Smuzhiyun 	u16 data;
4123*4882a593Smuzhiyun 
4124*4882a593Smuzhiyun 	r8152_mmd_indirect(tp, dev, reg);
4125*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_EEE_DATA);
4126*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
4127*4882a593Smuzhiyun 
4128*4882a593Smuzhiyun 	return data;
4129*4882a593Smuzhiyun }
4130*4882a593Smuzhiyun 
r8152_mmd_write(struct r8152 * tp,u16 dev,u16 reg,u16 data)4131*4882a593Smuzhiyun static void r8152_mmd_write(struct r8152 *tp, u16 dev, u16 reg, u16 data)
4132*4882a593Smuzhiyun {
4133*4882a593Smuzhiyun 	r8152_mmd_indirect(tp, dev, reg);
4134*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_DATA, data);
4135*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
4136*4882a593Smuzhiyun }
4137*4882a593Smuzhiyun 
r8152_eee_en(struct r8152 * tp,bool enable)4138*4882a593Smuzhiyun static void r8152_eee_en(struct r8152 *tp, bool enable)
4139*4882a593Smuzhiyun {
4140*4882a593Smuzhiyun 	u16 config1, config2, config3;
4141*4882a593Smuzhiyun 	u32 ocp_data;
4142*4882a593Smuzhiyun 
4143*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
4144*4882a593Smuzhiyun 	config1 = ocp_reg_read(tp, OCP_EEE_CONFIG1) & ~sd_rise_time_mask;
4145*4882a593Smuzhiyun 	config2 = ocp_reg_read(tp, OCP_EEE_CONFIG2);
4146*4882a593Smuzhiyun 	config3 = ocp_reg_read(tp, OCP_EEE_CONFIG3) & ~fast_snr_mask;
4147*4882a593Smuzhiyun 
4148*4882a593Smuzhiyun 	if (enable) {
4149*4882a593Smuzhiyun 		ocp_data |= EEE_RX_EN | EEE_TX_EN;
4150*4882a593Smuzhiyun 		config1 |= EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN | RX_QUIET_EN;
4151*4882a593Smuzhiyun 		config1 |= sd_rise_time(1);
4152*4882a593Smuzhiyun 		config2 |= RG_DACQUIET_EN | RG_LDVQUIET_EN;
4153*4882a593Smuzhiyun 		config3 |= fast_snr(42);
4154*4882a593Smuzhiyun 	} else {
4155*4882a593Smuzhiyun 		ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
4156*4882a593Smuzhiyun 		config1 &= ~(EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN |
4157*4882a593Smuzhiyun 			     RX_QUIET_EN);
4158*4882a593Smuzhiyun 		config1 |= sd_rise_time(7);
4159*4882a593Smuzhiyun 		config2 &= ~(RG_DACQUIET_EN | RG_LDVQUIET_EN);
4160*4882a593Smuzhiyun 		config3 |= fast_snr(511);
4161*4882a593Smuzhiyun 	}
4162*4882a593Smuzhiyun 
4163*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
4164*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_CONFIG1, config1);
4165*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_CONFIG2, config2);
4166*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_CONFIG3, config3);
4167*4882a593Smuzhiyun }
4168*4882a593Smuzhiyun 
r8153_eee_en(struct r8152 * tp,bool enable)4169*4882a593Smuzhiyun static void r8153_eee_en(struct r8152 *tp, bool enable)
4170*4882a593Smuzhiyun {
4171*4882a593Smuzhiyun 	u32 ocp_data;
4172*4882a593Smuzhiyun 	u16 config;
4173*4882a593Smuzhiyun 
4174*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
4175*4882a593Smuzhiyun 	config = ocp_reg_read(tp, OCP_EEE_CFG);
4176*4882a593Smuzhiyun 
4177*4882a593Smuzhiyun 	if (enable) {
4178*4882a593Smuzhiyun 		ocp_data |= EEE_RX_EN | EEE_TX_EN;
4179*4882a593Smuzhiyun 		config |= EEE10_EN;
4180*4882a593Smuzhiyun 	} else {
4181*4882a593Smuzhiyun 		ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
4182*4882a593Smuzhiyun 		config &= ~EEE10_EN;
4183*4882a593Smuzhiyun 	}
4184*4882a593Smuzhiyun 
4185*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
4186*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_EEE_CFG, config);
4187*4882a593Smuzhiyun 
4188*4882a593Smuzhiyun 	tp->ups_info.eee = enable;
4189*4882a593Smuzhiyun }
4190*4882a593Smuzhiyun 
rtl_eee_enable(struct r8152 * tp,bool enable)4191*4882a593Smuzhiyun static void rtl_eee_enable(struct r8152 *tp, bool enable)
4192*4882a593Smuzhiyun {
4193*4882a593Smuzhiyun 	switch (tp->version) {
4194*4882a593Smuzhiyun 	case RTL_VER_01:
4195*4882a593Smuzhiyun 	case RTL_VER_02:
4196*4882a593Smuzhiyun 	case RTL_VER_07:
4197*4882a593Smuzhiyun 		if (enable) {
4198*4882a593Smuzhiyun 			r8152_eee_en(tp, true);
4199*4882a593Smuzhiyun 			r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
4200*4882a593Smuzhiyun 					tp->eee_adv);
4201*4882a593Smuzhiyun 		} else {
4202*4882a593Smuzhiyun 			r8152_eee_en(tp, false);
4203*4882a593Smuzhiyun 			r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
4204*4882a593Smuzhiyun 		}
4205*4882a593Smuzhiyun 		break;
4206*4882a593Smuzhiyun 	case RTL_VER_03:
4207*4882a593Smuzhiyun 	case RTL_VER_04:
4208*4882a593Smuzhiyun 	case RTL_VER_05:
4209*4882a593Smuzhiyun 	case RTL_VER_06:
4210*4882a593Smuzhiyun 	case RTL_VER_08:
4211*4882a593Smuzhiyun 	case RTL_VER_09:
4212*4882a593Smuzhiyun 		if (enable) {
4213*4882a593Smuzhiyun 			r8153_eee_en(tp, true);
4214*4882a593Smuzhiyun 			ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv);
4215*4882a593Smuzhiyun 		} else {
4216*4882a593Smuzhiyun 			r8153_eee_en(tp, false);
4217*4882a593Smuzhiyun 			ocp_reg_write(tp, OCP_EEE_ADV, 0);
4218*4882a593Smuzhiyun 		}
4219*4882a593Smuzhiyun 		break;
4220*4882a593Smuzhiyun 	default:
4221*4882a593Smuzhiyun 		break;
4222*4882a593Smuzhiyun 	}
4223*4882a593Smuzhiyun }
4224*4882a593Smuzhiyun 
r8152b_enable_fc(struct r8152 * tp)4225*4882a593Smuzhiyun static void r8152b_enable_fc(struct r8152 *tp)
4226*4882a593Smuzhiyun {
4227*4882a593Smuzhiyun 	u16 anar;
4228*4882a593Smuzhiyun 
4229*4882a593Smuzhiyun 	anar = r8152_mdio_read(tp, MII_ADVERTISE);
4230*4882a593Smuzhiyun 	anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
4231*4882a593Smuzhiyun 	r8152_mdio_write(tp, MII_ADVERTISE, anar);
4232*4882a593Smuzhiyun 
4233*4882a593Smuzhiyun 	tp->ups_info.flow_control = true;
4234*4882a593Smuzhiyun }
4235*4882a593Smuzhiyun 
rtl8152_disable(struct r8152 * tp)4236*4882a593Smuzhiyun static void rtl8152_disable(struct r8152 *tp)
4237*4882a593Smuzhiyun {
4238*4882a593Smuzhiyun 	r8152_aldps_en(tp, false);
4239*4882a593Smuzhiyun 	rtl_disable(tp);
4240*4882a593Smuzhiyun 	r8152_aldps_en(tp, true);
4241*4882a593Smuzhiyun }
4242*4882a593Smuzhiyun 
r8152b_hw_phy_cfg(struct r8152 * tp)4243*4882a593Smuzhiyun static void r8152b_hw_phy_cfg(struct r8152 *tp)
4244*4882a593Smuzhiyun {
4245*4882a593Smuzhiyun 	rtl8152_apply_firmware(tp);
4246*4882a593Smuzhiyun 	rtl_eee_enable(tp, tp->eee_en);
4247*4882a593Smuzhiyun 	r8152_aldps_en(tp, true);
4248*4882a593Smuzhiyun 	r8152b_enable_fc(tp);
4249*4882a593Smuzhiyun 
4250*4882a593Smuzhiyun 	set_bit(PHY_RESET, &tp->flags);
4251*4882a593Smuzhiyun }
4252*4882a593Smuzhiyun 
wait_oob_link_list_ready(struct r8152 * tp)4253*4882a593Smuzhiyun static void wait_oob_link_list_ready(struct r8152 *tp)
4254*4882a593Smuzhiyun {
4255*4882a593Smuzhiyun 	u32 ocp_data;
4256*4882a593Smuzhiyun 	int i;
4257*4882a593Smuzhiyun 
4258*4882a593Smuzhiyun 	for (i = 0; i < 1000; i++) {
4259*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4260*4882a593Smuzhiyun 		if (ocp_data & LINK_LIST_READY)
4261*4882a593Smuzhiyun 			break;
4262*4882a593Smuzhiyun 		usleep_range(1000, 2000);
4263*4882a593Smuzhiyun 	}
4264*4882a593Smuzhiyun }
4265*4882a593Smuzhiyun 
r8152b_exit_oob(struct r8152 * tp)4266*4882a593Smuzhiyun static void r8152b_exit_oob(struct r8152 *tp)
4267*4882a593Smuzhiyun {
4268*4882a593Smuzhiyun 	u32 ocp_data;
4269*4882a593Smuzhiyun 
4270*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
4271*4882a593Smuzhiyun 	ocp_data &= ~RCR_ACPT_ALL;
4272*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
4273*4882a593Smuzhiyun 
4274*4882a593Smuzhiyun 	rxdy_gated_en(tp, true);
4275*4882a593Smuzhiyun 	r8153_teredo_off(tp);
4276*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
4277*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00);
4278*4882a593Smuzhiyun 
4279*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4280*4882a593Smuzhiyun 	ocp_data &= ~NOW_IS_OOB;
4281*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4282*4882a593Smuzhiyun 
4283*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4284*4882a593Smuzhiyun 	ocp_data &= ~MCU_BORW_EN;
4285*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4286*4882a593Smuzhiyun 
4287*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4288*4882a593Smuzhiyun 
4289*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4290*4882a593Smuzhiyun 	ocp_data |= RE_INIT_LL;
4291*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4292*4882a593Smuzhiyun 
4293*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4294*4882a593Smuzhiyun 
4295*4882a593Smuzhiyun 	rtl8152_nic_reset(tp);
4296*4882a593Smuzhiyun 
4297*4882a593Smuzhiyun 	/* rx share fifo credit full threshold */
4298*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
4299*4882a593Smuzhiyun 
4300*4882a593Smuzhiyun 	if (tp->udev->speed == USB_SPEED_FULL ||
4301*4882a593Smuzhiyun 	    tp->udev->speed == USB_SPEED_LOW) {
4302*4882a593Smuzhiyun 		/* rx share fifo credit near full threshold */
4303*4882a593Smuzhiyun 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
4304*4882a593Smuzhiyun 				RXFIFO_THR2_FULL);
4305*4882a593Smuzhiyun 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
4306*4882a593Smuzhiyun 				RXFIFO_THR3_FULL);
4307*4882a593Smuzhiyun 	} else {
4308*4882a593Smuzhiyun 		/* rx share fifo credit near full threshold */
4309*4882a593Smuzhiyun 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
4310*4882a593Smuzhiyun 				RXFIFO_THR2_HIGH);
4311*4882a593Smuzhiyun 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
4312*4882a593Smuzhiyun 				RXFIFO_THR3_HIGH);
4313*4882a593Smuzhiyun 	}
4314*4882a593Smuzhiyun 
4315*4882a593Smuzhiyun 	/* TX share fifo free credit full threshold */
4316*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
4317*4882a593Smuzhiyun 
4318*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
4319*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
4320*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
4321*4882a593Smuzhiyun 			TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
4322*4882a593Smuzhiyun 
4323*4882a593Smuzhiyun 	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
4324*4882a593Smuzhiyun 
4325*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
4326*4882a593Smuzhiyun 
4327*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
4328*4882a593Smuzhiyun 	ocp_data |= TCR0_AUTO_FIFO;
4329*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
4330*4882a593Smuzhiyun }
4331*4882a593Smuzhiyun 
r8152b_enter_oob(struct r8152 * tp)4332*4882a593Smuzhiyun static void r8152b_enter_oob(struct r8152 *tp)
4333*4882a593Smuzhiyun {
4334*4882a593Smuzhiyun 	u32 ocp_data;
4335*4882a593Smuzhiyun 
4336*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4337*4882a593Smuzhiyun 	ocp_data &= ~NOW_IS_OOB;
4338*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4339*4882a593Smuzhiyun 
4340*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
4341*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
4342*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
4343*4882a593Smuzhiyun 
4344*4882a593Smuzhiyun 	rtl_disable(tp);
4345*4882a593Smuzhiyun 
4346*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4347*4882a593Smuzhiyun 
4348*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4349*4882a593Smuzhiyun 	ocp_data |= RE_INIT_LL;
4350*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4351*4882a593Smuzhiyun 
4352*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4353*4882a593Smuzhiyun 
4354*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
4355*4882a593Smuzhiyun 
4356*4882a593Smuzhiyun 	rtl_rx_vlan_en(tp, true);
4357*4882a593Smuzhiyun 
4358*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
4359*4882a593Smuzhiyun 	ocp_data |= ALDPS_PROXY_MODE;
4360*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
4361*4882a593Smuzhiyun 
4362*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4363*4882a593Smuzhiyun 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
4364*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4365*4882a593Smuzhiyun 
4366*4882a593Smuzhiyun 	rxdy_gated_en(tp, false);
4367*4882a593Smuzhiyun 
4368*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
4369*4882a593Smuzhiyun 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
4370*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
4371*4882a593Smuzhiyun }
4372*4882a593Smuzhiyun 
r8153_pre_firmware_1(struct r8152 * tp)4373*4882a593Smuzhiyun static int r8153_pre_firmware_1(struct r8152 *tp)
4374*4882a593Smuzhiyun {
4375*4882a593Smuzhiyun 	int i;
4376*4882a593Smuzhiyun 
4377*4882a593Smuzhiyun 	/* Wait till the WTD timer is ready. It would take at most 104 ms. */
4378*4882a593Smuzhiyun 	for (i = 0; i < 104; i++) {
4379*4882a593Smuzhiyun 		u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_WDT1_CTRL);
4380*4882a593Smuzhiyun 
4381*4882a593Smuzhiyun 		if (!(ocp_data & WTD1_EN))
4382*4882a593Smuzhiyun 			break;
4383*4882a593Smuzhiyun 		usleep_range(1000, 2000);
4384*4882a593Smuzhiyun 	}
4385*4882a593Smuzhiyun 
4386*4882a593Smuzhiyun 	return 0;
4387*4882a593Smuzhiyun }
4388*4882a593Smuzhiyun 
r8153_post_firmware_1(struct r8152 * tp)4389*4882a593Smuzhiyun static int r8153_post_firmware_1(struct r8152 *tp)
4390*4882a593Smuzhiyun {
4391*4882a593Smuzhiyun 	/* set USB_BP_4 to support USB_SPEED_SUPER only */
4392*4882a593Smuzhiyun 	if (ocp_read_byte(tp, MCU_TYPE_USB, USB_CSTMR) & FORCE_SUPER)
4393*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_4, BP4_SUPER_ONLY);
4394*4882a593Smuzhiyun 
4395*4882a593Smuzhiyun 	/* reset UPHY timer to 36 ms */
4396*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_UPHY_TIMER, 36000 / 16);
4397*4882a593Smuzhiyun 
4398*4882a593Smuzhiyun 	return 0;
4399*4882a593Smuzhiyun }
4400*4882a593Smuzhiyun 
r8153_pre_firmware_2(struct r8152 * tp)4401*4882a593Smuzhiyun static int r8153_pre_firmware_2(struct r8152 *tp)
4402*4882a593Smuzhiyun {
4403*4882a593Smuzhiyun 	u32 ocp_data;
4404*4882a593Smuzhiyun 
4405*4882a593Smuzhiyun 	r8153_pre_firmware_1(tp);
4406*4882a593Smuzhiyun 
4407*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN0);
4408*4882a593Smuzhiyun 	ocp_data &= ~FW_FIX_SUSPEND;
4409*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN0, ocp_data);
4410*4882a593Smuzhiyun 
4411*4882a593Smuzhiyun 	return 0;
4412*4882a593Smuzhiyun }
4413*4882a593Smuzhiyun 
r8153_post_firmware_2(struct r8152 * tp)4414*4882a593Smuzhiyun static int r8153_post_firmware_2(struct r8152 *tp)
4415*4882a593Smuzhiyun {
4416*4882a593Smuzhiyun 	u32 ocp_data;
4417*4882a593Smuzhiyun 
4418*4882a593Smuzhiyun 	/* enable bp0 if support USB_SPEED_SUPER only */
4419*4882a593Smuzhiyun 	if (ocp_read_byte(tp, MCU_TYPE_USB, USB_CSTMR) & FORCE_SUPER) {
4420*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BP_EN);
4421*4882a593Smuzhiyun 		ocp_data |= BIT(0);
4422*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, ocp_data);
4423*4882a593Smuzhiyun 	}
4424*4882a593Smuzhiyun 
4425*4882a593Smuzhiyun 	/* reset UPHY timer to 36 ms */
4426*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_UPHY_TIMER, 36000 / 16);
4427*4882a593Smuzhiyun 
4428*4882a593Smuzhiyun 	/* enable U3P3 check, set the counter to 4 */
4429*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, U3P3_CHECK_EN | 4);
4430*4882a593Smuzhiyun 
4431*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN0);
4432*4882a593Smuzhiyun 	ocp_data |= FW_FIX_SUSPEND;
4433*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN0, ocp_data);
4434*4882a593Smuzhiyun 
4435*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY);
4436*4882a593Smuzhiyun 	ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND;
4437*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data);
4438*4882a593Smuzhiyun 
4439*4882a593Smuzhiyun 	return 0;
4440*4882a593Smuzhiyun }
4441*4882a593Smuzhiyun 
r8153_post_firmware_3(struct r8152 * tp)4442*4882a593Smuzhiyun static int r8153_post_firmware_3(struct r8152 *tp)
4443*4882a593Smuzhiyun {
4444*4882a593Smuzhiyun 	u32 ocp_data;
4445*4882a593Smuzhiyun 
4446*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY);
4447*4882a593Smuzhiyun 	ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND;
4448*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data);
4449*4882a593Smuzhiyun 
4450*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1);
4451*4882a593Smuzhiyun 	ocp_data |= FW_IP_RESET_EN;
4452*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1, ocp_data);
4453*4882a593Smuzhiyun 
4454*4882a593Smuzhiyun 	return 0;
4455*4882a593Smuzhiyun }
4456*4882a593Smuzhiyun 
r8153b_pre_firmware_1(struct r8152 * tp)4457*4882a593Smuzhiyun static int r8153b_pre_firmware_1(struct r8152 *tp)
4458*4882a593Smuzhiyun {
4459*4882a593Smuzhiyun 	/* enable fc timer and set timer to 1 second. */
4460*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER,
4461*4882a593Smuzhiyun 		       CTRL_TIMER_EN | (1000 / 8));
4462*4882a593Smuzhiyun 
4463*4882a593Smuzhiyun 	return 0;
4464*4882a593Smuzhiyun }
4465*4882a593Smuzhiyun 
r8153b_post_firmware_1(struct r8152 * tp)4466*4882a593Smuzhiyun static int r8153b_post_firmware_1(struct r8152 *tp)
4467*4882a593Smuzhiyun {
4468*4882a593Smuzhiyun 	u32 ocp_data;
4469*4882a593Smuzhiyun 
4470*4882a593Smuzhiyun 	/* enable bp0 for RTL8153-BND */
4471*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
4472*4882a593Smuzhiyun 	if (ocp_data & BND_MASK) {
4473*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BP_EN);
4474*4882a593Smuzhiyun 		ocp_data |= BIT(0);
4475*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, ocp_data);
4476*4882a593Smuzhiyun 	}
4477*4882a593Smuzhiyun 
4478*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL);
4479*4882a593Smuzhiyun 	ocp_data |= FLOW_CTRL_PATCH_OPT;
4480*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data);
4481*4882a593Smuzhiyun 
4482*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
4483*4882a593Smuzhiyun 	ocp_data |= FC_PATCH_TASK;
4484*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
4485*4882a593Smuzhiyun 
4486*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1);
4487*4882a593Smuzhiyun 	ocp_data |= FW_IP_RESET_EN;
4488*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1, ocp_data);
4489*4882a593Smuzhiyun 
4490*4882a593Smuzhiyun 	return 0;
4491*4882a593Smuzhiyun }
4492*4882a593Smuzhiyun 
r8153_aldps_en(struct r8152 * tp,bool enable)4493*4882a593Smuzhiyun static void r8153_aldps_en(struct r8152 *tp, bool enable)
4494*4882a593Smuzhiyun {
4495*4882a593Smuzhiyun 	u16 data;
4496*4882a593Smuzhiyun 
4497*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_POWER_CFG);
4498*4882a593Smuzhiyun 	if (enable) {
4499*4882a593Smuzhiyun 		data |= EN_ALDPS;
4500*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_POWER_CFG, data);
4501*4882a593Smuzhiyun 	} else {
4502*4882a593Smuzhiyun 		int i;
4503*4882a593Smuzhiyun 
4504*4882a593Smuzhiyun 		data &= ~EN_ALDPS;
4505*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_POWER_CFG, data);
4506*4882a593Smuzhiyun 		for (i = 0; i < 20; i++) {
4507*4882a593Smuzhiyun 			usleep_range(1000, 2000);
4508*4882a593Smuzhiyun 			if (ocp_read_word(tp, MCU_TYPE_PLA, 0xe000) & 0x0100)
4509*4882a593Smuzhiyun 				break;
4510*4882a593Smuzhiyun 		}
4511*4882a593Smuzhiyun 	}
4512*4882a593Smuzhiyun 
4513*4882a593Smuzhiyun 	tp->ups_info.aldps = enable;
4514*4882a593Smuzhiyun }
4515*4882a593Smuzhiyun 
r8153_hw_phy_cfg(struct r8152 * tp)4516*4882a593Smuzhiyun static void r8153_hw_phy_cfg(struct r8152 *tp)
4517*4882a593Smuzhiyun {
4518*4882a593Smuzhiyun 	u32 ocp_data;
4519*4882a593Smuzhiyun 	u16 data;
4520*4882a593Smuzhiyun 
4521*4882a593Smuzhiyun 	/* disable ALDPS before updating the PHY parameters */
4522*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
4523*4882a593Smuzhiyun 
4524*4882a593Smuzhiyun 	/* disable EEE before updating the PHY parameters */
4525*4882a593Smuzhiyun 	rtl_eee_enable(tp, false);
4526*4882a593Smuzhiyun 
4527*4882a593Smuzhiyun 	rtl8152_apply_firmware(tp);
4528*4882a593Smuzhiyun 
4529*4882a593Smuzhiyun 	if (tp->version == RTL_VER_03) {
4530*4882a593Smuzhiyun 		data = ocp_reg_read(tp, OCP_EEE_CFG);
4531*4882a593Smuzhiyun 		data &= ~CTAP_SHORT_EN;
4532*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_EEE_CFG, data);
4533*4882a593Smuzhiyun 	}
4534*4882a593Smuzhiyun 
4535*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_POWER_CFG);
4536*4882a593Smuzhiyun 	data |= EEE_CLKDIV_EN;
4537*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_POWER_CFG, data);
4538*4882a593Smuzhiyun 
4539*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_DOWN_SPEED);
4540*4882a593Smuzhiyun 	data |= EN_10M_BGOFF;
4541*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_DOWN_SPEED, data);
4542*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_POWER_CFG);
4543*4882a593Smuzhiyun 	data |= EN_10M_PLLOFF;
4544*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_POWER_CFG, data);
4545*4882a593Smuzhiyun 	sram_write(tp, SRAM_IMPEDANCE, 0x0b13);
4546*4882a593Smuzhiyun 
4547*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
4548*4882a593Smuzhiyun 	ocp_data |= PFM_PWM_SWITCH;
4549*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
4550*4882a593Smuzhiyun 
4551*4882a593Smuzhiyun 	/* Enable LPF corner auto tune */
4552*4882a593Smuzhiyun 	sram_write(tp, SRAM_LPF_CFG, 0xf70f);
4553*4882a593Smuzhiyun 
4554*4882a593Smuzhiyun 	/* Adjust 10M Amplitude */
4555*4882a593Smuzhiyun 	sram_write(tp, SRAM_10M_AMP1, 0x00af);
4556*4882a593Smuzhiyun 	sram_write(tp, SRAM_10M_AMP2, 0x0208);
4557*4882a593Smuzhiyun 
4558*4882a593Smuzhiyun 	if (tp->eee_en)
4559*4882a593Smuzhiyun 		rtl_eee_enable(tp, true);
4560*4882a593Smuzhiyun 
4561*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
4562*4882a593Smuzhiyun 	r8152b_enable_fc(tp);
4563*4882a593Smuzhiyun 
4564*4882a593Smuzhiyun 	switch (tp->version) {
4565*4882a593Smuzhiyun 	case RTL_VER_03:
4566*4882a593Smuzhiyun 	case RTL_VER_04:
4567*4882a593Smuzhiyun 		break;
4568*4882a593Smuzhiyun 	case RTL_VER_05:
4569*4882a593Smuzhiyun 	case RTL_VER_06:
4570*4882a593Smuzhiyun 	default:
4571*4882a593Smuzhiyun 		r8153_u2p3en(tp, true);
4572*4882a593Smuzhiyun 		break;
4573*4882a593Smuzhiyun 	}
4574*4882a593Smuzhiyun 
4575*4882a593Smuzhiyun 	set_bit(PHY_RESET, &tp->flags);
4576*4882a593Smuzhiyun }
4577*4882a593Smuzhiyun 
r8152_efuse_read(struct r8152 * tp,u8 addr)4578*4882a593Smuzhiyun static u32 r8152_efuse_read(struct r8152 *tp, u8 addr)
4579*4882a593Smuzhiyun {
4580*4882a593Smuzhiyun 	u32 ocp_data;
4581*4882a593Smuzhiyun 
4582*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD, EFUSE_READ_CMD | addr);
4583*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD);
4584*4882a593Smuzhiyun 	ocp_data = (ocp_data & EFUSE_DATA_BIT16) << 9;	/* data of bit16 */
4585*4882a593Smuzhiyun 	ocp_data |= ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_DATA);
4586*4882a593Smuzhiyun 
4587*4882a593Smuzhiyun 	return ocp_data;
4588*4882a593Smuzhiyun }
4589*4882a593Smuzhiyun 
r8153b_hw_phy_cfg(struct r8152 * tp)4590*4882a593Smuzhiyun static void r8153b_hw_phy_cfg(struct r8152 *tp)
4591*4882a593Smuzhiyun {
4592*4882a593Smuzhiyun 	u32 ocp_data;
4593*4882a593Smuzhiyun 	u16 data;
4594*4882a593Smuzhiyun 
4595*4882a593Smuzhiyun 	/* disable ALDPS before updating the PHY parameters */
4596*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
4597*4882a593Smuzhiyun 
4598*4882a593Smuzhiyun 	/* disable EEE before updating the PHY parameters */
4599*4882a593Smuzhiyun 	rtl_eee_enable(tp, false);
4600*4882a593Smuzhiyun 
4601*4882a593Smuzhiyun 	rtl8152_apply_firmware(tp);
4602*4882a593Smuzhiyun 
4603*4882a593Smuzhiyun 	r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
4604*4882a593Smuzhiyun 
4605*4882a593Smuzhiyun 	data = sram_read(tp, SRAM_GREEN_CFG);
4606*4882a593Smuzhiyun 	data |= R_TUNE_EN;
4607*4882a593Smuzhiyun 	sram_write(tp, SRAM_GREEN_CFG, data);
4608*4882a593Smuzhiyun 	data = ocp_reg_read(tp, OCP_NCTL_CFG);
4609*4882a593Smuzhiyun 	data |= PGA_RETURN_EN;
4610*4882a593Smuzhiyun 	ocp_reg_write(tp, OCP_NCTL_CFG, data);
4611*4882a593Smuzhiyun 
4612*4882a593Smuzhiyun 	/* ADC Bias Calibration:
4613*4882a593Smuzhiyun 	 * read efuse offset 0x7d to get a 17-bit data. Remove the dummy/fake
4614*4882a593Smuzhiyun 	 * bit (bit3) to rebuild the real 16-bit data. Write the data to the
4615*4882a593Smuzhiyun 	 * ADC ioffset.
4616*4882a593Smuzhiyun 	 */
4617*4882a593Smuzhiyun 	ocp_data = r8152_efuse_read(tp, 0x7d);
4618*4882a593Smuzhiyun 	data = (u16)(((ocp_data & 0x1fff0) >> 1) | (ocp_data & 0x7));
4619*4882a593Smuzhiyun 	if (data != 0xffff)
4620*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_ADC_IOFFSET, data);
4621*4882a593Smuzhiyun 
4622*4882a593Smuzhiyun 	/* ups mode tx-link-pulse timing adjustment:
4623*4882a593Smuzhiyun 	 * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]
4624*4882a593Smuzhiyun 	 * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt
4625*4882a593Smuzhiyun 	 */
4626*4882a593Smuzhiyun 	ocp_data = ocp_reg_read(tp, 0xc426);
4627*4882a593Smuzhiyun 	ocp_data &= 0x3fff;
4628*4882a593Smuzhiyun 	if (ocp_data) {
4629*4882a593Smuzhiyun 		u32 swr_cnt_1ms_ini;
4630*4882a593Smuzhiyun 
4631*4882a593Smuzhiyun 		swr_cnt_1ms_ini = (16000000 / ocp_data) & SAW_CNT_1MS_MASK;
4632*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG);
4633*4882a593Smuzhiyun 		ocp_data = (ocp_data & ~SAW_CNT_1MS_MASK) | swr_cnt_1ms_ini;
4634*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CFG, ocp_data);
4635*4882a593Smuzhiyun 	}
4636*4882a593Smuzhiyun 
4637*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
4638*4882a593Smuzhiyun 	ocp_data |= PFM_PWM_SWITCH;
4639*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
4640*4882a593Smuzhiyun 
4641*4882a593Smuzhiyun 	/* Advnace EEE */
4642*4882a593Smuzhiyun 	if (!r8153_patch_request(tp, true)) {
4643*4882a593Smuzhiyun 		data = ocp_reg_read(tp, OCP_POWER_CFG);
4644*4882a593Smuzhiyun 		data |= EEE_CLKDIV_EN;
4645*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_POWER_CFG, data);
4646*4882a593Smuzhiyun 		tp->ups_info.eee_ckdiv = true;
4647*4882a593Smuzhiyun 
4648*4882a593Smuzhiyun 		data = ocp_reg_read(tp, OCP_DOWN_SPEED);
4649*4882a593Smuzhiyun 		data |= EN_EEE_CMODE | EN_EEE_1000 | EN_10M_CLKDIV;
4650*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_DOWN_SPEED, data);
4651*4882a593Smuzhiyun 		tp->ups_info.eee_cmod_lv = true;
4652*4882a593Smuzhiyun 		tp->ups_info._10m_ckdiv = true;
4653*4882a593Smuzhiyun 		tp->ups_info.eee_plloff_giga = true;
4654*4882a593Smuzhiyun 
4655*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_SYSCLK_CFG, 0);
4656*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5));
4657*4882a593Smuzhiyun 		tp->ups_info._250m_ckdiv = true;
4658*4882a593Smuzhiyun 
4659*4882a593Smuzhiyun 		r8153_patch_request(tp, false);
4660*4882a593Smuzhiyun 	}
4661*4882a593Smuzhiyun 
4662*4882a593Smuzhiyun 	if (tp->eee_en)
4663*4882a593Smuzhiyun 		rtl_eee_enable(tp, true);
4664*4882a593Smuzhiyun 
4665*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
4666*4882a593Smuzhiyun 	r8152b_enable_fc(tp);
4667*4882a593Smuzhiyun 
4668*4882a593Smuzhiyun 	set_bit(PHY_RESET, &tp->flags);
4669*4882a593Smuzhiyun }
4670*4882a593Smuzhiyun 
r8153_first_init(struct r8152 * tp)4671*4882a593Smuzhiyun static void r8153_first_init(struct r8152 *tp)
4672*4882a593Smuzhiyun {
4673*4882a593Smuzhiyun 	u32 ocp_data;
4674*4882a593Smuzhiyun 
4675*4882a593Smuzhiyun 	rxdy_gated_en(tp, true);
4676*4882a593Smuzhiyun 	r8153_teredo_off(tp);
4677*4882a593Smuzhiyun 
4678*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
4679*4882a593Smuzhiyun 	ocp_data &= ~RCR_ACPT_ALL;
4680*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
4681*4882a593Smuzhiyun 
4682*4882a593Smuzhiyun 	rtl8152_nic_reset(tp);
4683*4882a593Smuzhiyun 	rtl_reset_bmu(tp);
4684*4882a593Smuzhiyun 
4685*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4686*4882a593Smuzhiyun 	ocp_data &= ~NOW_IS_OOB;
4687*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4688*4882a593Smuzhiyun 
4689*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4690*4882a593Smuzhiyun 	ocp_data &= ~MCU_BORW_EN;
4691*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4692*4882a593Smuzhiyun 
4693*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4694*4882a593Smuzhiyun 
4695*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4696*4882a593Smuzhiyun 	ocp_data |= RE_INIT_LL;
4697*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4698*4882a593Smuzhiyun 
4699*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4700*4882a593Smuzhiyun 
4701*4882a593Smuzhiyun 	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
4702*4882a593Smuzhiyun 
4703*4882a593Smuzhiyun 	ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
4704*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
4705*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
4706*4882a593Smuzhiyun 
4707*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
4708*4882a593Smuzhiyun 	ocp_data |= TCR0_AUTO_FIFO;
4709*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
4710*4882a593Smuzhiyun 
4711*4882a593Smuzhiyun 	rtl8152_nic_reset(tp);
4712*4882a593Smuzhiyun 
4713*4882a593Smuzhiyun 	/* rx share fifo credit full threshold */
4714*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
4715*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL);
4716*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL);
4717*4882a593Smuzhiyun 	/* TX share fifo free credit full threshold */
4718*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
4719*4882a593Smuzhiyun }
4720*4882a593Smuzhiyun 
r8153_enter_oob(struct r8152 * tp)4721*4882a593Smuzhiyun static void r8153_enter_oob(struct r8152 *tp)
4722*4882a593Smuzhiyun {
4723*4882a593Smuzhiyun 	u32 ocp_data;
4724*4882a593Smuzhiyun 
4725*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4726*4882a593Smuzhiyun 	ocp_data &= ~NOW_IS_OOB;
4727*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4728*4882a593Smuzhiyun 
4729*4882a593Smuzhiyun 	rtl_disable(tp);
4730*4882a593Smuzhiyun 	rtl_reset_bmu(tp);
4731*4882a593Smuzhiyun 
4732*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4733*4882a593Smuzhiyun 
4734*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
4735*4882a593Smuzhiyun 	ocp_data |= RE_INIT_LL;
4736*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
4737*4882a593Smuzhiyun 
4738*4882a593Smuzhiyun 	wait_oob_link_list_ready(tp);
4739*4882a593Smuzhiyun 
4740*4882a593Smuzhiyun 	ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
4741*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
4742*4882a593Smuzhiyun 
4743*4882a593Smuzhiyun 	switch (tp->version) {
4744*4882a593Smuzhiyun 	case RTL_VER_03:
4745*4882a593Smuzhiyun 	case RTL_VER_04:
4746*4882a593Smuzhiyun 	case RTL_VER_05:
4747*4882a593Smuzhiyun 	case RTL_VER_06:
4748*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
4749*4882a593Smuzhiyun 		ocp_data &= ~TEREDO_WAKE_MASK;
4750*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
4751*4882a593Smuzhiyun 		break;
4752*4882a593Smuzhiyun 
4753*4882a593Smuzhiyun 	case RTL_VER_08:
4754*4882a593Smuzhiyun 	case RTL_VER_09:
4755*4882a593Smuzhiyun 		/* Clear teredo wake event. bit[15:8] is the teredo wakeup
4756*4882a593Smuzhiyun 		 * type. Set it to zero. bits[7:0] are the W1C bits about
4757*4882a593Smuzhiyun 		 * the events. Set them to all 1 to clear them.
4758*4882a593Smuzhiyun 		 */
4759*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
4760*4882a593Smuzhiyun 		break;
4761*4882a593Smuzhiyun 
4762*4882a593Smuzhiyun 	default:
4763*4882a593Smuzhiyun 		break;
4764*4882a593Smuzhiyun 	}
4765*4882a593Smuzhiyun 
4766*4882a593Smuzhiyun 	rtl_rx_vlan_en(tp, true);
4767*4882a593Smuzhiyun 
4768*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
4769*4882a593Smuzhiyun 	ocp_data |= ALDPS_PROXY_MODE;
4770*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
4771*4882a593Smuzhiyun 
4772*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
4773*4882a593Smuzhiyun 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
4774*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
4775*4882a593Smuzhiyun 
4776*4882a593Smuzhiyun 	rxdy_gated_en(tp, false);
4777*4882a593Smuzhiyun 
4778*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
4779*4882a593Smuzhiyun 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
4780*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
4781*4882a593Smuzhiyun }
4782*4882a593Smuzhiyun 
rtl8153_disable(struct r8152 * tp)4783*4882a593Smuzhiyun static void rtl8153_disable(struct r8152 *tp)
4784*4882a593Smuzhiyun {
4785*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
4786*4882a593Smuzhiyun 	rtl_disable(tp);
4787*4882a593Smuzhiyun 	rtl_reset_bmu(tp);
4788*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
4789*4882a593Smuzhiyun }
4790*4882a593Smuzhiyun 
rtl8152_set_speed(struct r8152 * tp,u8 autoneg,u32 speed,u8 duplex,u32 advertising)4791*4882a593Smuzhiyun static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
4792*4882a593Smuzhiyun 			     u32 advertising)
4793*4882a593Smuzhiyun {
4794*4882a593Smuzhiyun 	u16 bmcr;
4795*4882a593Smuzhiyun 	int ret = 0;
4796*4882a593Smuzhiyun 
4797*4882a593Smuzhiyun 	if (autoneg == AUTONEG_DISABLE) {
4798*4882a593Smuzhiyun 		if (duplex != DUPLEX_HALF && duplex != DUPLEX_FULL)
4799*4882a593Smuzhiyun 			return -EINVAL;
4800*4882a593Smuzhiyun 
4801*4882a593Smuzhiyun 		switch (speed) {
4802*4882a593Smuzhiyun 		case SPEED_10:
4803*4882a593Smuzhiyun 			bmcr = BMCR_SPEED10;
4804*4882a593Smuzhiyun 			if (duplex == DUPLEX_FULL) {
4805*4882a593Smuzhiyun 				bmcr |= BMCR_FULLDPLX;
4806*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = FORCE_10M_FULL;
4807*4882a593Smuzhiyun 			} else {
4808*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = FORCE_10M_HALF;
4809*4882a593Smuzhiyun 			}
4810*4882a593Smuzhiyun 			break;
4811*4882a593Smuzhiyun 		case SPEED_100:
4812*4882a593Smuzhiyun 			bmcr = BMCR_SPEED100;
4813*4882a593Smuzhiyun 			if (duplex == DUPLEX_FULL) {
4814*4882a593Smuzhiyun 				bmcr |= BMCR_FULLDPLX;
4815*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = FORCE_100M_FULL;
4816*4882a593Smuzhiyun 			} else {
4817*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = FORCE_100M_HALF;
4818*4882a593Smuzhiyun 			}
4819*4882a593Smuzhiyun 			break;
4820*4882a593Smuzhiyun 		case SPEED_1000:
4821*4882a593Smuzhiyun 			if (tp->mii.supports_gmii) {
4822*4882a593Smuzhiyun 				bmcr = BMCR_SPEED1000 | BMCR_FULLDPLX;
4823*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = NWAY_1000M_FULL;
4824*4882a593Smuzhiyun 				break;
4825*4882a593Smuzhiyun 			}
4826*4882a593Smuzhiyun 			fallthrough;
4827*4882a593Smuzhiyun 		default:
4828*4882a593Smuzhiyun 			ret = -EINVAL;
4829*4882a593Smuzhiyun 			goto out;
4830*4882a593Smuzhiyun 		}
4831*4882a593Smuzhiyun 
4832*4882a593Smuzhiyun 		if (duplex == DUPLEX_FULL)
4833*4882a593Smuzhiyun 			tp->mii.full_duplex = 1;
4834*4882a593Smuzhiyun 		else
4835*4882a593Smuzhiyun 			tp->mii.full_duplex = 0;
4836*4882a593Smuzhiyun 
4837*4882a593Smuzhiyun 		tp->mii.force_media = 1;
4838*4882a593Smuzhiyun 	} else {
4839*4882a593Smuzhiyun 		u16 anar, tmp1;
4840*4882a593Smuzhiyun 		u32 support;
4841*4882a593Smuzhiyun 
4842*4882a593Smuzhiyun 		support = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL |
4843*4882a593Smuzhiyun 			  RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL;
4844*4882a593Smuzhiyun 
4845*4882a593Smuzhiyun 		if (tp->mii.supports_gmii)
4846*4882a593Smuzhiyun 			support |= RTL_ADVERTISED_1000_FULL;
4847*4882a593Smuzhiyun 
4848*4882a593Smuzhiyun 		if (!(advertising & support))
4849*4882a593Smuzhiyun 			return -EINVAL;
4850*4882a593Smuzhiyun 
4851*4882a593Smuzhiyun 		anar = r8152_mdio_read(tp, MII_ADVERTISE);
4852*4882a593Smuzhiyun 		tmp1 = anar & ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
4853*4882a593Smuzhiyun 				ADVERTISE_100HALF | ADVERTISE_100FULL);
4854*4882a593Smuzhiyun 		if (advertising & RTL_ADVERTISED_10_HALF) {
4855*4882a593Smuzhiyun 			tmp1 |= ADVERTISE_10HALF;
4856*4882a593Smuzhiyun 			tp->ups_info.speed_duplex = NWAY_10M_HALF;
4857*4882a593Smuzhiyun 		}
4858*4882a593Smuzhiyun 		if (advertising & RTL_ADVERTISED_10_FULL) {
4859*4882a593Smuzhiyun 			tmp1 |= ADVERTISE_10FULL;
4860*4882a593Smuzhiyun 			tp->ups_info.speed_duplex = NWAY_10M_FULL;
4861*4882a593Smuzhiyun 		}
4862*4882a593Smuzhiyun 
4863*4882a593Smuzhiyun 		if (advertising & RTL_ADVERTISED_100_HALF) {
4864*4882a593Smuzhiyun 			tmp1 |= ADVERTISE_100HALF;
4865*4882a593Smuzhiyun 			tp->ups_info.speed_duplex = NWAY_100M_HALF;
4866*4882a593Smuzhiyun 		}
4867*4882a593Smuzhiyun 		if (advertising & RTL_ADVERTISED_100_FULL) {
4868*4882a593Smuzhiyun 			tmp1 |= ADVERTISE_100FULL;
4869*4882a593Smuzhiyun 			tp->ups_info.speed_duplex = NWAY_100M_FULL;
4870*4882a593Smuzhiyun 		}
4871*4882a593Smuzhiyun 
4872*4882a593Smuzhiyun 		if (anar != tmp1) {
4873*4882a593Smuzhiyun 			r8152_mdio_write(tp, MII_ADVERTISE, tmp1);
4874*4882a593Smuzhiyun 			tp->mii.advertising = tmp1;
4875*4882a593Smuzhiyun 		}
4876*4882a593Smuzhiyun 
4877*4882a593Smuzhiyun 		if (tp->mii.supports_gmii) {
4878*4882a593Smuzhiyun 			u16 gbcr;
4879*4882a593Smuzhiyun 
4880*4882a593Smuzhiyun 			gbcr = r8152_mdio_read(tp, MII_CTRL1000);
4881*4882a593Smuzhiyun 			tmp1 = gbcr & ~(ADVERTISE_1000FULL |
4882*4882a593Smuzhiyun 					ADVERTISE_1000HALF);
4883*4882a593Smuzhiyun 
4884*4882a593Smuzhiyun 			if (advertising & RTL_ADVERTISED_1000_FULL) {
4885*4882a593Smuzhiyun 				tmp1 |= ADVERTISE_1000FULL;
4886*4882a593Smuzhiyun 				tp->ups_info.speed_duplex = NWAY_1000M_FULL;
4887*4882a593Smuzhiyun 			}
4888*4882a593Smuzhiyun 
4889*4882a593Smuzhiyun 			if (gbcr != tmp1)
4890*4882a593Smuzhiyun 				r8152_mdio_write(tp, MII_CTRL1000, tmp1);
4891*4882a593Smuzhiyun 		}
4892*4882a593Smuzhiyun 
4893*4882a593Smuzhiyun 		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
4894*4882a593Smuzhiyun 
4895*4882a593Smuzhiyun 		tp->mii.force_media = 0;
4896*4882a593Smuzhiyun 	}
4897*4882a593Smuzhiyun 
4898*4882a593Smuzhiyun 	if (test_and_clear_bit(PHY_RESET, &tp->flags))
4899*4882a593Smuzhiyun 		bmcr |= BMCR_RESET;
4900*4882a593Smuzhiyun 
4901*4882a593Smuzhiyun 	r8152_mdio_write(tp, MII_BMCR, bmcr);
4902*4882a593Smuzhiyun 
4903*4882a593Smuzhiyun 	if (bmcr & BMCR_RESET) {
4904*4882a593Smuzhiyun 		int i;
4905*4882a593Smuzhiyun 
4906*4882a593Smuzhiyun 		for (i = 0; i < 50; i++) {
4907*4882a593Smuzhiyun 			msleep(20);
4908*4882a593Smuzhiyun 			if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
4909*4882a593Smuzhiyun 				break;
4910*4882a593Smuzhiyun 		}
4911*4882a593Smuzhiyun 	}
4912*4882a593Smuzhiyun 
4913*4882a593Smuzhiyun out:
4914*4882a593Smuzhiyun 	return ret;
4915*4882a593Smuzhiyun }
4916*4882a593Smuzhiyun 
rtl8152_up(struct r8152 * tp)4917*4882a593Smuzhiyun static void rtl8152_up(struct r8152 *tp)
4918*4882a593Smuzhiyun {
4919*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
4920*4882a593Smuzhiyun 		return;
4921*4882a593Smuzhiyun 
4922*4882a593Smuzhiyun 	r8152_aldps_en(tp, false);
4923*4882a593Smuzhiyun 	r8152b_exit_oob(tp);
4924*4882a593Smuzhiyun 	r8152_aldps_en(tp, true);
4925*4882a593Smuzhiyun }
4926*4882a593Smuzhiyun 
rtl8152_down(struct r8152 * tp)4927*4882a593Smuzhiyun static void rtl8152_down(struct r8152 *tp)
4928*4882a593Smuzhiyun {
4929*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
4930*4882a593Smuzhiyun 		rtl_drop_queued_tx(tp);
4931*4882a593Smuzhiyun 		return;
4932*4882a593Smuzhiyun 	}
4933*4882a593Smuzhiyun 
4934*4882a593Smuzhiyun 	r8152_power_cut_en(tp, false);
4935*4882a593Smuzhiyun 	r8152_aldps_en(tp, false);
4936*4882a593Smuzhiyun 	r8152b_enter_oob(tp);
4937*4882a593Smuzhiyun 	r8152_aldps_en(tp, true);
4938*4882a593Smuzhiyun }
4939*4882a593Smuzhiyun 
rtl8153_up(struct r8152 * tp)4940*4882a593Smuzhiyun static void rtl8153_up(struct r8152 *tp)
4941*4882a593Smuzhiyun {
4942*4882a593Smuzhiyun 	u32 ocp_data;
4943*4882a593Smuzhiyun 
4944*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
4945*4882a593Smuzhiyun 		return;
4946*4882a593Smuzhiyun 
4947*4882a593Smuzhiyun 	r8153_u1u2en(tp, false);
4948*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
4949*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
4950*4882a593Smuzhiyun 	r8153_first_init(tp);
4951*4882a593Smuzhiyun 
4952*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
4953*4882a593Smuzhiyun 	ocp_data |= LANWAKE_CLR_EN;
4954*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
4955*4882a593Smuzhiyun 
4956*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
4957*4882a593Smuzhiyun 	ocp_data &= ~LANWAKE_PIN;
4958*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
4959*4882a593Smuzhiyun 
4960*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1);
4961*4882a593Smuzhiyun 	ocp_data &= ~DELAY_PHY_PWR_CHG;
4962*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1, ocp_data);
4963*4882a593Smuzhiyun 
4964*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
4965*4882a593Smuzhiyun 
4966*4882a593Smuzhiyun 	switch (tp->version) {
4967*4882a593Smuzhiyun 	case RTL_VER_03:
4968*4882a593Smuzhiyun 	case RTL_VER_04:
4969*4882a593Smuzhiyun 		break;
4970*4882a593Smuzhiyun 	case RTL_VER_05:
4971*4882a593Smuzhiyun 	case RTL_VER_06:
4972*4882a593Smuzhiyun 	default:
4973*4882a593Smuzhiyun 		r8153_u2p3en(tp, true);
4974*4882a593Smuzhiyun 		break;
4975*4882a593Smuzhiyun 	}
4976*4882a593Smuzhiyun 
4977*4882a593Smuzhiyun 	r8153_u1u2en(tp, true);
4978*4882a593Smuzhiyun }
4979*4882a593Smuzhiyun 
rtl8153_down(struct r8152 * tp)4980*4882a593Smuzhiyun static void rtl8153_down(struct r8152 *tp)
4981*4882a593Smuzhiyun {
4982*4882a593Smuzhiyun 	u32 ocp_data;
4983*4882a593Smuzhiyun 
4984*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
4985*4882a593Smuzhiyun 		rtl_drop_queued_tx(tp);
4986*4882a593Smuzhiyun 		return;
4987*4882a593Smuzhiyun 	}
4988*4882a593Smuzhiyun 
4989*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
4990*4882a593Smuzhiyun 	ocp_data &= ~LANWAKE_CLR_EN;
4991*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
4992*4882a593Smuzhiyun 
4993*4882a593Smuzhiyun 	r8153_u1u2en(tp, false);
4994*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
4995*4882a593Smuzhiyun 	r8153_power_cut_en(tp, false);
4996*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
4997*4882a593Smuzhiyun 	r8153_enter_oob(tp);
4998*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
4999*4882a593Smuzhiyun }
5000*4882a593Smuzhiyun 
rtl8153b_up(struct r8152 * tp)5001*4882a593Smuzhiyun static void rtl8153b_up(struct r8152 *tp)
5002*4882a593Smuzhiyun {
5003*4882a593Smuzhiyun 	u32 ocp_data;
5004*4882a593Smuzhiyun 
5005*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
5006*4882a593Smuzhiyun 		return;
5007*4882a593Smuzhiyun 
5008*4882a593Smuzhiyun 	r8153b_u1u2en(tp, false);
5009*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
5010*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
5011*4882a593Smuzhiyun 
5012*4882a593Smuzhiyun 	r8153_first_init(tp);
5013*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B);
5014*4882a593Smuzhiyun 
5015*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
5016*4882a593Smuzhiyun 	ocp_data &= ~PLA_MCU_SPDWN_EN;
5017*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
5018*4882a593Smuzhiyun 
5019*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
5020*4882a593Smuzhiyun 
5021*4882a593Smuzhiyun 	if (tp->udev->speed != USB_SPEED_HIGH)
5022*4882a593Smuzhiyun 		r8153b_u1u2en(tp, true);
5023*4882a593Smuzhiyun }
5024*4882a593Smuzhiyun 
rtl8153b_down(struct r8152 * tp)5025*4882a593Smuzhiyun static void rtl8153b_down(struct r8152 *tp)
5026*4882a593Smuzhiyun {
5027*4882a593Smuzhiyun 	u32 ocp_data;
5028*4882a593Smuzhiyun 
5029*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
5030*4882a593Smuzhiyun 		rtl_drop_queued_tx(tp);
5031*4882a593Smuzhiyun 		return;
5032*4882a593Smuzhiyun 	}
5033*4882a593Smuzhiyun 
5034*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
5035*4882a593Smuzhiyun 	ocp_data |= PLA_MCU_SPDWN_EN;
5036*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
5037*4882a593Smuzhiyun 
5038*4882a593Smuzhiyun 	r8153b_u1u2en(tp, false);
5039*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
5040*4882a593Smuzhiyun 	r8153b_power_cut_en(tp, false);
5041*4882a593Smuzhiyun 	r8153_aldps_en(tp, false);
5042*4882a593Smuzhiyun 	r8153_enter_oob(tp);
5043*4882a593Smuzhiyun 	r8153_aldps_en(tp, true);
5044*4882a593Smuzhiyun }
5045*4882a593Smuzhiyun 
rtl8152_in_nway(struct r8152 * tp)5046*4882a593Smuzhiyun static bool rtl8152_in_nway(struct r8152 *tp)
5047*4882a593Smuzhiyun {
5048*4882a593Smuzhiyun 	u16 nway_state;
5049*4882a593Smuzhiyun 
5050*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, 0x2000);
5051*4882a593Smuzhiyun 	tp->ocp_base = 0x2000;
5052*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, 0xb014, 0x4c);		/* phy state */
5053*4882a593Smuzhiyun 	nway_state = ocp_read_word(tp, MCU_TYPE_PLA, 0xb01a);
5054*4882a593Smuzhiyun 
5055*4882a593Smuzhiyun 	/* bit 15: TXDIS_STATE, bit 14: ABD_STATE */
5056*4882a593Smuzhiyun 	if (nway_state & 0xc000)
5057*4882a593Smuzhiyun 		return false;
5058*4882a593Smuzhiyun 	else
5059*4882a593Smuzhiyun 		return true;
5060*4882a593Smuzhiyun }
5061*4882a593Smuzhiyun 
rtl8153_in_nway(struct r8152 * tp)5062*4882a593Smuzhiyun static bool rtl8153_in_nway(struct r8152 *tp)
5063*4882a593Smuzhiyun {
5064*4882a593Smuzhiyun 	u16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) & 0xff;
5065*4882a593Smuzhiyun 
5066*4882a593Smuzhiyun 	if (phy_state == TXDIS_STATE || phy_state == ABD_STATE)
5067*4882a593Smuzhiyun 		return false;
5068*4882a593Smuzhiyun 	else
5069*4882a593Smuzhiyun 		return true;
5070*4882a593Smuzhiyun }
5071*4882a593Smuzhiyun 
set_carrier(struct r8152 * tp)5072*4882a593Smuzhiyun static void set_carrier(struct r8152 *tp)
5073*4882a593Smuzhiyun {
5074*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
5075*4882a593Smuzhiyun 	struct napi_struct *napi = &tp->napi;
5076*4882a593Smuzhiyun 	u8 speed;
5077*4882a593Smuzhiyun 
5078*4882a593Smuzhiyun 	speed = rtl8152_get_speed(tp);
5079*4882a593Smuzhiyun 
5080*4882a593Smuzhiyun 	if (speed & LINK_STATUS) {
5081*4882a593Smuzhiyun 		if (!netif_carrier_ok(netdev)) {
5082*4882a593Smuzhiyun 			tp->rtl_ops.enable(tp);
5083*4882a593Smuzhiyun 			netif_stop_queue(netdev);
5084*4882a593Smuzhiyun 			napi_disable(napi);
5085*4882a593Smuzhiyun 			netif_carrier_on(netdev);
5086*4882a593Smuzhiyun 			rtl_start_rx(tp);
5087*4882a593Smuzhiyun 			clear_bit(RTL8152_SET_RX_MODE, &tp->flags);
5088*4882a593Smuzhiyun 			_rtl8152_set_rx_mode(netdev);
5089*4882a593Smuzhiyun 			napi_enable(&tp->napi);
5090*4882a593Smuzhiyun 			netif_wake_queue(netdev);
5091*4882a593Smuzhiyun 			netif_info(tp, link, netdev, "carrier on\n");
5092*4882a593Smuzhiyun 		} else if (netif_queue_stopped(netdev) &&
5093*4882a593Smuzhiyun 			   skb_queue_len(&tp->tx_queue) < tp->tx_qlen) {
5094*4882a593Smuzhiyun 			netif_wake_queue(netdev);
5095*4882a593Smuzhiyun 		}
5096*4882a593Smuzhiyun 	} else {
5097*4882a593Smuzhiyun 		if (netif_carrier_ok(netdev)) {
5098*4882a593Smuzhiyun 			netif_carrier_off(netdev);
5099*4882a593Smuzhiyun 			tasklet_disable(&tp->tx_tl);
5100*4882a593Smuzhiyun 			napi_disable(napi);
5101*4882a593Smuzhiyun 			tp->rtl_ops.disable(tp);
5102*4882a593Smuzhiyun 			napi_enable(napi);
5103*4882a593Smuzhiyun 			tasklet_enable(&tp->tx_tl);
5104*4882a593Smuzhiyun 			netif_info(tp, link, netdev, "carrier off\n");
5105*4882a593Smuzhiyun 		}
5106*4882a593Smuzhiyun 	}
5107*4882a593Smuzhiyun }
5108*4882a593Smuzhiyun 
rtl_work_func_t(struct work_struct * work)5109*4882a593Smuzhiyun static void rtl_work_func_t(struct work_struct *work)
5110*4882a593Smuzhiyun {
5111*4882a593Smuzhiyun 	struct r8152 *tp = container_of(work, struct r8152, schedule.work);
5112*4882a593Smuzhiyun 
5113*4882a593Smuzhiyun 	/* If the device is unplugged or !netif_running(), the workqueue
5114*4882a593Smuzhiyun 	 * doesn't need to wake the device, and could return directly.
5115*4882a593Smuzhiyun 	 */
5116*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags) || !netif_running(tp->netdev))
5117*4882a593Smuzhiyun 		return;
5118*4882a593Smuzhiyun 
5119*4882a593Smuzhiyun 	if (usb_autopm_get_interface(tp->intf) < 0)
5120*4882a593Smuzhiyun 		return;
5121*4882a593Smuzhiyun 
5122*4882a593Smuzhiyun 	if (!test_bit(WORK_ENABLE, &tp->flags))
5123*4882a593Smuzhiyun 		goto out1;
5124*4882a593Smuzhiyun 
5125*4882a593Smuzhiyun 	if (!mutex_trylock(&tp->control)) {
5126*4882a593Smuzhiyun 		schedule_delayed_work(&tp->schedule, 0);
5127*4882a593Smuzhiyun 		goto out1;
5128*4882a593Smuzhiyun 	}
5129*4882a593Smuzhiyun 
5130*4882a593Smuzhiyun 	if (test_and_clear_bit(RTL8152_LINK_CHG, &tp->flags))
5131*4882a593Smuzhiyun 		set_carrier(tp);
5132*4882a593Smuzhiyun 
5133*4882a593Smuzhiyun 	if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags))
5134*4882a593Smuzhiyun 		_rtl8152_set_rx_mode(tp->netdev);
5135*4882a593Smuzhiyun 
5136*4882a593Smuzhiyun 	/* don't schedule tasket before linking */
5137*4882a593Smuzhiyun 	if (test_and_clear_bit(SCHEDULE_TASKLET, &tp->flags) &&
5138*4882a593Smuzhiyun 	    netif_carrier_ok(tp->netdev))
5139*4882a593Smuzhiyun 		tasklet_schedule(&tp->tx_tl);
5140*4882a593Smuzhiyun 
5141*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5142*4882a593Smuzhiyun 
5143*4882a593Smuzhiyun out1:
5144*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5145*4882a593Smuzhiyun }
5146*4882a593Smuzhiyun 
rtl_hw_phy_work_func_t(struct work_struct * work)5147*4882a593Smuzhiyun static void rtl_hw_phy_work_func_t(struct work_struct *work)
5148*4882a593Smuzhiyun {
5149*4882a593Smuzhiyun 	struct r8152 *tp = container_of(work, struct r8152, hw_phy_work.work);
5150*4882a593Smuzhiyun 
5151*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
5152*4882a593Smuzhiyun 		return;
5153*4882a593Smuzhiyun 
5154*4882a593Smuzhiyun 	if (usb_autopm_get_interface(tp->intf) < 0)
5155*4882a593Smuzhiyun 		return;
5156*4882a593Smuzhiyun 
5157*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5158*4882a593Smuzhiyun 
5159*4882a593Smuzhiyun 	if (rtl8152_request_firmware(tp) == -ENODEV && tp->rtl_fw.retry) {
5160*4882a593Smuzhiyun 		tp->rtl_fw.retry = false;
5161*4882a593Smuzhiyun 		tp->rtl_fw.fw = NULL;
5162*4882a593Smuzhiyun 
5163*4882a593Smuzhiyun 		/* Delay execution in case request_firmware() is not ready yet.
5164*4882a593Smuzhiyun 		 */
5165*4882a593Smuzhiyun 		queue_delayed_work(system_long_wq, &tp->hw_phy_work, HZ * 10);
5166*4882a593Smuzhiyun 		goto ignore_once;
5167*4882a593Smuzhiyun 	}
5168*4882a593Smuzhiyun 
5169*4882a593Smuzhiyun 	tp->rtl_ops.hw_phy_cfg(tp);
5170*4882a593Smuzhiyun 
5171*4882a593Smuzhiyun 	rtl8152_set_speed(tp, tp->autoneg, tp->speed, tp->duplex,
5172*4882a593Smuzhiyun 			  tp->advertising);
5173*4882a593Smuzhiyun 
5174*4882a593Smuzhiyun ignore_once:
5175*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5176*4882a593Smuzhiyun 
5177*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5178*4882a593Smuzhiyun }
5179*4882a593Smuzhiyun 
5180*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
rtl_notifier(struct notifier_block * nb,unsigned long action,void * data)5181*4882a593Smuzhiyun static int rtl_notifier(struct notifier_block *nb, unsigned long action,
5182*4882a593Smuzhiyun 			void *data)
5183*4882a593Smuzhiyun {
5184*4882a593Smuzhiyun 	struct r8152 *tp = container_of(nb, struct r8152, pm_notifier);
5185*4882a593Smuzhiyun 
5186*4882a593Smuzhiyun 	switch (action) {
5187*4882a593Smuzhiyun 	case PM_HIBERNATION_PREPARE:
5188*4882a593Smuzhiyun 	case PM_SUSPEND_PREPARE:
5189*4882a593Smuzhiyun 		usb_autopm_get_interface(tp->intf);
5190*4882a593Smuzhiyun 		break;
5191*4882a593Smuzhiyun 
5192*4882a593Smuzhiyun 	case PM_POST_HIBERNATION:
5193*4882a593Smuzhiyun 	case PM_POST_SUSPEND:
5194*4882a593Smuzhiyun 		usb_autopm_put_interface(tp->intf);
5195*4882a593Smuzhiyun 		break;
5196*4882a593Smuzhiyun 
5197*4882a593Smuzhiyun 	case PM_POST_RESTORE:
5198*4882a593Smuzhiyun 	case PM_RESTORE_PREPARE:
5199*4882a593Smuzhiyun 	default:
5200*4882a593Smuzhiyun 		break;
5201*4882a593Smuzhiyun 	}
5202*4882a593Smuzhiyun 
5203*4882a593Smuzhiyun 	return NOTIFY_DONE;
5204*4882a593Smuzhiyun }
5205*4882a593Smuzhiyun #endif
5206*4882a593Smuzhiyun 
rtl8152_open(struct net_device * netdev)5207*4882a593Smuzhiyun static int rtl8152_open(struct net_device *netdev)
5208*4882a593Smuzhiyun {
5209*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
5210*4882a593Smuzhiyun 	int res = 0;
5211*4882a593Smuzhiyun 
5212*4882a593Smuzhiyun 	if (work_busy(&tp->hw_phy_work.work) & WORK_BUSY_PENDING) {
5213*4882a593Smuzhiyun 		cancel_delayed_work_sync(&tp->hw_phy_work);
5214*4882a593Smuzhiyun 		rtl_hw_phy_work_func_t(&tp->hw_phy_work.work);
5215*4882a593Smuzhiyun 	}
5216*4882a593Smuzhiyun 
5217*4882a593Smuzhiyun 	res = alloc_all_mem(tp);
5218*4882a593Smuzhiyun 	if (res)
5219*4882a593Smuzhiyun 		goto out;
5220*4882a593Smuzhiyun 
5221*4882a593Smuzhiyun 	res = usb_autopm_get_interface(tp->intf);
5222*4882a593Smuzhiyun 	if (res < 0)
5223*4882a593Smuzhiyun 		goto out_free;
5224*4882a593Smuzhiyun 
5225*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5226*4882a593Smuzhiyun 
5227*4882a593Smuzhiyun 	tp->rtl_ops.up(tp);
5228*4882a593Smuzhiyun 
5229*4882a593Smuzhiyun 	netif_carrier_off(netdev);
5230*4882a593Smuzhiyun 	netif_start_queue(netdev);
5231*4882a593Smuzhiyun 	set_bit(WORK_ENABLE, &tp->flags);
5232*4882a593Smuzhiyun 
5233*4882a593Smuzhiyun 	res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
5234*4882a593Smuzhiyun 	if (res) {
5235*4882a593Smuzhiyun 		if (res == -ENODEV)
5236*4882a593Smuzhiyun 			netif_device_detach(tp->netdev);
5237*4882a593Smuzhiyun 		netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
5238*4882a593Smuzhiyun 			   res);
5239*4882a593Smuzhiyun 		goto out_unlock;
5240*4882a593Smuzhiyun 	}
5241*4882a593Smuzhiyun 	napi_enable(&tp->napi);
5242*4882a593Smuzhiyun 	tasklet_enable(&tp->tx_tl);
5243*4882a593Smuzhiyun 
5244*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5245*4882a593Smuzhiyun 
5246*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5247*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
5248*4882a593Smuzhiyun 	tp->pm_notifier.notifier_call = rtl_notifier;
5249*4882a593Smuzhiyun 	register_pm_notifier(&tp->pm_notifier);
5250*4882a593Smuzhiyun #endif
5251*4882a593Smuzhiyun 	return 0;
5252*4882a593Smuzhiyun 
5253*4882a593Smuzhiyun out_unlock:
5254*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5255*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5256*4882a593Smuzhiyun out_free:
5257*4882a593Smuzhiyun 	free_all_mem(tp);
5258*4882a593Smuzhiyun out:
5259*4882a593Smuzhiyun 	return res;
5260*4882a593Smuzhiyun }
5261*4882a593Smuzhiyun 
rtl8152_close(struct net_device * netdev)5262*4882a593Smuzhiyun static int rtl8152_close(struct net_device *netdev)
5263*4882a593Smuzhiyun {
5264*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
5265*4882a593Smuzhiyun 	int res = 0;
5266*4882a593Smuzhiyun 
5267*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
5268*4882a593Smuzhiyun 	unregister_pm_notifier(&tp->pm_notifier);
5269*4882a593Smuzhiyun #endif
5270*4882a593Smuzhiyun 	tasklet_disable(&tp->tx_tl);
5271*4882a593Smuzhiyun 	clear_bit(WORK_ENABLE, &tp->flags);
5272*4882a593Smuzhiyun 	usb_kill_urb(tp->intr_urb);
5273*4882a593Smuzhiyun 	cancel_delayed_work_sync(&tp->schedule);
5274*4882a593Smuzhiyun 	napi_disable(&tp->napi);
5275*4882a593Smuzhiyun 	netif_stop_queue(netdev);
5276*4882a593Smuzhiyun 
5277*4882a593Smuzhiyun 	res = usb_autopm_get_interface(tp->intf);
5278*4882a593Smuzhiyun 	if (res < 0 || test_bit(RTL8152_UNPLUG, &tp->flags)) {
5279*4882a593Smuzhiyun 		rtl_drop_queued_tx(tp);
5280*4882a593Smuzhiyun 		rtl_stop_rx(tp);
5281*4882a593Smuzhiyun 	} else {
5282*4882a593Smuzhiyun 		mutex_lock(&tp->control);
5283*4882a593Smuzhiyun 
5284*4882a593Smuzhiyun 		tp->rtl_ops.down(tp);
5285*4882a593Smuzhiyun 
5286*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
5287*4882a593Smuzhiyun 	}
5288*4882a593Smuzhiyun 
5289*4882a593Smuzhiyun 	if (!res)
5290*4882a593Smuzhiyun 		usb_autopm_put_interface(tp->intf);
5291*4882a593Smuzhiyun 
5292*4882a593Smuzhiyun 	free_all_mem(tp);
5293*4882a593Smuzhiyun 
5294*4882a593Smuzhiyun 	return res;
5295*4882a593Smuzhiyun }
5296*4882a593Smuzhiyun 
rtl_tally_reset(struct r8152 * tp)5297*4882a593Smuzhiyun static void rtl_tally_reset(struct r8152 *tp)
5298*4882a593Smuzhiyun {
5299*4882a593Smuzhiyun 	u32 ocp_data;
5300*4882a593Smuzhiyun 
5301*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY);
5302*4882a593Smuzhiyun 	ocp_data |= TALLY_RESET;
5303*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
5304*4882a593Smuzhiyun }
5305*4882a593Smuzhiyun 
r8152b_init(struct r8152 * tp)5306*4882a593Smuzhiyun static void r8152b_init(struct r8152 *tp)
5307*4882a593Smuzhiyun {
5308*4882a593Smuzhiyun 	u32 ocp_data;
5309*4882a593Smuzhiyun 	u16 data;
5310*4882a593Smuzhiyun 
5311*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
5312*4882a593Smuzhiyun 		return;
5313*4882a593Smuzhiyun 
5314*4882a593Smuzhiyun 	data = r8152_mdio_read(tp, MII_BMCR);
5315*4882a593Smuzhiyun 	if (data & BMCR_PDOWN) {
5316*4882a593Smuzhiyun 		data &= ~BMCR_PDOWN;
5317*4882a593Smuzhiyun 		r8152_mdio_write(tp, MII_BMCR, data);
5318*4882a593Smuzhiyun 	}
5319*4882a593Smuzhiyun 
5320*4882a593Smuzhiyun 	r8152_aldps_en(tp, false);
5321*4882a593Smuzhiyun 
5322*4882a593Smuzhiyun 	if (tp->version == RTL_VER_01) {
5323*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
5324*4882a593Smuzhiyun 		ocp_data &= ~LED_MODE_MASK;
5325*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
5326*4882a593Smuzhiyun 	}
5327*4882a593Smuzhiyun 
5328*4882a593Smuzhiyun 	r8152_power_cut_en(tp, false);
5329*4882a593Smuzhiyun 
5330*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
5331*4882a593Smuzhiyun 	ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
5332*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
5333*4882a593Smuzhiyun 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
5334*4882a593Smuzhiyun 	ocp_data &= ~MCU_CLK_RATIO_MASK;
5335*4882a593Smuzhiyun 	ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
5336*4882a593Smuzhiyun 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
5337*4882a593Smuzhiyun 	ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
5338*4882a593Smuzhiyun 		   SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
5339*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
5340*4882a593Smuzhiyun 
5341*4882a593Smuzhiyun 	rtl_tally_reset(tp);
5342*4882a593Smuzhiyun 
5343*4882a593Smuzhiyun 	/* enable rx aggregation */
5344*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
5345*4882a593Smuzhiyun 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
5346*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
5347*4882a593Smuzhiyun }
5348*4882a593Smuzhiyun 
r8153_init(struct r8152 * tp)5349*4882a593Smuzhiyun static void r8153_init(struct r8152 *tp)
5350*4882a593Smuzhiyun {
5351*4882a593Smuzhiyun 	u32 ocp_data;
5352*4882a593Smuzhiyun 	u16 data;
5353*4882a593Smuzhiyun 	int i;
5354*4882a593Smuzhiyun 
5355*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
5356*4882a593Smuzhiyun 		return;
5357*4882a593Smuzhiyun 
5358*4882a593Smuzhiyun 	r8153_u1u2en(tp, false);
5359*4882a593Smuzhiyun 
5360*4882a593Smuzhiyun 	for (i = 0; i < 500; i++) {
5361*4882a593Smuzhiyun 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
5362*4882a593Smuzhiyun 		    AUTOLOAD_DONE)
5363*4882a593Smuzhiyun 			break;
5364*4882a593Smuzhiyun 
5365*4882a593Smuzhiyun 		msleep(20);
5366*4882a593Smuzhiyun 		if (test_bit(RTL8152_UNPLUG, &tp->flags))
5367*4882a593Smuzhiyun 			break;
5368*4882a593Smuzhiyun 	}
5369*4882a593Smuzhiyun 
5370*4882a593Smuzhiyun 	data = r8153_phy_status(tp, 0);
5371*4882a593Smuzhiyun 
5372*4882a593Smuzhiyun 	if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 ||
5373*4882a593Smuzhiyun 	    tp->version == RTL_VER_05)
5374*4882a593Smuzhiyun 		ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
5375*4882a593Smuzhiyun 
5376*4882a593Smuzhiyun 	data = r8152_mdio_read(tp, MII_BMCR);
5377*4882a593Smuzhiyun 	if (data & BMCR_PDOWN) {
5378*4882a593Smuzhiyun 		data &= ~BMCR_PDOWN;
5379*4882a593Smuzhiyun 		r8152_mdio_write(tp, MII_BMCR, data);
5380*4882a593Smuzhiyun 	}
5381*4882a593Smuzhiyun 
5382*4882a593Smuzhiyun 	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
5383*4882a593Smuzhiyun 
5384*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
5385*4882a593Smuzhiyun 
5386*4882a593Smuzhiyun 	if (tp->version == RTL_VER_04) {
5387*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2);
5388*4882a593Smuzhiyun 		ocp_data &= ~pwd_dn_scale_mask;
5389*4882a593Smuzhiyun 		ocp_data |= pwd_dn_scale(96);
5390*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data);
5391*4882a593Smuzhiyun 
5392*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY);
5393*4882a593Smuzhiyun 		ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND;
5394*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data);
5395*4882a593Smuzhiyun 	} else if (tp->version == RTL_VER_05) {
5396*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0);
5397*4882a593Smuzhiyun 		ocp_data &= ~ECM_ALDPS;
5398*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data);
5399*4882a593Smuzhiyun 
5400*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
5401*4882a593Smuzhiyun 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
5402*4882a593Smuzhiyun 			ocp_data &= ~DYNAMIC_BURST;
5403*4882a593Smuzhiyun 		else
5404*4882a593Smuzhiyun 			ocp_data |= DYNAMIC_BURST;
5405*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
5406*4882a593Smuzhiyun 	} else if (tp->version == RTL_VER_06) {
5407*4882a593Smuzhiyun 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
5408*4882a593Smuzhiyun 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
5409*4882a593Smuzhiyun 			ocp_data &= ~DYNAMIC_BURST;
5410*4882a593Smuzhiyun 		else
5411*4882a593Smuzhiyun 			ocp_data |= DYNAMIC_BURST;
5412*4882a593Smuzhiyun 		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
5413*4882a593Smuzhiyun 
5414*4882a593Smuzhiyun 		r8153_queue_wake(tp, false);
5415*4882a593Smuzhiyun 
5416*4882a593Smuzhiyun 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
5417*4882a593Smuzhiyun 		if (rtl8152_get_speed(tp) & LINK_STATUS)
5418*4882a593Smuzhiyun 			ocp_data |= CUR_LINK_OK;
5419*4882a593Smuzhiyun 		else
5420*4882a593Smuzhiyun 			ocp_data &= ~CUR_LINK_OK;
5421*4882a593Smuzhiyun 		ocp_data |= POLL_LINK_CHG;
5422*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
5423*4882a593Smuzhiyun 	}
5424*4882a593Smuzhiyun 
5425*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2);
5426*4882a593Smuzhiyun 	ocp_data |= EP4_FULL_FC;
5427*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data);
5428*4882a593Smuzhiyun 
5429*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
5430*4882a593Smuzhiyun 	ocp_data &= ~TIMER11_EN;
5431*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
5432*4882a593Smuzhiyun 
5433*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
5434*4882a593Smuzhiyun 	ocp_data &= ~LED_MODE_MASK;
5435*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
5436*4882a593Smuzhiyun 
5437*4882a593Smuzhiyun 	ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM;
5438*4882a593Smuzhiyun 	if (tp->version == RTL_VER_04 && tp->udev->speed < USB_SPEED_SUPER)
5439*4882a593Smuzhiyun 		ocp_data |= LPM_TIMER_500MS;
5440*4882a593Smuzhiyun 	else
5441*4882a593Smuzhiyun 		ocp_data |= LPM_TIMER_500US;
5442*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data);
5443*4882a593Smuzhiyun 
5444*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2);
5445*4882a593Smuzhiyun 	ocp_data &= ~SEN_VAL_MASK;
5446*4882a593Smuzhiyun 	ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
5447*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
5448*4882a593Smuzhiyun 
5449*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
5450*4882a593Smuzhiyun 
5451*4882a593Smuzhiyun 	/* MAC clock speed down */
5452*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
5453*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
5454*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
5455*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
5456*4882a593Smuzhiyun 
5457*4882a593Smuzhiyun 	r8153_power_cut_en(tp, false);
5458*4882a593Smuzhiyun 	rtl_runtime_suspend_enable(tp, false);
5459*4882a593Smuzhiyun 	r8153_u1u2en(tp, true);
5460*4882a593Smuzhiyun 	usb_enable_lpm(tp->udev);
5461*4882a593Smuzhiyun 
5462*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
5463*4882a593Smuzhiyun 	ocp_data |= LANWAKE_CLR_EN;
5464*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
5465*4882a593Smuzhiyun 
5466*4882a593Smuzhiyun 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
5467*4882a593Smuzhiyun 	ocp_data &= ~LANWAKE_PIN;
5468*4882a593Smuzhiyun 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
5469*4882a593Smuzhiyun 
5470*4882a593Smuzhiyun 	/* rx aggregation */
5471*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
5472*4882a593Smuzhiyun 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
5473*4882a593Smuzhiyun 	if (test_bit(DELL_TB_RX_AGG_BUG, &tp->flags))
5474*4882a593Smuzhiyun 		ocp_data |= RX_AGG_DISABLE;
5475*4882a593Smuzhiyun 
5476*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
5477*4882a593Smuzhiyun 
5478*4882a593Smuzhiyun 	rtl_tally_reset(tp);
5479*4882a593Smuzhiyun 
5480*4882a593Smuzhiyun 	switch (tp->udev->speed) {
5481*4882a593Smuzhiyun 	case USB_SPEED_SUPER:
5482*4882a593Smuzhiyun 	case USB_SPEED_SUPER_PLUS:
5483*4882a593Smuzhiyun 		tp->coalesce = COALESCE_SUPER;
5484*4882a593Smuzhiyun 		break;
5485*4882a593Smuzhiyun 	case USB_SPEED_HIGH:
5486*4882a593Smuzhiyun 		tp->coalesce = COALESCE_HIGH;
5487*4882a593Smuzhiyun 		break;
5488*4882a593Smuzhiyun 	default:
5489*4882a593Smuzhiyun 		tp->coalesce = COALESCE_SLOW;
5490*4882a593Smuzhiyun 		break;
5491*4882a593Smuzhiyun 	}
5492*4882a593Smuzhiyun }
5493*4882a593Smuzhiyun 
r8153b_init(struct r8152 * tp)5494*4882a593Smuzhiyun static void r8153b_init(struct r8152 *tp)
5495*4882a593Smuzhiyun {
5496*4882a593Smuzhiyun 	u32 ocp_data;
5497*4882a593Smuzhiyun 	u16 data;
5498*4882a593Smuzhiyun 	int i;
5499*4882a593Smuzhiyun 
5500*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
5501*4882a593Smuzhiyun 		return;
5502*4882a593Smuzhiyun 
5503*4882a593Smuzhiyun 	r8153b_u1u2en(tp, false);
5504*4882a593Smuzhiyun 
5505*4882a593Smuzhiyun 	for (i = 0; i < 500; i++) {
5506*4882a593Smuzhiyun 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
5507*4882a593Smuzhiyun 		    AUTOLOAD_DONE)
5508*4882a593Smuzhiyun 			break;
5509*4882a593Smuzhiyun 
5510*4882a593Smuzhiyun 		msleep(20);
5511*4882a593Smuzhiyun 		if (test_bit(RTL8152_UNPLUG, &tp->flags))
5512*4882a593Smuzhiyun 			break;
5513*4882a593Smuzhiyun 	}
5514*4882a593Smuzhiyun 
5515*4882a593Smuzhiyun 	data = r8153_phy_status(tp, 0);
5516*4882a593Smuzhiyun 
5517*4882a593Smuzhiyun 	data = r8152_mdio_read(tp, MII_BMCR);
5518*4882a593Smuzhiyun 	if (data & BMCR_PDOWN) {
5519*4882a593Smuzhiyun 		data &= ~BMCR_PDOWN;
5520*4882a593Smuzhiyun 		r8152_mdio_write(tp, MII_BMCR, data);
5521*4882a593Smuzhiyun 	}
5522*4882a593Smuzhiyun 
5523*4882a593Smuzhiyun 	data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
5524*4882a593Smuzhiyun 
5525*4882a593Smuzhiyun 	r8153_u2p3en(tp, false);
5526*4882a593Smuzhiyun 
5527*4882a593Smuzhiyun 	/* MSC timer = 0xfff * 8ms = 32760 ms */
5528*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
5529*4882a593Smuzhiyun 
5530*4882a593Smuzhiyun 	/* U1/U2/L1 idle timer. 500 us */
5531*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
5532*4882a593Smuzhiyun 
5533*4882a593Smuzhiyun 	r8153b_power_cut_en(tp, false);
5534*4882a593Smuzhiyun 	r8153b_ups_en(tp, false);
5535*4882a593Smuzhiyun 	r8153_queue_wake(tp, false);
5536*4882a593Smuzhiyun 	rtl_runtime_suspend_enable(tp, false);
5537*4882a593Smuzhiyun 
5538*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
5539*4882a593Smuzhiyun 	if (rtl8152_get_speed(tp) & LINK_STATUS)
5540*4882a593Smuzhiyun 		ocp_data |= CUR_LINK_OK;
5541*4882a593Smuzhiyun 	else
5542*4882a593Smuzhiyun 		ocp_data &= ~CUR_LINK_OK;
5543*4882a593Smuzhiyun 	ocp_data |= POLL_LINK_CHG;
5544*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
5545*4882a593Smuzhiyun 
5546*4882a593Smuzhiyun 	if (tp->udev->speed != USB_SPEED_HIGH)
5547*4882a593Smuzhiyun 		r8153b_u1u2en(tp, true);
5548*4882a593Smuzhiyun 	usb_enable_lpm(tp->udev);
5549*4882a593Smuzhiyun 
5550*4882a593Smuzhiyun 	/* MAC clock speed down */
5551*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2);
5552*4882a593Smuzhiyun 	ocp_data |= MAC_CLK_SPDWN_EN;
5553*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data);
5554*4882a593Smuzhiyun 
5555*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
5556*4882a593Smuzhiyun 	ocp_data &= ~PLA_MCU_SPDWN_EN;
5557*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
5558*4882a593Smuzhiyun 
5559*4882a593Smuzhiyun 	if (tp->version == RTL_VER_09) {
5560*4882a593Smuzhiyun 		/* Disable Test IO for 32QFN */
5561*4882a593Smuzhiyun 		if (ocp_read_byte(tp, MCU_TYPE_PLA, 0xdc00) & BIT(5)) {
5562*4882a593Smuzhiyun 			ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
5563*4882a593Smuzhiyun 			ocp_data |= TEST_IO_OFF;
5564*4882a593Smuzhiyun 			ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
5565*4882a593Smuzhiyun 		}
5566*4882a593Smuzhiyun 	}
5567*4882a593Smuzhiyun 
5568*4882a593Smuzhiyun 	set_bit(GREEN_ETHERNET, &tp->flags);
5569*4882a593Smuzhiyun 
5570*4882a593Smuzhiyun 	/* rx aggregation */
5571*4882a593Smuzhiyun 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
5572*4882a593Smuzhiyun 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
5573*4882a593Smuzhiyun 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
5574*4882a593Smuzhiyun 
5575*4882a593Smuzhiyun 	rtl_tally_reset(tp);
5576*4882a593Smuzhiyun 
5577*4882a593Smuzhiyun 	tp->coalesce = 15000;	/* 15 us */
5578*4882a593Smuzhiyun }
5579*4882a593Smuzhiyun 
rtl8152_pre_reset(struct usb_interface * intf)5580*4882a593Smuzhiyun static int rtl8152_pre_reset(struct usb_interface *intf)
5581*4882a593Smuzhiyun {
5582*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
5583*4882a593Smuzhiyun 	struct net_device *netdev;
5584*4882a593Smuzhiyun 
5585*4882a593Smuzhiyun 	if (!tp)
5586*4882a593Smuzhiyun 		return 0;
5587*4882a593Smuzhiyun 
5588*4882a593Smuzhiyun 	netdev = tp->netdev;
5589*4882a593Smuzhiyun 	if (!netif_running(netdev))
5590*4882a593Smuzhiyun 		return 0;
5591*4882a593Smuzhiyun 
5592*4882a593Smuzhiyun 	netif_stop_queue(netdev);
5593*4882a593Smuzhiyun 	tasklet_disable(&tp->tx_tl);
5594*4882a593Smuzhiyun 	clear_bit(WORK_ENABLE, &tp->flags);
5595*4882a593Smuzhiyun 	usb_kill_urb(tp->intr_urb);
5596*4882a593Smuzhiyun 	cancel_delayed_work_sync(&tp->schedule);
5597*4882a593Smuzhiyun 	napi_disable(&tp->napi);
5598*4882a593Smuzhiyun 	if (netif_carrier_ok(netdev)) {
5599*4882a593Smuzhiyun 		mutex_lock(&tp->control);
5600*4882a593Smuzhiyun 		tp->rtl_ops.disable(tp);
5601*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
5602*4882a593Smuzhiyun 	}
5603*4882a593Smuzhiyun 
5604*4882a593Smuzhiyun 	return 0;
5605*4882a593Smuzhiyun }
5606*4882a593Smuzhiyun 
rtl8152_post_reset(struct usb_interface * intf)5607*4882a593Smuzhiyun static int rtl8152_post_reset(struct usb_interface *intf)
5608*4882a593Smuzhiyun {
5609*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
5610*4882a593Smuzhiyun 	struct net_device *netdev;
5611*4882a593Smuzhiyun 	struct sockaddr sa;
5612*4882a593Smuzhiyun 
5613*4882a593Smuzhiyun 	if (!tp)
5614*4882a593Smuzhiyun 		return 0;
5615*4882a593Smuzhiyun 
5616*4882a593Smuzhiyun 	/* reset the MAC adddress in case of policy change */
5617*4882a593Smuzhiyun 	if (determine_ethernet_addr(tp, &sa) >= 0) {
5618*4882a593Smuzhiyun 		rtnl_lock();
5619*4882a593Smuzhiyun 		dev_set_mac_address (tp->netdev, &sa, NULL);
5620*4882a593Smuzhiyun 		rtnl_unlock();
5621*4882a593Smuzhiyun 	}
5622*4882a593Smuzhiyun 
5623*4882a593Smuzhiyun 	netdev = tp->netdev;
5624*4882a593Smuzhiyun 	if (!netif_running(netdev))
5625*4882a593Smuzhiyun 		return 0;
5626*4882a593Smuzhiyun 
5627*4882a593Smuzhiyun 	set_bit(WORK_ENABLE, &tp->flags);
5628*4882a593Smuzhiyun 	if (netif_carrier_ok(netdev)) {
5629*4882a593Smuzhiyun 		mutex_lock(&tp->control);
5630*4882a593Smuzhiyun 		tp->rtl_ops.enable(tp);
5631*4882a593Smuzhiyun 		rtl_start_rx(tp);
5632*4882a593Smuzhiyun 		_rtl8152_set_rx_mode(netdev);
5633*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
5634*4882a593Smuzhiyun 	}
5635*4882a593Smuzhiyun 
5636*4882a593Smuzhiyun 	napi_enable(&tp->napi);
5637*4882a593Smuzhiyun 	tasklet_enable(&tp->tx_tl);
5638*4882a593Smuzhiyun 	netif_wake_queue(netdev);
5639*4882a593Smuzhiyun 	usb_submit_urb(tp->intr_urb, GFP_KERNEL);
5640*4882a593Smuzhiyun 
5641*4882a593Smuzhiyun 	if (!list_empty(&tp->rx_done))
5642*4882a593Smuzhiyun 		napi_schedule(&tp->napi);
5643*4882a593Smuzhiyun 
5644*4882a593Smuzhiyun 	return 0;
5645*4882a593Smuzhiyun }
5646*4882a593Smuzhiyun 
delay_autosuspend(struct r8152 * tp)5647*4882a593Smuzhiyun static bool delay_autosuspend(struct r8152 *tp)
5648*4882a593Smuzhiyun {
5649*4882a593Smuzhiyun 	bool sw_linking = !!netif_carrier_ok(tp->netdev);
5650*4882a593Smuzhiyun 	bool hw_linking = !!(rtl8152_get_speed(tp) & LINK_STATUS);
5651*4882a593Smuzhiyun 
5652*4882a593Smuzhiyun 	/* This means a linking change occurs and the driver doesn't detect it,
5653*4882a593Smuzhiyun 	 * yet. If the driver has disabled tx/rx and hw is linking on, the
5654*4882a593Smuzhiyun 	 * device wouldn't wake up by receiving any packet.
5655*4882a593Smuzhiyun 	 */
5656*4882a593Smuzhiyun 	if (work_busy(&tp->schedule.work) || sw_linking != hw_linking)
5657*4882a593Smuzhiyun 		return true;
5658*4882a593Smuzhiyun 
5659*4882a593Smuzhiyun 	/* If the linking down is occurred by nway, the device may miss the
5660*4882a593Smuzhiyun 	 * linking change event. And it wouldn't wake when linking on.
5661*4882a593Smuzhiyun 	 */
5662*4882a593Smuzhiyun 	if (!sw_linking && tp->rtl_ops.in_nway(tp))
5663*4882a593Smuzhiyun 		return true;
5664*4882a593Smuzhiyun 	else if (!skb_queue_empty(&tp->tx_queue))
5665*4882a593Smuzhiyun 		return true;
5666*4882a593Smuzhiyun 	else
5667*4882a593Smuzhiyun 		return false;
5668*4882a593Smuzhiyun }
5669*4882a593Smuzhiyun 
rtl8152_runtime_resume(struct r8152 * tp)5670*4882a593Smuzhiyun static int rtl8152_runtime_resume(struct r8152 *tp)
5671*4882a593Smuzhiyun {
5672*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
5673*4882a593Smuzhiyun 
5674*4882a593Smuzhiyun 	if (netif_running(netdev) && netdev->flags & IFF_UP) {
5675*4882a593Smuzhiyun 		struct napi_struct *napi = &tp->napi;
5676*4882a593Smuzhiyun 
5677*4882a593Smuzhiyun 		tp->rtl_ops.autosuspend_en(tp, false);
5678*4882a593Smuzhiyun 		napi_disable(napi);
5679*4882a593Smuzhiyun 		set_bit(WORK_ENABLE, &tp->flags);
5680*4882a593Smuzhiyun 
5681*4882a593Smuzhiyun 		if (netif_carrier_ok(netdev)) {
5682*4882a593Smuzhiyun 			if (rtl8152_get_speed(tp) & LINK_STATUS) {
5683*4882a593Smuzhiyun 				rtl_start_rx(tp);
5684*4882a593Smuzhiyun 			} else {
5685*4882a593Smuzhiyun 				netif_carrier_off(netdev);
5686*4882a593Smuzhiyun 				tp->rtl_ops.disable(tp);
5687*4882a593Smuzhiyun 				netif_info(tp, link, netdev, "linking down\n");
5688*4882a593Smuzhiyun 			}
5689*4882a593Smuzhiyun 		}
5690*4882a593Smuzhiyun 
5691*4882a593Smuzhiyun 		napi_enable(napi);
5692*4882a593Smuzhiyun 		clear_bit(SELECTIVE_SUSPEND, &tp->flags);
5693*4882a593Smuzhiyun 		smp_mb__after_atomic();
5694*4882a593Smuzhiyun 
5695*4882a593Smuzhiyun 		if (!list_empty(&tp->rx_done))
5696*4882a593Smuzhiyun 			napi_schedule(&tp->napi);
5697*4882a593Smuzhiyun 
5698*4882a593Smuzhiyun 		usb_submit_urb(tp->intr_urb, GFP_NOIO);
5699*4882a593Smuzhiyun 	} else {
5700*4882a593Smuzhiyun 		if (netdev->flags & IFF_UP)
5701*4882a593Smuzhiyun 			tp->rtl_ops.autosuspend_en(tp, false);
5702*4882a593Smuzhiyun 
5703*4882a593Smuzhiyun 		clear_bit(SELECTIVE_SUSPEND, &tp->flags);
5704*4882a593Smuzhiyun 	}
5705*4882a593Smuzhiyun 
5706*4882a593Smuzhiyun 	return 0;
5707*4882a593Smuzhiyun }
5708*4882a593Smuzhiyun 
rtl8152_system_resume(struct r8152 * tp)5709*4882a593Smuzhiyun static int rtl8152_system_resume(struct r8152 *tp)
5710*4882a593Smuzhiyun {
5711*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
5712*4882a593Smuzhiyun 
5713*4882a593Smuzhiyun 	netif_device_attach(netdev);
5714*4882a593Smuzhiyun 
5715*4882a593Smuzhiyun 	if (netif_running(netdev) && (netdev->flags & IFF_UP)) {
5716*4882a593Smuzhiyun 		tp->rtl_ops.up(tp);
5717*4882a593Smuzhiyun 		netif_carrier_off(netdev);
5718*4882a593Smuzhiyun 		set_bit(WORK_ENABLE, &tp->flags);
5719*4882a593Smuzhiyun 		usb_submit_urb(tp->intr_urb, GFP_NOIO);
5720*4882a593Smuzhiyun 	}
5721*4882a593Smuzhiyun 
5722*4882a593Smuzhiyun 	return 0;
5723*4882a593Smuzhiyun }
5724*4882a593Smuzhiyun 
rtl8152_runtime_suspend(struct r8152 * tp)5725*4882a593Smuzhiyun static int rtl8152_runtime_suspend(struct r8152 *tp)
5726*4882a593Smuzhiyun {
5727*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
5728*4882a593Smuzhiyun 	int ret = 0;
5729*4882a593Smuzhiyun 
5730*4882a593Smuzhiyun 	set_bit(SELECTIVE_SUSPEND, &tp->flags);
5731*4882a593Smuzhiyun 	smp_mb__after_atomic();
5732*4882a593Smuzhiyun 
5733*4882a593Smuzhiyun 	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
5734*4882a593Smuzhiyun 		u32 rcr = 0;
5735*4882a593Smuzhiyun 
5736*4882a593Smuzhiyun 		if (netif_carrier_ok(netdev)) {
5737*4882a593Smuzhiyun 			u32 ocp_data;
5738*4882a593Smuzhiyun 
5739*4882a593Smuzhiyun 			rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
5740*4882a593Smuzhiyun 			ocp_data = rcr & ~RCR_ACPT_ALL;
5741*4882a593Smuzhiyun 			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
5742*4882a593Smuzhiyun 			rxdy_gated_en(tp, true);
5743*4882a593Smuzhiyun 			ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
5744*4882a593Smuzhiyun 						 PLA_OOB_CTRL);
5745*4882a593Smuzhiyun 			if (!(ocp_data & RXFIFO_EMPTY)) {
5746*4882a593Smuzhiyun 				rxdy_gated_en(tp, false);
5747*4882a593Smuzhiyun 				ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
5748*4882a593Smuzhiyun 				clear_bit(SELECTIVE_SUSPEND, &tp->flags);
5749*4882a593Smuzhiyun 				smp_mb__after_atomic();
5750*4882a593Smuzhiyun 				ret = -EBUSY;
5751*4882a593Smuzhiyun 				goto out1;
5752*4882a593Smuzhiyun 			}
5753*4882a593Smuzhiyun 		}
5754*4882a593Smuzhiyun 
5755*4882a593Smuzhiyun 		clear_bit(WORK_ENABLE, &tp->flags);
5756*4882a593Smuzhiyun 		usb_kill_urb(tp->intr_urb);
5757*4882a593Smuzhiyun 
5758*4882a593Smuzhiyun 		tp->rtl_ops.autosuspend_en(tp, true);
5759*4882a593Smuzhiyun 
5760*4882a593Smuzhiyun 		if (netif_carrier_ok(netdev)) {
5761*4882a593Smuzhiyun 			struct napi_struct *napi = &tp->napi;
5762*4882a593Smuzhiyun 
5763*4882a593Smuzhiyun 			napi_disable(napi);
5764*4882a593Smuzhiyun 			rtl_stop_rx(tp);
5765*4882a593Smuzhiyun 			rxdy_gated_en(tp, false);
5766*4882a593Smuzhiyun 			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
5767*4882a593Smuzhiyun 			napi_enable(napi);
5768*4882a593Smuzhiyun 		}
5769*4882a593Smuzhiyun 
5770*4882a593Smuzhiyun 		if (delay_autosuspend(tp)) {
5771*4882a593Smuzhiyun 			rtl8152_runtime_resume(tp);
5772*4882a593Smuzhiyun 			ret = -EBUSY;
5773*4882a593Smuzhiyun 		}
5774*4882a593Smuzhiyun 	}
5775*4882a593Smuzhiyun 
5776*4882a593Smuzhiyun out1:
5777*4882a593Smuzhiyun 	return ret;
5778*4882a593Smuzhiyun }
5779*4882a593Smuzhiyun 
rtl8152_system_suspend(struct r8152 * tp)5780*4882a593Smuzhiyun static int rtl8152_system_suspend(struct r8152 *tp)
5781*4882a593Smuzhiyun {
5782*4882a593Smuzhiyun 	struct net_device *netdev = tp->netdev;
5783*4882a593Smuzhiyun 
5784*4882a593Smuzhiyun 	netif_device_detach(netdev);
5785*4882a593Smuzhiyun 
5786*4882a593Smuzhiyun 	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
5787*4882a593Smuzhiyun 		struct napi_struct *napi = &tp->napi;
5788*4882a593Smuzhiyun 
5789*4882a593Smuzhiyun 		clear_bit(WORK_ENABLE, &tp->flags);
5790*4882a593Smuzhiyun 		usb_kill_urb(tp->intr_urb);
5791*4882a593Smuzhiyun 		tasklet_disable(&tp->tx_tl);
5792*4882a593Smuzhiyun 		napi_disable(napi);
5793*4882a593Smuzhiyun 		cancel_delayed_work_sync(&tp->schedule);
5794*4882a593Smuzhiyun 		tp->rtl_ops.down(tp);
5795*4882a593Smuzhiyun 		napi_enable(napi);
5796*4882a593Smuzhiyun 		tasklet_enable(&tp->tx_tl);
5797*4882a593Smuzhiyun 	}
5798*4882a593Smuzhiyun 
5799*4882a593Smuzhiyun 	return 0;
5800*4882a593Smuzhiyun }
5801*4882a593Smuzhiyun 
rtl8152_suspend(struct usb_interface * intf,pm_message_t message)5802*4882a593Smuzhiyun static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
5803*4882a593Smuzhiyun {
5804*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
5805*4882a593Smuzhiyun 	int ret;
5806*4882a593Smuzhiyun 
5807*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5808*4882a593Smuzhiyun 
5809*4882a593Smuzhiyun 	if (PMSG_IS_AUTO(message))
5810*4882a593Smuzhiyun 		ret = rtl8152_runtime_suspend(tp);
5811*4882a593Smuzhiyun 	else
5812*4882a593Smuzhiyun 		ret = rtl8152_system_suspend(tp);
5813*4882a593Smuzhiyun 
5814*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5815*4882a593Smuzhiyun 
5816*4882a593Smuzhiyun 	return ret;
5817*4882a593Smuzhiyun }
5818*4882a593Smuzhiyun 
rtl8152_resume(struct usb_interface * intf)5819*4882a593Smuzhiyun static int rtl8152_resume(struct usb_interface *intf)
5820*4882a593Smuzhiyun {
5821*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
5822*4882a593Smuzhiyun 	int ret;
5823*4882a593Smuzhiyun 
5824*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5825*4882a593Smuzhiyun 
5826*4882a593Smuzhiyun 	if (test_bit(SELECTIVE_SUSPEND, &tp->flags))
5827*4882a593Smuzhiyun 		ret = rtl8152_runtime_resume(tp);
5828*4882a593Smuzhiyun 	else
5829*4882a593Smuzhiyun 		ret = rtl8152_system_resume(tp);
5830*4882a593Smuzhiyun 
5831*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5832*4882a593Smuzhiyun 
5833*4882a593Smuzhiyun 	return ret;
5834*4882a593Smuzhiyun }
5835*4882a593Smuzhiyun 
rtl8152_reset_resume(struct usb_interface * intf)5836*4882a593Smuzhiyun static int rtl8152_reset_resume(struct usb_interface *intf)
5837*4882a593Smuzhiyun {
5838*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
5839*4882a593Smuzhiyun 
5840*4882a593Smuzhiyun 	clear_bit(SELECTIVE_SUSPEND, &tp->flags);
5841*4882a593Smuzhiyun 	tp->rtl_ops.init(tp);
5842*4882a593Smuzhiyun 	queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
5843*4882a593Smuzhiyun 	set_ethernet_addr(tp);
5844*4882a593Smuzhiyun 	return rtl8152_resume(intf);
5845*4882a593Smuzhiyun }
5846*4882a593Smuzhiyun 
rtl8152_get_wol(struct net_device * dev,struct ethtool_wolinfo * wol)5847*4882a593Smuzhiyun static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
5848*4882a593Smuzhiyun {
5849*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
5850*4882a593Smuzhiyun 
5851*4882a593Smuzhiyun 	if (usb_autopm_get_interface(tp->intf) < 0)
5852*4882a593Smuzhiyun 		return;
5853*4882a593Smuzhiyun 
5854*4882a593Smuzhiyun 	if (!rtl_can_wakeup(tp)) {
5855*4882a593Smuzhiyun 		wol->supported = 0;
5856*4882a593Smuzhiyun 		wol->wolopts = 0;
5857*4882a593Smuzhiyun 	} else {
5858*4882a593Smuzhiyun 		mutex_lock(&tp->control);
5859*4882a593Smuzhiyun 		wol->supported = WAKE_ANY;
5860*4882a593Smuzhiyun 		wol->wolopts = __rtl_get_wol(tp);
5861*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
5862*4882a593Smuzhiyun 	}
5863*4882a593Smuzhiyun 
5864*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5865*4882a593Smuzhiyun }
5866*4882a593Smuzhiyun 
rtl8152_set_wol(struct net_device * dev,struct ethtool_wolinfo * wol)5867*4882a593Smuzhiyun static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
5868*4882a593Smuzhiyun {
5869*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
5870*4882a593Smuzhiyun 	int ret;
5871*4882a593Smuzhiyun 
5872*4882a593Smuzhiyun 	if (!rtl_can_wakeup(tp))
5873*4882a593Smuzhiyun 		return -EOPNOTSUPP;
5874*4882a593Smuzhiyun 
5875*4882a593Smuzhiyun 	if (wol->wolopts & ~WAKE_ANY)
5876*4882a593Smuzhiyun 		return -EINVAL;
5877*4882a593Smuzhiyun 
5878*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
5879*4882a593Smuzhiyun 	if (ret < 0)
5880*4882a593Smuzhiyun 		goto out_set_wol;
5881*4882a593Smuzhiyun 
5882*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5883*4882a593Smuzhiyun 
5884*4882a593Smuzhiyun 	__rtl_set_wol(tp, wol->wolopts);
5885*4882a593Smuzhiyun 	tp->saved_wolopts = wol->wolopts & WAKE_ANY;
5886*4882a593Smuzhiyun 
5887*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5888*4882a593Smuzhiyun 
5889*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5890*4882a593Smuzhiyun 
5891*4882a593Smuzhiyun out_set_wol:
5892*4882a593Smuzhiyun 	return ret;
5893*4882a593Smuzhiyun }
5894*4882a593Smuzhiyun 
rtl8152_get_msglevel(struct net_device * dev)5895*4882a593Smuzhiyun static u32 rtl8152_get_msglevel(struct net_device *dev)
5896*4882a593Smuzhiyun {
5897*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
5898*4882a593Smuzhiyun 
5899*4882a593Smuzhiyun 	return tp->msg_enable;
5900*4882a593Smuzhiyun }
5901*4882a593Smuzhiyun 
rtl8152_set_msglevel(struct net_device * dev,u32 value)5902*4882a593Smuzhiyun static void rtl8152_set_msglevel(struct net_device *dev, u32 value)
5903*4882a593Smuzhiyun {
5904*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
5905*4882a593Smuzhiyun 
5906*4882a593Smuzhiyun 	tp->msg_enable = value;
5907*4882a593Smuzhiyun }
5908*4882a593Smuzhiyun 
rtl8152_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)5909*4882a593Smuzhiyun static void rtl8152_get_drvinfo(struct net_device *netdev,
5910*4882a593Smuzhiyun 				struct ethtool_drvinfo *info)
5911*4882a593Smuzhiyun {
5912*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
5913*4882a593Smuzhiyun 
5914*4882a593Smuzhiyun 	strlcpy(info->driver, MODULENAME, sizeof(info->driver));
5915*4882a593Smuzhiyun 	strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
5916*4882a593Smuzhiyun 	usb_make_path(tp->udev, info->bus_info, sizeof(info->bus_info));
5917*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(tp->rtl_fw.fw))
5918*4882a593Smuzhiyun 		strlcpy(info->fw_version, tp->rtl_fw.version,
5919*4882a593Smuzhiyun 			sizeof(info->fw_version));
5920*4882a593Smuzhiyun }
5921*4882a593Smuzhiyun 
5922*4882a593Smuzhiyun static
rtl8152_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)5923*4882a593Smuzhiyun int rtl8152_get_link_ksettings(struct net_device *netdev,
5924*4882a593Smuzhiyun 			       struct ethtool_link_ksettings *cmd)
5925*4882a593Smuzhiyun {
5926*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
5927*4882a593Smuzhiyun 	int ret;
5928*4882a593Smuzhiyun 
5929*4882a593Smuzhiyun 	if (!tp->mii.mdio_read)
5930*4882a593Smuzhiyun 		return -EOPNOTSUPP;
5931*4882a593Smuzhiyun 
5932*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
5933*4882a593Smuzhiyun 	if (ret < 0)
5934*4882a593Smuzhiyun 		goto out;
5935*4882a593Smuzhiyun 
5936*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5937*4882a593Smuzhiyun 
5938*4882a593Smuzhiyun 	mii_ethtool_get_link_ksettings(&tp->mii, cmd);
5939*4882a593Smuzhiyun 
5940*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5941*4882a593Smuzhiyun 
5942*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5943*4882a593Smuzhiyun 
5944*4882a593Smuzhiyun out:
5945*4882a593Smuzhiyun 	return ret;
5946*4882a593Smuzhiyun }
5947*4882a593Smuzhiyun 
rtl8152_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)5948*4882a593Smuzhiyun static int rtl8152_set_link_ksettings(struct net_device *dev,
5949*4882a593Smuzhiyun 				      const struct ethtool_link_ksettings *cmd)
5950*4882a593Smuzhiyun {
5951*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
5952*4882a593Smuzhiyun 	u32 advertising = 0;
5953*4882a593Smuzhiyun 	int ret;
5954*4882a593Smuzhiyun 
5955*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
5956*4882a593Smuzhiyun 	if (ret < 0)
5957*4882a593Smuzhiyun 		goto out;
5958*4882a593Smuzhiyun 
5959*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
5960*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5961*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_10_HALF;
5962*4882a593Smuzhiyun 
5963*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
5964*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5965*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_10_FULL;
5966*4882a593Smuzhiyun 
5967*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
5968*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5969*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_100_HALF;
5970*4882a593Smuzhiyun 
5971*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
5972*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5973*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_100_FULL;
5974*4882a593Smuzhiyun 
5975*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
5976*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5977*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_1000_HALF;
5978*4882a593Smuzhiyun 
5979*4882a593Smuzhiyun 	if (test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
5980*4882a593Smuzhiyun 		     cmd->link_modes.advertising))
5981*4882a593Smuzhiyun 		advertising |= RTL_ADVERTISED_1000_FULL;
5982*4882a593Smuzhiyun 
5983*4882a593Smuzhiyun 	mutex_lock(&tp->control);
5984*4882a593Smuzhiyun 
5985*4882a593Smuzhiyun 	ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
5986*4882a593Smuzhiyun 				cmd->base.duplex, advertising);
5987*4882a593Smuzhiyun 	if (!ret) {
5988*4882a593Smuzhiyun 		tp->autoneg = cmd->base.autoneg;
5989*4882a593Smuzhiyun 		tp->speed = cmd->base.speed;
5990*4882a593Smuzhiyun 		tp->duplex = cmd->base.duplex;
5991*4882a593Smuzhiyun 		tp->advertising = advertising;
5992*4882a593Smuzhiyun 	}
5993*4882a593Smuzhiyun 
5994*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
5995*4882a593Smuzhiyun 
5996*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
5997*4882a593Smuzhiyun 
5998*4882a593Smuzhiyun out:
5999*4882a593Smuzhiyun 	return ret;
6000*4882a593Smuzhiyun }
6001*4882a593Smuzhiyun 
6002*4882a593Smuzhiyun static const char rtl8152_gstrings[][ETH_GSTRING_LEN] = {
6003*4882a593Smuzhiyun 	"tx_packets",
6004*4882a593Smuzhiyun 	"rx_packets",
6005*4882a593Smuzhiyun 	"tx_errors",
6006*4882a593Smuzhiyun 	"rx_errors",
6007*4882a593Smuzhiyun 	"rx_missed",
6008*4882a593Smuzhiyun 	"align_errors",
6009*4882a593Smuzhiyun 	"tx_single_collisions",
6010*4882a593Smuzhiyun 	"tx_multi_collisions",
6011*4882a593Smuzhiyun 	"rx_unicast",
6012*4882a593Smuzhiyun 	"rx_broadcast",
6013*4882a593Smuzhiyun 	"rx_multicast",
6014*4882a593Smuzhiyun 	"tx_aborted",
6015*4882a593Smuzhiyun 	"tx_underrun",
6016*4882a593Smuzhiyun };
6017*4882a593Smuzhiyun 
rtl8152_get_sset_count(struct net_device * dev,int sset)6018*4882a593Smuzhiyun static int rtl8152_get_sset_count(struct net_device *dev, int sset)
6019*4882a593Smuzhiyun {
6020*4882a593Smuzhiyun 	switch (sset) {
6021*4882a593Smuzhiyun 	case ETH_SS_STATS:
6022*4882a593Smuzhiyun 		return ARRAY_SIZE(rtl8152_gstrings);
6023*4882a593Smuzhiyun 	default:
6024*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6025*4882a593Smuzhiyun 	}
6026*4882a593Smuzhiyun }
6027*4882a593Smuzhiyun 
rtl8152_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)6028*4882a593Smuzhiyun static void rtl8152_get_ethtool_stats(struct net_device *dev,
6029*4882a593Smuzhiyun 				      struct ethtool_stats *stats, u64 *data)
6030*4882a593Smuzhiyun {
6031*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
6032*4882a593Smuzhiyun 	struct tally_counter tally;
6033*4882a593Smuzhiyun 
6034*4882a593Smuzhiyun 	if (usb_autopm_get_interface(tp->intf) < 0)
6035*4882a593Smuzhiyun 		return;
6036*4882a593Smuzhiyun 
6037*4882a593Smuzhiyun 	generic_ocp_read(tp, PLA_TALLYCNT, sizeof(tally), &tally, MCU_TYPE_PLA);
6038*4882a593Smuzhiyun 
6039*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6040*4882a593Smuzhiyun 
6041*4882a593Smuzhiyun 	data[0] = le64_to_cpu(tally.tx_packets);
6042*4882a593Smuzhiyun 	data[1] = le64_to_cpu(tally.rx_packets);
6043*4882a593Smuzhiyun 	data[2] = le64_to_cpu(tally.tx_errors);
6044*4882a593Smuzhiyun 	data[3] = le32_to_cpu(tally.rx_errors);
6045*4882a593Smuzhiyun 	data[4] = le16_to_cpu(tally.rx_missed);
6046*4882a593Smuzhiyun 	data[5] = le16_to_cpu(tally.align_errors);
6047*4882a593Smuzhiyun 	data[6] = le32_to_cpu(tally.tx_one_collision);
6048*4882a593Smuzhiyun 	data[7] = le32_to_cpu(tally.tx_multi_collision);
6049*4882a593Smuzhiyun 	data[8] = le64_to_cpu(tally.rx_unicast);
6050*4882a593Smuzhiyun 	data[9] = le64_to_cpu(tally.rx_broadcast);
6051*4882a593Smuzhiyun 	data[10] = le32_to_cpu(tally.rx_multicast);
6052*4882a593Smuzhiyun 	data[11] = le16_to_cpu(tally.tx_aborted);
6053*4882a593Smuzhiyun 	data[12] = le16_to_cpu(tally.tx_underrun);
6054*4882a593Smuzhiyun }
6055*4882a593Smuzhiyun 
rtl8152_get_strings(struct net_device * dev,u32 stringset,u8 * data)6056*4882a593Smuzhiyun static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data)
6057*4882a593Smuzhiyun {
6058*4882a593Smuzhiyun 	switch (stringset) {
6059*4882a593Smuzhiyun 	case ETH_SS_STATS:
6060*4882a593Smuzhiyun 		memcpy(data, rtl8152_gstrings, sizeof(rtl8152_gstrings));
6061*4882a593Smuzhiyun 		break;
6062*4882a593Smuzhiyun 	}
6063*4882a593Smuzhiyun }
6064*4882a593Smuzhiyun 
r8152_get_eee(struct r8152 * tp,struct ethtool_eee * eee)6065*4882a593Smuzhiyun static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
6066*4882a593Smuzhiyun {
6067*4882a593Smuzhiyun 	u32 lp, adv, supported = 0;
6068*4882a593Smuzhiyun 	u16 val;
6069*4882a593Smuzhiyun 
6070*4882a593Smuzhiyun 	val = r8152_mmd_read(tp, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
6071*4882a593Smuzhiyun 	supported = mmd_eee_cap_to_ethtool_sup_t(val);
6072*4882a593Smuzhiyun 
6073*4882a593Smuzhiyun 	val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
6074*4882a593Smuzhiyun 	adv = mmd_eee_adv_to_ethtool_adv_t(val);
6075*4882a593Smuzhiyun 
6076*4882a593Smuzhiyun 	val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
6077*4882a593Smuzhiyun 	lp = mmd_eee_adv_to_ethtool_adv_t(val);
6078*4882a593Smuzhiyun 
6079*4882a593Smuzhiyun 	eee->eee_enabled = tp->eee_en;
6080*4882a593Smuzhiyun 	eee->eee_active = !!(supported & adv & lp);
6081*4882a593Smuzhiyun 	eee->supported = supported;
6082*4882a593Smuzhiyun 	eee->advertised = tp->eee_adv;
6083*4882a593Smuzhiyun 	eee->lp_advertised = lp;
6084*4882a593Smuzhiyun 
6085*4882a593Smuzhiyun 	return 0;
6086*4882a593Smuzhiyun }
6087*4882a593Smuzhiyun 
r8152_set_eee(struct r8152 * tp,struct ethtool_eee * eee)6088*4882a593Smuzhiyun static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
6089*4882a593Smuzhiyun {
6090*4882a593Smuzhiyun 	u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
6091*4882a593Smuzhiyun 
6092*4882a593Smuzhiyun 	tp->eee_en = eee->eee_enabled;
6093*4882a593Smuzhiyun 	tp->eee_adv = val;
6094*4882a593Smuzhiyun 
6095*4882a593Smuzhiyun 	rtl_eee_enable(tp, tp->eee_en);
6096*4882a593Smuzhiyun 
6097*4882a593Smuzhiyun 	return 0;
6098*4882a593Smuzhiyun }
6099*4882a593Smuzhiyun 
r8153_get_eee(struct r8152 * tp,struct ethtool_eee * eee)6100*4882a593Smuzhiyun static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
6101*4882a593Smuzhiyun {
6102*4882a593Smuzhiyun 	u32 lp, adv, supported = 0;
6103*4882a593Smuzhiyun 	u16 val;
6104*4882a593Smuzhiyun 
6105*4882a593Smuzhiyun 	val = ocp_reg_read(tp, OCP_EEE_ABLE);
6106*4882a593Smuzhiyun 	supported = mmd_eee_cap_to_ethtool_sup_t(val);
6107*4882a593Smuzhiyun 
6108*4882a593Smuzhiyun 	val = ocp_reg_read(tp, OCP_EEE_ADV);
6109*4882a593Smuzhiyun 	adv = mmd_eee_adv_to_ethtool_adv_t(val);
6110*4882a593Smuzhiyun 
6111*4882a593Smuzhiyun 	val = ocp_reg_read(tp, OCP_EEE_LPABLE);
6112*4882a593Smuzhiyun 	lp = mmd_eee_adv_to_ethtool_adv_t(val);
6113*4882a593Smuzhiyun 
6114*4882a593Smuzhiyun 	eee->eee_enabled = tp->eee_en;
6115*4882a593Smuzhiyun 	eee->eee_active = !!(supported & adv & lp);
6116*4882a593Smuzhiyun 	eee->supported = supported;
6117*4882a593Smuzhiyun 	eee->advertised = tp->eee_adv;
6118*4882a593Smuzhiyun 	eee->lp_advertised = lp;
6119*4882a593Smuzhiyun 
6120*4882a593Smuzhiyun 	return 0;
6121*4882a593Smuzhiyun }
6122*4882a593Smuzhiyun 
6123*4882a593Smuzhiyun static int
rtl_ethtool_get_eee(struct net_device * net,struct ethtool_eee * edata)6124*4882a593Smuzhiyun rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata)
6125*4882a593Smuzhiyun {
6126*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(net);
6127*4882a593Smuzhiyun 	int ret;
6128*4882a593Smuzhiyun 
6129*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
6130*4882a593Smuzhiyun 	if (ret < 0)
6131*4882a593Smuzhiyun 		goto out;
6132*4882a593Smuzhiyun 
6133*4882a593Smuzhiyun 	mutex_lock(&tp->control);
6134*4882a593Smuzhiyun 
6135*4882a593Smuzhiyun 	ret = tp->rtl_ops.eee_get(tp, edata);
6136*4882a593Smuzhiyun 
6137*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
6138*4882a593Smuzhiyun 
6139*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6140*4882a593Smuzhiyun 
6141*4882a593Smuzhiyun out:
6142*4882a593Smuzhiyun 	return ret;
6143*4882a593Smuzhiyun }
6144*4882a593Smuzhiyun 
6145*4882a593Smuzhiyun static int
rtl_ethtool_set_eee(struct net_device * net,struct ethtool_eee * edata)6146*4882a593Smuzhiyun rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata)
6147*4882a593Smuzhiyun {
6148*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(net);
6149*4882a593Smuzhiyun 	int ret;
6150*4882a593Smuzhiyun 
6151*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
6152*4882a593Smuzhiyun 	if (ret < 0)
6153*4882a593Smuzhiyun 		goto out;
6154*4882a593Smuzhiyun 
6155*4882a593Smuzhiyun 	mutex_lock(&tp->control);
6156*4882a593Smuzhiyun 
6157*4882a593Smuzhiyun 	ret = tp->rtl_ops.eee_set(tp, edata);
6158*4882a593Smuzhiyun 	if (!ret)
6159*4882a593Smuzhiyun 		ret = mii_nway_restart(&tp->mii);
6160*4882a593Smuzhiyun 
6161*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
6162*4882a593Smuzhiyun 
6163*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6164*4882a593Smuzhiyun 
6165*4882a593Smuzhiyun out:
6166*4882a593Smuzhiyun 	return ret;
6167*4882a593Smuzhiyun }
6168*4882a593Smuzhiyun 
rtl8152_nway_reset(struct net_device * dev)6169*4882a593Smuzhiyun static int rtl8152_nway_reset(struct net_device *dev)
6170*4882a593Smuzhiyun {
6171*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
6172*4882a593Smuzhiyun 	int ret;
6173*4882a593Smuzhiyun 
6174*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
6175*4882a593Smuzhiyun 	if (ret < 0)
6176*4882a593Smuzhiyun 		goto out;
6177*4882a593Smuzhiyun 
6178*4882a593Smuzhiyun 	mutex_lock(&tp->control);
6179*4882a593Smuzhiyun 
6180*4882a593Smuzhiyun 	ret = mii_nway_restart(&tp->mii);
6181*4882a593Smuzhiyun 
6182*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
6183*4882a593Smuzhiyun 
6184*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6185*4882a593Smuzhiyun 
6186*4882a593Smuzhiyun out:
6187*4882a593Smuzhiyun 	return ret;
6188*4882a593Smuzhiyun }
6189*4882a593Smuzhiyun 
rtl8152_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * coalesce)6190*4882a593Smuzhiyun static int rtl8152_get_coalesce(struct net_device *netdev,
6191*4882a593Smuzhiyun 				struct ethtool_coalesce *coalesce)
6192*4882a593Smuzhiyun {
6193*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6194*4882a593Smuzhiyun 
6195*4882a593Smuzhiyun 	switch (tp->version) {
6196*4882a593Smuzhiyun 	case RTL_VER_01:
6197*4882a593Smuzhiyun 	case RTL_VER_02:
6198*4882a593Smuzhiyun 	case RTL_VER_07:
6199*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6200*4882a593Smuzhiyun 	default:
6201*4882a593Smuzhiyun 		break;
6202*4882a593Smuzhiyun 	}
6203*4882a593Smuzhiyun 
6204*4882a593Smuzhiyun 	coalesce->rx_coalesce_usecs = tp->coalesce;
6205*4882a593Smuzhiyun 
6206*4882a593Smuzhiyun 	return 0;
6207*4882a593Smuzhiyun }
6208*4882a593Smuzhiyun 
rtl8152_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * coalesce)6209*4882a593Smuzhiyun static int rtl8152_set_coalesce(struct net_device *netdev,
6210*4882a593Smuzhiyun 				struct ethtool_coalesce *coalesce)
6211*4882a593Smuzhiyun {
6212*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6213*4882a593Smuzhiyun 	int ret;
6214*4882a593Smuzhiyun 
6215*4882a593Smuzhiyun 	switch (tp->version) {
6216*4882a593Smuzhiyun 	case RTL_VER_01:
6217*4882a593Smuzhiyun 	case RTL_VER_02:
6218*4882a593Smuzhiyun 	case RTL_VER_07:
6219*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6220*4882a593Smuzhiyun 	default:
6221*4882a593Smuzhiyun 		break;
6222*4882a593Smuzhiyun 	}
6223*4882a593Smuzhiyun 
6224*4882a593Smuzhiyun 	if (coalesce->rx_coalesce_usecs > COALESCE_SLOW)
6225*4882a593Smuzhiyun 		return -EINVAL;
6226*4882a593Smuzhiyun 
6227*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
6228*4882a593Smuzhiyun 	if (ret < 0)
6229*4882a593Smuzhiyun 		return ret;
6230*4882a593Smuzhiyun 
6231*4882a593Smuzhiyun 	mutex_lock(&tp->control);
6232*4882a593Smuzhiyun 
6233*4882a593Smuzhiyun 	if (tp->coalesce != coalesce->rx_coalesce_usecs) {
6234*4882a593Smuzhiyun 		tp->coalesce = coalesce->rx_coalesce_usecs;
6235*4882a593Smuzhiyun 
6236*4882a593Smuzhiyun 		if (netif_running(netdev) && netif_carrier_ok(netdev)) {
6237*4882a593Smuzhiyun 			netif_stop_queue(netdev);
6238*4882a593Smuzhiyun 			napi_disable(&tp->napi);
6239*4882a593Smuzhiyun 			tp->rtl_ops.disable(tp);
6240*4882a593Smuzhiyun 			tp->rtl_ops.enable(tp);
6241*4882a593Smuzhiyun 			rtl_start_rx(tp);
6242*4882a593Smuzhiyun 			clear_bit(RTL8152_SET_RX_MODE, &tp->flags);
6243*4882a593Smuzhiyun 			_rtl8152_set_rx_mode(netdev);
6244*4882a593Smuzhiyun 			napi_enable(&tp->napi);
6245*4882a593Smuzhiyun 			netif_wake_queue(netdev);
6246*4882a593Smuzhiyun 		}
6247*4882a593Smuzhiyun 	}
6248*4882a593Smuzhiyun 
6249*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
6250*4882a593Smuzhiyun 
6251*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6252*4882a593Smuzhiyun 
6253*4882a593Smuzhiyun 	return ret;
6254*4882a593Smuzhiyun }
6255*4882a593Smuzhiyun 
rtl8152_get_tunable(struct net_device * netdev,const struct ethtool_tunable * tunable,void * d)6256*4882a593Smuzhiyun static int rtl8152_get_tunable(struct net_device *netdev,
6257*4882a593Smuzhiyun 			       const struct ethtool_tunable *tunable, void *d)
6258*4882a593Smuzhiyun {
6259*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6260*4882a593Smuzhiyun 
6261*4882a593Smuzhiyun 	switch (tunable->id) {
6262*4882a593Smuzhiyun 	case ETHTOOL_RX_COPYBREAK:
6263*4882a593Smuzhiyun 		*(u32 *)d = tp->rx_copybreak;
6264*4882a593Smuzhiyun 		break;
6265*4882a593Smuzhiyun 	default:
6266*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6267*4882a593Smuzhiyun 	}
6268*4882a593Smuzhiyun 
6269*4882a593Smuzhiyun 	return 0;
6270*4882a593Smuzhiyun }
6271*4882a593Smuzhiyun 
rtl8152_set_tunable(struct net_device * netdev,const struct ethtool_tunable * tunable,const void * d)6272*4882a593Smuzhiyun static int rtl8152_set_tunable(struct net_device *netdev,
6273*4882a593Smuzhiyun 			       const struct ethtool_tunable *tunable,
6274*4882a593Smuzhiyun 			       const void *d)
6275*4882a593Smuzhiyun {
6276*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6277*4882a593Smuzhiyun 	u32 val;
6278*4882a593Smuzhiyun 
6279*4882a593Smuzhiyun 	switch (tunable->id) {
6280*4882a593Smuzhiyun 	case ETHTOOL_RX_COPYBREAK:
6281*4882a593Smuzhiyun 		val = *(u32 *)d;
6282*4882a593Smuzhiyun 		if (val < ETH_ZLEN) {
6283*4882a593Smuzhiyun 			netif_err(tp, rx_err, netdev,
6284*4882a593Smuzhiyun 				  "Invalid rx copy break value\n");
6285*4882a593Smuzhiyun 			return -EINVAL;
6286*4882a593Smuzhiyun 		}
6287*4882a593Smuzhiyun 
6288*4882a593Smuzhiyun 		if (tp->rx_copybreak != val) {
6289*4882a593Smuzhiyun 			if (netdev->flags & IFF_UP) {
6290*4882a593Smuzhiyun 				mutex_lock(&tp->control);
6291*4882a593Smuzhiyun 				napi_disable(&tp->napi);
6292*4882a593Smuzhiyun 				tp->rx_copybreak = val;
6293*4882a593Smuzhiyun 				napi_enable(&tp->napi);
6294*4882a593Smuzhiyun 				mutex_unlock(&tp->control);
6295*4882a593Smuzhiyun 			} else {
6296*4882a593Smuzhiyun 				tp->rx_copybreak = val;
6297*4882a593Smuzhiyun 			}
6298*4882a593Smuzhiyun 		}
6299*4882a593Smuzhiyun 		break;
6300*4882a593Smuzhiyun 	default:
6301*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6302*4882a593Smuzhiyun 	}
6303*4882a593Smuzhiyun 
6304*4882a593Smuzhiyun 	return 0;
6305*4882a593Smuzhiyun }
6306*4882a593Smuzhiyun 
rtl8152_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring)6307*4882a593Smuzhiyun static void rtl8152_get_ringparam(struct net_device *netdev,
6308*4882a593Smuzhiyun 				  struct ethtool_ringparam *ring)
6309*4882a593Smuzhiyun {
6310*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6311*4882a593Smuzhiyun 
6312*4882a593Smuzhiyun 	ring->rx_max_pending = RTL8152_RX_MAX_PENDING;
6313*4882a593Smuzhiyun 	ring->rx_pending = tp->rx_pending;
6314*4882a593Smuzhiyun }
6315*4882a593Smuzhiyun 
rtl8152_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring)6316*4882a593Smuzhiyun static int rtl8152_set_ringparam(struct net_device *netdev,
6317*4882a593Smuzhiyun 				 struct ethtool_ringparam *ring)
6318*4882a593Smuzhiyun {
6319*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6320*4882a593Smuzhiyun 
6321*4882a593Smuzhiyun 	if (ring->rx_pending < (RTL8152_MAX_RX * 2))
6322*4882a593Smuzhiyun 		return -EINVAL;
6323*4882a593Smuzhiyun 
6324*4882a593Smuzhiyun 	if (tp->rx_pending != ring->rx_pending) {
6325*4882a593Smuzhiyun 		if (netdev->flags & IFF_UP) {
6326*4882a593Smuzhiyun 			mutex_lock(&tp->control);
6327*4882a593Smuzhiyun 			napi_disable(&tp->napi);
6328*4882a593Smuzhiyun 			tp->rx_pending = ring->rx_pending;
6329*4882a593Smuzhiyun 			napi_enable(&tp->napi);
6330*4882a593Smuzhiyun 			mutex_unlock(&tp->control);
6331*4882a593Smuzhiyun 		} else {
6332*4882a593Smuzhiyun 			tp->rx_pending = ring->rx_pending;
6333*4882a593Smuzhiyun 		}
6334*4882a593Smuzhiyun 	}
6335*4882a593Smuzhiyun 
6336*4882a593Smuzhiyun 	return 0;
6337*4882a593Smuzhiyun }
6338*4882a593Smuzhiyun 
6339*4882a593Smuzhiyun static const struct ethtool_ops ops = {
6340*4882a593Smuzhiyun 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
6341*4882a593Smuzhiyun 	.get_drvinfo = rtl8152_get_drvinfo,
6342*4882a593Smuzhiyun 	.get_link = ethtool_op_get_link,
6343*4882a593Smuzhiyun 	.nway_reset = rtl8152_nway_reset,
6344*4882a593Smuzhiyun 	.get_msglevel = rtl8152_get_msglevel,
6345*4882a593Smuzhiyun 	.set_msglevel = rtl8152_set_msglevel,
6346*4882a593Smuzhiyun 	.get_wol = rtl8152_get_wol,
6347*4882a593Smuzhiyun 	.set_wol = rtl8152_set_wol,
6348*4882a593Smuzhiyun 	.get_strings = rtl8152_get_strings,
6349*4882a593Smuzhiyun 	.get_sset_count = rtl8152_get_sset_count,
6350*4882a593Smuzhiyun 	.get_ethtool_stats = rtl8152_get_ethtool_stats,
6351*4882a593Smuzhiyun 	.get_coalesce = rtl8152_get_coalesce,
6352*4882a593Smuzhiyun 	.set_coalesce = rtl8152_set_coalesce,
6353*4882a593Smuzhiyun 	.get_eee = rtl_ethtool_get_eee,
6354*4882a593Smuzhiyun 	.set_eee = rtl_ethtool_set_eee,
6355*4882a593Smuzhiyun 	.get_link_ksettings = rtl8152_get_link_ksettings,
6356*4882a593Smuzhiyun 	.set_link_ksettings = rtl8152_set_link_ksettings,
6357*4882a593Smuzhiyun 	.get_tunable = rtl8152_get_tunable,
6358*4882a593Smuzhiyun 	.set_tunable = rtl8152_set_tunable,
6359*4882a593Smuzhiyun 	.get_ringparam = rtl8152_get_ringparam,
6360*4882a593Smuzhiyun 	.set_ringparam = rtl8152_set_ringparam,
6361*4882a593Smuzhiyun };
6362*4882a593Smuzhiyun 
rtl8152_ioctl(struct net_device * netdev,struct ifreq * rq,int cmd)6363*4882a593Smuzhiyun static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
6364*4882a593Smuzhiyun {
6365*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(netdev);
6366*4882a593Smuzhiyun 	struct mii_ioctl_data *data = if_mii(rq);
6367*4882a593Smuzhiyun 	int res;
6368*4882a593Smuzhiyun 
6369*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
6370*4882a593Smuzhiyun 		return -ENODEV;
6371*4882a593Smuzhiyun 
6372*4882a593Smuzhiyun 	res = usb_autopm_get_interface(tp->intf);
6373*4882a593Smuzhiyun 	if (res < 0)
6374*4882a593Smuzhiyun 		goto out;
6375*4882a593Smuzhiyun 
6376*4882a593Smuzhiyun 	switch (cmd) {
6377*4882a593Smuzhiyun 	case SIOCGMIIPHY:
6378*4882a593Smuzhiyun 		data->phy_id = R8152_PHY_ID; /* Internal PHY */
6379*4882a593Smuzhiyun 		break;
6380*4882a593Smuzhiyun 
6381*4882a593Smuzhiyun 	case SIOCGMIIREG:
6382*4882a593Smuzhiyun 		mutex_lock(&tp->control);
6383*4882a593Smuzhiyun 		data->val_out = r8152_mdio_read(tp, data->reg_num);
6384*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
6385*4882a593Smuzhiyun 		break;
6386*4882a593Smuzhiyun 
6387*4882a593Smuzhiyun 	case SIOCSMIIREG:
6388*4882a593Smuzhiyun 		if (!capable(CAP_NET_ADMIN)) {
6389*4882a593Smuzhiyun 			res = -EPERM;
6390*4882a593Smuzhiyun 			break;
6391*4882a593Smuzhiyun 		}
6392*4882a593Smuzhiyun 		mutex_lock(&tp->control);
6393*4882a593Smuzhiyun 		r8152_mdio_write(tp, data->reg_num, data->val_in);
6394*4882a593Smuzhiyun 		mutex_unlock(&tp->control);
6395*4882a593Smuzhiyun 		break;
6396*4882a593Smuzhiyun 
6397*4882a593Smuzhiyun 	default:
6398*4882a593Smuzhiyun 		res = -EOPNOTSUPP;
6399*4882a593Smuzhiyun 	}
6400*4882a593Smuzhiyun 
6401*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6402*4882a593Smuzhiyun 
6403*4882a593Smuzhiyun out:
6404*4882a593Smuzhiyun 	return res;
6405*4882a593Smuzhiyun }
6406*4882a593Smuzhiyun 
rtl8152_change_mtu(struct net_device * dev,int new_mtu)6407*4882a593Smuzhiyun static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
6408*4882a593Smuzhiyun {
6409*4882a593Smuzhiyun 	struct r8152 *tp = netdev_priv(dev);
6410*4882a593Smuzhiyun 	int ret;
6411*4882a593Smuzhiyun 
6412*4882a593Smuzhiyun 	switch (tp->version) {
6413*4882a593Smuzhiyun 	case RTL_VER_01:
6414*4882a593Smuzhiyun 	case RTL_VER_02:
6415*4882a593Smuzhiyun 	case RTL_VER_07:
6416*4882a593Smuzhiyun 		dev->mtu = new_mtu;
6417*4882a593Smuzhiyun 		return 0;
6418*4882a593Smuzhiyun 	default:
6419*4882a593Smuzhiyun 		break;
6420*4882a593Smuzhiyun 	}
6421*4882a593Smuzhiyun 
6422*4882a593Smuzhiyun 	ret = usb_autopm_get_interface(tp->intf);
6423*4882a593Smuzhiyun 	if (ret < 0)
6424*4882a593Smuzhiyun 		return ret;
6425*4882a593Smuzhiyun 
6426*4882a593Smuzhiyun 	mutex_lock(&tp->control);
6427*4882a593Smuzhiyun 
6428*4882a593Smuzhiyun 	dev->mtu = new_mtu;
6429*4882a593Smuzhiyun 
6430*4882a593Smuzhiyun 	if (netif_running(dev)) {
6431*4882a593Smuzhiyun 		u32 rms = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
6432*4882a593Smuzhiyun 
6433*4882a593Smuzhiyun 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms);
6434*4882a593Smuzhiyun 
6435*4882a593Smuzhiyun 		if (netif_carrier_ok(dev))
6436*4882a593Smuzhiyun 			r8153_set_rx_early_size(tp);
6437*4882a593Smuzhiyun 	}
6438*4882a593Smuzhiyun 
6439*4882a593Smuzhiyun 	mutex_unlock(&tp->control);
6440*4882a593Smuzhiyun 
6441*4882a593Smuzhiyun 	usb_autopm_put_interface(tp->intf);
6442*4882a593Smuzhiyun 
6443*4882a593Smuzhiyun 	return ret;
6444*4882a593Smuzhiyun }
6445*4882a593Smuzhiyun 
6446*4882a593Smuzhiyun static const struct net_device_ops rtl8152_netdev_ops = {
6447*4882a593Smuzhiyun 	.ndo_open		= rtl8152_open,
6448*4882a593Smuzhiyun 	.ndo_stop		= rtl8152_close,
6449*4882a593Smuzhiyun 	.ndo_do_ioctl		= rtl8152_ioctl,
6450*4882a593Smuzhiyun 	.ndo_start_xmit		= rtl8152_start_xmit,
6451*4882a593Smuzhiyun 	.ndo_tx_timeout		= rtl8152_tx_timeout,
6452*4882a593Smuzhiyun 	.ndo_set_features	= rtl8152_set_features,
6453*4882a593Smuzhiyun 	.ndo_set_rx_mode	= rtl8152_set_rx_mode,
6454*4882a593Smuzhiyun 	.ndo_set_mac_address	= rtl8152_set_mac_address,
6455*4882a593Smuzhiyun 	.ndo_change_mtu		= rtl8152_change_mtu,
6456*4882a593Smuzhiyun 	.ndo_validate_addr	= eth_validate_addr,
6457*4882a593Smuzhiyun 	.ndo_features_check	= rtl8152_features_check,
6458*4882a593Smuzhiyun };
6459*4882a593Smuzhiyun 
rtl8152_unload(struct r8152 * tp)6460*4882a593Smuzhiyun static void rtl8152_unload(struct r8152 *tp)
6461*4882a593Smuzhiyun {
6462*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
6463*4882a593Smuzhiyun 		return;
6464*4882a593Smuzhiyun 
6465*4882a593Smuzhiyun 	if (tp->version != RTL_VER_01)
6466*4882a593Smuzhiyun 		r8152_power_cut_en(tp, true);
6467*4882a593Smuzhiyun }
6468*4882a593Smuzhiyun 
rtl8153_unload(struct r8152 * tp)6469*4882a593Smuzhiyun static void rtl8153_unload(struct r8152 *tp)
6470*4882a593Smuzhiyun {
6471*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
6472*4882a593Smuzhiyun 		return;
6473*4882a593Smuzhiyun 
6474*4882a593Smuzhiyun 	r8153_power_cut_en(tp, false);
6475*4882a593Smuzhiyun }
6476*4882a593Smuzhiyun 
rtl8153b_unload(struct r8152 * tp)6477*4882a593Smuzhiyun static void rtl8153b_unload(struct r8152 *tp)
6478*4882a593Smuzhiyun {
6479*4882a593Smuzhiyun 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
6480*4882a593Smuzhiyun 		return;
6481*4882a593Smuzhiyun 
6482*4882a593Smuzhiyun 	r8153b_power_cut_en(tp, false);
6483*4882a593Smuzhiyun }
6484*4882a593Smuzhiyun 
rtl_ops_init(struct r8152 * tp)6485*4882a593Smuzhiyun static int rtl_ops_init(struct r8152 *tp)
6486*4882a593Smuzhiyun {
6487*4882a593Smuzhiyun 	struct rtl_ops *ops = &tp->rtl_ops;
6488*4882a593Smuzhiyun 	int ret = 0;
6489*4882a593Smuzhiyun 
6490*4882a593Smuzhiyun 	switch (tp->version) {
6491*4882a593Smuzhiyun 	case RTL_VER_01:
6492*4882a593Smuzhiyun 	case RTL_VER_02:
6493*4882a593Smuzhiyun 	case RTL_VER_07:
6494*4882a593Smuzhiyun 		ops->init		= r8152b_init;
6495*4882a593Smuzhiyun 		ops->enable		= rtl8152_enable;
6496*4882a593Smuzhiyun 		ops->disable		= rtl8152_disable;
6497*4882a593Smuzhiyun 		ops->up			= rtl8152_up;
6498*4882a593Smuzhiyun 		ops->down		= rtl8152_down;
6499*4882a593Smuzhiyun 		ops->unload		= rtl8152_unload;
6500*4882a593Smuzhiyun 		ops->eee_get		= r8152_get_eee;
6501*4882a593Smuzhiyun 		ops->eee_set		= r8152_set_eee;
6502*4882a593Smuzhiyun 		ops->in_nway		= rtl8152_in_nway;
6503*4882a593Smuzhiyun 		ops->hw_phy_cfg		= r8152b_hw_phy_cfg;
6504*4882a593Smuzhiyun 		ops->autosuspend_en	= rtl_runtime_suspend_enable;
6505*4882a593Smuzhiyun 		tp->rx_buf_sz		= 16 * 1024;
6506*4882a593Smuzhiyun 		tp->eee_en		= true;
6507*4882a593Smuzhiyun 		tp->eee_adv		= MDIO_EEE_100TX;
6508*4882a593Smuzhiyun 		break;
6509*4882a593Smuzhiyun 
6510*4882a593Smuzhiyun 	case RTL_VER_03:
6511*4882a593Smuzhiyun 	case RTL_VER_04:
6512*4882a593Smuzhiyun 	case RTL_VER_05:
6513*4882a593Smuzhiyun 	case RTL_VER_06:
6514*4882a593Smuzhiyun 		ops->init		= r8153_init;
6515*4882a593Smuzhiyun 		ops->enable		= rtl8153_enable;
6516*4882a593Smuzhiyun 		ops->disable		= rtl8153_disable;
6517*4882a593Smuzhiyun 		ops->up			= rtl8153_up;
6518*4882a593Smuzhiyun 		ops->down		= rtl8153_down;
6519*4882a593Smuzhiyun 		ops->unload		= rtl8153_unload;
6520*4882a593Smuzhiyun 		ops->eee_get		= r8153_get_eee;
6521*4882a593Smuzhiyun 		ops->eee_set		= r8152_set_eee;
6522*4882a593Smuzhiyun 		ops->in_nway		= rtl8153_in_nway;
6523*4882a593Smuzhiyun 		ops->hw_phy_cfg		= r8153_hw_phy_cfg;
6524*4882a593Smuzhiyun 		ops->autosuspend_en	= rtl8153_runtime_enable;
6525*4882a593Smuzhiyun 		if (tp->udev->speed < USB_SPEED_SUPER)
6526*4882a593Smuzhiyun 			tp->rx_buf_sz	= 16 * 1024;
6527*4882a593Smuzhiyun 		else
6528*4882a593Smuzhiyun 			tp->rx_buf_sz	= 32 * 1024;
6529*4882a593Smuzhiyun 		tp->eee_en		= true;
6530*4882a593Smuzhiyun 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
6531*4882a593Smuzhiyun 		break;
6532*4882a593Smuzhiyun 
6533*4882a593Smuzhiyun 	case RTL_VER_08:
6534*4882a593Smuzhiyun 	case RTL_VER_09:
6535*4882a593Smuzhiyun 		ops->init		= r8153b_init;
6536*4882a593Smuzhiyun 		ops->enable		= rtl8153_enable;
6537*4882a593Smuzhiyun 		ops->disable		= rtl8153_disable;
6538*4882a593Smuzhiyun 		ops->up			= rtl8153b_up;
6539*4882a593Smuzhiyun 		ops->down		= rtl8153b_down;
6540*4882a593Smuzhiyun 		ops->unload		= rtl8153b_unload;
6541*4882a593Smuzhiyun 		ops->eee_get		= r8153_get_eee;
6542*4882a593Smuzhiyun 		ops->eee_set		= r8152_set_eee;
6543*4882a593Smuzhiyun 		ops->in_nway		= rtl8153_in_nway;
6544*4882a593Smuzhiyun 		ops->hw_phy_cfg		= r8153b_hw_phy_cfg;
6545*4882a593Smuzhiyun 		ops->autosuspend_en	= rtl8153b_runtime_enable;
6546*4882a593Smuzhiyun 		tp->rx_buf_sz		= 32 * 1024;
6547*4882a593Smuzhiyun 		tp->eee_en		= true;
6548*4882a593Smuzhiyun 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
6549*4882a593Smuzhiyun 		break;
6550*4882a593Smuzhiyun 
6551*4882a593Smuzhiyun 	default:
6552*4882a593Smuzhiyun 		ret = -ENODEV;
6553*4882a593Smuzhiyun 		netif_err(tp, probe, tp->netdev, "Unknown Device\n");
6554*4882a593Smuzhiyun 		break;
6555*4882a593Smuzhiyun 	}
6556*4882a593Smuzhiyun 
6557*4882a593Smuzhiyun 	return ret;
6558*4882a593Smuzhiyun }
6559*4882a593Smuzhiyun 
6560*4882a593Smuzhiyun #define FIRMWARE_8153A_2	"rtl_nic/rtl8153a-2.fw"
6561*4882a593Smuzhiyun #define FIRMWARE_8153A_3	"rtl_nic/rtl8153a-3.fw"
6562*4882a593Smuzhiyun #define FIRMWARE_8153A_4	"rtl_nic/rtl8153a-4.fw"
6563*4882a593Smuzhiyun #define FIRMWARE_8153B_2	"rtl_nic/rtl8153b-2.fw"
6564*4882a593Smuzhiyun 
6565*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_8153A_2);
6566*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_8153A_3);
6567*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_8153A_4);
6568*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_8153B_2);
6569*4882a593Smuzhiyun 
rtl_fw_init(struct r8152 * tp)6570*4882a593Smuzhiyun static int rtl_fw_init(struct r8152 *tp)
6571*4882a593Smuzhiyun {
6572*4882a593Smuzhiyun 	struct rtl_fw *rtl_fw = &tp->rtl_fw;
6573*4882a593Smuzhiyun 
6574*4882a593Smuzhiyun 	switch (tp->version) {
6575*4882a593Smuzhiyun 	case RTL_VER_04:
6576*4882a593Smuzhiyun 		rtl_fw->fw_name		= FIRMWARE_8153A_2;
6577*4882a593Smuzhiyun 		rtl_fw->pre_fw		= r8153_pre_firmware_1;
6578*4882a593Smuzhiyun 		rtl_fw->post_fw		= r8153_post_firmware_1;
6579*4882a593Smuzhiyun 		break;
6580*4882a593Smuzhiyun 	case RTL_VER_05:
6581*4882a593Smuzhiyun 		rtl_fw->fw_name		= FIRMWARE_8153A_3;
6582*4882a593Smuzhiyun 		rtl_fw->pre_fw		= r8153_pre_firmware_2;
6583*4882a593Smuzhiyun 		rtl_fw->post_fw		= r8153_post_firmware_2;
6584*4882a593Smuzhiyun 		break;
6585*4882a593Smuzhiyun 	case RTL_VER_06:
6586*4882a593Smuzhiyun 		rtl_fw->fw_name		= FIRMWARE_8153A_4;
6587*4882a593Smuzhiyun 		rtl_fw->post_fw		= r8153_post_firmware_3;
6588*4882a593Smuzhiyun 		break;
6589*4882a593Smuzhiyun 	case RTL_VER_09:
6590*4882a593Smuzhiyun 		rtl_fw->fw_name		= FIRMWARE_8153B_2;
6591*4882a593Smuzhiyun 		rtl_fw->pre_fw		= r8153b_pre_firmware_1;
6592*4882a593Smuzhiyun 		rtl_fw->post_fw		= r8153b_post_firmware_1;
6593*4882a593Smuzhiyun 		break;
6594*4882a593Smuzhiyun 	default:
6595*4882a593Smuzhiyun 		break;
6596*4882a593Smuzhiyun 	}
6597*4882a593Smuzhiyun 
6598*4882a593Smuzhiyun 	return 0;
6599*4882a593Smuzhiyun }
6600*4882a593Smuzhiyun 
rtl_get_version(struct usb_interface * intf)6601*4882a593Smuzhiyun static u8 rtl_get_version(struct usb_interface *intf)
6602*4882a593Smuzhiyun {
6603*4882a593Smuzhiyun 	struct usb_device *udev = interface_to_usbdev(intf);
6604*4882a593Smuzhiyun 	u32 ocp_data = 0;
6605*4882a593Smuzhiyun 	__le32 *tmp;
6606*4882a593Smuzhiyun 	u8 version;
6607*4882a593Smuzhiyun 	int ret;
6608*4882a593Smuzhiyun 
6609*4882a593Smuzhiyun 	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
6610*4882a593Smuzhiyun 	if (!tmp)
6611*4882a593Smuzhiyun 		return 0;
6612*4882a593Smuzhiyun 
6613*4882a593Smuzhiyun 	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
6614*4882a593Smuzhiyun 			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
6615*4882a593Smuzhiyun 			      PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500);
6616*4882a593Smuzhiyun 	if (ret > 0)
6617*4882a593Smuzhiyun 		ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
6618*4882a593Smuzhiyun 
6619*4882a593Smuzhiyun 	kfree(tmp);
6620*4882a593Smuzhiyun 
6621*4882a593Smuzhiyun 	switch (ocp_data) {
6622*4882a593Smuzhiyun 	case 0x4c00:
6623*4882a593Smuzhiyun 		version = RTL_VER_01;
6624*4882a593Smuzhiyun 		break;
6625*4882a593Smuzhiyun 	case 0x4c10:
6626*4882a593Smuzhiyun 		version = RTL_VER_02;
6627*4882a593Smuzhiyun 		break;
6628*4882a593Smuzhiyun 	case 0x5c00:
6629*4882a593Smuzhiyun 		version = RTL_VER_03;
6630*4882a593Smuzhiyun 		break;
6631*4882a593Smuzhiyun 	case 0x5c10:
6632*4882a593Smuzhiyun 		version = RTL_VER_04;
6633*4882a593Smuzhiyun 		break;
6634*4882a593Smuzhiyun 	case 0x5c20:
6635*4882a593Smuzhiyun 		version = RTL_VER_05;
6636*4882a593Smuzhiyun 		break;
6637*4882a593Smuzhiyun 	case 0x5c30:
6638*4882a593Smuzhiyun 		version = RTL_VER_06;
6639*4882a593Smuzhiyun 		break;
6640*4882a593Smuzhiyun 	case 0x4800:
6641*4882a593Smuzhiyun 		version = RTL_VER_07;
6642*4882a593Smuzhiyun 		break;
6643*4882a593Smuzhiyun 	case 0x6000:
6644*4882a593Smuzhiyun 		version = RTL_VER_08;
6645*4882a593Smuzhiyun 		break;
6646*4882a593Smuzhiyun 	case 0x6010:
6647*4882a593Smuzhiyun 		version = RTL_VER_09;
6648*4882a593Smuzhiyun 		break;
6649*4882a593Smuzhiyun 	default:
6650*4882a593Smuzhiyun 		version = RTL_VER_UNKNOWN;
6651*4882a593Smuzhiyun 		dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data);
6652*4882a593Smuzhiyun 		break;
6653*4882a593Smuzhiyun 	}
6654*4882a593Smuzhiyun 
6655*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "Detected version 0x%04x\n", version);
6656*4882a593Smuzhiyun 
6657*4882a593Smuzhiyun 	return version;
6658*4882a593Smuzhiyun }
6659*4882a593Smuzhiyun 
rtl8152_probe(struct usb_interface * intf,const struct usb_device_id * id)6660*4882a593Smuzhiyun static int rtl8152_probe(struct usb_interface *intf,
6661*4882a593Smuzhiyun 			 const struct usb_device_id *id)
6662*4882a593Smuzhiyun {
6663*4882a593Smuzhiyun 	struct usb_device *udev = interface_to_usbdev(intf);
6664*4882a593Smuzhiyun 	u8 version = rtl_get_version(intf);
6665*4882a593Smuzhiyun 	struct r8152 *tp;
6666*4882a593Smuzhiyun 	struct net_device *netdev;
6667*4882a593Smuzhiyun 	int ret;
6668*4882a593Smuzhiyun 
6669*4882a593Smuzhiyun 	if (version == RTL_VER_UNKNOWN)
6670*4882a593Smuzhiyun 		return -ENODEV;
6671*4882a593Smuzhiyun 
6672*4882a593Smuzhiyun 	if (udev->actconfig->desc.bConfigurationValue != 1) {
6673*4882a593Smuzhiyun 		usb_driver_set_configuration(udev, 1);
6674*4882a593Smuzhiyun 		return -ENODEV;
6675*4882a593Smuzhiyun 	}
6676*4882a593Smuzhiyun 
6677*4882a593Smuzhiyun 	if (intf->cur_altsetting->desc.bNumEndpoints < 3)
6678*4882a593Smuzhiyun 		return -ENODEV;
6679*4882a593Smuzhiyun 
6680*4882a593Smuzhiyun 	usb_reset_device(udev);
6681*4882a593Smuzhiyun 	netdev = alloc_etherdev(sizeof(struct r8152));
6682*4882a593Smuzhiyun 	if (!netdev) {
6683*4882a593Smuzhiyun 		dev_err(&intf->dev, "Out of memory\n");
6684*4882a593Smuzhiyun 		return -ENOMEM;
6685*4882a593Smuzhiyun 	}
6686*4882a593Smuzhiyun 
6687*4882a593Smuzhiyun 	SET_NETDEV_DEV(netdev, &intf->dev);
6688*4882a593Smuzhiyun 	tp = netdev_priv(netdev);
6689*4882a593Smuzhiyun 	tp->msg_enable = 0x7FFF;
6690*4882a593Smuzhiyun 
6691*4882a593Smuzhiyun 	tp->udev = udev;
6692*4882a593Smuzhiyun 	tp->netdev = netdev;
6693*4882a593Smuzhiyun 	tp->intf = intf;
6694*4882a593Smuzhiyun 	tp->version = version;
6695*4882a593Smuzhiyun 
6696*4882a593Smuzhiyun 	switch (version) {
6697*4882a593Smuzhiyun 	case RTL_VER_01:
6698*4882a593Smuzhiyun 	case RTL_VER_02:
6699*4882a593Smuzhiyun 	case RTL_VER_07:
6700*4882a593Smuzhiyun 		tp->mii.supports_gmii = 0;
6701*4882a593Smuzhiyun 		break;
6702*4882a593Smuzhiyun 	default:
6703*4882a593Smuzhiyun 		tp->mii.supports_gmii = 1;
6704*4882a593Smuzhiyun 		break;
6705*4882a593Smuzhiyun 	}
6706*4882a593Smuzhiyun 
6707*4882a593Smuzhiyun 	ret = rtl_ops_init(tp);
6708*4882a593Smuzhiyun 	if (ret)
6709*4882a593Smuzhiyun 		goto out;
6710*4882a593Smuzhiyun 
6711*4882a593Smuzhiyun 	rtl_fw_init(tp);
6712*4882a593Smuzhiyun 
6713*4882a593Smuzhiyun 	mutex_init(&tp->control);
6714*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
6715*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t);
6716*4882a593Smuzhiyun 	tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp);
6717*4882a593Smuzhiyun 	tasklet_disable(&tp->tx_tl);
6718*4882a593Smuzhiyun 
6719*4882a593Smuzhiyun 	netdev->netdev_ops = &rtl8152_netdev_ops;
6720*4882a593Smuzhiyun 	netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
6721*4882a593Smuzhiyun 
6722*4882a593Smuzhiyun 	netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
6723*4882a593Smuzhiyun 			    NETIF_F_TSO | NETIF_F_FRAGLIST | NETIF_F_IPV6_CSUM |
6724*4882a593Smuzhiyun 			    NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_RX |
6725*4882a593Smuzhiyun 			    NETIF_F_HW_VLAN_CTAG_TX;
6726*4882a593Smuzhiyun 	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
6727*4882a593Smuzhiyun 			      NETIF_F_TSO | NETIF_F_FRAGLIST |
6728*4882a593Smuzhiyun 			      NETIF_F_IPV6_CSUM | NETIF_F_TSO6 |
6729*4882a593Smuzhiyun 			      NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX;
6730*4882a593Smuzhiyun 	netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6731*4882a593Smuzhiyun 				NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
6732*4882a593Smuzhiyun 				NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
6733*4882a593Smuzhiyun 
6734*4882a593Smuzhiyun 	if (tp->version == RTL_VER_01) {
6735*4882a593Smuzhiyun 		netdev->features &= ~NETIF_F_RXCSUM;
6736*4882a593Smuzhiyun 		netdev->hw_features &= ~NETIF_F_RXCSUM;
6737*4882a593Smuzhiyun 	}
6738*4882a593Smuzhiyun 
6739*4882a593Smuzhiyun 	if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO) {
6740*4882a593Smuzhiyun 		switch (le16_to_cpu(udev->descriptor.idProduct)) {
6741*4882a593Smuzhiyun 		case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
6742*4882a593Smuzhiyun 		case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
6743*4882a593Smuzhiyun 			set_bit(LENOVO_MACPASSTHRU, &tp->flags);
6744*4882a593Smuzhiyun 		}
6745*4882a593Smuzhiyun 	}
6746*4882a593Smuzhiyun 
6747*4882a593Smuzhiyun 	if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial &&
6748*4882a593Smuzhiyun 	    (!strcmp(udev->serial, "000001000000") ||
6749*4882a593Smuzhiyun 	     !strcmp(udev->serial, "000002000000"))) {
6750*4882a593Smuzhiyun 		dev_info(&udev->dev, "Dell TB16 Dock, disable RX aggregation");
6751*4882a593Smuzhiyun 		set_bit(DELL_TB_RX_AGG_BUG, &tp->flags);
6752*4882a593Smuzhiyun 	}
6753*4882a593Smuzhiyun 
6754*4882a593Smuzhiyun 	netdev->ethtool_ops = &ops;
6755*4882a593Smuzhiyun 	netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
6756*4882a593Smuzhiyun 
6757*4882a593Smuzhiyun 	/* MTU range: 68 - 1500 or 9194 */
6758*4882a593Smuzhiyun 	netdev->min_mtu = ETH_MIN_MTU;
6759*4882a593Smuzhiyun 	switch (tp->version) {
6760*4882a593Smuzhiyun 	case RTL_VER_01:
6761*4882a593Smuzhiyun 	case RTL_VER_02:
6762*4882a593Smuzhiyun 		netdev->max_mtu = ETH_DATA_LEN;
6763*4882a593Smuzhiyun 		break;
6764*4882a593Smuzhiyun 	default:
6765*4882a593Smuzhiyun 		netdev->max_mtu = RTL8153_MAX_MTU;
6766*4882a593Smuzhiyun 		break;
6767*4882a593Smuzhiyun 	}
6768*4882a593Smuzhiyun 
6769*4882a593Smuzhiyun 	tp->mii.dev = netdev;
6770*4882a593Smuzhiyun 	tp->mii.mdio_read = read_mii_word;
6771*4882a593Smuzhiyun 	tp->mii.mdio_write = write_mii_word;
6772*4882a593Smuzhiyun 	tp->mii.phy_id_mask = 0x3f;
6773*4882a593Smuzhiyun 	tp->mii.reg_num_mask = 0x1f;
6774*4882a593Smuzhiyun 	tp->mii.phy_id = R8152_PHY_ID;
6775*4882a593Smuzhiyun 
6776*4882a593Smuzhiyun 	tp->autoneg = AUTONEG_ENABLE;
6777*4882a593Smuzhiyun 	tp->speed = SPEED_100;
6778*4882a593Smuzhiyun 	tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL |
6779*4882a593Smuzhiyun 			  RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL;
6780*4882a593Smuzhiyun 	if (tp->mii.supports_gmii) {
6781*4882a593Smuzhiyun 		tp->speed = SPEED_1000;
6782*4882a593Smuzhiyun 		tp->advertising |= RTL_ADVERTISED_1000_FULL;
6783*4882a593Smuzhiyun 	}
6784*4882a593Smuzhiyun 	tp->duplex = DUPLEX_FULL;
6785*4882a593Smuzhiyun 
6786*4882a593Smuzhiyun 	tp->rx_copybreak = RTL8152_RXFG_HEADSZ;
6787*4882a593Smuzhiyun 	tp->rx_pending = 10 * RTL8152_MAX_RX;
6788*4882a593Smuzhiyun 
6789*4882a593Smuzhiyun 	intf->needs_remote_wakeup = 1;
6790*4882a593Smuzhiyun 
6791*4882a593Smuzhiyun 	if (!rtl_can_wakeup(tp))
6792*4882a593Smuzhiyun 		__rtl_set_wol(tp, 0);
6793*4882a593Smuzhiyun 	else
6794*4882a593Smuzhiyun 		tp->saved_wolopts = __rtl_get_wol(tp);
6795*4882a593Smuzhiyun 
6796*4882a593Smuzhiyun 	tp->rtl_ops.init(tp);
6797*4882a593Smuzhiyun #if IS_BUILTIN(CONFIG_USB_RTL8152)
6798*4882a593Smuzhiyun 	/* Retry in case request_firmware() is not ready yet. */
6799*4882a593Smuzhiyun 	tp->rtl_fw.retry = true;
6800*4882a593Smuzhiyun #endif
6801*4882a593Smuzhiyun 	queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
6802*4882a593Smuzhiyun 	set_ethernet_addr(tp);
6803*4882a593Smuzhiyun 
6804*4882a593Smuzhiyun 	usb_set_intfdata(intf, tp);
6805*4882a593Smuzhiyun 	netif_napi_add(netdev, &tp->napi, r8152_poll, RTL8152_NAPI_WEIGHT);
6806*4882a593Smuzhiyun 
6807*4882a593Smuzhiyun 	ret = register_netdev(netdev);
6808*4882a593Smuzhiyun 	if (ret != 0) {
6809*4882a593Smuzhiyun 		netif_err(tp, probe, netdev, "couldn't register the device\n");
6810*4882a593Smuzhiyun 		goto out1;
6811*4882a593Smuzhiyun 	}
6812*4882a593Smuzhiyun 
6813*4882a593Smuzhiyun 	if (tp->saved_wolopts)
6814*4882a593Smuzhiyun 		device_set_wakeup_enable(&udev->dev, true);
6815*4882a593Smuzhiyun 	else
6816*4882a593Smuzhiyun 		device_set_wakeup_enable(&udev->dev, false);
6817*4882a593Smuzhiyun 
6818*4882a593Smuzhiyun 	netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
6819*4882a593Smuzhiyun 
6820*4882a593Smuzhiyun 	return 0;
6821*4882a593Smuzhiyun 
6822*4882a593Smuzhiyun out1:
6823*4882a593Smuzhiyun 	tasklet_kill(&tp->tx_tl);
6824*4882a593Smuzhiyun 	usb_set_intfdata(intf, NULL);
6825*4882a593Smuzhiyun out:
6826*4882a593Smuzhiyun 	free_netdev(netdev);
6827*4882a593Smuzhiyun 	return ret;
6828*4882a593Smuzhiyun }
6829*4882a593Smuzhiyun 
rtl8152_disconnect(struct usb_interface * intf)6830*4882a593Smuzhiyun static void rtl8152_disconnect(struct usb_interface *intf)
6831*4882a593Smuzhiyun {
6832*4882a593Smuzhiyun 	struct r8152 *tp = usb_get_intfdata(intf);
6833*4882a593Smuzhiyun 
6834*4882a593Smuzhiyun 	usb_set_intfdata(intf, NULL);
6835*4882a593Smuzhiyun 	if (tp) {
6836*4882a593Smuzhiyun 		rtl_set_unplug(tp);
6837*4882a593Smuzhiyun 
6838*4882a593Smuzhiyun 		unregister_netdev(tp->netdev);
6839*4882a593Smuzhiyun 		tasklet_kill(&tp->tx_tl);
6840*4882a593Smuzhiyun 		cancel_delayed_work_sync(&tp->hw_phy_work);
6841*4882a593Smuzhiyun 		tp->rtl_ops.unload(tp);
6842*4882a593Smuzhiyun 		rtl8152_release_firmware(tp);
6843*4882a593Smuzhiyun 		free_netdev(tp->netdev);
6844*4882a593Smuzhiyun 	}
6845*4882a593Smuzhiyun }
6846*4882a593Smuzhiyun 
6847*4882a593Smuzhiyun #define REALTEK_USB_DEVICE(vend, prod)	\
6848*4882a593Smuzhiyun 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
6849*4882a593Smuzhiyun 		       USB_DEVICE_ID_MATCH_INT_CLASS, \
6850*4882a593Smuzhiyun 	.idVendor = (vend), \
6851*4882a593Smuzhiyun 	.idProduct = (prod), \
6852*4882a593Smuzhiyun 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC \
6853*4882a593Smuzhiyun }, \
6854*4882a593Smuzhiyun { \
6855*4882a593Smuzhiyun 	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \
6856*4882a593Smuzhiyun 		       USB_DEVICE_ID_MATCH_DEVICE, \
6857*4882a593Smuzhiyun 	.idVendor = (vend), \
6858*4882a593Smuzhiyun 	.idProduct = (prod), \
6859*4882a593Smuzhiyun 	.bInterfaceClass = USB_CLASS_COMM, \
6860*4882a593Smuzhiyun 	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
6861*4882a593Smuzhiyun 	.bInterfaceProtocol = USB_CDC_PROTO_NONE
6862*4882a593Smuzhiyun 
6863*4882a593Smuzhiyun /* table of devices that work with this driver */
6864*4882a593Smuzhiyun static const struct usb_device_id rtl8152_table[] = {
6865*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050)},
6866*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
6867*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
6868*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
6869*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
6870*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)},
6871*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
6872*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
6873*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3054)},
6874*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},
6875*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3069)},
6876*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3082)},
6877*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
6878*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
6879*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
6880*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x721e)},
6881*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0xa387)},
6882*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
6883*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
6884*4882a593Smuzhiyun 	{REALTEK_USB_DEVICE(VENDOR_ID_TPLINK,  0x0601)},
6885*4882a593Smuzhiyun 	{}
6886*4882a593Smuzhiyun };
6887*4882a593Smuzhiyun 
6888*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, rtl8152_table);
6889*4882a593Smuzhiyun 
6890*4882a593Smuzhiyun static struct usb_driver rtl8152_driver = {
6891*4882a593Smuzhiyun 	.name =		MODULENAME,
6892*4882a593Smuzhiyun 	.id_table =	rtl8152_table,
6893*4882a593Smuzhiyun 	.probe =	rtl8152_probe,
6894*4882a593Smuzhiyun 	.disconnect =	rtl8152_disconnect,
6895*4882a593Smuzhiyun 	.suspend =	rtl8152_suspend,
6896*4882a593Smuzhiyun 	.resume =	rtl8152_resume,
6897*4882a593Smuzhiyun 	.reset_resume =	rtl8152_reset_resume,
6898*4882a593Smuzhiyun 	.pre_reset =	rtl8152_pre_reset,
6899*4882a593Smuzhiyun 	.post_reset =	rtl8152_post_reset,
6900*4882a593Smuzhiyun 	.supports_autosuspend = 1,
6901*4882a593Smuzhiyun 	.disable_hub_initiated_lpm = 1,
6902*4882a593Smuzhiyun };
6903*4882a593Smuzhiyun 
6904*4882a593Smuzhiyun module_usb_driver(rtl8152_driver);
6905*4882a593Smuzhiyun 
6906*4882a593Smuzhiyun MODULE_AUTHOR(DRIVER_AUTHOR);
6907*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
6908*4882a593Smuzhiyun MODULE_LICENSE("GPL");
6909*4882a593Smuzhiyun MODULE_VERSION(DRIVER_VERSION);
6910