blob: 891feee49ba99134ff601a761b4fafaa4d0db8c7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Francois Romieu07d3f512007-02-21 22:40:46 +01002 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/pci.h>
14#include <linux/netdevice.h>
15#include <linux/etherdevice.h>
16#include <linux/delay.h>
17#include <linux/ethtool.h>
18#include <linux/mii.h>
19#include <linux/if_vlan.h>
20#include <linux/crc32.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/tcp.h>
24#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000025#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000027#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000028#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000029#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040030#include <linux/prefetch.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/io.h>
33#include <asm/irq.h>
34
Francois Romieu865c6522008-05-11 14:51:00 +020035#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MODULENAME "r8169"
37#define PFX MODULENAME ": "
38
françois romieubca03d52011-01-03 15:07:31 +000039#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
40#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000041#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
42#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080043#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080044#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
45#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080046#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080047#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080048#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080049#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
Hayes Wangc5583862012-07-02 17:23:22 +080050#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw"
françois romieubca03d52011-01-03 15:07:31 +000051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#ifdef RTL8169_DEBUG
53#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020054 if (!(expr)) { \
55 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070056 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020057 }
Joe Perches06fa7352007-10-18 21:15:00 +020058#define dprintk(fmt, args...) \
59 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
61#define assert(expr) do {} while (0)
62#define dprintk(fmt, args...) do {} while (0)
63#endif /* RTL8169_DEBUG */
64
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020065#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
86#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
88#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
89
90#define RTL8169_TX_TIMEOUT (6*HZ)
91#define RTL8169_PHY_TIMEOUT (10*HZ)
92
93/* write/read MMIO register */
94#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
95#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
96#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
97#define RTL_R8(reg) readb (ioaddr + (reg))
98#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +000099#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200102 RTL_GIGA_MAC_VER_01 = 0,
103 RTL_GIGA_MAC_VER_02,
104 RTL_GIGA_MAC_VER_03,
105 RTL_GIGA_MAC_VER_04,
106 RTL_GIGA_MAC_VER_05,
107 RTL_GIGA_MAC_VER_06,
108 RTL_GIGA_MAC_VER_07,
109 RTL_GIGA_MAC_VER_08,
110 RTL_GIGA_MAC_VER_09,
111 RTL_GIGA_MAC_VER_10,
112 RTL_GIGA_MAC_VER_11,
113 RTL_GIGA_MAC_VER_12,
114 RTL_GIGA_MAC_VER_13,
115 RTL_GIGA_MAC_VER_14,
116 RTL_GIGA_MAC_VER_15,
117 RTL_GIGA_MAC_VER_16,
118 RTL_GIGA_MAC_VER_17,
119 RTL_GIGA_MAC_VER_18,
120 RTL_GIGA_MAC_VER_19,
121 RTL_GIGA_MAC_VER_20,
122 RTL_GIGA_MAC_VER_21,
123 RTL_GIGA_MAC_VER_22,
124 RTL_GIGA_MAC_VER_23,
125 RTL_GIGA_MAC_VER_24,
126 RTL_GIGA_MAC_VER_25,
127 RTL_GIGA_MAC_VER_26,
128 RTL_GIGA_MAC_VER_27,
129 RTL_GIGA_MAC_VER_28,
130 RTL_GIGA_MAC_VER_29,
131 RTL_GIGA_MAC_VER_30,
132 RTL_GIGA_MAC_VER_31,
133 RTL_GIGA_MAC_VER_32,
134 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800135 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800136 RTL_GIGA_MAC_VER_35,
137 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800138 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800139 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800140 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800141 RTL_GIGA_MAC_VER_40,
142 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200143 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
Francois Romieu2b7b4312011-04-18 22:53:24 -0700146enum rtl_tx_desc_version {
147 RTL_TD_0 = 0,
148 RTL_TD_1 = 1,
149};
150
Francois Romieud58d46b2011-05-03 16:38:29 +0200151#define JUMBO_1K ETH_DATA_LEN
152#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
153#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
154#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
155#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
156
157#define _R(NAME,TD,FW,SZ,B) { \
158 .name = NAME, \
159 .txd_version = TD, \
160 .fw_name = FW, \
161 .jumbo_max = SZ, \
162 .jumbo_tx_csum = B \
163}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800165static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700167 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200168 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200169 u16 jumbo_max;
170 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200171} rtl_chip_infos[] = {
172 /* PCI devices. */
173 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200175 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200176 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200177 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200178 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200179 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200180 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200181 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200182 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200183 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200184 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200185 /* PCI-E devices. */
186 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200191 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200192 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200193 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200194 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200195 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200196 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200197 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200198 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200199 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200200 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200201 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200202 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200203 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200204 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200205 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200206 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200207 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200208 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200209 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200210 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200211 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200212 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200213 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200214 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200215 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200216 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200217 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200218 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200219 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200220 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200221 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200222 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200223 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
224 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
227 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200228 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200229 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200232 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200233 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
234 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
237 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200238 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200239 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
242 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
245 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800246 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200247 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
248 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800249 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200250 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
251 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800252 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200253 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
254 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800255 [RTL_GIGA_MAC_VER_37] =
256 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
257 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800258 [RTL_GIGA_MAC_VER_38] =
259 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
260 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800261 [RTL_GIGA_MAC_VER_39] =
262 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
263 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800264 [RTL_GIGA_MAC_VER_40] =
265 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
266 JUMBO_9K, false),
267 [RTL_GIGA_MAC_VER_41] =
268 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269};
270#undef _R
271
Francois Romieubcf0bf92006-07-26 23:14:13 +0200272enum cfg_version {
273 RTL_CFG_0 = 0x00,
274 RTL_CFG_1,
275 RTL_CFG_2
276};
277
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000278static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200279 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200280 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200281 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100282 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200283 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200284 { PCI_VENDOR_ID_DLINK, 0x4300,
285 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000287 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200289 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
290 { PCI_VENDOR_ID_LINKSYS, 0x1032,
291 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100292 { 0x0001, 0x8168,
293 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 {0,},
295};
296
297MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
298
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000299static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700300static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200301static struct {
302 u32 msg_enable;
303} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Francois Romieu07d3f512007-02-21 22:40:46 +0100305enum rtl_registers {
306 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100307 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100308 MAR0 = 8, /* Multicast filter. */
309 CounterAddrLow = 0x10,
310 CounterAddrHigh = 0x14,
311 TxDescStartAddrLow = 0x20,
312 TxDescStartAddrHigh = 0x24,
313 TxHDescStartAddrLow = 0x28,
314 TxHDescStartAddrHigh = 0x2c,
315 FLASH = 0x30,
316 ERSR = 0x36,
317 ChipCmd = 0x37,
318 TxPoll = 0x38,
319 IntrMask = 0x3c,
320 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700321
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800322 TxConfig = 0x40,
323#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
324#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
325
326 RxConfig = 0x44,
327#define RX128_INT_EN (1 << 15) /* 8111c and later */
328#define RX_MULTI_EN (1 << 14) /* 8111c only */
329#define RXCFG_FIFO_SHIFT 13
330 /* No threshold before first PCI xfer */
331#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
332#define RXCFG_DMA_SHIFT 8
333 /* Unlimited maximum PCI burst. */
334#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700335
Francois Romieu07d3f512007-02-21 22:40:46 +0100336 RxMissed = 0x4c,
337 Cfg9346 = 0x50,
338 Config0 = 0x51,
339 Config1 = 0x52,
340 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200341#define PME_SIGNAL (1 << 5) /* 8168c and later */
342
Francois Romieu07d3f512007-02-21 22:40:46 +0100343 Config3 = 0x54,
344 Config4 = 0x55,
345 Config5 = 0x56,
346 MultiIntr = 0x5c,
347 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 PHYstatus = 0x6c,
349 RxMaxSize = 0xda,
350 CPlusCmd = 0xe0,
351 IntrMitigate = 0xe2,
352 RxDescAddrLow = 0xe4,
353 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000354 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
355
356#define NoEarlyTx 0x3f /* Max value : no early transmit. */
357
358 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
359
360#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800361#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000362
Francois Romieu07d3f512007-02-21 22:40:46 +0100363 FuncEvent = 0xf0,
364 FuncEventMask = 0xf4,
365 FuncPresetState = 0xf8,
366 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Francois Romieuf162a5d2008-06-01 22:37:49 +0200369enum rtl8110_registers {
370 TBICSR = 0x64,
371 TBI_ANAR = 0x68,
372 TBI_LPAR = 0x6a,
373};
374
375enum rtl8168_8101_registers {
376 CSIDR = 0x64,
377 CSIAR = 0x68,
378#define CSIAR_FLAG 0x80000000
379#define CSIAR_WRITE_CMD 0x80000000
380#define CSIAR_BYTE_ENABLE 0x0f
381#define CSIAR_BYTE_ENABLE_SHIFT 12
382#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800383#define CSIAR_FUNC_CARD 0x00000000
384#define CSIAR_FUNC_SDIO 0x00010000
385#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000386 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200387 EPHYAR = 0x80,
388#define EPHYAR_FLAG 0x80000000
389#define EPHYAR_WRITE_CMD 0x80000000
390#define EPHYAR_REG_MASK 0x1f
391#define EPHYAR_REG_SHIFT 16
392#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800393 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800394#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200395 DBG_REG = 0xd1,
396#define FIX_NAK_1 (1 << 4)
397#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 TWSI = 0xd2,
399 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800400#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800401#define TX_EMPTY (1 << 5)
402#define RX_EMPTY (1 << 4)
403#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800404#define EN_NDP (1 << 3)
405#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000407 EFUSEAR = 0xdc,
408#define EFUSEAR_FLAG 0x80000000
409#define EFUSEAR_WRITE_CMD 0x80000000
410#define EFUSEAR_READ_CMD 0x00000000
411#define EFUSEAR_REG_MASK 0x03ff
412#define EFUSEAR_REG_SHIFT 8
413#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200414};
415
françois romieuc0e45c12011-01-03 15:08:04 +0000416enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800417 LED_FREQ = 0x1a,
418 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000419 ERIDR = 0x70,
420 ERIAR = 0x74,
421#define ERIAR_FLAG 0x80000000
422#define ERIAR_WRITE_CMD 0x80000000
423#define ERIAR_READ_CMD 0x00000000
424#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000425#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800426#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
427#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
428#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
429#define ERIAR_MASK_SHIFT 12
430#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
431#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800432#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800433#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000434 EPHY_RXER_NUM = 0x7c,
435 OCPDR = 0xb0, /* OCP GPHY access */
436#define OCPDR_WRITE_CMD 0x80000000
437#define OCPDR_READ_CMD 0x00000000
438#define OCPDR_REG_MASK 0x7f
439#define OCPDR_GPHY_REG_SHIFT 16
440#define OCPDR_DATA_MASK 0xffff
441 OCPAR = 0xb4,
442#define OCPAR_FLAG 0x80000000
443#define OCPAR_GPHY_WRITE_CMD 0x8000f060
444#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800445 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000446 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
447 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200448#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800449#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800450#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800451#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800452#define EARLY_TALLY_EN (1 << 16)
hayeswangd64ec842012-11-01 16:46:28 +0000453#define FORCE_CLK (1 << 15) /* force clock request */
françois romieuc0e45c12011-01-03 15:08:04 +0000454};
455
Francois Romieu07d3f512007-02-21 22:40:46 +0100456enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100458 SYSErr = 0x8000,
459 PCSTimeout = 0x4000,
460 SWInt = 0x0100,
461 TxDescUnavail = 0x0080,
462 RxFIFOOver = 0x0040,
463 LinkChg = 0x0020,
464 RxOverflow = 0x0010,
465 TxErr = 0x0008,
466 TxOK = 0x0004,
467 RxErr = 0x0002,
468 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400471 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200472 RxFOVF = (1 << 23),
473 RxRWT = (1 << 22),
474 RxRES = (1 << 21),
475 RxRUNT = (1 << 20),
476 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
478 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800479 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100480 CmdReset = 0x10,
481 CmdRxEnb = 0x08,
482 CmdTxEnb = 0x04,
483 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Francois Romieu275391a2007-02-23 23:50:28 +0100485 /* TXPoll register p.5 */
486 HPQ = 0x80, /* Poll cmd on the high prio queue */
487 NPQ = 0x40, /* Poll cmd on the low prio queue */
488 FSWInt = 0x01, /* Forced software interrupt */
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100491 Cfg9346_Lock = 0x00,
492 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
494 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100495 AcceptErr = 0x20,
496 AcceptRunt = 0x10,
497 AcceptBroadcast = 0x08,
498 AcceptMulticast = 0x04,
499 AcceptMyPhys = 0x02,
500 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200501#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 /* TxConfigBits */
504 TxInterFrameGapShift = 24,
505 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
506
Francois Romieu5d06a992006-02-23 00:47:58 +0100507 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200508 LEDS1 = (1 << 7),
509 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200510 Speed_down = (1 << 4),
511 MEMMAP = (1 << 3),
512 IOMAP = (1 << 2),
513 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100514 PMEnable = (1 << 0), /* Power Management Enable */
515
Francois Romieu6dccd162007-02-13 23:38:05 +0100516 /* Config2 register p. 25 */
hayeswangd64ec842012-11-01 16:46:28 +0000517 ClkReqEn = (1 << 7), /* Clock Request Enable */
françois romieu2ca6cf02011-12-15 08:37:43 +0000518 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100519 PCI_Clock_66MHz = 0x01,
520 PCI_Clock_33MHz = 0x00,
521
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100522 /* Config3 register p.25 */
523 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
524 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200525 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200526 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100527
Francois Romieud58d46b2011-05-03 16:38:29 +0200528 /* Config4 register */
529 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
530
Francois Romieu5d06a992006-02-23 00:47:58 +0100531 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100532 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
533 MWF = (1 << 5), /* Accept Multicast wakeup frame */
534 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200535 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100536 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100537 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
hayeswangd64ec842012-11-01 16:46:28 +0000538 ASPM_en = (1 << 0), /* ASPM enable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* TBICSR p.28 */
541 TBIReset = 0x80000000,
542 TBILoopback = 0x40000000,
543 TBINwEnable = 0x20000000,
544 TBINwRestart = 0x10000000,
545 TBILinkOk = 0x02000000,
546 TBINwComplete = 0x01000000,
547
548 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200549 EnableBist = (1 << 15), // 8168 8101
550 Mac_dbgo_oe = (1 << 14), // 8168 8101
551 Normal_mode = (1 << 13), // unused
552 Force_half_dup = (1 << 12), // 8168 8101
553 Force_rxflow_en = (1 << 11), // 8168 8101
554 Force_txflow_en = (1 << 10), // 8168 8101
555 Cxpl_dbg_sel = (1 << 9), // 8168 8101
556 ASF = (1 << 8), // 8168 8101
557 PktCntrDisable = (1 << 7), // 8168 8101
558 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 RxVlan = (1 << 6),
560 RxChkSum = (1 << 5),
561 PCIDAC = (1 << 4),
562 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100563 INTT_0 = 0x0000, // 8168
564 INTT_1 = 0x0001, // 8168
565 INTT_2 = 0x0002, // 8168
566 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100569 TBI_Enable = 0x80,
570 TxFlowCtrl = 0x40,
571 RxFlowCtrl = 0x20,
572 _1000bpsF = 0x10,
573 _100bps = 0x08,
574 _10bps = 0x04,
575 LinkStatus = 0x02,
576 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100579 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200580
581 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100582 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583};
584
Francois Romieu2b7b4312011-04-18 22:53:24 -0700585enum rtl_desc_bit {
586 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
588 RingEnd = (1 << 30), /* End of descriptor ring */
589 FirstFrag = (1 << 29), /* First segment of a packet */
590 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700591};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Francois Romieu2b7b4312011-04-18 22:53:24 -0700593/* Generic case. */
594enum rtl_tx_desc_bit {
595 /* First doubleword. */
596 TD_LSO = (1 << 27), /* Large Send Offload */
597#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Francois Romieu2b7b4312011-04-18 22:53:24 -0700599 /* Second doubleword. */
600 TxVlanTag = (1 << 17), /* Add VLAN tag */
601};
602
603/* 8169, 8168b and 810x except 8102e. */
604enum rtl_tx_desc_bit_0 {
605 /* First doubleword. */
606#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
607 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
608 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
609 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
610};
611
612/* 8102e, 8168c and beyond. */
613enum rtl_tx_desc_bit_1 {
614 /* Second doubleword. */
615#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
616 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
617 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
618 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
619};
620
621static const struct rtl_tx_desc_info {
622 struct {
623 u32 udp;
624 u32 tcp;
625 } checksum;
626 u16 mss_shift;
627 u16 opts_offset;
628} tx_desc_info [] = {
629 [RTL_TD_0] = {
630 .checksum = {
631 .udp = TD0_IP_CS | TD0_UDP_CS,
632 .tcp = TD0_IP_CS | TD0_TCP_CS
633 },
634 .mss_shift = TD0_MSS_SHIFT,
635 .opts_offset = 0
636 },
637 [RTL_TD_1] = {
638 .checksum = {
639 .udp = TD1_IP_CS | TD1_UDP_CS,
640 .tcp = TD1_IP_CS | TD1_TCP_CS
641 },
642 .mss_shift = TD1_MSS_SHIFT,
643 .opts_offset = 1
644 }
645};
646
647enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 /* Rx private */
649 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
650 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
651
652#define RxProtoUDP (PID1)
653#define RxProtoTCP (PID0)
654#define RxProtoIP (PID1 | PID0)
655#define RxProtoMask RxProtoIP
656
657 IPFail = (1 << 16), /* IP checksum failed */
658 UDPFail = (1 << 15), /* UDP/IP checksum failed */
659 TCPFail = (1 << 14), /* TCP/IP checksum failed */
660 RxVlanTag = (1 << 16), /* VLAN tag available */
661};
662
663#define RsvdMask 0x3fffc000
664
665struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200666 __le32 opts1;
667 __le32 opts2;
668 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669};
670
671struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200672 __le32 opts1;
673 __le32 opts2;
674 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675};
676
677struct ring_info {
678 struct sk_buff *skb;
679 u32 len;
680 u8 __pad[sizeof(void *) - sizeof(u32)];
681};
682
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200683enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200684 RTL_FEATURE_WOL = (1 << 0),
685 RTL_FEATURE_MSI = (1 << 1),
686 RTL_FEATURE_GMII = (1 << 2),
hayeswange0c07552012-10-23 20:24:03 +0000687 RTL_FEATURE_FW_LOADED = (1 << 3),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200688};
689
Ivan Vecera355423d2009-02-06 21:49:57 -0800690struct rtl8169_counters {
691 __le64 tx_packets;
692 __le64 rx_packets;
693 __le64 tx_errors;
694 __le32 rx_errors;
695 __le16 rx_missed;
696 __le16 align_errors;
697 __le32 tx_one_collision;
698 __le32 tx_multi_collision;
699 __le64 rx_unicast;
700 __le64 rx_broadcast;
701 __le32 rx_multicast;
702 __le16 tx_aborted;
703 __le16 tx_underun;
704};
705
Francois Romieuda78dbf2012-01-26 14:18:23 +0100706enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100707 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100708 RTL_FLAG_TASK_SLOW_PENDING,
709 RTL_FLAG_TASK_RESET_PENDING,
710 RTL_FLAG_TASK_PHY_PENDING,
711 RTL_FLAG_MAX
712};
713
Junchang Wang8027aa22012-03-04 23:30:32 +0100714struct rtl8169_stats {
715 u64 packets;
716 u64 bytes;
717 struct u64_stats_sync syncp;
718};
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720struct rtl8169_private {
721 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200722 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000723 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700724 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200725 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700726 u16 txd_version;
727 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
729 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
730 u32 dirty_rx;
731 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100732 struct rtl8169_stats rx_stats;
733 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
735 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
736 dma_addr_t TxPhyAddr;
737 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000738 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 struct timer_list timer;
741 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100742
743 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000744
745 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200746 void (*write)(struct rtl8169_private *, int, int);
747 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000748 } mdio_ops;
749
françois romieu065c27c2011-01-03 15:08:12 +0000750 struct pll_power_ops {
751 void (*down)(struct rtl8169_private *);
752 void (*up)(struct rtl8169_private *);
753 } pll_power_ops;
754
Francois Romieud58d46b2011-05-03 16:38:29 +0200755 struct jumbo_ops {
756 void (*enable)(struct rtl8169_private *);
757 void (*disable)(struct rtl8169_private *);
758 } jumbo_ops;
759
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800760 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200761 void (*write)(struct rtl8169_private *, int, int);
762 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800763 } csi_ops;
764
Oliver Neukum54405cd2011-01-06 21:55:13 +0100765 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200766 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000767 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100768 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000769 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800771 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100772
773 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100774 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
775 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100776 struct work_struct work;
777 } wk;
778
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200779 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200780
781 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800782 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000783 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400784 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000785
Francois Romieub6ffd972011-06-17 17:00:05 +0200786 struct rtl_fw {
787 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200788
789#define RTL_VER_SIZE 32
790
791 char version[RTL_VER_SIZE];
792
793 struct rtl_fw_phy_action {
794 __le32 *code;
795 size_t size;
796 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200797 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300798#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800799
800 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801};
802
Ralf Baechle979b6c12005-06-13 14:30:40 -0700803MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700806MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200807module_param_named(debug, debug.msg_enable, int, 0);
808MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809MODULE_LICENSE("GPL");
810MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000811MODULE_FIRMWARE(FIRMWARE_8168D_1);
812MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000813MODULE_FIRMWARE(FIRMWARE_8168E_1);
814MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400815MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800816MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800817MODULE_FIRMWARE(FIRMWARE_8168F_1);
818MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800819MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800820MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800821MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800822MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Francois Romieuda78dbf2012-01-26 14:18:23 +0100824static void rtl_lock_work(struct rtl8169_private *tp)
825{
826 mutex_lock(&tp->wk.mutex);
827}
828
829static void rtl_unlock_work(struct rtl8169_private *tp)
830{
831 mutex_unlock(&tp->wk.mutex);
832}
833
Francois Romieud58d46b2011-05-03 16:38:29 +0200834static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
835{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800836 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
837 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200838}
839
Francois Romieuffc46952012-07-06 14:19:23 +0200840struct rtl_cond {
841 bool (*check)(struct rtl8169_private *);
842 const char *msg;
843};
844
845static void rtl_udelay(unsigned int d)
846{
847 udelay(d);
848}
849
850static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
851 void (*delay)(unsigned int), unsigned int d, int n,
852 bool high)
853{
854 int i;
855
856 for (i = 0; i < n; i++) {
857 delay(d);
858 if (c->check(tp) == high)
859 return true;
860 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200861 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
862 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200863 return false;
864}
865
866static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
867 const struct rtl_cond *c,
868 unsigned int d, int n)
869{
870 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
871}
872
873static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
874 const struct rtl_cond *c,
875 unsigned int d, int n)
876{
877 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
878}
879
880static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
881 const struct rtl_cond *c,
882 unsigned int d, int n)
883{
884 return rtl_loop_wait(tp, c, msleep, d, n, true);
885}
886
887static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
888 const struct rtl_cond *c,
889 unsigned int d, int n)
890{
891 return rtl_loop_wait(tp, c, msleep, d, n, false);
892}
893
894#define DECLARE_RTL_COND(name) \
895static bool name ## _check(struct rtl8169_private *); \
896 \
897static const struct rtl_cond name = { \
898 .check = name ## _check, \
899 .msg = #name \
900}; \
901 \
902static bool name ## _check(struct rtl8169_private *tp)
903
904DECLARE_RTL_COND(rtl_ocpar_cond)
905{
906 void __iomem *ioaddr = tp->mmio_addr;
907
908 return RTL_R32(OCPAR) & OCPAR_FLAG;
909}
910
françois romieub646d902011-01-03 15:08:21 +0000911static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
912{
913 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000914
915 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200916
917 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
918 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000919}
920
921static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
922{
923 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000924
925 RTL_W32(OCPDR, data);
926 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200927
928 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
929}
930
931DECLARE_RTL_COND(rtl_eriar_cond)
932{
933 void __iomem *ioaddr = tp->mmio_addr;
934
935 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000936}
937
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800938static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000939{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800940 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000941
942 RTL_W8(ERIDR, cmd);
943 RTL_W32(ERIAR, 0x800010e8);
944 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200945
946 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
947 return;
françois romieub646d902011-01-03 15:08:21 +0000948
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800949 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000950}
951
952#define OOB_CMD_RESET 0x00
953#define OOB_CMD_DRIVER_START 0x05
954#define OOB_CMD_DRIVER_STOP 0x06
955
Francois Romieucecb5fd2011-04-01 10:21:07 +0200956static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
957{
958 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
959}
960
Francois Romieuffc46952012-07-06 14:19:23 +0200961DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000962{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200963 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000964
Francois Romieucecb5fd2011-04-01 10:21:07 +0200965 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000966
Francois Romieuffc46952012-07-06 14:19:23 +0200967 return ocp_read(tp, 0x0f, reg) & 0x00000800;
968}
969
970static void rtl8168_driver_start(struct rtl8169_private *tp)
971{
972 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
973
974 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000975}
976
977static void rtl8168_driver_stop(struct rtl8169_private *tp)
978{
françois romieub646d902011-01-03 15:08:21 +0000979 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
980
Francois Romieuffc46952012-07-06 14:19:23 +0200981 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000982}
983
hayeswang4804b3b2011-03-21 01:50:29 +0000984static int r8168dp_check_dash(struct rtl8169_private *tp)
985{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200986 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000987
Francois Romieucecb5fd2011-04-01 10:21:07 +0200988 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000989}
françois romieub646d902011-01-03 15:08:21 +0000990
Hayes Wangc5583862012-07-02 17:23:22 +0800991static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
992{
993 if (reg & 0xffff0001) {
994 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
995 return true;
996 }
997 return false;
998}
999
1000DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1001{
1002 void __iomem *ioaddr = tp->mmio_addr;
1003
1004 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1005}
1006
1007static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1008{
1009 void __iomem *ioaddr = tp->mmio_addr;
1010
1011 if (rtl_ocp_reg_failure(tp, reg))
1012 return;
1013
1014 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1015
1016 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1017}
1018
1019static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1020{
1021 void __iomem *ioaddr = tp->mmio_addr;
1022
1023 if (rtl_ocp_reg_failure(tp, reg))
1024 return 0;
1025
1026 RTL_W32(GPHY_OCP, reg << 15);
1027
1028 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1029 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1030}
1031
1032static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1033{
1034 int val;
1035
1036 val = r8168_phy_ocp_read(tp, reg);
1037 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1038}
1039
Hayes Wangc5583862012-07-02 17:23:22 +08001040static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1041{
1042 void __iomem *ioaddr = tp->mmio_addr;
1043
1044 if (rtl_ocp_reg_failure(tp, reg))
1045 return;
1046
1047 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001048}
1049
1050static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1051{
1052 void __iomem *ioaddr = tp->mmio_addr;
1053
1054 if (rtl_ocp_reg_failure(tp, reg))
1055 return 0;
1056
1057 RTL_W32(OCPDR, reg << 15);
1058
Hayes Wang3a83ad12012-07-11 20:31:56 +08001059 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001060}
1061
1062#define OCP_STD_PHY_BASE 0xa400
1063
1064static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1065{
1066 if (reg == 0x1f) {
1067 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1068 return;
1069 }
1070
1071 if (tp->ocp_base != OCP_STD_PHY_BASE)
1072 reg -= 0x10;
1073
1074 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1075}
1076
1077static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1078{
1079 if (tp->ocp_base != OCP_STD_PHY_BASE)
1080 reg -= 0x10;
1081
1082 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1083}
1084
Francois Romieuffc46952012-07-06 14:19:23 +02001085DECLARE_RTL_COND(rtl_phyar_cond)
1086{
1087 void __iomem *ioaddr = tp->mmio_addr;
1088
1089 return RTL_R32(PHYAR) & 0x80000000;
1090}
1091
Francois Romieu24192212012-07-06 20:19:42 +02001092static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Francois Romieu24192212012-07-06 20:19:42 +02001094 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Francois Romieu24192212012-07-06 20:19:42 +02001096 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Francois Romieuffc46952012-07-06 14:19:23 +02001098 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001099 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001100 * According to hardware specs a 20us delay is required after write
1101 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001102 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001103 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
Francois Romieu24192212012-07-06 20:19:42 +02001106static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
Francois Romieu24192212012-07-06 20:19:42 +02001108 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001109 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Francois Romieu24192212012-07-06 20:19:42 +02001111 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Francois Romieuffc46952012-07-06 14:19:23 +02001113 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1114 RTL_R32(PHYAR) & 0xffff : ~0;
1115
Timo Teräs81a95f02010-06-09 17:31:48 -07001116 /*
1117 * According to hardware specs a 20us delay is required after read
1118 * complete indication, but before sending next command.
1119 */
1120 udelay(20);
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return value;
1123}
1124
Francois Romieu24192212012-07-06 20:19:42 +02001125static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001126{
Francois Romieu24192212012-07-06 20:19:42 +02001127 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001128
Francois Romieu24192212012-07-06 20:19:42 +02001129 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001130 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1131 RTL_W32(EPHY_RXER_NUM, 0);
1132
Francois Romieuffc46952012-07-06 14:19:23 +02001133 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001134}
1135
Francois Romieu24192212012-07-06 20:19:42 +02001136static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001137{
Francois Romieu24192212012-07-06 20:19:42 +02001138 r8168dp_1_mdio_access(tp, reg,
1139 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001140}
1141
Francois Romieu24192212012-07-06 20:19:42 +02001142static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001143{
Francois Romieu24192212012-07-06 20:19:42 +02001144 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001145
Francois Romieu24192212012-07-06 20:19:42 +02001146 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001147
1148 mdelay(1);
1149 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1150 RTL_W32(EPHY_RXER_NUM, 0);
1151
Francois Romieuffc46952012-07-06 14:19:23 +02001152 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1153 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001154}
1155
françois romieue6de30d2011-01-03 15:08:37 +00001156#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1157
1158static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1159{
1160 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1161}
1162
1163static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1164{
1165 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1166}
1167
Francois Romieu24192212012-07-06 20:19:42 +02001168static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001169{
Francois Romieu24192212012-07-06 20:19:42 +02001170 void __iomem *ioaddr = tp->mmio_addr;
1171
françois romieue6de30d2011-01-03 15:08:37 +00001172 r8168dp_2_mdio_start(ioaddr);
1173
Francois Romieu24192212012-07-06 20:19:42 +02001174 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001175
1176 r8168dp_2_mdio_stop(ioaddr);
1177}
1178
Francois Romieu24192212012-07-06 20:19:42 +02001179static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001180{
Francois Romieu24192212012-07-06 20:19:42 +02001181 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001182 int value;
1183
1184 r8168dp_2_mdio_start(ioaddr);
1185
Francois Romieu24192212012-07-06 20:19:42 +02001186 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001187
1188 r8168dp_2_mdio_stop(ioaddr);
1189
1190 return value;
1191}
1192
françois romieu4da19632011-01-03 15:07:55 +00001193static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001194{
Francois Romieu24192212012-07-06 20:19:42 +02001195 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001196}
1197
françois romieu4da19632011-01-03 15:07:55 +00001198static int rtl_readphy(struct rtl8169_private *tp, int location)
1199{
Francois Romieu24192212012-07-06 20:19:42 +02001200 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001201}
1202
1203static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1204{
1205 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1206}
1207
1208static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001209{
1210 int val;
1211
françois romieu4da19632011-01-03 15:07:55 +00001212 val = rtl_readphy(tp, reg_addr);
1213 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001214}
1215
Francois Romieuccdffb92008-07-26 14:26:06 +02001216static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1217 int val)
1218{
1219 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001220
françois romieu4da19632011-01-03 15:07:55 +00001221 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001222}
1223
1224static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1225{
1226 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001227
françois romieu4da19632011-01-03 15:07:55 +00001228 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001229}
1230
Francois Romieuffc46952012-07-06 14:19:23 +02001231DECLARE_RTL_COND(rtl_ephyar_cond)
1232{
1233 void __iomem *ioaddr = tp->mmio_addr;
1234
1235 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1236}
1237
Francois Romieufdf6fc02012-07-06 22:40:38 +02001238static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001239{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001240 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001241
1242 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1243 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1244
Francois Romieuffc46952012-07-06 14:19:23 +02001245 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1246
1247 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001248}
1249
Francois Romieufdf6fc02012-07-06 22:40:38 +02001250static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001251{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001252 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001253
1254 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1255
Francois Romieuffc46952012-07-06 14:19:23 +02001256 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1257 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001258}
1259
Francois Romieufdf6fc02012-07-06 22:40:38 +02001260static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1261 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001262{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001263 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001264
1265 BUG_ON((addr & 3) || (mask == 0));
1266 RTL_W32(ERIDR, val);
1267 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1268
Francois Romieuffc46952012-07-06 14:19:23 +02001269 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001270}
1271
Francois Romieufdf6fc02012-07-06 22:40:38 +02001272static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001273{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001274 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001275
1276 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1277
Francois Romieuffc46952012-07-06 14:19:23 +02001278 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1279 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001280}
1281
Francois Romieufdf6fc02012-07-06 22:40:38 +02001282static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1283 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001284{
1285 u32 val;
1286
Francois Romieufdf6fc02012-07-06 22:40:38 +02001287 val = rtl_eri_read(tp, addr, type);
1288 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001289}
1290
françois romieuc28aa382011-08-02 03:53:43 +00001291struct exgmac_reg {
1292 u16 addr;
1293 u16 mask;
1294 u32 val;
1295};
1296
Francois Romieufdf6fc02012-07-06 22:40:38 +02001297static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001298 const struct exgmac_reg *r, int len)
1299{
1300 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001301 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001302 r++;
1303 }
1304}
1305
Francois Romieuffc46952012-07-06 14:19:23 +02001306DECLARE_RTL_COND(rtl_efusear_cond)
1307{
1308 void __iomem *ioaddr = tp->mmio_addr;
1309
1310 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1311}
1312
Francois Romieufdf6fc02012-07-06 22:40:38 +02001313static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001314{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001315 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001316
1317 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1318
Francois Romieuffc46952012-07-06 14:19:23 +02001319 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1320 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001321}
1322
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001323static u16 rtl_get_events(struct rtl8169_private *tp)
1324{
1325 void __iomem *ioaddr = tp->mmio_addr;
1326
1327 return RTL_R16(IntrStatus);
1328}
1329
1330static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1331{
1332 void __iomem *ioaddr = tp->mmio_addr;
1333
1334 RTL_W16(IntrStatus, bits);
1335 mmiowb();
1336}
1337
1338static void rtl_irq_disable(struct rtl8169_private *tp)
1339{
1340 void __iomem *ioaddr = tp->mmio_addr;
1341
1342 RTL_W16(IntrMask, 0);
1343 mmiowb();
1344}
1345
Francois Romieu3e990ff2012-01-26 12:50:01 +01001346static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1347{
1348 void __iomem *ioaddr = tp->mmio_addr;
1349
1350 RTL_W16(IntrMask, bits);
1351}
1352
Francois Romieuda78dbf2012-01-26 14:18:23 +01001353#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1354#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1355#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1356
1357static void rtl_irq_enable_all(struct rtl8169_private *tp)
1358{
1359 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1360}
1361
françois romieu811fd302011-12-04 20:30:45 +00001362static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
françois romieu811fd302011-12-04 20:30:45 +00001364 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001366 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001367 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001368 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369}
1370
françois romieu4da19632011-01-03 15:07:55 +00001371static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
françois romieu4da19632011-01-03 15:07:55 +00001373 void __iomem *ioaddr = tp->mmio_addr;
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return RTL_R32(TBICSR) & TBIReset;
1376}
1377
françois romieu4da19632011-01-03 15:07:55 +00001378static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
françois romieu4da19632011-01-03 15:07:55 +00001380 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381}
1382
1383static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1384{
1385 return RTL_R32(TBICSR) & TBILinkOk;
1386}
1387
1388static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1389{
1390 return RTL_R8(PHYstatus) & LinkStatus;
1391}
1392
françois romieu4da19632011-01-03 15:07:55 +00001393static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
françois romieu4da19632011-01-03 15:07:55 +00001395 void __iomem *ioaddr = tp->mmio_addr;
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1398}
1399
françois romieu4da19632011-01-03 15:07:55 +00001400static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 unsigned int val;
1403
françois romieu4da19632011-01-03 15:07:55 +00001404 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1405 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Hayes Wang70090422011-07-06 15:58:06 +08001408static void rtl_link_chg_patch(struct rtl8169_private *tp)
1409{
1410 void __iomem *ioaddr = tp->mmio_addr;
1411 struct net_device *dev = tp->dev;
1412
1413 if (!netif_running(dev))
1414 return;
1415
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001416 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1417 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001418 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001419 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1420 ERIAR_EXGMAC);
1421 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1422 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001423 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001424 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1425 ERIAR_EXGMAC);
1426 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1427 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001428 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001429 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1430 ERIAR_EXGMAC);
1431 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1432 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001433 }
1434 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001435 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001436 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001437 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001438 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001439 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1440 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1441 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001442 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1443 ERIAR_EXGMAC);
1444 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1445 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001446 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001447 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1448 ERIAR_EXGMAC);
1449 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1450 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001451 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001452 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1453 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001454 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1455 ERIAR_EXGMAC);
1456 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1457 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001458 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001459 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1460 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001461 }
Hayes Wang70090422011-07-06 15:58:06 +08001462 }
1463}
1464
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001465static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001466 struct rtl8169_private *tp,
1467 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001470 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001471 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001472 if (pm)
1473 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001475 if (net_ratelimit())
1476 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001477 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001479 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001480 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001481 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483}
1484
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001485static void rtl8169_check_link_status(struct net_device *dev,
1486 struct rtl8169_private *tp,
1487 void __iomem *ioaddr)
1488{
1489 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1490}
1491
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001492#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1493
1494static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1495{
1496 void __iomem *ioaddr = tp->mmio_addr;
1497 u8 options;
1498 u32 wolopts = 0;
1499
1500 options = RTL_R8(Config1);
1501 if (!(options & PMEnable))
1502 return 0;
1503
1504 options = RTL_R8(Config3);
1505 if (options & LinkUp)
1506 wolopts |= WAKE_PHY;
1507 if (options & MagicPacket)
1508 wolopts |= WAKE_MAGIC;
1509
1510 options = RTL_R8(Config5);
1511 if (options & UWF)
1512 wolopts |= WAKE_UCAST;
1513 if (options & BWF)
1514 wolopts |= WAKE_BCAST;
1515 if (options & MWF)
1516 wolopts |= WAKE_MCAST;
1517
1518 return wolopts;
1519}
1520
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001521static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1522{
1523 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001524
Francois Romieuda78dbf2012-01-26 14:18:23 +01001525 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001527 wol->supported = WAKE_ANY;
1528 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001529
Francois Romieuda78dbf2012-01-26 14:18:23 +01001530 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001531}
1532
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001533static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001535 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001536 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001537 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001538 u32 opt;
1539 u16 reg;
1540 u8 mask;
1541 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001542 { WAKE_PHY, Config3, LinkUp },
1543 { WAKE_MAGIC, Config3, MagicPacket },
1544 { WAKE_UCAST, Config5, UWF },
1545 { WAKE_BCAST, Config5, BWF },
1546 { WAKE_MCAST, Config5, MWF },
1547 { WAKE_ANY, Config5, LanWake }
1548 };
Francois Romieu851e6022012-04-17 11:10:11 +02001549 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001550
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001551 RTL_W8(Cfg9346, Cfg9346_Unlock);
1552
1553 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001554 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001555 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001556 options |= cfg[i].mask;
1557 RTL_W8(cfg[i].reg, options);
1558 }
1559
Francois Romieu851e6022012-04-17 11:10:11 +02001560 switch (tp->mac_version) {
1561 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1562 options = RTL_R8(Config1) & ~PMEnable;
1563 if (wolopts)
1564 options |= PMEnable;
1565 RTL_W8(Config1, options);
1566 break;
1567 default:
Francois Romieud387b422012-04-17 11:12:01 +02001568 options = RTL_R8(Config2) & ~PME_SIGNAL;
1569 if (wolopts)
1570 options |= PME_SIGNAL;
1571 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001572 break;
1573 }
1574
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001575 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001576}
1577
1578static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1579{
1580 struct rtl8169_private *tp = netdev_priv(dev);
1581
Francois Romieuda78dbf2012-01-26 14:18:23 +01001582 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001583
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001584 if (wol->wolopts)
1585 tp->features |= RTL_FEATURE_WOL;
1586 else
1587 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001588 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001589
1590 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001591
françois romieuea809072010-11-08 13:23:58 +00001592 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1593
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001594 return 0;
1595}
1596
Francois Romieu31bd2042011-04-26 18:58:59 +02001597static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1598{
Francois Romieu85bffe62011-04-27 08:22:39 +02001599 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001600}
1601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602static void rtl8169_get_drvinfo(struct net_device *dev,
1603 struct ethtool_drvinfo *info)
1604{
1605 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001606 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
Rick Jones68aad782011-11-07 13:29:27 +00001608 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1609 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1610 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001611 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001612 if (!IS_ERR_OR_NULL(rtl_fw))
1613 strlcpy(info->fw_version, rtl_fw->version,
1614 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615}
1616
1617static int rtl8169_get_regs_len(struct net_device *dev)
1618{
1619 return R8169_REGS_SIZE;
1620}
1621
1622static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001623 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
1625 struct rtl8169_private *tp = netdev_priv(dev);
1626 void __iomem *ioaddr = tp->mmio_addr;
1627 int ret = 0;
1628 u32 reg;
1629
1630 reg = RTL_R32(TBICSR);
1631 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1632 (duplex == DUPLEX_FULL)) {
1633 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1634 } else if (autoneg == AUTONEG_ENABLE)
1635 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1636 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001637 netif_warn(tp, link, dev,
1638 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 ret = -EOPNOTSUPP;
1640 }
1641
1642 return ret;
1643}
1644
1645static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001646 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
1648 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001649 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001650 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Hayes Wang716b50a2011-02-22 17:26:18 +08001652 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001655 int auto_nego;
1656
françois romieu4da19632011-01-03 15:07:55 +00001657 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001658 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1659 ADVERTISE_100HALF | ADVERTISE_100FULL);
1660
1661 if (adv & ADVERTISED_10baseT_Half)
1662 auto_nego |= ADVERTISE_10HALF;
1663 if (adv & ADVERTISED_10baseT_Full)
1664 auto_nego |= ADVERTISE_10FULL;
1665 if (adv & ADVERTISED_100baseT_Half)
1666 auto_nego |= ADVERTISE_100HALF;
1667 if (adv & ADVERTISED_100baseT_Full)
1668 auto_nego |= ADVERTISE_100FULL;
1669
françois romieu3577aa12009-05-19 10:46:48 +00001670 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1671
françois romieu4da19632011-01-03 15:07:55 +00001672 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001673 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1674
1675 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001676 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001677 if (adv & ADVERTISED_1000baseT_Half)
1678 giga_ctrl |= ADVERTISE_1000HALF;
1679 if (adv & ADVERTISED_1000baseT_Full)
1680 giga_ctrl |= ADVERTISE_1000FULL;
1681 } else if (adv & (ADVERTISED_1000baseT_Half |
1682 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001683 netif_info(tp, link, dev,
1684 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001685 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
françois romieu3577aa12009-05-19 10:46:48 +00001688 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001689
françois romieu4da19632011-01-03 15:07:55 +00001690 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1691 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001692 } else {
1693 giga_ctrl = 0;
1694
1695 if (speed == SPEED_10)
1696 bmcr = 0;
1697 else if (speed == SPEED_100)
1698 bmcr = BMCR_SPEED100;
1699 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001700 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001701
1702 if (duplex == DUPLEX_FULL)
1703 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001704 }
1705
françois romieu4da19632011-01-03 15:07:55 +00001706 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001707
Francois Romieucecb5fd2011-04-01 10:21:07 +02001708 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1709 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001710 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001711 rtl_writephy(tp, 0x17, 0x2138);
1712 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001713 } else {
françois romieu4da19632011-01-03 15:07:55 +00001714 rtl_writephy(tp, 0x17, 0x2108);
1715 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001716 }
1717 }
1718
Oliver Neukum54405cd2011-01-06 21:55:13 +01001719 rc = 0;
1720out:
1721 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722}
1723
1724static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001725 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
1727 struct rtl8169_private *tp = netdev_priv(dev);
1728 int ret;
1729
Oliver Neukum54405cd2011-01-06 21:55:13 +01001730 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001731 if (ret < 0)
1732 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Francois Romieu4876cc12011-03-11 21:07:11 +01001734 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1735 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001737 }
1738out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 return ret;
1740}
1741
1742static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1743{
1744 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 int ret;
1746
Francois Romieu4876cc12011-03-11 21:07:11 +01001747 del_timer_sync(&tp->timer);
1748
Francois Romieuda78dbf2012-01-26 14:18:23 +01001749 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001750 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001751 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001752 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return ret;
1755}
1756
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001757static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1758 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
Francois Romieud58d46b2011-05-03 16:38:29 +02001760 struct rtl8169_private *tp = netdev_priv(dev);
1761
Francois Romieu2b7b4312011-04-18 22:53:24 -07001762 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001763 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
Francois Romieud58d46b2011-05-03 16:38:29 +02001765 if (dev->mtu > JUMBO_1K &&
1766 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1767 features &= ~NETIF_F_IP_CSUM;
1768
Michał Mirosław350fb322011-04-08 06:35:56 +00001769 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
Francois Romieuda78dbf2012-01-26 14:18:23 +01001772static void __rtl8169_set_features(struct net_device *dev,
1773 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774{
1775 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001776 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001777 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Ben Greear6bbe0212012-02-10 15:04:33 +00001779 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1780 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Ben Greear6bbe0212012-02-10 15:04:33 +00001782 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1783 if (features & NETIF_F_RXCSUM)
1784 tp->cp_cmd |= RxChkSum;
1785 else
1786 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001787
Ben Greear6bbe0212012-02-10 15:04:33 +00001788 if (dev->features & NETIF_F_HW_VLAN_RX)
1789 tp->cp_cmd |= RxVlan;
1790 else
1791 tp->cp_cmd &= ~RxVlan;
1792
1793 RTL_W16(CPlusCmd, tp->cp_cmd);
1794 RTL_R16(CPlusCmd);
1795 }
1796 if (changed & NETIF_F_RXALL) {
1797 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1798 if (features & NETIF_F_RXALL)
1799 tmp |= (AcceptErr | AcceptRunt);
1800 RTL_W32(RxConfig, tmp);
1801 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001802}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Francois Romieuda78dbf2012-01-26 14:18:23 +01001804static int rtl8169_set_features(struct net_device *dev,
1805 netdev_features_t features)
1806{
1807 struct rtl8169_private *tp = netdev_priv(dev);
1808
1809 rtl_lock_work(tp);
1810 __rtl8169_set_features(dev, features);
1811 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 return 0;
1814}
1815
Francois Romieuda78dbf2012-01-26 14:18:23 +01001816
Kirill Smelkov810f4892012-11-10 21:11:02 +04001817static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818{
Jesse Grosseab6d182010-10-20 13:56:03 +00001819 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1821}
1822
Francois Romieu7a8fc772011-03-01 17:18:33 +01001823static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824{
1825 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Francois Romieu7a8fc772011-03-01 17:18:33 +01001827 if (opts2 & RxVlanTag)
1828 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Eric Dumazet2edae082010-09-06 18:46:39 +00001829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 desc->opts2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831}
1832
Francois Romieuccdffb92008-07-26 14:26:06 +02001833static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
1835 struct rtl8169_private *tp = netdev_priv(dev);
1836 void __iomem *ioaddr = tp->mmio_addr;
1837 u32 status;
1838
1839 cmd->supported =
1840 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1841 cmd->port = PORT_FIBRE;
1842 cmd->transceiver = XCVR_INTERNAL;
1843
1844 status = RTL_R32(TBICSR);
1845 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1846 cmd->autoneg = !!(status & TBINwEnable);
1847
David Decotigny70739492011-04-27 18:32:40 +00001848 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001850
1851 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
Francois Romieuccdffb92008-07-26 14:26:06 +02001854static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
1856 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Francois Romieuccdffb92008-07-26 14:26:06 +02001858 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859}
1860
1861static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1862{
1863 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001864 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Francois Romieuda78dbf2012-01-26 14:18:23 +01001866 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001867 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001868 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Francois Romieuccdffb92008-07-26 14:26:06 +02001870 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}
1872
1873static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1874 void *p)
1875{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001876 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Francois Romieu5b0384f2006-08-16 16:00:01 +02001878 if (regs->len > R8169_REGS_SIZE)
1879 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Francois Romieuda78dbf2012-01-26 14:18:23 +01001881 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001882 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001883 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884}
1885
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001886static u32 rtl8169_get_msglevel(struct net_device *dev)
1887{
1888 struct rtl8169_private *tp = netdev_priv(dev);
1889
1890 return tp->msg_enable;
1891}
1892
1893static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1894{
1895 struct rtl8169_private *tp = netdev_priv(dev);
1896
1897 tp->msg_enable = value;
1898}
1899
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001900static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1901 "tx_packets",
1902 "rx_packets",
1903 "tx_errors",
1904 "rx_errors",
1905 "rx_missed",
1906 "align_errors",
1907 "tx_single_collisions",
1908 "tx_multi_collisions",
1909 "unicast",
1910 "broadcast",
1911 "multicast",
1912 "tx_aborted",
1913 "tx_underrun",
1914};
1915
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001916static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001917{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001918 switch (sset) {
1919 case ETH_SS_STATS:
1920 return ARRAY_SIZE(rtl8169_gstrings);
1921 default:
1922 return -EOPNOTSUPP;
1923 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001924}
1925
Francois Romieuffc46952012-07-06 14:19:23 +02001926DECLARE_RTL_COND(rtl_counters_cond)
1927{
1928 void __iomem *ioaddr = tp->mmio_addr;
1929
1930 return RTL_R32(CounterAddrLow) & CounterDump;
1931}
1932
Ivan Vecera355423d2009-02-06 21:49:57 -08001933static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001934{
1935 struct rtl8169_private *tp = netdev_priv(dev);
1936 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001937 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001938 struct rtl8169_counters *counters;
1939 dma_addr_t paddr;
1940 u32 cmd;
1941
Ivan Vecera355423d2009-02-06 21:49:57 -08001942 /*
1943 * Some chips are unable to dump tally counters when the receiver
1944 * is disabled.
1945 */
1946 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1947 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001948
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001949 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001950 if (!counters)
1951 return;
1952
1953 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001954 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001955 RTL_W32(CounterAddrLow, cmd);
1956 RTL_W32(CounterAddrLow, cmd | CounterDump);
1957
Francois Romieuffc46952012-07-06 14:19:23 +02001958 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1959 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001960
1961 RTL_W32(CounterAddrLow, 0);
1962 RTL_W32(CounterAddrHigh, 0);
1963
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001964 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001965}
1966
Ivan Vecera355423d2009-02-06 21:49:57 -08001967static void rtl8169_get_ethtool_stats(struct net_device *dev,
1968 struct ethtool_stats *stats, u64 *data)
1969{
1970 struct rtl8169_private *tp = netdev_priv(dev);
1971
1972 ASSERT_RTNL();
1973
1974 rtl8169_update_counters(dev);
1975
1976 data[0] = le64_to_cpu(tp->counters.tx_packets);
1977 data[1] = le64_to_cpu(tp->counters.rx_packets);
1978 data[2] = le64_to_cpu(tp->counters.tx_errors);
1979 data[3] = le32_to_cpu(tp->counters.rx_errors);
1980 data[4] = le16_to_cpu(tp->counters.rx_missed);
1981 data[5] = le16_to_cpu(tp->counters.align_errors);
1982 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1983 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1984 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1985 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1986 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1987 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1988 data[12] = le16_to_cpu(tp->counters.tx_underun);
1989}
1990
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001991static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1992{
1993 switch(stringset) {
1994 case ETH_SS_STATS:
1995 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1996 break;
1997 }
1998}
1999
Jeff Garzik7282d492006-09-13 14:30:00 -04002000static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 .get_drvinfo = rtl8169_get_drvinfo,
2002 .get_regs_len = rtl8169_get_regs_len,
2003 .get_link = ethtool_op_get_link,
2004 .get_settings = rtl8169_get_settings,
2005 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002006 .get_msglevel = rtl8169_get_msglevel,
2007 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002009 .get_wol = rtl8169_get_wol,
2010 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002011 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002012 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002013 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002014 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015};
2016
Francois Romieu07d3f512007-02-21 22:40:46 +01002017static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002018 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019{
Francois Romieu5d320a22011-05-08 17:47:36 +02002020 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002021 /*
2022 * The driver currently handles the 8168Bf and the 8168Be identically
2023 * but they can be identified more specifically through the test below
2024 * if needed:
2025 *
2026 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002027 *
2028 * Same thing for the 8101Eb and the 8101Ec:
2029 *
2030 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002031 */
Francois Romieu37441002011-06-17 22:58:54 +02002032 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002034 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 int mac_version;
2036 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002037 /* 8168G family. */
2038 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2039 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2040
Hayes Wangc2218922011-09-06 16:55:18 +08002041 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002042 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002043 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2044 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2045
hayeswang01dc7fe2011-03-21 01:50:28 +00002046 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002047 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002048 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2049 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2050 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2051
Francois Romieu5b538df2008-07-20 16:22:45 +02002052 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002053 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2054 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002055 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002056
françois romieue6de30d2011-01-03 15:08:37 +00002057 /* 8168DP family. */
2058 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2059 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002060 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002061
Francois Romieuef808d52008-06-29 13:10:54 +02002062 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002063 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002064 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002065 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002066 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002067 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2068 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002069 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002070 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002071 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002072
2073 /* 8168B family. */
2074 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2075 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2076 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2077 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2078
2079 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002080 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2081 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002082 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002083 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002084 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2085 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2086 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002087 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2088 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2089 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2090 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2091 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2092 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002093 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002094 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002095 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002096 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2097 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002098 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2099 /* FIXME: where did these entries come from ? -- FR */
2100 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2101 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2102
2103 /* 8110 family. */
2104 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2105 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2106 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2107 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2108 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2109 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2110
Jean Delvaref21b75e2009-05-26 20:54:48 -07002111 /* Catch-all */
2112 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002113 };
2114 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 u32 reg;
2116
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002117 reg = RTL_R32(TxConfig);
2118 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 p++;
2120 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002121
2122 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2123 netif_notice(tp, probe, dev,
2124 "unknown MAC, using family default\n");
2125 tp->mac_version = default_version;
2126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127}
2128
2129static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2130{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002131 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Francois Romieu867763c2007-08-17 18:21:58 +02002134struct phy_reg {
2135 u16 reg;
2136 u16 val;
2137};
2138
françois romieu4da19632011-01-03 15:07:55 +00002139static void rtl_writephy_batch(struct rtl8169_private *tp,
2140 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002141{
2142 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002143 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002144 regs++;
2145 }
2146}
2147
françois romieubca03d52011-01-03 15:07:31 +00002148#define PHY_READ 0x00000000
2149#define PHY_DATA_OR 0x10000000
2150#define PHY_DATA_AND 0x20000000
2151#define PHY_BJMPN 0x30000000
2152#define PHY_READ_EFUSE 0x40000000
2153#define PHY_READ_MAC_BYTE 0x50000000
2154#define PHY_WRITE_MAC_BYTE 0x60000000
2155#define PHY_CLEAR_READCOUNT 0x70000000
2156#define PHY_WRITE 0x80000000
2157#define PHY_READCOUNT_EQ_SKIP 0x90000000
2158#define PHY_COMP_EQ_SKIPN 0xa0000000
2159#define PHY_COMP_NEQ_SKIPN 0xb0000000
2160#define PHY_WRITE_PREVIOUS 0xc0000000
2161#define PHY_SKIPN 0xd0000000
2162#define PHY_DELAY_MS 0xe0000000
2163#define PHY_WRITE_ERI_WORD 0xf0000000
2164
Hayes Wang960aee62011-06-18 11:37:48 +02002165struct fw_info {
2166 u32 magic;
2167 char version[RTL_VER_SIZE];
2168 __le32 fw_start;
2169 __le32 fw_len;
2170 u8 chksum;
2171} __packed;
2172
Francois Romieu1c361ef2011-06-17 17:16:24 +02002173#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2174
2175static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002176{
Francois Romieub6ffd972011-06-17 17:00:05 +02002177 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002178 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002179 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2180 char *version = rtl_fw->version;
2181 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002182
Francois Romieu1c361ef2011-06-17 17:16:24 +02002183 if (fw->size < FW_OPCODE_SIZE)
2184 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002185
2186 if (!fw_info->magic) {
2187 size_t i, size, start;
2188 u8 checksum = 0;
2189
2190 if (fw->size < sizeof(*fw_info))
2191 goto out;
2192
2193 for (i = 0; i < fw->size; i++)
2194 checksum += fw->data[i];
2195 if (checksum != 0)
2196 goto out;
2197
2198 start = le32_to_cpu(fw_info->fw_start);
2199 if (start > fw->size)
2200 goto out;
2201
2202 size = le32_to_cpu(fw_info->fw_len);
2203 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2204 goto out;
2205
2206 memcpy(version, fw_info->version, RTL_VER_SIZE);
2207
2208 pa->code = (__le32 *)(fw->data + start);
2209 pa->size = size;
2210 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002211 if (fw->size % FW_OPCODE_SIZE)
2212 goto out;
2213
2214 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2215
2216 pa->code = (__le32 *)fw->data;
2217 pa->size = fw->size / FW_OPCODE_SIZE;
2218 }
2219 version[RTL_VER_SIZE - 1] = 0;
2220
2221 rc = true;
2222out:
2223 return rc;
2224}
2225
Francois Romieufd112f22011-06-18 00:10:29 +02002226static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2227 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002228{
Francois Romieufd112f22011-06-18 00:10:29 +02002229 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002230 size_t index;
2231
Francois Romieu1c361ef2011-06-17 17:16:24 +02002232 for (index = 0; index < pa->size; index++) {
2233 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002234 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002235
hayeswang42b82dc2011-01-10 02:07:25 +00002236 switch(action & 0xf0000000) {
2237 case PHY_READ:
2238 case PHY_DATA_OR:
2239 case PHY_DATA_AND:
2240 case PHY_READ_EFUSE:
2241 case PHY_CLEAR_READCOUNT:
2242 case PHY_WRITE:
2243 case PHY_WRITE_PREVIOUS:
2244 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002245 break;
2246
hayeswang42b82dc2011-01-10 02:07:25 +00002247 case PHY_BJMPN:
2248 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002249 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002250 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002251 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002252 }
2253 break;
2254 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002255 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002256 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002257 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002258 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002259 }
2260 break;
2261 case PHY_COMP_EQ_SKIPN:
2262 case PHY_COMP_NEQ_SKIPN:
2263 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002264 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002265 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002266 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002267 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002268 }
2269 break;
2270
2271 case PHY_READ_MAC_BYTE:
2272 case PHY_WRITE_MAC_BYTE:
2273 case PHY_WRITE_ERI_WORD:
2274 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002275 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002276 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002277 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002278 }
2279 }
Francois Romieufd112f22011-06-18 00:10:29 +02002280 rc = true;
2281out:
2282 return rc;
2283}
françois romieubca03d52011-01-03 15:07:31 +00002284
Francois Romieufd112f22011-06-18 00:10:29 +02002285static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2286{
2287 struct net_device *dev = tp->dev;
2288 int rc = -EINVAL;
2289
2290 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2291 netif_err(tp, ifup, dev, "invalid firwmare\n");
2292 goto out;
2293 }
2294
2295 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2296 rc = 0;
2297out:
2298 return rc;
2299}
2300
2301static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2302{
2303 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2304 u32 predata, count;
2305 size_t index;
2306
2307 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002308
Francois Romieu1c361ef2011-06-17 17:16:24 +02002309 for (index = 0; index < pa->size; ) {
2310 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002311 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002312 u32 regno = (action & 0x0fff0000) >> 16;
2313
2314 if (!action)
2315 break;
françois romieubca03d52011-01-03 15:07:31 +00002316
2317 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002318 case PHY_READ:
2319 predata = rtl_readphy(tp, regno);
2320 count++;
2321 index++;
françois romieubca03d52011-01-03 15:07:31 +00002322 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002323 case PHY_DATA_OR:
2324 predata |= data;
2325 index++;
2326 break;
2327 case PHY_DATA_AND:
2328 predata &= data;
2329 index++;
2330 break;
2331 case PHY_BJMPN:
2332 index -= regno;
2333 break;
2334 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002335 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002336 index++;
2337 break;
2338 case PHY_CLEAR_READCOUNT:
2339 count = 0;
2340 index++;
2341 break;
2342 case PHY_WRITE:
2343 rtl_writephy(tp, regno, data);
2344 index++;
2345 break;
2346 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002347 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002348 break;
2349 case PHY_COMP_EQ_SKIPN:
2350 if (predata == data)
2351 index += regno;
2352 index++;
2353 break;
2354 case PHY_COMP_NEQ_SKIPN:
2355 if (predata != data)
2356 index += regno;
2357 index++;
2358 break;
2359 case PHY_WRITE_PREVIOUS:
2360 rtl_writephy(tp, regno, predata);
2361 index++;
2362 break;
2363 case PHY_SKIPN:
2364 index += regno + 1;
2365 break;
2366 case PHY_DELAY_MS:
2367 mdelay(data);
2368 index++;
2369 break;
2370
2371 case PHY_READ_MAC_BYTE:
2372 case PHY_WRITE_MAC_BYTE:
2373 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002374 default:
2375 BUG();
2376 }
2377 }
2378}
2379
françois romieuf1e02ed2011-01-13 13:07:53 +00002380static void rtl_release_firmware(struct rtl8169_private *tp)
2381{
Francois Romieub6ffd972011-06-17 17:00:05 +02002382 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2383 release_firmware(tp->rtl_fw->fw);
2384 kfree(tp->rtl_fw);
2385 }
2386 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002387}
2388
François Romieu953a12c2011-04-24 17:38:48 +02002389static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002390{
Francois Romieub6ffd972011-06-17 17:00:05 +02002391 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002392
2393 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002394 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002395 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002396 tp->features |= RTL_FEATURE_FW_LOADED;
2397 }
François Romieu953a12c2011-04-24 17:38:48 +02002398}
2399
2400static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2401{
2402 if (rtl_readphy(tp, reg) != val)
2403 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2404 else
2405 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002406}
2407
hayeswange0c07552012-10-23 20:24:03 +00002408static void r810x_aldps_disable(struct rtl8169_private *tp)
2409{
2410 rtl_writephy(tp, 0x1f, 0x0000);
2411 rtl_writephy(tp, 0x18, 0x0310);
2412 msleep(100);
2413}
2414
2415static void r810x_aldps_enable(struct rtl8169_private *tp)
2416{
2417 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2418 return;
2419
2420 rtl_writephy(tp, 0x1f, 0x0000);
2421 rtl_writephy(tp, 0x18, 0x8310);
2422}
2423
2424static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2425{
2426 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2427 return;
2428
2429 rtl_writephy(tp, 0x1f, 0x0000);
2430 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2431}
2432
françois romieu4da19632011-01-03 15:07:55 +00002433static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002435 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002436 { 0x1f, 0x0001 },
2437 { 0x06, 0x006e },
2438 { 0x08, 0x0708 },
2439 { 0x15, 0x4000 },
2440 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
françois romieu0b9b5712009-08-10 19:44:56 +00002442 { 0x1f, 0x0001 },
2443 { 0x03, 0x00a1 },
2444 { 0x02, 0x0008 },
2445 { 0x01, 0x0120 },
2446 { 0x00, 0x1000 },
2447 { 0x04, 0x0800 },
2448 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
françois romieu0b9b5712009-08-10 19:44:56 +00002450 { 0x03, 0xff41 },
2451 { 0x02, 0xdf60 },
2452 { 0x01, 0x0140 },
2453 { 0x00, 0x0077 },
2454 { 0x04, 0x7800 },
2455 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
françois romieu0b9b5712009-08-10 19:44:56 +00002457 { 0x03, 0x802f },
2458 { 0x02, 0x4f02 },
2459 { 0x01, 0x0409 },
2460 { 0x00, 0xf0f9 },
2461 { 0x04, 0x9800 },
2462 { 0x04, 0x9000 },
2463
2464 { 0x03, 0xdf01 },
2465 { 0x02, 0xdf20 },
2466 { 0x01, 0xff95 },
2467 { 0x00, 0xba00 },
2468 { 0x04, 0xa800 },
2469 { 0x04, 0xa000 },
2470
2471 { 0x03, 0xff41 },
2472 { 0x02, 0xdf20 },
2473 { 0x01, 0x0140 },
2474 { 0x00, 0x00bb },
2475 { 0x04, 0xb800 },
2476 { 0x04, 0xb000 },
2477
2478 { 0x03, 0xdf41 },
2479 { 0x02, 0xdc60 },
2480 { 0x01, 0x6340 },
2481 { 0x00, 0x007d },
2482 { 0x04, 0xd800 },
2483 { 0x04, 0xd000 },
2484
2485 { 0x03, 0xdf01 },
2486 { 0x02, 0xdf20 },
2487 { 0x01, 0x100a },
2488 { 0x00, 0xa0ff },
2489 { 0x04, 0xf800 },
2490 { 0x04, 0xf000 },
2491
2492 { 0x1f, 0x0000 },
2493 { 0x0b, 0x0000 },
2494 { 0x00, 0x9200 }
2495 };
2496
françois romieu4da19632011-01-03 15:07:55 +00002497 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498}
2499
françois romieu4da19632011-01-03 15:07:55 +00002500static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002501{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002502 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002503 { 0x1f, 0x0002 },
2504 { 0x01, 0x90d0 },
2505 { 0x1f, 0x0000 }
2506 };
2507
françois romieu4da19632011-01-03 15:07:55 +00002508 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002509}
2510
françois romieu4da19632011-01-03 15:07:55 +00002511static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002512{
2513 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002514
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002515 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2516 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002517 return;
2518
françois romieu4da19632011-01-03 15:07:55 +00002519 rtl_writephy(tp, 0x1f, 0x0001);
2520 rtl_writephy(tp, 0x10, 0xf01b);
2521 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002522}
2523
françois romieu4da19632011-01-03 15:07:55 +00002524static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002525{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002526 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002527 { 0x1f, 0x0001 },
2528 { 0x04, 0x0000 },
2529 { 0x03, 0x00a1 },
2530 { 0x02, 0x0008 },
2531 { 0x01, 0x0120 },
2532 { 0x00, 0x1000 },
2533 { 0x04, 0x0800 },
2534 { 0x04, 0x9000 },
2535 { 0x03, 0x802f },
2536 { 0x02, 0x4f02 },
2537 { 0x01, 0x0409 },
2538 { 0x00, 0xf099 },
2539 { 0x04, 0x9800 },
2540 { 0x04, 0xa000 },
2541 { 0x03, 0xdf01 },
2542 { 0x02, 0xdf20 },
2543 { 0x01, 0xff95 },
2544 { 0x00, 0xba00 },
2545 { 0x04, 0xa800 },
2546 { 0x04, 0xf000 },
2547 { 0x03, 0xdf01 },
2548 { 0x02, 0xdf20 },
2549 { 0x01, 0x101a },
2550 { 0x00, 0xa0ff },
2551 { 0x04, 0xf800 },
2552 { 0x04, 0x0000 },
2553 { 0x1f, 0x0000 },
2554
2555 { 0x1f, 0x0001 },
2556 { 0x10, 0xf41b },
2557 { 0x14, 0xfb54 },
2558 { 0x18, 0xf5c7 },
2559 { 0x1f, 0x0000 },
2560
2561 { 0x1f, 0x0001 },
2562 { 0x17, 0x0cc0 },
2563 { 0x1f, 0x0000 }
2564 };
2565
françois romieu4da19632011-01-03 15:07:55 +00002566 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002567
françois romieu4da19632011-01-03 15:07:55 +00002568 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002569}
2570
françois romieu4da19632011-01-03 15:07:55 +00002571static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002572{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002573 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002574 { 0x1f, 0x0001 },
2575 { 0x04, 0x0000 },
2576 { 0x03, 0x00a1 },
2577 { 0x02, 0x0008 },
2578 { 0x01, 0x0120 },
2579 { 0x00, 0x1000 },
2580 { 0x04, 0x0800 },
2581 { 0x04, 0x9000 },
2582 { 0x03, 0x802f },
2583 { 0x02, 0x4f02 },
2584 { 0x01, 0x0409 },
2585 { 0x00, 0xf099 },
2586 { 0x04, 0x9800 },
2587 { 0x04, 0xa000 },
2588 { 0x03, 0xdf01 },
2589 { 0x02, 0xdf20 },
2590 { 0x01, 0xff95 },
2591 { 0x00, 0xba00 },
2592 { 0x04, 0xa800 },
2593 { 0x04, 0xf000 },
2594 { 0x03, 0xdf01 },
2595 { 0x02, 0xdf20 },
2596 { 0x01, 0x101a },
2597 { 0x00, 0xa0ff },
2598 { 0x04, 0xf800 },
2599 { 0x04, 0x0000 },
2600 { 0x1f, 0x0000 },
2601
2602 { 0x1f, 0x0001 },
2603 { 0x0b, 0x8480 },
2604 { 0x1f, 0x0000 },
2605
2606 { 0x1f, 0x0001 },
2607 { 0x18, 0x67c7 },
2608 { 0x04, 0x2000 },
2609 { 0x03, 0x002f },
2610 { 0x02, 0x4360 },
2611 { 0x01, 0x0109 },
2612 { 0x00, 0x3022 },
2613 { 0x04, 0x2800 },
2614 { 0x1f, 0x0000 },
2615
2616 { 0x1f, 0x0001 },
2617 { 0x17, 0x0cc0 },
2618 { 0x1f, 0x0000 }
2619 };
2620
françois romieu4da19632011-01-03 15:07:55 +00002621 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002622}
2623
françois romieu4da19632011-01-03 15:07:55 +00002624static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002625{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002626 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002627 { 0x10, 0xf41b },
2628 { 0x1f, 0x0000 }
2629 };
2630
françois romieu4da19632011-01-03 15:07:55 +00002631 rtl_writephy(tp, 0x1f, 0x0001);
2632 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002633
françois romieu4da19632011-01-03 15:07:55 +00002634 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002635}
2636
françois romieu4da19632011-01-03 15:07:55 +00002637static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002638{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002639 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002640 { 0x1f, 0x0001 },
2641 { 0x10, 0xf41b },
2642 { 0x1f, 0x0000 }
2643 };
2644
françois romieu4da19632011-01-03 15:07:55 +00002645 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002646}
2647
françois romieu4da19632011-01-03 15:07:55 +00002648static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002649{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002650 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002651 { 0x1f, 0x0000 },
2652 { 0x1d, 0x0f00 },
2653 { 0x1f, 0x0002 },
2654 { 0x0c, 0x1ec8 },
2655 { 0x1f, 0x0000 }
2656 };
2657
françois romieu4da19632011-01-03 15:07:55 +00002658 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002659}
2660
françois romieu4da19632011-01-03 15:07:55 +00002661static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002662{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002663 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002664 { 0x1f, 0x0001 },
2665 { 0x1d, 0x3d98 },
2666 { 0x1f, 0x0000 }
2667 };
2668
françois romieu4da19632011-01-03 15:07:55 +00002669 rtl_writephy(tp, 0x1f, 0x0000);
2670 rtl_patchphy(tp, 0x14, 1 << 5);
2671 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002672
françois romieu4da19632011-01-03 15:07:55 +00002673 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002674}
2675
françois romieu4da19632011-01-03 15:07:55 +00002676static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002677{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002678 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002679 { 0x1f, 0x0001 },
2680 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002681 { 0x1f, 0x0002 },
2682 { 0x00, 0x88d4 },
2683 { 0x01, 0x82b1 },
2684 { 0x03, 0x7002 },
2685 { 0x08, 0x9e30 },
2686 { 0x09, 0x01f0 },
2687 { 0x0a, 0x5500 },
2688 { 0x0c, 0x00c8 },
2689 { 0x1f, 0x0003 },
2690 { 0x12, 0xc096 },
2691 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002692 { 0x1f, 0x0000 },
2693 { 0x1f, 0x0000 },
2694 { 0x09, 0x2000 },
2695 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002696 };
2697
françois romieu4da19632011-01-03 15:07:55 +00002698 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002699
françois romieu4da19632011-01-03 15:07:55 +00002700 rtl_patchphy(tp, 0x14, 1 << 5);
2701 rtl_patchphy(tp, 0x0d, 1 << 5);
2702 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002703}
2704
françois romieu4da19632011-01-03 15:07:55 +00002705static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002706{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002707 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002708 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002709 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002710 { 0x03, 0x802f },
2711 { 0x02, 0x4f02 },
2712 { 0x01, 0x0409 },
2713 { 0x00, 0xf099 },
2714 { 0x04, 0x9800 },
2715 { 0x04, 0x9000 },
2716 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002717 { 0x1f, 0x0002 },
2718 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002719 { 0x06, 0x0761 },
2720 { 0x1f, 0x0003 },
2721 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002722 { 0x1f, 0x0000 }
2723 };
2724
françois romieu4da19632011-01-03 15:07:55 +00002725 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002726
françois romieu4da19632011-01-03 15:07:55 +00002727 rtl_patchphy(tp, 0x16, 1 << 0);
2728 rtl_patchphy(tp, 0x14, 1 << 5);
2729 rtl_patchphy(tp, 0x0d, 1 << 5);
2730 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002731}
2732
françois romieu4da19632011-01-03 15:07:55 +00002733static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002734{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002735 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002736 { 0x1f, 0x0001 },
2737 { 0x12, 0x2300 },
2738 { 0x1d, 0x3d98 },
2739 { 0x1f, 0x0002 },
2740 { 0x0c, 0x7eb8 },
2741 { 0x06, 0x5461 },
2742 { 0x1f, 0x0003 },
2743 { 0x16, 0x0f0a },
2744 { 0x1f, 0x0000 }
2745 };
2746
françois romieu4da19632011-01-03 15:07:55 +00002747 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002748
françois romieu4da19632011-01-03 15:07:55 +00002749 rtl_patchphy(tp, 0x16, 1 << 0);
2750 rtl_patchphy(tp, 0x14, 1 << 5);
2751 rtl_patchphy(tp, 0x0d, 1 << 5);
2752 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002753}
2754
françois romieu4da19632011-01-03 15:07:55 +00002755static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002756{
françois romieu4da19632011-01-03 15:07:55 +00002757 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002758}
2759
françois romieubca03d52011-01-03 15:07:31 +00002760static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002761{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002762 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002763 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002764 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002765 { 0x06, 0x4064 },
2766 { 0x07, 0x2863 },
2767 { 0x08, 0x059c },
2768 { 0x09, 0x26b4 },
2769 { 0x0a, 0x6a19 },
2770 { 0x0b, 0xdcc8 },
2771 { 0x10, 0xf06d },
2772 { 0x14, 0x7f68 },
2773 { 0x18, 0x7fd9 },
2774 { 0x1c, 0xf0ff },
2775 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002776 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002777 { 0x12, 0xf49f },
2778 { 0x13, 0x070b },
2779 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002780 { 0x14, 0x94c0 },
2781
2782 /*
2783 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002784 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002785 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002786 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002787 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002788 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002789 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002790 { 0x06, 0x5561 },
2791
2792 /*
2793 * Can not link to 1Gbps with bad cable
2794 * Decrease SNR threshold form 21.07dB to 19.04dB
2795 */
2796 { 0x1f, 0x0001 },
2797 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002798
2799 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002800 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002801 };
2802
françois romieu4da19632011-01-03 15:07:55 +00002803 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002804
françois romieubca03d52011-01-03 15:07:31 +00002805 /*
2806 * Rx Error Issue
2807 * Fine Tune Switching regulator parameter
2808 */
françois romieu4da19632011-01-03 15:07:55 +00002809 rtl_writephy(tp, 0x1f, 0x0002);
2810 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2811 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002812
Francois Romieufdf6fc02012-07-06 22:40:38 +02002813 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002814 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002815 { 0x1f, 0x0002 },
2816 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002817 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002818 { 0x05, 0x8330 },
2819 { 0x06, 0x669a },
2820 { 0x1f, 0x0002 }
2821 };
2822 int val;
2823
françois romieu4da19632011-01-03 15:07:55 +00002824 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002825
françois romieu4da19632011-01-03 15:07:55 +00002826 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002827
2828 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002829 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002830 0x0065, 0x0066, 0x0067, 0x0068,
2831 0x0069, 0x006a, 0x006b, 0x006c
2832 };
2833 int i;
2834
françois romieu4da19632011-01-03 15:07:55 +00002835 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002836
2837 val &= 0xff00;
2838 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002839 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002840 }
2841 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002842 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002843 { 0x1f, 0x0002 },
2844 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002845 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002846 { 0x05, 0x8330 },
2847 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002848 };
2849
françois romieu4da19632011-01-03 15:07:55 +00002850 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002851 }
2852
françois romieubca03d52011-01-03 15:07:31 +00002853 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002854 rtl_writephy(tp, 0x1f, 0x0002);
2855 rtl_patchphy(tp, 0x0d, 0x0300);
2856 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002857
françois romieubca03d52011-01-03 15:07:31 +00002858 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002859 rtl_writephy(tp, 0x1f, 0x0002);
2860 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2861 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002862
françois romieu4da19632011-01-03 15:07:55 +00002863 rtl_writephy(tp, 0x1f, 0x0005);
2864 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002865
2866 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002867
françois romieu4da19632011-01-03 15:07:55 +00002868 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002869}
2870
françois romieubca03d52011-01-03 15:07:31 +00002871static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002872{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002873 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002874 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002875 { 0x1f, 0x0001 },
2876 { 0x06, 0x4064 },
2877 { 0x07, 0x2863 },
2878 { 0x08, 0x059c },
2879 { 0x09, 0x26b4 },
2880 { 0x0a, 0x6a19 },
2881 { 0x0b, 0xdcc8 },
2882 { 0x10, 0xf06d },
2883 { 0x14, 0x7f68 },
2884 { 0x18, 0x7fd9 },
2885 { 0x1c, 0xf0ff },
2886 { 0x1d, 0x3d9c },
2887 { 0x1f, 0x0003 },
2888 { 0x12, 0xf49f },
2889 { 0x13, 0x070b },
2890 { 0x1a, 0x05ad },
2891 { 0x14, 0x94c0 },
2892
françois romieubca03d52011-01-03 15:07:31 +00002893 /*
2894 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002895 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002896 */
françois romieudaf9df62009-10-07 12:44:20 +00002897 { 0x1f, 0x0002 },
2898 { 0x06, 0x5561 },
2899 { 0x1f, 0x0005 },
2900 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002901 { 0x06, 0x5561 },
2902
2903 /*
2904 * Can not link to 1Gbps with bad cable
2905 * Decrease SNR threshold form 21.07dB to 19.04dB
2906 */
2907 { 0x1f, 0x0001 },
2908 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002909
2910 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002911 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002912 };
2913
françois romieu4da19632011-01-03 15:07:55 +00002914 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002915
Francois Romieufdf6fc02012-07-06 22:40:38 +02002916 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002917 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002918 { 0x1f, 0x0002 },
2919 { 0x05, 0x669a },
2920 { 0x1f, 0x0005 },
2921 { 0x05, 0x8330 },
2922 { 0x06, 0x669a },
2923
2924 { 0x1f, 0x0002 }
2925 };
2926 int val;
2927
françois romieu4da19632011-01-03 15:07:55 +00002928 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002929
françois romieu4da19632011-01-03 15:07:55 +00002930 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002931 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002932 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002933 0x0065, 0x0066, 0x0067, 0x0068,
2934 0x0069, 0x006a, 0x006b, 0x006c
2935 };
2936 int i;
2937
françois romieu4da19632011-01-03 15:07:55 +00002938 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002939
2940 val &= 0xff00;
2941 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002942 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002943 }
2944 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002945 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002946 { 0x1f, 0x0002 },
2947 { 0x05, 0x2642 },
2948 { 0x1f, 0x0005 },
2949 { 0x05, 0x8330 },
2950 { 0x06, 0x2642 }
2951 };
2952
françois romieu4da19632011-01-03 15:07:55 +00002953 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002954 }
2955
françois romieubca03d52011-01-03 15:07:31 +00002956 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002957 rtl_writephy(tp, 0x1f, 0x0002);
2958 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2959 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002960
françois romieubca03d52011-01-03 15:07:31 +00002961 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002962 rtl_writephy(tp, 0x1f, 0x0002);
2963 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002964
françois romieu4da19632011-01-03 15:07:55 +00002965 rtl_writephy(tp, 0x1f, 0x0005);
2966 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002967
2968 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002969
françois romieu4da19632011-01-03 15:07:55 +00002970 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002971}
2972
françois romieu4da19632011-01-03 15:07:55 +00002973static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002974{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002975 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002976 { 0x1f, 0x0002 },
2977 { 0x10, 0x0008 },
2978 { 0x0d, 0x006c },
2979
2980 { 0x1f, 0x0000 },
2981 { 0x0d, 0xf880 },
2982
2983 { 0x1f, 0x0001 },
2984 { 0x17, 0x0cc0 },
2985
2986 { 0x1f, 0x0001 },
2987 { 0x0b, 0xa4d8 },
2988 { 0x09, 0x281c },
2989 { 0x07, 0x2883 },
2990 { 0x0a, 0x6b35 },
2991 { 0x1d, 0x3da4 },
2992 { 0x1c, 0xeffd },
2993 { 0x14, 0x7f52 },
2994 { 0x18, 0x7fc6 },
2995 { 0x08, 0x0601 },
2996 { 0x06, 0x4063 },
2997 { 0x10, 0xf074 },
2998 { 0x1f, 0x0003 },
2999 { 0x13, 0x0789 },
3000 { 0x12, 0xf4bd },
3001 { 0x1a, 0x04fd },
3002 { 0x14, 0x84b0 },
3003 { 0x1f, 0x0000 },
3004 { 0x00, 0x9200 },
3005
3006 { 0x1f, 0x0005 },
3007 { 0x01, 0x0340 },
3008 { 0x1f, 0x0001 },
3009 { 0x04, 0x4000 },
3010 { 0x03, 0x1d21 },
3011 { 0x02, 0x0c32 },
3012 { 0x01, 0x0200 },
3013 { 0x00, 0x5554 },
3014 { 0x04, 0x4800 },
3015 { 0x04, 0x4000 },
3016 { 0x04, 0xf000 },
3017 { 0x03, 0xdf01 },
3018 { 0x02, 0xdf20 },
3019 { 0x01, 0x101a },
3020 { 0x00, 0xa0ff },
3021 { 0x04, 0xf800 },
3022 { 0x04, 0xf000 },
3023 { 0x1f, 0x0000 },
3024
3025 { 0x1f, 0x0007 },
3026 { 0x1e, 0x0023 },
3027 { 0x16, 0x0000 },
3028 { 0x1f, 0x0000 }
3029 };
3030
françois romieu4da19632011-01-03 15:07:55 +00003031 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003032}
3033
françois romieue6de30d2011-01-03 15:08:37 +00003034static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3035{
3036 static const struct phy_reg phy_reg_init[] = {
3037 { 0x1f, 0x0001 },
3038 { 0x17, 0x0cc0 },
3039
3040 { 0x1f, 0x0007 },
3041 { 0x1e, 0x002d },
3042 { 0x18, 0x0040 },
3043 { 0x1f, 0x0000 }
3044 };
3045
3046 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3047 rtl_patchphy(tp, 0x0d, 1 << 5);
3048}
3049
Hayes Wang70090422011-07-06 15:58:06 +08003050static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003051{
3052 static const struct phy_reg phy_reg_init[] = {
3053 /* Enable Delay cap */
3054 { 0x1f, 0x0005 },
3055 { 0x05, 0x8b80 },
3056 { 0x06, 0xc896 },
3057 { 0x1f, 0x0000 },
3058
3059 /* Channel estimation fine tune */
3060 { 0x1f, 0x0001 },
3061 { 0x0b, 0x6c20 },
3062 { 0x07, 0x2872 },
3063 { 0x1c, 0xefff },
3064 { 0x1f, 0x0003 },
3065 { 0x14, 0x6420 },
3066 { 0x1f, 0x0000 },
3067
3068 /* Update PFM & 10M TX idle timer */
3069 { 0x1f, 0x0007 },
3070 { 0x1e, 0x002f },
3071 { 0x15, 0x1919 },
3072 { 0x1f, 0x0000 },
3073
3074 { 0x1f, 0x0007 },
3075 { 0x1e, 0x00ac },
3076 { 0x18, 0x0006 },
3077 { 0x1f, 0x0000 }
3078 };
3079
Francois Romieu15ecd032011-04-27 13:52:22 -07003080 rtl_apply_firmware(tp);
3081
hayeswang01dc7fe2011-03-21 01:50:28 +00003082 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3083
3084 /* DCO enable for 10M IDLE Power */
3085 rtl_writephy(tp, 0x1f, 0x0007);
3086 rtl_writephy(tp, 0x1e, 0x0023);
3087 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3088 rtl_writephy(tp, 0x1f, 0x0000);
3089
3090 /* For impedance matching */
3091 rtl_writephy(tp, 0x1f, 0x0002);
3092 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003093 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003094
3095 /* PHY auto speed down */
3096 rtl_writephy(tp, 0x1f, 0x0007);
3097 rtl_writephy(tp, 0x1e, 0x002d);
3098 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3099 rtl_writephy(tp, 0x1f, 0x0000);
3100 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3101
3102 rtl_writephy(tp, 0x1f, 0x0005);
3103 rtl_writephy(tp, 0x05, 0x8b86);
3104 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3105 rtl_writephy(tp, 0x1f, 0x0000);
3106
3107 rtl_writephy(tp, 0x1f, 0x0005);
3108 rtl_writephy(tp, 0x05, 0x8b85);
3109 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3110 rtl_writephy(tp, 0x1f, 0x0007);
3111 rtl_writephy(tp, 0x1e, 0x0020);
3112 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3113 rtl_writephy(tp, 0x1f, 0x0006);
3114 rtl_writephy(tp, 0x00, 0x5a00);
3115 rtl_writephy(tp, 0x1f, 0x0000);
3116 rtl_writephy(tp, 0x0d, 0x0007);
3117 rtl_writephy(tp, 0x0e, 0x003c);
3118 rtl_writephy(tp, 0x0d, 0x4007);
3119 rtl_writephy(tp, 0x0e, 0x0000);
3120 rtl_writephy(tp, 0x0d, 0x0000);
3121}
3122
Hayes Wang70090422011-07-06 15:58:06 +08003123static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3124{
3125 static const struct phy_reg phy_reg_init[] = {
3126 /* Enable Delay cap */
3127 { 0x1f, 0x0004 },
3128 { 0x1f, 0x0007 },
3129 { 0x1e, 0x00ac },
3130 { 0x18, 0x0006 },
3131 { 0x1f, 0x0002 },
3132 { 0x1f, 0x0000 },
3133 { 0x1f, 0x0000 },
3134
3135 /* Channel estimation fine tune */
3136 { 0x1f, 0x0003 },
3137 { 0x09, 0xa20f },
3138 { 0x1f, 0x0000 },
3139 { 0x1f, 0x0000 },
3140
3141 /* Green Setting */
3142 { 0x1f, 0x0005 },
3143 { 0x05, 0x8b5b },
3144 { 0x06, 0x9222 },
3145 { 0x05, 0x8b6d },
3146 { 0x06, 0x8000 },
3147 { 0x05, 0x8b76 },
3148 { 0x06, 0x8000 },
3149 { 0x1f, 0x0000 }
3150 };
3151
3152 rtl_apply_firmware(tp);
3153
3154 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3155
3156 /* For 4-corner performance improve */
3157 rtl_writephy(tp, 0x1f, 0x0005);
3158 rtl_writephy(tp, 0x05, 0x8b80);
3159 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3160 rtl_writephy(tp, 0x1f, 0x0000);
3161
3162 /* PHY auto speed down */
3163 rtl_writephy(tp, 0x1f, 0x0004);
3164 rtl_writephy(tp, 0x1f, 0x0007);
3165 rtl_writephy(tp, 0x1e, 0x002d);
3166 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3167 rtl_writephy(tp, 0x1f, 0x0002);
3168 rtl_writephy(tp, 0x1f, 0x0000);
3169 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3170
3171 /* improve 10M EEE waveform */
3172 rtl_writephy(tp, 0x1f, 0x0005);
3173 rtl_writephy(tp, 0x05, 0x8b86);
3174 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3175 rtl_writephy(tp, 0x1f, 0x0000);
3176
3177 /* Improve 2-pair detection performance */
3178 rtl_writephy(tp, 0x1f, 0x0005);
3179 rtl_writephy(tp, 0x05, 0x8b85);
3180 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3181 rtl_writephy(tp, 0x1f, 0x0000);
3182
3183 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003184 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003185 rtl_writephy(tp, 0x1f, 0x0005);
3186 rtl_writephy(tp, 0x05, 0x8b85);
3187 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3188 rtl_writephy(tp, 0x1f, 0x0004);
3189 rtl_writephy(tp, 0x1f, 0x0007);
3190 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003191 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003192 rtl_writephy(tp, 0x1f, 0x0002);
3193 rtl_writephy(tp, 0x1f, 0x0000);
3194 rtl_writephy(tp, 0x0d, 0x0007);
3195 rtl_writephy(tp, 0x0e, 0x003c);
3196 rtl_writephy(tp, 0x0d, 0x4007);
3197 rtl_writephy(tp, 0x0e, 0x0000);
3198 rtl_writephy(tp, 0x0d, 0x0000);
3199
3200 /* Green feature */
3201 rtl_writephy(tp, 0x1f, 0x0003);
3202 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3203 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3204 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003205
3206 r8168_aldps_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08003207}
3208
Hayes Wang5f886e02012-03-30 14:33:03 +08003209static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3210{
3211 /* For 4-corner performance improve */
3212 rtl_writephy(tp, 0x1f, 0x0005);
3213 rtl_writephy(tp, 0x05, 0x8b80);
3214 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3215 rtl_writephy(tp, 0x1f, 0x0000);
3216
3217 /* PHY auto speed down */
3218 rtl_writephy(tp, 0x1f, 0x0007);
3219 rtl_writephy(tp, 0x1e, 0x002d);
3220 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3221 rtl_writephy(tp, 0x1f, 0x0000);
3222 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3223
3224 /* Improve 10M EEE waveform */
3225 rtl_writephy(tp, 0x1f, 0x0005);
3226 rtl_writephy(tp, 0x05, 0x8b86);
3227 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3228 rtl_writephy(tp, 0x1f, 0x0000);
3229}
3230
Hayes Wangc2218922011-09-06 16:55:18 +08003231static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3232{
3233 static const struct phy_reg phy_reg_init[] = {
3234 /* Channel estimation fine tune */
3235 { 0x1f, 0x0003 },
3236 { 0x09, 0xa20f },
3237 { 0x1f, 0x0000 },
3238
3239 /* Modify green table for giga & fnet */
3240 { 0x1f, 0x0005 },
3241 { 0x05, 0x8b55 },
3242 { 0x06, 0x0000 },
3243 { 0x05, 0x8b5e },
3244 { 0x06, 0x0000 },
3245 { 0x05, 0x8b67 },
3246 { 0x06, 0x0000 },
3247 { 0x05, 0x8b70 },
3248 { 0x06, 0x0000 },
3249 { 0x1f, 0x0000 },
3250 { 0x1f, 0x0007 },
3251 { 0x1e, 0x0078 },
3252 { 0x17, 0x0000 },
3253 { 0x19, 0x00fb },
3254 { 0x1f, 0x0000 },
3255
3256 /* Modify green table for 10M */
3257 { 0x1f, 0x0005 },
3258 { 0x05, 0x8b79 },
3259 { 0x06, 0xaa00 },
3260 { 0x1f, 0x0000 },
3261
3262 /* Disable hiimpedance detection (RTCT) */
3263 { 0x1f, 0x0003 },
3264 { 0x01, 0x328a },
3265 { 0x1f, 0x0000 }
3266 };
3267
3268 rtl_apply_firmware(tp);
3269
3270 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3271
Hayes Wang5f886e02012-03-30 14:33:03 +08003272 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003273
3274 /* Improve 2-pair detection performance */
3275 rtl_writephy(tp, 0x1f, 0x0005);
3276 rtl_writephy(tp, 0x05, 0x8b85);
3277 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3278 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003279
3280 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003281}
3282
3283static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3284{
3285 rtl_apply_firmware(tp);
3286
Hayes Wang5f886e02012-03-30 14:33:03 +08003287 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003288
3289 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003290}
3291
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003292static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3293{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003294 static const struct phy_reg phy_reg_init[] = {
3295 /* Channel estimation fine tune */
3296 { 0x1f, 0x0003 },
3297 { 0x09, 0xa20f },
3298 { 0x1f, 0x0000 },
3299
3300 /* Modify green table for giga & fnet */
3301 { 0x1f, 0x0005 },
3302 { 0x05, 0x8b55 },
3303 { 0x06, 0x0000 },
3304 { 0x05, 0x8b5e },
3305 { 0x06, 0x0000 },
3306 { 0x05, 0x8b67 },
3307 { 0x06, 0x0000 },
3308 { 0x05, 0x8b70 },
3309 { 0x06, 0x0000 },
3310 { 0x1f, 0x0000 },
3311 { 0x1f, 0x0007 },
3312 { 0x1e, 0x0078 },
3313 { 0x17, 0x0000 },
3314 { 0x19, 0x00aa },
3315 { 0x1f, 0x0000 },
3316
3317 /* Modify green table for 10M */
3318 { 0x1f, 0x0005 },
3319 { 0x05, 0x8b79 },
3320 { 0x06, 0xaa00 },
3321 { 0x1f, 0x0000 },
3322
3323 /* Disable hiimpedance detection (RTCT) */
3324 { 0x1f, 0x0003 },
3325 { 0x01, 0x328a },
3326 { 0x1f, 0x0000 }
3327 };
3328
3329
3330 rtl_apply_firmware(tp);
3331
3332 rtl8168f_hw_phy_config(tp);
3333
3334 /* Improve 2-pair detection performance */
3335 rtl_writephy(tp, 0x1f, 0x0005);
3336 rtl_writephy(tp, 0x05, 0x8b85);
3337 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3338 rtl_writephy(tp, 0x1f, 0x0000);
3339
3340 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3341
3342 /* Modify green table for giga */
3343 rtl_writephy(tp, 0x1f, 0x0005);
3344 rtl_writephy(tp, 0x05, 0x8b54);
3345 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3346 rtl_writephy(tp, 0x05, 0x8b5d);
3347 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3348 rtl_writephy(tp, 0x05, 0x8a7c);
3349 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3350 rtl_writephy(tp, 0x05, 0x8a7f);
3351 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3352 rtl_writephy(tp, 0x05, 0x8a82);
3353 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3354 rtl_writephy(tp, 0x05, 0x8a85);
3355 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3356 rtl_writephy(tp, 0x05, 0x8a88);
3357 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3358 rtl_writephy(tp, 0x1f, 0x0000);
3359
3360 /* uc same-seed solution */
3361 rtl_writephy(tp, 0x1f, 0x0005);
3362 rtl_writephy(tp, 0x05, 0x8b85);
3363 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3364 rtl_writephy(tp, 0x1f, 0x0000);
3365
3366 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003367 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003368 rtl_writephy(tp, 0x1f, 0x0005);
3369 rtl_writephy(tp, 0x05, 0x8b85);
3370 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3371 rtl_writephy(tp, 0x1f, 0x0004);
3372 rtl_writephy(tp, 0x1f, 0x0007);
3373 rtl_writephy(tp, 0x1e, 0x0020);
3374 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3375 rtl_writephy(tp, 0x1f, 0x0000);
3376 rtl_writephy(tp, 0x0d, 0x0007);
3377 rtl_writephy(tp, 0x0e, 0x003c);
3378 rtl_writephy(tp, 0x0d, 0x4007);
3379 rtl_writephy(tp, 0x0e, 0x0000);
3380 rtl_writephy(tp, 0x0d, 0x0000);
3381
3382 /* Green feature */
3383 rtl_writephy(tp, 0x1f, 0x0003);
3384 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3385 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3386 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003387
3388 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003389}
3390
Hayes Wangc5583862012-07-02 17:23:22 +08003391static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3392{
3393 static const u16 mac_ocp_patch[] = {
3394 0xe008, 0xe01b, 0xe01d, 0xe01f,
3395 0xe021, 0xe023, 0xe025, 0xe027,
3396 0x49d2, 0xf10d, 0x766c, 0x49e2,
3397 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3398
3399 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3400 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3401 0xbe00, 0xb416, 0x0076, 0xe86c,
3402 0xc602, 0xbe00, 0x0000, 0xc602,
3403
3404 0xbe00, 0x0000, 0xc602, 0xbe00,
3405 0x0000, 0xc602, 0xbe00, 0x0000,
3406 0xc602, 0xbe00, 0x0000, 0xc602,
3407 0xbe00, 0x0000, 0xc602, 0xbe00,
3408
3409 0x0000, 0x0000, 0x0000, 0x0000
3410 };
3411 u32 i;
3412
3413 /* Patch code for GPHY reset */
3414 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3415 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3416 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3417 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3418
3419 rtl_apply_firmware(tp);
3420
3421 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3422 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3423 else
3424 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3425
3426 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3427 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3428 else
3429 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3430
3431 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3432 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3433
3434 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3435 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3436
3437 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3438}
3439
françois romieu4da19632011-01-03 15:07:55 +00003440static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003441{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003442 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003443 { 0x1f, 0x0003 },
3444 { 0x08, 0x441d },
3445 { 0x01, 0x9100 },
3446 { 0x1f, 0x0000 }
3447 };
3448
françois romieu4da19632011-01-03 15:07:55 +00003449 rtl_writephy(tp, 0x1f, 0x0000);
3450 rtl_patchphy(tp, 0x11, 1 << 12);
3451 rtl_patchphy(tp, 0x19, 1 << 13);
3452 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003453
françois romieu4da19632011-01-03 15:07:55 +00003454 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003455}
3456
Hayes Wang5a5e4442011-02-22 17:26:21 +08003457static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3458{
3459 static const struct phy_reg phy_reg_init[] = {
3460 { 0x1f, 0x0005 },
3461 { 0x1a, 0x0000 },
3462 { 0x1f, 0x0000 },
3463
3464 { 0x1f, 0x0004 },
3465 { 0x1c, 0x0000 },
3466 { 0x1f, 0x0000 },
3467
3468 { 0x1f, 0x0001 },
3469 { 0x15, 0x7701 },
3470 { 0x1f, 0x0000 }
3471 };
3472
3473 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003474 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003475
François Romieu953a12c2011-04-24 17:38:48 +02003476 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003477
3478 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003479
3480 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003481}
3482
Hayes Wang7e18dca2012-03-30 14:33:02 +08003483static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3484{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003485 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003486 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003487
3488 rtl_apply_firmware(tp);
3489
3490 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003491 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003492 rtl_writephy(tp, 0x1f, 0x0004);
3493 rtl_writephy(tp, 0x10, 0x401f);
3494 rtl_writephy(tp, 0x19, 0x7030);
3495 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003496
3497 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003498}
3499
Hayes Wang5598bfe2012-07-02 17:23:21 +08003500static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3501{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003502 static const struct phy_reg phy_reg_init[] = {
3503 { 0x1f, 0x0004 },
3504 { 0x10, 0xc07f },
3505 { 0x19, 0x7030 },
3506 { 0x1f, 0x0000 }
3507 };
3508
3509 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003510 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003511
3512 rtl_apply_firmware(tp);
3513
Francois Romieufdf6fc02012-07-06 22:40:38 +02003514 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003515 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3516
Francois Romieufdf6fc02012-07-06 22:40:38 +02003517 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003518
3519 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003520}
3521
Francois Romieu5615d9f2007-08-17 17:50:46 +02003522static void rtl_hw_phy_config(struct net_device *dev)
3523{
3524 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003525
3526 rtl8169_print_mac_version(tp);
3527
3528 switch (tp->mac_version) {
3529 case RTL_GIGA_MAC_VER_01:
3530 break;
3531 case RTL_GIGA_MAC_VER_02:
3532 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003533 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003534 break;
3535 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003536 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003537 break;
françois romieu2e9558562009-08-10 19:44:19 +00003538 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003539 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003540 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003541 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003542 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003543 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003544 case RTL_GIGA_MAC_VER_07:
3545 case RTL_GIGA_MAC_VER_08:
3546 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003547 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003548 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003549 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003550 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003551 break;
3552 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003554 break;
3555 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003556 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003557 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003558 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003559 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003560 break;
3561 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003563 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003564 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003565 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003566 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003567 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003568 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003569 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003570 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003571 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003572 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003573 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003574 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003575 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003576 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003577 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003578 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003579 break;
3580 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003581 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003582 break;
3583 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003584 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003585 break;
françois romieue6de30d2011-01-03 15:08:37 +00003586 case RTL_GIGA_MAC_VER_28:
3587 rtl8168d_4_hw_phy_config(tp);
3588 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003589 case RTL_GIGA_MAC_VER_29:
3590 case RTL_GIGA_MAC_VER_30:
3591 rtl8105e_hw_phy_config(tp);
3592 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003593 case RTL_GIGA_MAC_VER_31:
3594 /* None. */
3595 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003596 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003597 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003598 rtl8168e_1_hw_phy_config(tp);
3599 break;
3600 case RTL_GIGA_MAC_VER_34:
3601 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003602 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003603 case RTL_GIGA_MAC_VER_35:
3604 rtl8168f_1_hw_phy_config(tp);
3605 break;
3606 case RTL_GIGA_MAC_VER_36:
3607 rtl8168f_2_hw_phy_config(tp);
3608 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003609
Hayes Wang7e18dca2012-03-30 14:33:02 +08003610 case RTL_GIGA_MAC_VER_37:
3611 rtl8402_hw_phy_config(tp);
3612 break;
3613
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003614 case RTL_GIGA_MAC_VER_38:
3615 rtl8411_hw_phy_config(tp);
3616 break;
3617
Hayes Wang5598bfe2012-07-02 17:23:21 +08003618 case RTL_GIGA_MAC_VER_39:
3619 rtl8106e_hw_phy_config(tp);
3620 break;
3621
Hayes Wangc5583862012-07-02 17:23:22 +08003622 case RTL_GIGA_MAC_VER_40:
3623 rtl8168g_1_hw_phy_config(tp);
3624 break;
3625
3626 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003627 default:
3628 break;
3629 }
3630}
3631
Francois Romieuda78dbf2012-01-26 14:18:23 +01003632static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 struct timer_list *timer = &tp->timer;
3635 void __iomem *ioaddr = tp->mmio_addr;
3636 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3637
Francois Romieubcf0bf92006-07-26 23:14:13 +02003638 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
françois romieu4da19632011-01-03 15:07:55 +00003640 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003641 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 * A busy loop could burn quite a few cycles on nowadays CPU.
3643 * Let's delay the execution of the timer for a few ticks.
3644 */
3645 timeout = HZ/10;
3646 goto out_mod_timer;
3647 }
3648
3649 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003650 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Francois Romieuda78dbf2012-01-26 14:18:23 +01003652 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
françois romieu4da19632011-01-03 15:07:55 +00003654 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
3656out_mod_timer:
3657 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003658}
3659
3660static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3661{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003662 if (!test_and_set_bit(flag, tp->wk.flags))
3663 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003664}
3665
3666static void rtl8169_phy_timer(unsigned long __opaque)
3667{
3668 struct net_device *dev = (struct net_device *)__opaque;
3669 struct rtl8169_private *tp = netdev_priv(dev);
3670
Francois Romieu98ddf982012-01-31 10:47:34 +01003671 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672}
3673
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3675 void __iomem *ioaddr)
3676{
3677 iounmap(ioaddr);
3678 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003679 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 pci_disable_device(pdev);
3681 free_netdev(dev);
3682}
3683
Francois Romieuffc46952012-07-06 14:19:23 +02003684DECLARE_RTL_COND(rtl_phy_reset_cond)
3685{
3686 return tp->phy_reset_pending(tp);
3687}
3688
Francois Romieubf793292006-11-01 00:53:05 +01003689static void rtl8169_phy_reset(struct net_device *dev,
3690 struct rtl8169_private *tp)
3691{
françois romieu4da19632011-01-03 15:07:55 +00003692 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003693 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003694}
3695
David S. Miller8decf862011-09-22 03:23:13 -04003696static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3697{
3698 void __iomem *ioaddr = tp->mmio_addr;
3699
3700 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3701 (RTL_R8(PHYstatus) & TBI_Enable);
3702}
3703
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003704static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003706 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003707
Francois Romieu5615d9f2007-08-17 17:50:46 +02003708 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003709
Marcus Sundberg773328942008-07-10 21:28:08 +02003710 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3711 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3712 RTL_W8(0x82, 0x01);
3713 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003714
Francois Romieu6dccd162007-02-13 23:38:05 +01003715 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3716
3717 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3718 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003719
Francois Romieubcf0bf92006-07-26 23:14:13 +02003720 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003721 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3722 RTL_W8(0x82, 0x01);
3723 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003724 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003725 }
3726
Francois Romieubf793292006-11-01 00:53:05 +01003727 rtl8169_phy_reset(dev, tp);
3728
Oliver Neukum54405cd2011-01-06 21:55:13 +01003729 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003730 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3731 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3732 (tp->mii.supports_gmii ?
3733 ADVERTISED_1000baseT_Half |
3734 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003735
David S. Miller8decf862011-09-22 03:23:13 -04003736 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003737 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003738}
3739
Francois Romieu773d2022007-01-31 23:47:43 +01003740static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3741{
3742 void __iomem *ioaddr = tp->mmio_addr;
3743 u32 high;
3744 u32 low;
3745
3746 low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
3747 high = addr[4] | (addr[5] << 8);
3748
Francois Romieuda78dbf2012-01-26 14:18:23 +01003749 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003750
3751 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003752
Francois Romieu773d2022007-01-31 23:47:43 +01003753 RTL_W32(MAC4, high);
françois romieu908ba2b2010-04-26 11:42:58 +00003754 RTL_R32(MAC4);
3755
Francois Romieu78f1cd02010-03-27 19:35:46 -07003756 RTL_W32(MAC0, low);
françois romieu908ba2b2010-04-26 11:42:58 +00003757 RTL_R32(MAC0);
3758
françois romieuc28aa382011-08-02 03:53:43 +00003759 if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
3760 const struct exgmac_reg e[] = {
3761 { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
3762 { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
3763 { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
3764 { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
3765 low >> 16 },
3766 };
3767
Francois Romieufdf6fc02012-07-06 22:40:38 +02003768 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
françois romieuc28aa382011-08-02 03:53:43 +00003769 }
3770
Francois Romieu773d2022007-01-31 23:47:43 +01003771 RTL_W8(Cfg9346, Cfg9346_Lock);
3772
Francois Romieuda78dbf2012-01-26 14:18:23 +01003773 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003774}
3775
3776static int rtl_set_mac_address(struct net_device *dev, void *p)
3777{
3778 struct rtl8169_private *tp = netdev_priv(dev);
3779 struct sockaddr *addr = p;
3780
3781 if (!is_valid_ether_addr(addr->sa_data))
3782 return -EADDRNOTAVAIL;
3783
3784 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3785
3786 rtl_rar_set(tp, dev->dev_addr);
3787
3788 return 0;
3789}
3790
Francois Romieu5f787a12006-08-17 13:02:36 +02003791static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3792{
3793 struct rtl8169_private *tp = netdev_priv(dev);
3794 struct mii_ioctl_data *data = if_mii(ifr);
3795
Francois Romieu8b4ab282008-11-19 22:05:25 -08003796 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3797}
Francois Romieu5f787a12006-08-17 13:02:36 +02003798
Francois Romieucecb5fd2011-04-01 10:21:07 +02003799static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3800 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003801{
Francois Romieu5f787a12006-08-17 13:02:36 +02003802 switch (cmd) {
3803 case SIOCGMIIPHY:
3804 data->phy_id = 32; /* Internal PHY */
3805 return 0;
3806
3807 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003808 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003809 return 0;
3810
3811 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003812 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003813 return 0;
3814 }
3815 return -EOPNOTSUPP;
3816}
3817
Francois Romieu8b4ab282008-11-19 22:05:25 -08003818static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3819{
3820 return -EOPNOTSUPP;
3821}
3822
Francois Romieufbac58f2007-10-04 22:51:38 +02003823static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3824{
3825 if (tp->features & RTL_FEATURE_MSI) {
3826 pci_disable_msi(pdev);
3827 tp->features &= ~RTL_FEATURE_MSI;
3828 }
3829}
3830
Bill Pembertonbaf63292012-12-03 09:23:28 -05003831static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003832{
3833 struct mdio_ops *ops = &tp->mdio_ops;
3834
3835 switch (tp->mac_version) {
3836 case RTL_GIGA_MAC_VER_27:
3837 ops->write = r8168dp_1_mdio_write;
3838 ops->read = r8168dp_1_mdio_read;
3839 break;
françois romieue6de30d2011-01-03 15:08:37 +00003840 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003841 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003842 ops->write = r8168dp_2_mdio_write;
3843 ops->read = r8168dp_2_mdio_read;
3844 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003845 case RTL_GIGA_MAC_VER_40:
3846 case RTL_GIGA_MAC_VER_41:
3847 ops->write = r8168g_mdio_write;
3848 ops->read = r8168g_mdio_read;
3849 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003850 default:
3851 ops->write = r8169_mdio_write;
3852 ops->read = r8169_mdio_read;
3853 break;
3854 }
3855}
3856
David S. Miller1805b2f2011-10-24 18:18:09 -04003857static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3858{
3859 void __iomem *ioaddr = tp->mmio_addr;
3860
3861 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003862 case RTL_GIGA_MAC_VER_25:
3863 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003864 case RTL_GIGA_MAC_VER_29:
3865 case RTL_GIGA_MAC_VER_30:
3866 case RTL_GIGA_MAC_VER_32:
3867 case RTL_GIGA_MAC_VER_33:
3868 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003869 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003870 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003871 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003872 case RTL_GIGA_MAC_VER_40:
3873 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003874 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3875 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3876 break;
3877 default:
3878 break;
3879 }
3880}
3881
3882static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3883{
3884 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3885 return false;
3886
3887 rtl_writephy(tp, 0x1f, 0x0000);
3888 rtl_writephy(tp, MII_BMCR, 0x0000);
3889
3890 rtl_wol_suspend_quirk(tp);
3891
3892 return true;
3893}
3894
françois romieu065c27c2011-01-03 15:08:12 +00003895static void r810x_phy_power_down(struct rtl8169_private *tp)
3896{
3897 rtl_writephy(tp, 0x1f, 0x0000);
3898 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3899}
3900
3901static void r810x_phy_power_up(struct rtl8169_private *tp)
3902{
3903 rtl_writephy(tp, 0x1f, 0x0000);
3904 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3905}
3906
3907static void r810x_pll_power_down(struct rtl8169_private *tp)
3908{
Hayes Wang00042992012-03-30 14:33:00 +08003909 void __iomem *ioaddr = tp->mmio_addr;
3910
David S. Miller1805b2f2011-10-24 18:18:09 -04003911 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003912 return;
françois romieu065c27c2011-01-03 15:08:12 +00003913
3914 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003915
3916 switch (tp->mac_version) {
3917 case RTL_GIGA_MAC_VER_07:
3918 case RTL_GIGA_MAC_VER_08:
3919 case RTL_GIGA_MAC_VER_09:
3920 case RTL_GIGA_MAC_VER_10:
3921 case RTL_GIGA_MAC_VER_13:
3922 case RTL_GIGA_MAC_VER_16:
3923 break;
3924 default:
3925 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3926 break;
3927 }
françois romieu065c27c2011-01-03 15:08:12 +00003928}
3929
3930static void r810x_pll_power_up(struct rtl8169_private *tp)
3931{
Hayes Wang00042992012-03-30 14:33:00 +08003932 void __iomem *ioaddr = tp->mmio_addr;
3933
françois romieu065c27c2011-01-03 15:08:12 +00003934 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003935
3936 switch (tp->mac_version) {
3937 case RTL_GIGA_MAC_VER_07:
3938 case RTL_GIGA_MAC_VER_08:
3939 case RTL_GIGA_MAC_VER_09:
3940 case RTL_GIGA_MAC_VER_10:
3941 case RTL_GIGA_MAC_VER_13:
3942 case RTL_GIGA_MAC_VER_16:
3943 break;
3944 default:
3945 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3946 break;
3947 }
françois romieu065c27c2011-01-03 15:08:12 +00003948}
3949
3950static void r8168_phy_power_up(struct rtl8169_private *tp)
3951{
3952 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003953 switch (tp->mac_version) {
3954 case RTL_GIGA_MAC_VER_11:
3955 case RTL_GIGA_MAC_VER_12:
3956 case RTL_GIGA_MAC_VER_17:
3957 case RTL_GIGA_MAC_VER_18:
3958 case RTL_GIGA_MAC_VER_19:
3959 case RTL_GIGA_MAC_VER_20:
3960 case RTL_GIGA_MAC_VER_21:
3961 case RTL_GIGA_MAC_VER_22:
3962 case RTL_GIGA_MAC_VER_23:
3963 case RTL_GIGA_MAC_VER_24:
3964 case RTL_GIGA_MAC_VER_25:
3965 case RTL_GIGA_MAC_VER_26:
3966 case RTL_GIGA_MAC_VER_27:
3967 case RTL_GIGA_MAC_VER_28:
3968 case RTL_GIGA_MAC_VER_31:
3969 rtl_writephy(tp, 0x0e, 0x0000);
3970 break;
3971 default:
3972 break;
3973 }
françois romieu065c27c2011-01-03 15:08:12 +00003974 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3975}
3976
3977static void r8168_phy_power_down(struct rtl8169_private *tp)
3978{
3979 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003980 switch (tp->mac_version) {
3981 case RTL_GIGA_MAC_VER_32:
3982 case RTL_GIGA_MAC_VER_33:
3983 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3984 break;
3985
3986 case RTL_GIGA_MAC_VER_11:
3987 case RTL_GIGA_MAC_VER_12:
3988 case RTL_GIGA_MAC_VER_17:
3989 case RTL_GIGA_MAC_VER_18:
3990 case RTL_GIGA_MAC_VER_19:
3991 case RTL_GIGA_MAC_VER_20:
3992 case RTL_GIGA_MAC_VER_21:
3993 case RTL_GIGA_MAC_VER_22:
3994 case RTL_GIGA_MAC_VER_23:
3995 case RTL_GIGA_MAC_VER_24:
3996 case RTL_GIGA_MAC_VER_25:
3997 case RTL_GIGA_MAC_VER_26:
3998 case RTL_GIGA_MAC_VER_27:
3999 case RTL_GIGA_MAC_VER_28:
4000 case RTL_GIGA_MAC_VER_31:
4001 rtl_writephy(tp, 0x0e, 0x0200);
4002 default:
4003 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4004 break;
4005 }
françois romieu065c27c2011-01-03 15:08:12 +00004006}
4007
4008static void r8168_pll_power_down(struct rtl8169_private *tp)
4009{
4010 void __iomem *ioaddr = tp->mmio_addr;
4011
Francois Romieucecb5fd2011-04-01 10:21:07 +02004012 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4013 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4014 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004015 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004016 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004017 }
françois romieu065c27c2011-01-03 15:08:12 +00004018
Francois Romieucecb5fd2011-04-01 10:21:07 +02004019 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4020 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004021 (RTL_R16(CPlusCmd) & ASF)) {
4022 return;
4023 }
4024
hayeswang01dc7fe2011-03-21 01:50:28 +00004025 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4026 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004027 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004028
David S. Miller1805b2f2011-10-24 18:18:09 -04004029 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004030 return;
françois romieu065c27c2011-01-03 15:08:12 +00004031
4032 r8168_phy_power_down(tp);
4033
4034 switch (tp->mac_version) {
4035 case RTL_GIGA_MAC_VER_25:
4036 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004037 case RTL_GIGA_MAC_VER_27:
4038 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004039 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004040 case RTL_GIGA_MAC_VER_32:
4041 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004042 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4043 break;
4044 }
4045}
4046
4047static void r8168_pll_power_up(struct rtl8169_private *tp)
4048{
4049 void __iomem *ioaddr = tp->mmio_addr;
4050
françois romieu065c27c2011-01-03 15:08:12 +00004051 switch (tp->mac_version) {
4052 case RTL_GIGA_MAC_VER_25:
4053 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004054 case RTL_GIGA_MAC_VER_27:
4055 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004056 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004057 case RTL_GIGA_MAC_VER_32:
4058 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004059 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4060 break;
4061 }
4062
4063 r8168_phy_power_up(tp);
4064}
4065
Francois Romieud58d46b2011-05-03 16:38:29 +02004066static void rtl_generic_op(struct rtl8169_private *tp,
4067 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004068{
4069 if (op)
4070 op(tp);
4071}
4072
4073static void rtl_pll_power_down(struct rtl8169_private *tp)
4074{
Francois Romieud58d46b2011-05-03 16:38:29 +02004075 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004076}
4077
4078static void rtl_pll_power_up(struct rtl8169_private *tp)
4079{
Francois Romieud58d46b2011-05-03 16:38:29 +02004080 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004081}
4082
Bill Pembertonbaf63292012-12-03 09:23:28 -05004083static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004084{
4085 struct pll_power_ops *ops = &tp->pll_power_ops;
4086
4087 switch (tp->mac_version) {
4088 case RTL_GIGA_MAC_VER_07:
4089 case RTL_GIGA_MAC_VER_08:
4090 case RTL_GIGA_MAC_VER_09:
4091 case RTL_GIGA_MAC_VER_10:
4092 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004093 case RTL_GIGA_MAC_VER_29:
4094 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004095 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004096 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004097 ops->down = r810x_pll_power_down;
4098 ops->up = r810x_pll_power_up;
4099 break;
4100
4101 case RTL_GIGA_MAC_VER_11:
4102 case RTL_GIGA_MAC_VER_12:
4103 case RTL_GIGA_MAC_VER_17:
4104 case RTL_GIGA_MAC_VER_18:
4105 case RTL_GIGA_MAC_VER_19:
4106 case RTL_GIGA_MAC_VER_20:
4107 case RTL_GIGA_MAC_VER_21:
4108 case RTL_GIGA_MAC_VER_22:
4109 case RTL_GIGA_MAC_VER_23:
4110 case RTL_GIGA_MAC_VER_24:
4111 case RTL_GIGA_MAC_VER_25:
4112 case RTL_GIGA_MAC_VER_26:
4113 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004114 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004115 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004116 case RTL_GIGA_MAC_VER_32:
4117 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004118 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004119 case RTL_GIGA_MAC_VER_35:
4120 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004121 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004122 case RTL_GIGA_MAC_VER_40:
4123 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004124 ops->down = r8168_pll_power_down;
4125 ops->up = r8168_pll_power_up;
4126 break;
4127
4128 default:
4129 ops->down = NULL;
4130 ops->up = NULL;
4131 break;
4132 }
4133}
4134
Hayes Wange542a222011-07-06 15:58:04 +08004135static void rtl_init_rxcfg(struct rtl8169_private *tp)
4136{
4137 void __iomem *ioaddr = tp->mmio_addr;
4138
4139 switch (tp->mac_version) {
4140 case RTL_GIGA_MAC_VER_01:
4141 case RTL_GIGA_MAC_VER_02:
4142 case RTL_GIGA_MAC_VER_03:
4143 case RTL_GIGA_MAC_VER_04:
4144 case RTL_GIGA_MAC_VER_05:
4145 case RTL_GIGA_MAC_VER_06:
4146 case RTL_GIGA_MAC_VER_10:
4147 case RTL_GIGA_MAC_VER_11:
4148 case RTL_GIGA_MAC_VER_12:
4149 case RTL_GIGA_MAC_VER_13:
4150 case RTL_GIGA_MAC_VER_14:
4151 case RTL_GIGA_MAC_VER_15:
4152 case RTL_GIGA_MAC_VER_16:
4153 case RTL_GIGA_MAC_VER_17:
4154 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4155 break;
4156 case RTL_GIGA_MAC_VER_18:
4157 case RTL_GIGA_MAC_VER_19:
4158 case RTL_GIGA_MAC_VER_20:
4159 case RTL_GIGA_MAC_VER_21:
4160 case RTL_GIGA_MAC_VER_22:
4161 case RTL_GIGA_MAC_VER_23:
4162 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004163 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004164 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4165 break;
4166 default:
4167 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4168 break;
4169 }
4170}
4171
Hayes Wang92fc43b2011-07-06 15:58:03 +08004172static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4173{
4174 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4175}
4176
Francois Romieud58d46b2011-05-03 16:38:29 +02004177static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4178{
françois romieu9c5028e2012-03-02 04:43:14 +00004179 void __iomem *ioaddr = tp->mmio_addr;
4180
4181 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004182 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004183 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004184}
4185
4186static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4187{
françois romieu9c5028e2012-03-02 04:43:14 +00004188 void __iomem *ioaddr = tp->mmio_addr;
4189
4190 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004191 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004192 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004193}
4194
4195static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4196{
4197 void __iomem *ioaddr = tp->mmio_addr;
4198
4199 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4200 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4201 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4202}
4203
4204static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4205{
4206 void __iomem *ioaddr = tp->mmio_addr;
4207
4208 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4209 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4210 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4211}
4212
4213static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4214{
4215 void __iomem *ioaddr = tp->mmio_addr;
4216
4217 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4218}
4219
4220static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4221{
4222 void __iomem *ioaddr = tp->mmio_addr;
4223
4224 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4225}
4226
4227static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4228{
4229 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004230
4231 RTL_W8(MaxTxPacketSize, 0x3f);
4232 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4233 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004234 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004235}
4236
4237static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4238{
4239 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004240
4241 RTL_W8(MaxTxPacketSize, 0x0c);
4242 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4243 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004244 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004245}
4246
4247static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4248{
4249 rtl_tx_performance_tweak(tp->pci_dev,
4250 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4251}
4252
4253static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4254{
4255 rtl_tx_performance_tweak(tp->pci_dev,
4256 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4257}
4258
4259static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4260{
4261 void __iomem *ioaddr = tp->mmio_addr;
4262
4263 r8168b_0_hw_jumbo_enable(tp);
4264
4265 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4266}
4267
4268static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4269{
4270 void __iomem *ioaddr = tp->mmio_addr;
4271
4272 r8168b_0_hw_jumbo_disable(tp);
4273
4274 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4275}
4276
Bill Pembertonbaf63292012-12-03 09:23:28 -05004277static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004278{
4279 struct jumbo_ops *ops = &tp->jumbo_ops;
4280
4281 switch (tp->mac_version) {
4282 case RTL_GIGA_MAC_VER_11:
4283 ops->disable = r8168b_0_hw_jumbo_disable;
4284 ops->enable = r8168b_0_hw_jumbo_enable;
4285 break;
4286 case RTL_GIGA_MAC_VER_12:
4287 case RTL_GIGA_MAC_VER_17:
4288 ops->disable = r8168b_1_hw_jumbo_disable;
4289 ops->enable = r8168b_1_hw_jumbo_enable;
4290 break;
4291 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4292 case RTL_GIGA_MAC_VER_19:
4293 case RTL_GIGA_MAC_VER_20:
4294 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4295 case RTL_GIGA_MAC_VER_22:
4296 case RTL_GIGA_MAC_VER_23:
4297 case RTL_GIGA_MAC_VER_24:
4298 case RTL_GIGA_MAC_VER_25:
4299 case RTL_GIGA_MAC_VER_26:
4300 ops->disable = r8168c_hw_jumbo_disable;
4301 ops->enable = r8168c_hw_jumbo_enable;
4302 break;
4303 case RTL_GIGA_MAC_VER_27:
4304 case RTL_GIGA_MAC_VER_28:
4305 ops->disable = r8168dp_hw_jumbo_disable;
4306 ops->enable = r8168dp_hw_jumbo_enable;
4307 break;
4308 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4309 case RTL_GIGA_MAC_VER_32:
4310 case RTL_GIGA_MAC_VER_33:
4311 case RTL_GIGA_MAC_VER_34:
4312 ops->disable = r8168e_hw_jumbo_disable;
4313 ops->enable = r8168e_hw_jumbo_enable;
4314 break;
4315
4316 /*
4317 * No action needed for jumbo frames with 8169.
4318 * No jumbo for 810x at all.
4319 */
Hayes Wangc5583862012-07-02 17:23:22 +08004320 case RTL_GIGA_MAC_VER_40:
4321 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004322 default:
4323 ops->disable = NULL;
4324 ops->enable = NULL;
4325 break;
4326 }
4327}
4328
Francois Romieuffc46952012-07-06 14:19:23 +02004329DECLARE_RTL_COND(rtl_chipcmd_cond)
4330{
4331 void __iomem *ioaddr = tp->mmio_addr;
4332
4333 return RTL_R8(ChipCmd) & CmdReset;
4334}
4335
Francois Romieu6f43adc2011-04-29 15:05:51 +02004336static void rtl_hw_reset(struct rtl8169_private *tp)
4337{
4338 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004339
Francois Romieu6f43adc2011-04-29 15:05:51 +02004340 RTL_W8(ChipCmd, CmdReset);
4341
Francois Romieuffc46952012-07-06 14:19:23 +02004342 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004343}
4344
Francois Romieub6ffd972011-06-17 17:00:05 +02004345static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4346{
4347 struct rtl_fw *rtl_fw;
4348 const char *name;
4349 int rc = -ENOMEM;
4350
4351 name = rtl_lookup_firmware_name(tp);
4352 if (!name)
4353 goto out_no_firmware;
4354
4355 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4356 if (!rtl_fw)
4357 goto err_warn;
4358
4359 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4360 if (rc < 0)
4361 goto err_free;
4362
Francois Romieufd112f22011-06-18 00:10:29 +02004363 rc = rtl_check_firmware(tp, rtl_fw);
4364 if (rc < 0)
4365 goto err_release_firmware;
4366
Francois Romieub6ffd972011-06-17 17:00:05 +02004367 tp->rtl_fw = rtl_fw;
4368out:
4369 return;
4370
Francois Romieufd112f22011-06-18 00:10:29 +02004371err_release_firmware:
4372 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004373err_free:
4374 kfree(rtl_fw);
4375err_warn:
4376 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4377 name, rc);
4378out_no_firmware:
4379 tp->rtl_fw = NULL;
4380 goto out;
4381}
4382
François Romieu953a12c2011-04-24 17:38:48 +02004383static void rtl_request_firmware(struct rtl8169_private *tp)
4384{
Francois Romieub6ffd972011-06-17 17:00:05 +02004385 if (IS_ERR(tp->rtl_fw))
4386 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004387}
4388
Hayes Wang92fc43b2011-07-06 15:58:03 +08004389static void rtl_rx_close(struct rtl8169_private *tp)
4390{
4391 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004392
Francois Romieu1687b562011-07-19 17:21:29 +02004393 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004394}
4395
Francois Romieuffc46952012-07-06 14:19:23 +02004396DECLARE_RTL_COND(rtl_npq_cond)
4397{
4398 void __iomem *ioaddr = tp->mmio_addr;
4399
4400 return RTL_R8(TxPoll) & NPQ;
4401}
4402
4403DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4404{
4405 void __iomem *ioaddr = tp->mmio_addr;
4406
4407 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4408}
4409
françois romieue6de30d2011-01-03 15:08:37 +00004410static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411{
françois romieue6de30d2011-01-03 15:08:37 +00004412 void __iomem *ioaddr = tp->mmio_addr;
4413
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004415 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Hayes Wang92fc43b2011-07-06 15:58:03 +08004417 rtl_rx_close(tp);
4418
Hayes Wang5d2e1952011-02-22 17:26:22 +08004419 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004420 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4421 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004422 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004423 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4424 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004425 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004426 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004427 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4428 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004429 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004430 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004431 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004432 } else {
4433 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4434 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004435 }
4436
Hayes Wang92fc43b2011-07-06 15:58:03 +08004437 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438}
4439
Francois Romieu7f796d832007-06-11 23:04:41 +02004440static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004441{
4442 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004443
4444 /* Set DMA burst size and Interframe Gap Time */
4445 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4446 (InterFrameGap << TxInterFrameGapShift));
4447}
4448
Francois Romieu07ce4062007-02-23 23:36:39 +01004449static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450{
4451 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Francois Romieu07ce4062007-02-23 23:36:39 +01004453 tp->hw_start(dev);
4454
Francois Romieuda78dbf2012-01-26 14:18:23 +01004455 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004456}
4457
Francois Romieu7f796d832007-06-11 23:04:41 +02004458static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4459 void __iomem *ioaddr)
4460{
4461 /*
4462 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4463 * register to be written before TxDescAddrLow to work.
4464 * Switching from MMIO to I/O access fixes the issue as well.
4465 */
4466 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004467 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004468 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004469 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004470}
4471
4472static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4473{
4474 u16 cmd;
4475
4476 cmd = RTL_R16(CPlusCmd);
4477 RTL_W16(CPlusCmd, cmd);
4478 return cmd;
4479}
4480
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004481static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004482{
4483 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004484 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004485}
4486
Francois Romieu6dccd162007-02-13 23:38:05 +01004487static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4488{
Francois Romieu37441002011-06-17 22:58:54 +02004489 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004490 u32 mac_version;
4491 u32 clk;
4492 u32 val;
4493 } cfg2_info [] = {
4494 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4495 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4496 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4497 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004498 };
4499 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004500 unsigned int i;
4501 u32 clk;
4502
4503 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004504 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004505 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4506 RTL_W32(0x7c, p->val);
4507 break;
4508 }
4509 }
4510}
4511
Francois Romieue6b763e2012-03-08 09:35:39 +01004512static void rtl_set_rx_mode(struct net_device *dev)
4513{
4514 struct rtl8169_private *tp = netdev_priv(dev);
4515 void __iomem *ioaddr = tp->mmio_addr;
4516 u32 mc_filter[2]; /* Multicast hash filter */
4517 int rx_mode;
4518 u32 tmp = 0;
4519
4520 if (dev->flags & IFF_PROMISC) {
4521 /* Unconditionally log net taps. */
4522 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4523 rx_mode =
4524 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4525 AcceptAllPhys;
4526 mc_filter[1] = mc_filter[0] = 0xffffffff;
4527 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4528 (dev->flags & IFF_ALLMULTI)) {
4529 /* Too many to filter perfectly -- accept all multicasts. */
4530 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4531 mc_filter[1] = mc_filter[0] = 0xffffffff;
4532 } else {
4533 struct netdev_hw_addr *ha;
4534
4535 rx_mode = AcceptBroadcast | AcceptMyPhys;
4536 mc_filter[1] = mc_filter[0] = 0;
4537 netdev_for_each_mc_addr(ha, dev) {
4538 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4539 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4540 rx_mode |= AcceptMulticast;
4541 }
4542 }
4543
4544 if (dev->features & NETIF_F_RXALL)
4545 rx_mode |= (AcceptErr | AcceptRunt);
4546
4547 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4548
4549 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4550 u32 data = mc_filter[0];
4551
4552 mc_filter[0] = swab32(mc_filter[1]);
4553 mc_filter[1] = swab32(data);
4554 }
4555
Nathan Walp04817762012-11-01 12:08:47 +00004556 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4557 mc_filter[1] = mc_filter[0] = 0xffffffff;
4558
Francois Romieue6b763e2012-03-08 09:35:39 +01004559 RTL_W32(MAR0 + 4, mc_filter[1]);
4560 RTL_W32(MAR0 + 0, mc_filter[0]);
4561
4562 RTL_W32(RxConfig, tmp);
4563}
4564
Francois Romieu07ce4062007-02-23 23:36:39 +01004565static void rtl_hw_start_8169(struct net_device *dev)
4566{
4567 struct rtl8169_private *tp = netdev_priv(dev);
4568 void __iomem *ioaddr = tp->mmio_addr;
4569 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004570
Francois Romieu9cb427b2006-11-02 00:10:16 +01004571 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4572 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4573 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4574 }
4575
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004577 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4578 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4579 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4580 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004581 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4582
Hayes Wange542a222011-07-06 15:58:04 +08004583 rtl_init_rxcfg(tp);
4584
françois romieuf0298f82011-01-03 15:07:42 +00004585 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004587 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Francois Romieucecb5fd2011-04-01 10:21:07 +02004589 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4590 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4591 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4592 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004593 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
Francois Romieu7f796d832007-06-11 23:04:41 +02004595 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004596
Francois Romieucecb5fd2011-04-01 10:21:07 +02004597 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4598 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004599 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004601 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 }
4603
Francois Romieubcf0bf92006-07-26 23:14:13 +02004604 RTL_W16(CPlusCmd, tp->cp_cmd);
4605
Francois Romieu6dccd162007-02-13 23:38:05 +01004606 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4607
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 /*
4609 * Undocumented corner. Supposedly:
4610 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4611 */
4612 RTL_W16(IntrMitigate, 0x0000);
4613
Francois Romieu7f796d832007-06-11 23:04:41 +02004614 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004615
Francois Romieucecb5fd2011-04-01 10:21:07 +02004616 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4617 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4618 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4619 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004620 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4621 rtl_set_rx_tx_config_registers(tp);
4622 }
4623
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004625
4626 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4627 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628
4629 RTL_W32(RxMissed, 0);
4630
Francois Romieu07ce4062007-02-23 23:36:39 +01004631 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632
4633 /* no early-rx interrupts */
4634 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004635}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004637static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4638{
4639 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004640 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004641}
4642
4643static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4644{
Francois Romieu52989f02012-07-06 13:37:00 +02004645 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004646}
4647
4648static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004649{
4650 u32 csi;
4651
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004652 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4653 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004654}
4655
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004656static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004657{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004658 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004659}
4660
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004661static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004662{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004663 rtl_csi_access_enable(tp, 0x27000000);
4664}
4665
Francois Romieuffc46952012-07-06 14:19:23 +02004666DECLARE_RTL_COND(rtl_csiar_cond)
4667{
4668 void __iomem *ioaddr = tp->mmio_addr;
4669
4670 return RTL_R32(CSIAR) & CSIAR_FLAG;
4671}
4672
Francois Romieu52989f02012-07-06 13:37:00 +02004673static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004674{
Francois Romieu52989f02012-07-06 13:37:00 +02004675 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004676
4677 RTL_W32(CSIDR, value);
4678 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4679 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4680
Francois Romieuffc46952012-07-06 14:19:23 +02004681 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004682}
4683
Francois Romieu52989f02012-07-06 13:37:00 +02004684static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004685{
Francois Romieu52989f02012-07-06 13:37:00 +02004686 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004687
4688 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4689 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4690
Francois Romieuffc46952012-07-06 14:19:23 +02004691 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4692 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004693}
4694
Francois Romieu52989f02012-07-06 13:37:00 +02004695static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004696{
Francois Romieu52989f02012-07-06 13:37:00 +02004697 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004698
4699 RTL_W32(CSIDR, value);
4700 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4701 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4702 CSIAR_FUNC_NIC);
4703
Francois Romieuffc46952012-07-06 14:19:23 +02004704 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004705}
4706
Francois Romieu52989f02012-07-06 13:37:00 +02004707static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004708{
Francois Romieu52989f02012-07-06 13:37:00 +02004709 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004710
4711 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4712 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4713
Francois Romieuffc46952012-07-06 14:19:23 +02004714 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4715 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004716}
4717
Bill Pembertonbaf63292012-12-03 09:23:28 -05004718static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004719{
4720 struct csi_ops *ops = &tp->csi_ops;
4721
4722 switch (tp->mac_version) {
4723 case RTL_GIGA_MAC_VER_01:
4724 case RTL_GIGA_MAC_VER_02:
4725 case RTL_GIGA_MAC_VER_03:
4726 case RTL_GIGA_MAC_VER_04:
4727 case RTL_GIGA_MAC_VER_05:
4728 case RTL_GIGA_MAC_VER_06:
4729 case RTL_GIGA_MAC_VER_10:
4730 case RTL_GIGA_MAC_VER_11:
4731 case RTL_GIGA_MAC_VER_12:
4732 case RTL_GIGA_MAC_VER_13:
4733 case RTL_GIGA_MAC_VER_14:
4734 case RTL_GIGA_MAC_VER_15:
4735 case RTL_GIGA_MAC_VER_16:
4736 case RTL_GIGA_MAC_VER_17:
4737 ops->write = NULL;
4738 ops->read = NULL;
4739 break;
4740
Hayes Wang7e18dca2012-03-30 14:33:02 +08004741 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004742 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004743 ops->write = r8402_csi_write;
4744 ops->read = r8402_csi_read;
4745 break;
4746
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004747 default:
4748 ops->write = r8169_csi_write;
4749 ops->read = r8169_csi_read;
4750 break;
4751 }
Francois Romieudacf8152008-08-02 20:44:13 +02004752}
4753
4754struct ephy_info {
4755 unsigned int offset;
4756 u16 mask;
4757 u16 bits;
4758};
4759
Francois Romieufdf6fc02012-07-06 22:40:38 +02004760static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4761 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004762{
4763 u16 w;
4764
4765 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004766 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4767 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004768 e++;
4769 }
4770}
4771
Francois Romieub726e492008-06-28 12:22:59 +02004772static void rtl_disable_clock_request(struct pci_dev *pdev)
4773{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004774 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4775 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004776}
4777
françois romieue6de30d2011-01-03 15:08:37 +00004778static void rtl_enable_clock_request(struct pci_dev *pdev)
4779{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004780 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4781 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004782}
4783
Francois Romieub726e492008-06-28 12:22:59 +02004784#define R8168_CPCMD_QUIRK_MASK (\
4785 EnableBist | \
4786 Mac_dbgo_oe | \
4787 Force_half_dup | \
4788 Force_rxflow_en | \
4789 Force_txflow_en | \
4790 Cxpl_dbg_sel | \
4791 ASF | \
4792 PktCntrDisable | \
4793 Mac_dbgo_sel)
4794
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004795static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004796{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004797 void __iomem *ioaddr = tp->mmio_addr;
4798 struct pci_dev *pdev = tp->pci_dev;
4799
Francois Romieub726e492008-06-28 12:22:59 +02004800 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4801
4802 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4803
Francois Romieu2e68ae42008-06-28 12:00:55 +02004804 rtl_tx_performance_tweak(pdev,
4805 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004806}
4807
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004808static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004809{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004810 void __iomem *ioaddr = tp->mmio_addr;
4811
4812 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004813
françois romieuf0298f82011-01-03 15:07:42 +00004814 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004815
4816 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004817}
4818
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004819static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004820{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004821 void __iomem *ioaddr = tp->mmio_addr;
4822 struct pci_dev *pdev = tp->pci_dev;
4823
Francois Romieub726e492008-06-28 12:22:59 +02004824 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4825
4826 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4827
Francois Romieu219a1e92008-06-28 11:58:39 +02004828 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004829
4830 rtl_disable_clock_request(pdev);
4831
4832 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004833}
4834
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004835static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004836{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004837 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004838 { 0x01, 0, 0x0001 },
4839 { 0x02, 0x0800, 0x1000 },
4840 { 0x03, 0, 0x0042 },
4841 { 0x06, 0x0080, 0x0000 },
4842 { 0x07, 0, 0x2000 }
4843 };
4844
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004845 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004846
Francois Romieufdf6fc02012-07-06 22:40:38 +02004847 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004848
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004849 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004850}
4851
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004852static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004853{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004854 void __iomem *ioaddr = tp->mmio_addr;
4855 struct pci_dev *pdev = tp->pci_dev;
4856
4857 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004858
4859 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4860
4861 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4862
4863 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4864}
4865
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004866static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004867{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004868 void __iomem *ioaddr = tp->mmio_addr;
4869 struct pci_dev *pdev = tp->pci_dev;
4870
4871 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004872
4873 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4874
4875 /* Magic. */
4876 RTL_W8(DBG_REG, 0x20);
4877
françois romieuf0298f82011-01-03 15:07:42 +00004878 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004879
4880 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4881
4882 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4883}
4884
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004885static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004886{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004887 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004888 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004889 { 0x02, 0x0800, 0x1000 },
4890 { 0x03, 0, 0x0002 },
4891 { 0x06, 0x0080, 0x0000 }
4892 };
4893
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004894 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004895
4896 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4897
Francois Romieufdf6fc02012-07-06 22:40:38 +02004898 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004899
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004900 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004901}
4902
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004903static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004904{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004905 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004906 { 0x01, 0, 0x0001 },
4907 { 0x03, 0x0400, 0x0220 }
4908 };
4909
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004910 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004911
Francois Romieufdf6fc02012-07-06 22:40:38 +02004912 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004913
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004914 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004915}
4916
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004917static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004918{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004919 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004920}
4921
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004922static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004923{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004924 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004925
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004926 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004927}
4928
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004929static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004930{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004931 void __iomem *ioaddr = tp->mmio_addr;
4932 struct pci_dev *pdev = tp->pci_dev;
4933
4934 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004935
4936 rtl_disable_clock_request(pdev);
4937
françois romieuf0298f82011-01-03 15:07:42 +00004938 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004939
4940 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4941
4942 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4943}
4944
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004945static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004946{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004947 void __iomem *ioaddr = tp->mmio_addr;
4948 struct pci_dev *pdev = tp->pci_dev;
4949
4950 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004951
4952 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4953
4954 RTL_W8(MaxTxPacketSize, TxPacketMax);
4955
4956 rtl_disable_clock_request(pdev);
4957}
4958
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004959static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004960{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004961 void __iomem *ioaddr = tp->mmio_addr;
4962 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004963 static const struct ephy_info e_info_8168d_4[] = {
4964 { 0x0b, ~0, 0x48 },
4965 { 0x19, 0x20, 0x50 },
4966 { 0x0c, ~0, 0x20 }
4967 };
4968 int i;
4969
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004970 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004971
4972 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4973
4974 RTL_W8(MaxTxPacketSize, TxPacketMax);
4975
4976 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4977 const struct ephy_info *e = e_info_8168d_4 + i;
4978 u16 w;
4979
Francois Romieufdf6fc02012-07-06 22:40:38 +02004980 w = rtl_ephy_read(tp, e->offset);
4981 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004982 }
4983
4984 rtl_enable_clock_request(pdev);
4985}
4986
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004987static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004988{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004989 void __iomem *ioaddr = tp->mmio_addr;
4990 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004991 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004992 { 0x00, 0x0200, 0x0100 },
4993 { 0x00, 0x0000, 0x0004 },
4994 { 0x06, 0x0002, 0x0001 },
4995 { 0x06, 0x0000, 0x0030 },
4996 { 0x07, 0x0000, 0x2000 },
4997 { 0x00, 0x0000, 0x0020 },
4998 { 0x03, 0x5800, 0x2000 },
4999 { 0x03, 0x0000, 0x0001 },
5000 { 0x01, 0x0800, 0x1000 },
5001 { 0x07, 0x0000, 0x4000 },
5002 { 0x1e, 0x0000, 0x2000 },
5003 { 0x19, 0xffff, 0xfe6c },
5004 { 0x0a, 0x0000, 0x0040 }
5005 };
5006
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005007 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005008
Francois Romieufdf6fc02012-07-06 22:40:38 +02005009 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005010
5011 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5012
5013 RTL_W8(MaxTxPacketSize, TxPacketMax);
5014
5015 rtl_disable_clock_request(pdev);
5016
5017 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005018 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5019 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005020
Francois Romieucecb5fd2011-04-01 10:21:07 +02005021 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005022}
5023
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005024static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005025{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005026 void __iomem *ioaddr = tp->mmio_addr;
5027 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005028 static const struct ephy_info e_info_8168e_2[] = {
5029 { 0x09, 0x0000, 0x0080 },
5030 { 0x19, 0x0000, 0x0224 }
5031 };
5032
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005033 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005034
Francois Romieufdf6fc02012-07-06 22:40:38 +02005035 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005036
5037 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5038
Francois Romieufdf6fc02012-07-06 22:40:38 +02005039 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5040 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5041 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5042 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5043 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5044 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5045 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5046 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005047
Hayes Wang3090bd92011-09-06 16:55:15 +08005048 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005049
Hayes Wang70090422011-07-06 15:58:06 +08005050 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5051 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5052
5053 /* Adjust EEE LED frequency */
5054 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5055
5056 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5057 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005058 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5059 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005060}
5061
Hayes Wang5f886e02012-03-30 14:33:03 +08005062static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005063{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005064 void __iomem *ioaddr = tp->mmio_addr;
5065 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005066
Hayes Wang5f886e02012-03-30 14:33:03 +08005067 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005068
5069 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5070
Francois Romieufdf6fc02012-07-06 22:40:38 +02005071 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5072 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5073 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5074 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5075 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5076 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5077 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5078 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5079 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5080 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005081
5082 RTL_W8(MaxTxPacketSize, EarlySize);
5083
Hayes Wangc2218922011-09-06 16:55:18 +08005084 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5085 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005086 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005087 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5088 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5089 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005090}
5091
Hayes Wang5f886e02012-03-30 14:33:03 +08005092static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5093{
5094 void __iomem *ioaddr = tp->mmio_addr;
5095 static const struct ephy_info e_info_8168f_1[] = {
5096 { 0x06, 0x00c0, 0x0020 },
5097 { 0x08, 0x0001, 0x0002 },
5098 { 0x09, 0x0000, 0x0080 },
5099 { 0x19, 0x0000, 0x0224 }
5100 };
5101
5102 rtl_hw_start_8168f(tp);
5103
Francois Romieufdf6fc02012-07-06 22:40:38 +02005104 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005105
Francois Romieufdf6fc02012-07-06 22:40:38 +02005106 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005107
5108 /* Adjust EEE LED frequency */
5109 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5110}
5111
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005112static void rtl_hw_start_8411(struct rtl8169_private *tp)
5113{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005114 static const struct ephy_info e_info_8168f_1[] = {
5115 { 0x06, 0x00c0, 0x0020 },
5116 { 0x0f, 0xffff, 0x5200 },
5117 { 0x1e, 0x0000, 0x4000 },
5118 { 0x19, 0x0000, 0x0224 }
5119 };
5120
5121 rtl_hw_start_8168f(tp);
5122
Francois Romieufdf6fc02012-07-06 22:40:38 +02005123 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005124
Francois Romieufdf6fc02012-07-06 22:40:38 +02005125 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005126}
5127
Hayes Wangc5583862012-07-02 17:23:22 +08005128static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5129{
5130 void __iomem *ioaddr = tp->mmio_addr;
5131 struct pci_dev *pdev = tp->pci_dev;
5132
5133 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5134 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5135 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5136 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5137
5138 rtl_csi_access_enable_1(tp);
5139
5140 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5141
5142 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5143 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5144
5145 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005146 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005147 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005148 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5149 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005150
5151 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5152 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5153
5154 /* Adjust EEE LED frequency */
5155 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5156
5157 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5158}
5159
Francois Romieu07ce4062007-02-23 23:36:39 +01005160static void rtl_hw_start_8168(struct net_device *dev)
5161{
Francois Romieu2dd99532007-06-11 23:22:52 +02005162 struct rtl8169_private *tp = netdev_priv(dev);
5163 void __iomem *ioaddr = tp->mmio_addr;
5164
5165 RTL_W8(Cfg9346, Cfg9346_Unlock);
5166
françois romieuf0298f82011-01-03 15:07:42 +00005167 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005168
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005169 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005170
Francois Romieu0e485152007-02-20 00:00:26 +01005171 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005172
5173 RTL_W16(CPlusCmd, tp->cp_cmd);
5174
Francois Romieu0e485152007-02-20 00:00:26 +01005175 RTL_W16(IntrMitigate, 0x5151);
5176
5177 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005178 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005179 tp->event_slow |= RxFIFOOver | PCSTimeout;
5180 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005181 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005182
5183 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5184
Francois Romieub8363902008-06-01 12:31:57 +02005185 rtl_set_rx_mode(dev);
5186
5187 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5188 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005189
5190 RTL_R8(IntrMask);
5191
Francois Romieu219a1e92008-06-28 11:58:39 +02005192 switch (tp->mac_version) {
5193 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005194 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005195 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005196
5197 case RTL_GIGA_MAC_VER_12:
5198 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005199 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005200 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005201
5202 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005203 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005204 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005205
5206 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005207 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005208 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005209
5210 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005211 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005212 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005213
Francois Romieu197ff762008-06-28 13:16:02 +02005214 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005215 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005216 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005217
Francois Romieu6fb07052008-06-29 11:54:28 +02005218 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005219 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005220 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005221
Francois Romieuef3386f2008-06-29 12:24:30 +02005222 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005223 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005224 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005225
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005226 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005227 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005228 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005229
Francois Romieu5b538df2008-07-20 16:22:45 +02005230 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005231 case RTL_GIGA_MAC_VER_26:
5232 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005233 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005234 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005235
françois romieue6de30d2011-01-03 15:08:37 +00005236 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005237 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005238 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005239
hayeswang4804b3b2011-03-21 01:50:29 +00005240 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005241 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005242 break;
5243
hayeswang01dc7fe2011-03-21 01:50:28 +00005244 case RTL_GIGA_MAC_VER_32:
5245 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005246 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005247 break;
5248 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005249 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005250 break;
françois romieue6de30d2011-01-03 15:08:37 +00005251
Hayes Wangc2218922011-09-06 16:55:18 +08005252 case RTL_GIGA_MAC_VER_35:
5253 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005254 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005255 break;
5256
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005257 case RTL_GIGA_MAC_VER_38:
5258 rtl_hw_start_8411(tp);
5259 break;
5260
Hayes Wangc5583862012-07-02 17:23:22 +08005261 case RTL_GIGA_MAC_VER_40:
5262 case RTL_GIGA_MAC_VER_41:
5263 rtl_hw_start_8168g_1(tp);
5264 break;
5265
Francois Romieu219a1e92008-06-28 11:58:39 +02005266 default:
5267 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5268 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005269 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005270 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005271
Francois Romieu0e485152007-02-20 00:00:26 +01005272 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5273
Francois Romieub8363902008-06-01 12:31:57 +02005274 RTL_W8(Cfg9346, Cfg9346_Lock);
5275
Francois Romieu2dd99532007-06-11 23:22:52 +02005276 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005277}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278
Francois Romieu2857ffb2008-08-02 21:08:49 +02005279#define R810X_CPCMD_QUIRK_MASK (\
5280 EnableBist | \
5281 Mac_dbgo_oe | \
5282 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005283 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005284 Force_txflow_en | \
5285 Cxpl_dbg_sel | \
5286 ASF | \
5287 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005288 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005289
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005290static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005291{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005292 void __iomem *ioaddr = tp->mmio_addr;
5293 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005294 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005295 { 0x01, 0, 0x6e65 },
5296 { 0x02, 0, 0x091f },
5297 { 0x03, 0, 0xc2f9 },
5298 { 0x06, 0, 0xafb5 },
5299 { 0x07, 0, 0x0e00 },
5300 { 0x19, 0, 0xec80 },
5301 { 0x01, 0, 0x2e65 },
5302 { 0x01, 0, 0x6e65 }
5303 };
5304 u8 cfg1;
5305
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005306 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005307
5308 RTL_W8(DBG_REG, FIX_NAK_1);
5309
5310 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5311
5312 RTL_W8(Config1,
5313 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5314 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5315
5316 cfg1 = RTL_R8(Config1);
5317 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5318 RTL_W8(Config1, cfg1 & ~LEDS0);
5319
Francois Romieufdf6fc02012-07-06 22:40:38 +02005320 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005321}
5322
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005323static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005324{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005325 void __iomem *ioaddr = tp->mmio_addr;
5326 struct pci_dev *pdev = tp->pci_dev;
5327
5328 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005329
5330 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5331
5332 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5333 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005334}
5335
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005336static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005337{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005338 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005339
Francois Romieufdf6fc02012-07-06 22:40:38 +02005340 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005341}
5342
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005343static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005344{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005345 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005346 static const struct ephy_info e_info_8105e_1[] = {
5347 { 0x07, 0, 0x4000 },
5348 { 0x19, 0, 0x0200 },
5349 { 0x19, 0, 0x0020 },
5350 { 0x1e, 0, 0x2000 },
5351 { 0x03, 0, 0x0001 },
5352 { 0x19, 0, 0x0100 },
5353 { 0x19, 0, 0x0004 },
5354 { 0x0a, 0, 0x0020 }
5355 };
5356
Francois Romieucecb5fd2011-04-01 10:21:07 +02005357 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005358 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5359
Francois Romieucecb5fd2011-04-01 10:21:07 +02005360 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005361 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5362
5363 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005364 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005365 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5366 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5367 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005368
Francois Romieufdf6fc02012-07-06 22:40:38 +02005369 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005370}
5371
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005372static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005373{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005374 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005375 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005376}
5377
Hayes Wang7e18dca2012-03-30 14:33:02 +08005378static void rtl_hw_start_8402(struct rtl8169_private *tp)
5379{
5380 void __iomem *ioaddr = tp->mmio_addr;
5381 static const struct ephy_info e_info_8402[] = {
5382 { 0x19, 0xffff, 0xff64 },
5383 { 0x1e, 0, 0x4000 }
5384 };
5385
5386 rtl_csi_access_enable_2(tp);
5387
5388 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5389 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5390
5391 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5392 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005393 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5394 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5395 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005396
Francois Romieufdf6fc02012-07-06 22:40:38 +02005397 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005398
5399 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5400
Francois Romieufdf6fc02012-07-06 22:40:38 +02005401 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5402 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5403 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5404 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5405 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5406 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5407 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005408}
5409
Hayes Wang5598bfe2012-07-02 17:23:21 +08005410static void rtl_hw_start_8106(struct rtl8169_private *tp)
5411{
5412 void __iomem *ioaddr = tp->mmio_addr;
5413
5414 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5415 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5416
hayeswangd64ec842012-11-01 16:46:28 +00005417 RTL_W32(MISC,
5418 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5419 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5420 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005421 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5422 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5423}
5424
Francois Romieu07ce4062007-02-23 23:36:39 +01005425static void rtl_hw_start_8101(struct net_device *dev)
5426{
Francois Romieucdf1a602007-06-11 23:29:50 +02005427 struct rtl8169_private *tp = netdev_priv(dev);
5428 void __iomem *ioaddr = tp->mmio_addr;
5429 struct pci_dev *pdev = tp->pci_dev;
5430
Francois Romieuda78dbf2012-01-26 14:18:23 +01005431 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5432 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005433
Francois Romieucecb5fd2011-04-01 10:21:07 +02005434 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005435 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005436 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5437 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005438
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005439 RTL_W8(Cfg9346, Cfg9346_Unlock);
5440
Francois Romieu2857ffb2008-08-02 21:08:49 +02005441 switch (tp->mac_version) {
5442 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005443 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005444 break;
5445
5446 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005447 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005448 break;
5449
5450 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005451 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005452 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005453
5454 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005455 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005456 break;
5457 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005458 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005459 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005460
5461 case RTL_GIGA_MAC_VER_37:
5462 rtl_hw_start_8402(tp);
5463 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005464
5465 case RTL_GIGA_MAC_VER_39:
5466 rtl_hw_start_8106(tp);
5467 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005468 }
5469
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005470 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005471
françois romieuf0298f82011-01-03 15:07:42 +00005472 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005473
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005474 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005475
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005476 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005477 RTL_W16(CPlusCmd, tp->cp_cmd);
5478
5479 RTL_W16(IntrMitigate, 0x0000);
5480
5481 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5482
5483 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5484 rtl_set_rx_tx_config_registers(tp);
5485
Francois Romieucdf1a602007-06-11 23:29:50 +02005486 RTL_R8(IntrMask);
5487
Francois Romieucdf1a602007-06-11 23:29:50 +02005488 rtl_set_rx_mode(dev);
5489
5490 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491}
5492
5493static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5494{
Francois Romieud58d46b2011-05-03 16:38:29 +02005495 struct rtl8169_private *tp = netdev_priv(dev);
5496
5497 if (new_mtu < ETH_ZLEN ||
5498 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499 return -EINVAL;
5500
Francois Romieud58d46b2011-05-03 16:38:29 +02005501 if (new_mtu > ETH_DATA_LEN)
5502 rtl_hw_jumbo_enable(tp);
5503 else
5504 rtl_hw_jumbo_disable(tp);
5505
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005507 netdev_update_features(dev);
5508
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005509 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510}
5511
5512static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5513{
Al Viro95e09182007-12-22 18:55:39 +00005514 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5516}
5517
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005518static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5519 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005521 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005522 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005523
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005524 kfree(*data_buff);
5525 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526 rtl8169_make_unusable_by_asic(desc);
5527}
5528
5529static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5530{
5531 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5532
5533 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5534}
5535
5536static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5537 u32 rx_buf_sz)
5538{
5539 desc->addr = cpu_to_le64(mapping);
5540 wmb();
5541 rtl8169_mark_to_asic(desc, rx_buf_sz);
5542}
5543
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005544static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005546 return (void *)ALIGN((long)data, 16);
5547}
5548
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005549static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5550 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005551{
5552 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005554 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005555 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005556 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005558 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5559 if (!data)
5560 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005561
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005562 if (rtl8169_align(data) != data) {
5563 kfree(data);
5564 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5565 if (!data)
5566 return NULL;
5567 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005568
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005569 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005570 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005571 if (unlikely(dma_mapping_error(d, mapping))) {
5572 if (net_ratelimit())
5573 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005574 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
5577 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005578 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005579
5580err_out:
5581 kfree(data);
5582 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583}
5584
5585static void rtl8169_rx_clear(struct rtl8169_private *tp)
5586{
Francois Romieu07d3f512007-02-21 22:40:46 +01005587 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588
5589 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005590 if (tp->Rx_databuff[i]) {
5591 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592 tp->RxDescArray + i);
5593 }
5594 }
5595}
5596
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005597static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005599 desc->opts1 |= cpu_to_le32(RingEnd);
5600}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005601
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005602static int rtl8169_rx_fill(struct rtl8169_private *tp)
5603{
5604 unsigned int i;
5605
5606 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005607 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005608
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005609 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005611
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005612 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005613 if (!data) {
5614 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005615 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005616 }
5617 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005619
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005620 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5621 return 0;
5622
5623err_out:
5624 rtl8169_rx_clear(tp);
5625 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626}
5627
Linus Torvalds1da177e2005-04-16 15:20:36 -07005628static int rtl8169_init_ring(struct net_device *dev)
5629{
5630 struct rtl8169_private *tp = netdev_priv(dev);
5631
5632 rtl8169_init_ring_indexes(tp);
5633
5634 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005635 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005637 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638}
5639
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005640static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641 struct TxDesc *desc)
5642{
5643 unsigned int len = tx_skb->len;
5644
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005645 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5646
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647 desc->opts1 = 0x00;
5648 desc->opts2 = 0x00;
5649 desc->addr = 0x00;
5650 tx_skb->len = 0;
5651}
5652
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005653static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5654 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655{
5656 unsigned int i;
5657
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005658 for (i = 0; i < n; i++) {
5659 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660 struct ring_info *tx_skb = tp->tx_skb + entry;
5661 unsigned int len = tx_skb->len;
5662
5663 if (len) {
5664 struct sk_buff *skb = tx_skb->skb;
5665
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005666 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667 tp->TxDescArray + entry);
5668 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005669 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670 dev_kfree_skb(skb);
5671 tx_skb->skb = NULL;
5672 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673 }
5674 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005675}
5676
5677static void rtl8169_tx_clear(struct rtl8169_private *tp)
5678{
5679 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680 tp->cur_tx = tp->dirty_tx = 0;
5681}
5682
Francois Romieu4422bcd2012-01-26 11:23:32 +01005683static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684{
David Howellsc4028952006-11-22 14:57:56 +00005685 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005686 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005687
Francois Romieuda78dbf2012-01-26 14:18:23 +01005688 napi_disable(&tp->napi);
5689 netif_stop_queue(dev);
5690 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691
françois romieuc7c2c392011-12-04 20:30:52 +00005692 rtl8169_hw_reset(tp);
5693
Francois Romieu56de4142011-03-15 17:29:31 +01005694 for (i = 0; i < NUM_RX_DESC; i++)
5695 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5696
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005698 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005699
Francois Romieuda78dbf2012-01-26 14:18:23 +01005700 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005701 rtl_hw_start(dev);
5702 netif_wake_queue(dev);
5703 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704}
5705
5706static void rtl8169_tx_timeout(struct net_device *dev)
5707{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005708 struct rtl8169_private *tp = netdev_priv(dev);
5709
5710 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711}
5712
5713static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005714 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715{
5716 struct skb_shared_info *info = skb_shinfo(skb);
5717 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005718 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005719 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720
5721 entry = tp->cur_tx;
5722 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005723 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724 dma_addr_t mapping;
5725 u32 status, len;
5726 void *addr;
5727
5728 entry = (entry + 1) % NUM_TX_DESC;
5729
5730 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005731 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005732 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005733 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005734 if (unlikely(dma_mapping_error(d, mapping))) {
5735 if (net_ratelimit())
5736 netif_err(tp, drv, tp->dev,
5737 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005738 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740
Francois Romieucecb5fd2011-04-01 10:21:07 +02005741 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005742 status = opts[0] | len |
5743 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
5745 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005746 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747 txd->addr = cpu_to_le64(mapping);
5748
5749 tp->tx_skb[entry].len = len;
5750 }
5751
5752 if (cur_frag) {
5753 tp->tx_skb[entry].skb = skb;
5754 txd->opts1 |= cpu_to_le32(LastFrag);
5755 }
5756
5757 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005758
5759err_out:
5760 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5761 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762}
5763
Francois Romieu2b7b4312011-04-18 22:53:24 -07005764static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5765 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005767 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005768 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005769 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770
Francois Romieu2b7b4312011-04-18 22:53:24 -07005771 if (mss) {
5772 opts[0] |= TD_LSO;
5773 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5774 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005775 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776
5777 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005778 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005780 opts[offset] |= info->checksum.udp;
5781 else
5782 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784}
5785
Stephen Hemminger613573252009-08-31 19:50:58 +00005786static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5787 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788{
5789 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005790 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791 struct TxDesc *txd = tp->TxDescArray + entry;
5792 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005793 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794 dma_addr_t mapping;
5795 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005796 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005797 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005798
Julien Ducourthial477206a2012-05-09 00:00:06 +02005799 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005800 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005801 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802 }
5803
5804 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005805 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005807 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005808 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005809 if (unlikely(dma_mapping_error(d, mapping))) {
5810 if (net_ratelimit())
5811 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005812 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814
5815 tp->tx_skb[entry].len = len;
5816 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817
Kirill Smelkov810f4892012-11-10 21:11:02 +04005818 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005819 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005820
Francois Romieu2b7b4312011-04-18 22:53:24 -07005821 rtl8169_tso_csum(tp, skb, opts);
5822
5823 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005824 if (frags < 0)
5825 goto err_dma_1;
5826 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005827 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005828 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005829 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005830 tp->tx_skb[entry].skb = skb;
5831 }
5832
Francois Romieu2b7b4312011-04-18 22:53:24 -07005833 txd->opts2 = cpu_to_le32(opts[1]);
5834
Richard Cochran5047fb52012-03-10 07:29:42 +00005835 skb_tx_timestamp(skb);
5836
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837 wmb();
5838
Francois Romieucecb5fd2011-04-01 10:21:07 +02005839 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005840 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841 txd->opts1 = cpu_to_le32(status);
5842
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843 tp->cur_tx += frags + 1;
5844
David Dillow4c020a92010-03-03 16:33:10 +00005845 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846
Francois Romieucecb5fd2011-04-01 10:21:07 +02005847 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848
Francois Romieuda78dbf2012-01-26 14:18:23 +01005849 mmiowb();
5850
Julien Ducourthial477206a2012-05-09 00:00:06 +02005851 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005852 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5853 * not miss a ring update when it notices a stopped queue.
5854 */
5855 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005857 /* Sync with rtl_tx:
5858 * - publish queue status and cur_tx ring index (write barrier)
5859 * - refresh dirty_tx ring index (read barrier).
5860 * May the current thread have a pessimistic view of the ring
5861 * status and forget to wake up queue, a racing rtl_tx thread
5862 * can't.
5863 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005864 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005865 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005866 netif_wake_queue(dev);
5867 }
5868
Stephen Hemminger613573252009-08-31 19:50:58 +00005869 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005871err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005872 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005873err_dma_0:
5874 dev_kfree_skb(skb);
5875 dev->stats.tx_dropped++;
5876 return NETDEV_TX_OK;
5877
5878err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005880 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005881 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882}
5883
5884static void rtl8169_pcierr_interrupt(struct net_device *dev)
5885{
5886 struct rtl8169_private *tp = netdev_priv(dev);
5887 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888 u16 pci_status, pci_cmd;
5889
5890 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5891 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5892
Joe Perchesbf82c182010-02-09 11:49:50 +00005893 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5894 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895
5896 /*
5897 * The recovery sequence below admits a very elaborated explanation:
5898 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005899 * - I did not see what else could be done;
5900 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901 *
5902 * Feel free to adjust to your needs.
5903 */
Francois Romieua27993f2006-12-18 00:04:19 +01005904 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005905 pci_cmd &= ~PCI_COMMAND_PARITY;
5906 else
5907 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5908
5909 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910
5911 pci_write_config_word(pdev, PCI_STATUS,
5912 pci_status & (PCI_STATUS_DETECTED_PARITY |
5913 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5914 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5915
5916 /* The infamous DAC f*ckup only happens at boot time */
5917 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005918 void __iomem *ioaddr = tp->mmio_addr;
5919
Joe Perchesbf82c182010-02-09 11:49:50 +00005920 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921 tp->cp_cmd &= ~PCIDAC;
5922 RTL_W16(CPlusCmd, tp->cp_cmd);
5923 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924 }
5925
françois romieue6de30d2011-01-03 15:08:37 +00005926 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005927
Francois Romieu98ddf982012-01-31 10:47:34 +01005928 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929}
5930
Francois Romieuda78dbf2012-01-26 14:18:23 +01005931static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932{
5933 unsigned int dirty_tx, tx_left;
5934
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935 dirty_tx = tp->dirty_tx;
5936 smp_rmb();
5937 tx_left = tp->cur_tx - dirty_tx;
5938
5939 while (tx_left > 0) {
5940 unsigned int entry = dirty_tx % NUM_TX_DESC;
5941 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 u32 status;
5943
5944 rmb();
5945 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5946 if (status & DescOwn)
5947 break;
5948
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005949 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5950 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005952 u64_stats_update_begin(&tp->tx_stats.syncp);
5953 tp->tx_stats.packets++;
5954 tp->tx_stats.bytes += tx_skb->skb->len;
5955 u64_stats_update_end(&tp->tx_stats.syncp);
5956 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957 tx_skb->skb = NULL;
5958 }
5959 dirty_tx++;
5960 tx_left--;
5961 }
5962
5963 if (tp->dirty_tx != dirty_tx) {
5964 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005965 /* Sync with rtl8169_start_xmit:
5966 * - publish dirty_tx ring index (write barrier)
5967 * - refresh cur_tx ring index and queue status (read barrier)
5968 * May the current thread miss the stopped queue condition,
5969 * a racing xmit thread can only have a right view of the
5970 * ring status.
5971 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005972 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005974 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975 netif_wake_queue(dev);
5976 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005977 /*
5978 * 8168 hack: TxPoll requests are lost when the Tx packets are
5979 * too close. Let's kick an extra TxPoll request when a burst
5980 * of start_xmit activity is detected (if it is not detected,
5981 * it is slow enough). -- FR
5982 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005983 if (tp->cur_tx != dirty_tx) {
5984 void __iomem *ioaddr = tp->mmio_addr;
5985
Francois Romieud78ae2d2007-08-26 20:08:19 +02005986 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988 }
5989}
5990
Francois Romieu126fa4b2005-05-12 20:09:17 -04005991static inline int rtl8169_fragmented_frame(u32 status)
5992{
5993 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5994}
5995
Eric Dumazetadea1ac72010-09-05 20:04:05 -07005996static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998 u32 status = opts1 & RxProtoMask;
5999
6000 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006001 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002 skb->ip_summed = CHECKSUM_UNNECESSARY;
6003 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006004 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005}
6006
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006007static struct sk_buff *rtl8169_try_rx_copy(void *data,
6008 struct rtl8169_private *tp,
6009 int pkt_size,
6010 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006012 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006013 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006015 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006016 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006017 prefetch(data);
6018 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6019 if (skb)
6020 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006021 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6022
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006023 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024}
6025
Francois Romieuda78dbf2012-01-26 14:18:23 +01006026static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027{
6028 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006029 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031 cur_rx = tp->cur_rx;
6032 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006033 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006035 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006037 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038 u32 status;
6039
6040 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006041 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042
6043 if (status & DescOwn)
6044 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006045 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006046 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6047 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006048 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006050 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006052 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006053 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006054 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006055 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006056 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006057 if ((status & (RxRUNT | RxCRC)) &&
6058 !(status & (RxRWT | RxFOVF)) &&
6059 (dev->features & NETIF_F_RXALL))
6060 goto process_pkt;
6061
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006062 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006064 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006065 dma_addr_t addr;
6066 int pkt_size;
6067
6068process_pkt:
6069 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006070 if (likely(!(dev->features & NETIF_F_RXFCS)))
6071 pkt_size = (status & 0x00003fff) - 4;
6072 else
6073 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074
Francois Romieu126fa4b2005-05-12 20:09:17 -04006075 /*
6076 * The driver does not support incoming fragmented
6077 * frames. They are seen as a symptom of over-mtu
6078 * sized frames.
6079 */
6080 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006081 dev->stats.rx_dropped++;
6082 dev->stats.rx_length_errors++;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006083 rtl8169_mark_to_asic(desc, rx_buf_sz);
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006084 continue;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006085 }
6086
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006087 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6088 tp, pkt_size, addr);
6089 rtl8169_mark_to_asic(desc, rx_buf_sz);
6090 if (!skb) {
6091 dev->stats.rx_dropped++;
6092 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093 }
6094
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006095 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 skb_put(skb, pkt_size);
6097 skb->protocol = eth_type_trans(skb, dev);
6098
Francois Romieu7a8fc772011-03-01 17:18:33 +01006099 rtl8169_rx_vlan_tag(desc, skb);
6100
Francois Romieu56de4142011-03-15 17:29:31 +01006101 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102
Junchang Wang8027aa22012-03-04 23:30:32 +01006103 u64_stats_update_begin(&tp->rx_stats.syncp);
6104 tp->rx_stats.packets++;
6105 tp->rx_stats.bytes += pkt_size;
6106 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107 }
Francois Romieu6dccd162007-02-13 23:38:05 +01006108
6109 /* Work around for AMD plateform. */
Al Viro95e09182007-12-22 18:55:39 +00006110 if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
Francois Romieu6dccd162007-02-13 23:38:05 +01006111 (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
6112 desc->opts2 = 0;
6113 cur_rx++;
6114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115 }
6116
6117 count = cur_rx - tp->cur_rx;
6118 tp->cur_rx = cur_rx;
6119
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006120 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
6122 return count;
6123}
6124
Francois Romieu07d3f512007-02-21 22:40:46 +01006125static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126{
Francois Romieu07d3f512007-02-21 22:40:46 +01006127 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006130 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006132 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006133 if (status && status != 0xffff) {
6134 status &= RTL_EVENT_NAPI | tp->event_slow;
6135 if (status) {
6136 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006137
Francois Romieuda78dbf2012-01-26 14:18:23 +01006138 rtl_irq_disable(tp);
6139 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142 return IRQ_RETVAL(handled);
6143}
6144
Francois Romieuda78dbf2012-01-26 14:18:23 +01006145/*
6146 * Workqueue context.
6147 */
6148static void rtl_slow_event_work(struct rtl8169_private *tp)
6149{
6150 struct net_device *dev = tp->dev;
6151 u16 status;
6152
6153 status = rtl_get_events(tp) & tp->event_slow;
6154 rtl_ack_events(tp, status);
6155
6156 if (unlikely(status & RxFIFOOver)) {
6157 switch (tp->mac_version) {
6158 /* Work around for rx fifo overflow */
6159 case RTL_GIGA_MAC_VER_11:
6160 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006161 /* XXX - Hack alert. See rtl_task(). */
6162 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006163 default:
6164 break;
6165 }
6166 }
6167
6168 if (unlikely(status & SYSErr))
6169 rtl8169_pcierr_interrupt(dev);
6170
6171 if (status & LinkChg)
6172 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6173
françois romieu7dbb4912012-06-09 10:53:16 +00006174 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006175}
6176
Francois Romieu4422bcd2012-01-26 11:23:32 +01006177static void rtl_task(struct work_struct *work)
6178{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006179 static const struct {
6180 int bitnr;
6181 void (*action)(struct rtl8169_private *);
6182 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006183 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006184 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6185 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6186 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6187 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006188 struct rtl8169_private *tp =
6189 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006190 struct net_device *dev = tp->dev;
6191 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006192
Francois Romieuda78dbf2012-01-26 14:18:23 +01006193 rtl_lock_work(tp);
6194
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006195 if (!netif_running(dev) ||
6196 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006197 goto out_unlock;
6198
6199 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6200 bool pending;
6201
Francois Romieuda78dbf2012-01-26 14:18:23 +01006202 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006203 if (pending)
6204 rtl_work[i].action(tp);
6205 }
6206
6207out_unlock:
6208 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006209}
6210
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006211static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006213 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6214 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006215 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6216 int work_done= 0;
6217 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
Francois Romieuda78dbf2012-01-26 14:18:23 +01006219 status = rtl_get_events(tp);
6220 rtl_ack_events(tp, status & ~tp->event_slow);
6221
6222 if (status & RTL_EVENT_NAPI_RX)
6223 work_done = rtl_rx(dev, tp, (u32) budget);
6224
6225 if (status & RTL_EVENT_NAPI_TX)
6226 rtl_tx(dev, tp);
6227
6228 if (status & tp->event_slow) {
6229 enable_mask &= ~tp->event_slow;
6230
6231 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006234 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006235 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006236
Francois Romieuda78dbf2012-01-26 14:18:23 +01006237 rtl_irq_enable(tp, enable_mask);
6238 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006239 }
6240
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006241 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243
Francois Romieu523a6092008-09-10 22:28:56 +02006244static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6245{
6246 struct rtl8169_private *tp = netdev_priv(dev);
6247
6248 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6249 return;
6250
6251 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6252 RTL_W32(RxMissed, 0);
6253}
6254
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255static void rtl8169_down(struct net_device *dev)
6256{
6257 struct rtl8169_private *tp = netdev_priv(dev);
6258 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259
Francois Romieu4876cc12011-03-11 21:07:11 +01006260 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006262 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006263 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264
Hayes Wang92fc43b2011-07-06 15:58:03 +08006265 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006266 /*
6267 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006268 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6269 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006270 */
Francois Romieu523a6092008-09-10 22:28:56 +02006271 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006274 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006275
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276 rtl8169_tx_clear(tp);
6277
6278 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006279
6280 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281}
6282
6283static int rtl8169_close(struct net_device *dev)
6284{
6285 struct rtl8169_private *tp = netdev_priv(dev);
6286 struct pci_dev *pdev = tp->pci_dev;
6287
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006288 pm_runtime_get_sync(&pdev->dev);
6289
Francois Romieucecb5fd2011-04-01 10:21:07 +02006290 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006291 rtl8169_update_counters(dev);
6292
Francois Romieuda78dbf2012-01-26 14:18:23 +01006293 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006294 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006295
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006297 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006299 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006300
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006301 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6302 tp->RxPhyAddr);
6303 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6304 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006305 tp->TxDescArray = NULL;
6306 tp->RxDescArray = NULL;
6307
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006308 pm_runtime_put_sync(&pdev->dev);
6309
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310 return 0;
6311}
6312
Francois Romieudc1c00c2012-03-08 10:06:18 +01006313#ifdef CONFIG_NET_POLL_CONTROLLER
6314static void rtl8169_netpoll(struct net_device *dev)
6315{
6316 struct rtl8169_private *tp = netdev_priv(dev);
6317
6318 rtl8169_interrupt(tp->pci_dev->irq, dev);
6319}
6320#endif
6321
Francois Romieudf43ac72012-03-08 09:48:40 +01006322static int rtl_open(struct net_device *dev)
6323{
6324 struct rtl8169_private *tp = netdev_priv(dev);
6325 void __iomem *ioaddr = tp->mmio_addr;
6326 struct pci_dev *pdev = tp->pci_dev;
6327 int retval = -ENOMEM;
6328
6329 pm_runtime_get_sync(&pdev->dev);
6330
6331 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006332 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006333 * dma_alloc_coherent provides more.
6334 */
6335 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6336 &tp->TxPhyAddr, GFP_KERNEL);
6337 if (!tp->TxDescArray)
6338 goto err_pm_runtime_put;
6339
6340 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6341 &tp->RxPhyAddr, GFP_KERNEL);
6342 if (!tp->RxDescArray)
6343 goto err_free_tx_0;
6344
6345 retval = rtl8169_init_ring(dev);
6346 if (retval < 0)
6347 goto err_free_rx_1;
6348
6349 INIT_WORK(&tp->wk.work, rtl_task);
6350
6351 smp_mb();
6352
6353 rtl_request_firmware(tp);
6354
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006355 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006356 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6357 dev->name, dev);
6358 if (retval < 0)
6359 goto err_release_fw_2;
6360
6361 rtl_lock_work(tp);
6362
6363 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6364
6365 napi_enable(&tp->napi);
6366
6367 rtl8169_init_phy(dev, tp);
6368
6369 __rtl8169_set_features(dev, dev->features);
6370
6371 rtl_pll_power_up(tp);
6372
6373 rtl_hw_start(dev);
6374
6375 netif_start_queue(dev);
6376
6377 rtl_unlock_work(tp);
6378
6379 tp->saved_wolopts = 0;
6380 pm_runtime_put_noidle(&pdev->dev);
6381
6382 rtl8169_check_link_status(dev, tp, ioaddr);
6383out:
6384 return retval;
6385
6386err_release_fw_2:
6387 rtl_release_firmware(tp);
6388 rtl8169_rx_clear(tp);
6389err_free_rx_1:
6390 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6391 tp->RxPhyAddr);
6392 tp->RxDescArray = NULL;
6393err_free_tx_0:
6394 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6395 tp->TxPhyAddr);
6396 tp->TxDescArray = NULL;
6397err_pm_runtime_put:
6398 pm_runtime_put_noidle(&pdev->dev);
6399 goto out;
6400}
6401
Junchang Wang8027aa22012-03-04 23:30:32 +01006402static struct rtnl_link_stats64 *
6403rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006404{
6405 struct rtl8169_private *tp = netdev_priv(dev);
6406 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006407 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006408
Francois Romieuda78dbf2012-01-26 14:18:23 +01006409 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006410 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006411
Junchang Wang8027aa22012-03-04 23:30:32 +01006412 do {
6413 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6414 stats->rx_packets = tp->rx_stats.packets;
6415 stats->rx_bytes = tp->rx_stats.bytes;
6416 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6417
6418
6419 do {
6420 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6421 stats->tx_packets = tp->tx_stats.packets;
6422 stats->tx_bytes = tp->tx_stats.bytes;
6423 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6424
6425 stats->rx_dropped = dev->stats.rx_dropped;
6426 stats->tx_dropped = dev->stats.tx_dropped;
6427 stats->rx_length_errors = dev->stats.rx_length_errors;
6428 stats->rx_errors = dev->stats.rx_errors;
6429 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6430 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6431 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6432
6433 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434}
6435
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006436static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006437{
françois romieu065c27c2011-01-03 15:08:12 +00006438 struct rtl8169_private *tp = netdev_priv(dev);
6439
Francois Romieu5d06a992006-02-23 00:47:58 +01006440 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006441 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006442
6443 netif_device_detach(dev);
6444 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006445
6446 rtl_lock_work(tp);
6447 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006448 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006449 rtl_unlock_work(tp);
6450
6451 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006452}
Francois Romieu5d06a992006-02-23 00:47:58 +01006453
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006454#ifdef CONFIG_PM
6455
6456static int rtl8169_suspend(struct device *device)
6457{
6458 struct pci_dev *pdev = to_pci_dev(device);
6459 struct net_device *dev = pci_get_drvdata(pdev);
6460
6461 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006462
Francois Romieu5d06a992006-02-23 00:47:58 +01006463 return 0;
6464}
6465
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006466static void __rtl8169_resume(struct net_device *dev)
6467{
françois romieu065c27c2011-01-03 15:08:12 +00006468 struct rtl8169_private *tp = netdev_priv(dev);
6469
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006470 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006471
6472 rtl_pll_power_up(tp);
6473
Artem Savkovcff4c162012-04-03 10:29:11 +00006474 rtl_lock_work(tp);
6475 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006476 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006477 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006478
Francois Romieu98ddf982012-01-31 10:47:34 +01006479 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006480}
6481
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006482static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006483{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006484 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006485 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006486 struct rtl8169_private *tp = netdev_priv(dev);
6487
6488 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006489
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006490 if (netif_running(dev))
6491 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006492
Francois Romieu5d06a992006-02-23 00:47:58 +01006493 return 0;
6494}
6495
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006496static int rtl8169_runtime_suspend(struct device *device)
6497{
6498 struct pci_dev *pdev = to_pci_dev(device);
6499 struct net_device *dev = pci_get_drvdata(pdev);
6500 struct rtl8169_private *tp = netdev_priv(dev);
6501
6502 if (!tp->TxDescArray)
6503 return 0;
6504
Francois Romieuda78dbf2012-01-26 14:18:23 +01006505 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006506 tp->saved_wolopts = __rtl8169_get_wol(tp);
6507 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006508 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006509
6510 rtl8169_net_suspend(dev);
6511
6512 return 0;
6513}
6514
6515static int rtl8169_runtime_resume(struct device *device)
6516{
6517 struct pci_dev *pdev = to_pci_dev(device);
6518 struct net_device *dev = pci_get_drvdata(pdev);
6519 struct rtl8169_private *tp = netdev_priv(dev);
6520
6521 if (!tp->TxDescArray)
6522 return 0;
6523
Francois Romieuda78dbf2012-01-26 14:18:23 +01006524 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006525 __rtl8169_set_wol(tp, tp->saved_wolopts);
6526 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006527 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006528
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006529 rtl8169_init_phy(dev, tp);
6530
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006531 __rtl8169_resume(dev);
6532
6533 return 0;
6534}
6535
6536static int rtl8169_runtime_idle(struct device *device)
6537{
6538 struct pci_dev *pdev = to_pci_dev(device);
6539 struct net_device *dev = pci_get_drvdata(pdev);
6540 struct rtl8169_private *tp = netdev_priv(dev);
6541
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006542 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006543}
6544
Alexey Dobriyan47145212009-12-14 18:00:08 -08006545static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006546 .suspend = rtl8169_suspend,
6547 .resume = rtl8169_resume,
6548 .freeze = rtl8169_suspend,
6549 .thaw = rtl8169_resume,
6550 .poweroff = rtl8169_suspend,
6551 .restore = rtl8169_resume,
6552 .runtime_suspend = rtl8169_runtime_suspend,
6553 .runtime_resume = rtl8169_runtime_resume,
6554 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006555};
6556
6557#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6558
6559#else /* !CONFIG_PM */
6560
6561#define RTL8169_PM_OPS NULL
6562
6563#endif /* !CONFIG_PM */
6564
David S. Miller1805b2f2011-10-24 18:18:09 -04006565static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6566{
6567 void __iomem *ioaddr = tp->mmio_addr;
6568
6569 /* WoL fails with 8168b when the receiver is disabled. */
6570 switch (tp->mac_version) {
6571 case RTL_GIGA_MAC_VER_11:
6572 case RTL_GIGA_MAC_VER_12:
6573 case RTL_GIGA_MAC_VER_17:
6574 pci_clear_master(tp->pci_dev);
6575
6576 RTL_W8(ChipCmd, CmdRxEnb);
6577 /* PCI commit */
6578 RTL_R8(ChipCmd);
6579 break;
6580 default:
6581 break;
6582 }
6583}
6584
Francois Romieu1765f952008-09-13 17:21:40 +02006585static void rtl_shutdown(struct pci_dev *pdev)
6586{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006587 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006588 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006589 struct device *d = &pdev->dev;
6590
6591 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006592
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006593 rtl8169_net_suspend(dev);
6594
Francois Romieucecb5fd2011-04-01 10:21:07 +02006595 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006596 rtl_rar_set(tp, dev->perm_addr);
6597
Hayes Wang92fc43b2011-07-06 15:58:03 +08006598 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006599
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006600 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006601 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6602 rtl_wol_suspend_quirk(tp);
6603 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006604 }
6605
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006606 pci_wake_from_d3(pdev, true);
6607 pci_set_power_state(pdev, PCI_D3hot);
6608 }
françois romieu2a15cd22012-03-06 01:14:12 +00006609
6610 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006611}
Francois Romieu5d06a992006-02-23 00:47:58 +01006612
Bill Pembertonbaf63292012-12-03 09:23:28 -05006613static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006614{
6615 struct net_device *dev = pci_get_drvdata(pdev);
6616 struct rtl8169_private *tp = netdev_priv(dev);
6617
6618 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6619 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6620 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6621 rtl8168_driver_stop(tp);
6622 }
6623
6624 cancel_work_sync(&tp->wk.work);
6625
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006626 netif_napi_del(&tp->napi);
6627
Francois Romieue27566e2012-03-08 09:54:01 +01006628 unregister_netdev(dev);
6629
6630 rtl_release_firmware(tp);
6631
6632 if (pci_dev_run_wake(pdev))
6633 pm_runtime_get_noresume(&pdev->dev);
6634
6635 /* restore original MAC address */
6636 rtl_rar_set(tp, dev->perm_addr);
6637
6638 rtl_disable_msi(pdev, tp);
6639 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6640 pci_set_drvdata(pdev, NULL);
6641}
6642
Francois Romieufa9c3852012-03-08 10:01:50 +01006643static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006644 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006645 .ndo_stop = rtl8169_close,
6646 .ndo_get_stats64 = rtl8169_get_stats64,
6647 .ndo_start_xmit = rtl8169_start_xmit,
6648 .ndo_tx_timeout = rtl8169_tx_timeout,
6649 .ndo_validate_addr = eth_validate_addr,
6650 .ndo_change_mtu = rtl8169_change_mtu,
6651 .ndo_fix_features = rtl8169_fix_features,
6652 .ndo_set_features = rtl8169_set_features,
6653 .ndo_set_mac_address = rtl_set_mac_address,
6654 .ndo_do_ioctl = rtl8169_ioctl,
6655 .ndo_set_rx_mode = rtl_set_rx_mode,
6656#ifdef CONFIG_NET_POLL_CONTROLLER
6657 .ndo_poll_controller = rtl8169_netpoll,
6658#endif
6659
6660};
6661
Francois Romieu31fa8b12012-03-08 10:09:40 +01006662static const struct rtl_cfg_info {
6663 void (*hw_start)(struct net_device *);
6664 unsigned int region;
6665 unsigned int align;
6666 u16 event_slow;
6667 unsigned features;
6668 u8 default_ver;
6669} rtl_cfg_infos [] = {
6670 [RTL_CFG_0] = {
6671 .hw_start = rtl_hw_start_8169,
6672 .region = 1,
6673 .align = 0,
6674 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6675 .features = RTL_FEATURE_GMII,
6676 .default_ver = RTL_GIGA_MAC_VER_01,
6677 },
6678 [RTL_CFG_1] = {
6679 .hw_start = rtl_hw_start_8168,
6680 .region = 2,
6681 .align = 8,
6682 .event_slow = SYSErr | LinkChg | RxOverflow,
6683 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6684 .default_ver = RTL_GIGA_MAC_VER_11,
6685 },
6686 [RTL_CFG_2] = {
6687 .hw_start = rtl_hw_start_8101,
6688 .region = 2,
6689 .align = 8,
6690 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6691 PCSTimeout,
6692 .features = RTL_FEATURE_MSI,
6693 .default_ver = RTL_GIGA_MAC_VER_13,
6694 }
6695};
6696
6697/* Cfg9346_Unlock assumed. */
6698static unsigned rtl_try_msi(struct rtl8169_private *tp,
6699 const struct rtl_cfg_info *cfg)
6700{
6701 void __iomem *ioaddr = tp->mmio_addr;
6702 unsigned msi = 0;
6703 u8 cfg2;
6704
6705 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6706 if (cfg->features & RTL_FEATURE_MSI) {
6707 if (pci_enable_msi(tp->pci_dev)) {
6708 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6709 } else {
6710 cfg2 |= MSIEnable;
6711 msi = RTL_FEATURE_MSI;
6712 }
6713 }
6714 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6715 RTL_W8(Config2, cfg2);
6716 return msi;
6717}
6718
Hayes Wangc5583862012-07-02 17:23:22 +08006719DECLARE_RTL_COND(rtl_link_list_ready_cond)
6720{
6721 void __iomem *ioaddr = tp->mmio_addr;
6722
6723 return RTL_R8(MCU) & LINK_LIST_RDY;
6724}
6725
6726DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6727{
6728 void __iomem *ioaddr = tp->mmio_addr;
6729
6730 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6731}
6732
Bill Pembertonbaf63292012-12-03 09:23:28 -05006733static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006734{
6735 void __iomem *ioaddr = tp->mmio_addr;
6736 u32 data;
6737
6738 tp->ocp_base = OCP_STD_PHY_BASE;
6739
6740 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6741
6742 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6743 return;
6744
6745 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6746 return;
6747
6748 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6749 msleep(1);
6750 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6751
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006752 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006753 data &= ~(1 << 14);
6754 r8168_mac_ocp_write(tp, 0xe8de, data);
6755
6756 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6757 return;
6758
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006759 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006760 data |= (1 << 15);
6761 r8168_mac_ocp_write(tp, 0xe8de, data);
6762
6763 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6764 return;
6765}
6766
Bill Pembertonbaf63292012-12-03 09:23:28 -05006767static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006768{
6769 switch (tp->mac_version) {
6770 case RTL_GIGA_MAC_VER_40:
6771 case RTL_GIGA_MAC_VER_41:
6772 rtl_hw_init_8168g(tp);
6773 break;
6774
6775 default:
6776 break;
6777 }
6778}
6779
Bill Pembertonbaf63292012-12-03 09:23:28 -05006780static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006781rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6782{
6783 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6784 const unsigned int region = cfg->region;
6785 struct rtl8169_private *tp;
6786 struct mii_if_info *mii;
6787 struct net_device *dev;
6788 void __iomem *ioaddr;
6789 int chipset, i;
6790 int rc;
6791
6792 if (netif_msg_drv(&debug)) {
6793 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6794 MODULENAME, RTL8169_VERSION);
6795 }
6796
6797 dev = alloc_etherdev(sizeof (*tp));
6798 if (!dev) {
6799 rc = -ENOMEM;
6800 goto out;
6801 }
6802
6803 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006804 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006805 tp = netdev_priv(dev);
6806 tp->dev = dev;
6807 tp->pci_dev = pdev;
6808 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6809
6810 mii = &tp->mii;
6811 mii->dev = dev;
6812 mii->mdio_read = rtl_mdio_read;
6813 mii->mdio_write = rtl_mdio_write;
6814 mii->phy_id_mask = 0x1f;
6815 mii->reg_num_mask = 0x1f;
6816 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6817
6818 /* disable ASPM completely as that cause random device stop working
6819 * problems as well as full system hangs for some PCIe devices users */
6820 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6821 PCIE_LINK_STATE_CLKPM);
6822
6823 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6824 rc = pci_enable_device(pdev);
6825 if (rc < 0) {
6826 netif_err(tp, probe, dev, "enable failure\n");
6827 goto err_out_free_dev_1;
6828 }
6829
6830 if (pci_set_mwi(pdev) < 0)
6831 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6832
6833 /* make sure PCI base addr 1 is MMIO */
6834 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6835 netif_err(tp, probe, dev,
6836 "region #%d not an MMIO resource, aborting\n",
6837 region);
6838 rc = -ENODEV;
6839 goto err_out_mwi_2;
6840 }
6841
6842 /* check for weird/broken PCI region reporting */
6843 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6844 netif_err(tp, probe, dev,
6845 "Invalid PCI region size(s), aborting\n");
6846 rc = -ENODEV;
6847 goto err_out_mwi_2;
6848 }
6849
6850 rc = pci_request_regions(pdev, MODULENAME);
6851 if (rc < 0) {
6852 netif_err(tp, probe, dev, "could not request regions\n");
6853 goto err_out_mwi_2;
6854 }
6855
6856 tp->cp_cmd = RxChkSum;
6857
6858 if ((sizeof(dma_addr_t) > 4) &&
6859 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6860 tp->cp_cmd |= PCIDAC;
6861 dev->features |= NETIF_F_HIGHDMA;
6862 } else {
6863 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6864 if (rc < 0) {
6865 netif_err(tp, probe, dev, "DMA configuration failed\n");
6866 goto err_out_free_res_3;
6867 }
6868 }
6869
6870 /* ioremap MMIO region */
6871 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6872 if (!ioaddr) {
6873 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6874 rc = -EIO;
6875 goto err_out_free_res_3;
6876 }
6877 tp->mmio_addr = ioaddr;
6878
6879 if (!pci_is_pcie(pdev))
6880 netif_info(tp, probe, dev, "not PCI Express\n");
6881
6882 /* Identify chip attached to board */
6883 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6884
6885 rtl_init_rxcfg(tp);
6886
6887 rtl_irq_disable(tp);
6888
Hayes Wangc5583862012-07-02 17:23:22 +08006889 rtl_hw_initialize(tp);
6890
Francois Romieu3b6cf252012-03-08 09:59:04 +01006891 rtl_hw_reset(tp);
6892
6893 rtl_ack_events(tp, 0xffff);
6894
6895 pci_set_master(pdev);
6896
6897 /*
6898 * Pretend we are using VLANs; This bypasses a nasty bug where
6899 * Interrupts stop flowing on high load on 8110SCd controllers.
6900 */
6901 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6902 tp->cp_cmd |= RxVlan;
6903
6904 rtl_init_mdio_ops(tp);
6905 rtl_init_pll_power_ops(tp);
6906 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006907 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006908
6909 rtl8169_print_mac_version(tp);
6910
6911 chipset = tp->mac_version;
6912 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6913
6914 RTL_W8(Cfg9346, Cfg9346_Unlock);
6915 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6916 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6917 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6918 tp->features |= RTL_FEATURE_WOL;
6919 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6920 tp->features |= RTL_FEATURE_WOL;
6921 tp->features |= rtl_try_msi(tp, cfg);
6922 RTL_W8(Cfg9346, Cfg9346_Lock);
6923
6924 if (rtl_tbi_enabled(tp)) {
6925 tp->set_speed = rtl8169_set_speed_tbi;
6926 tp->get_settings = rtl8169_gset_tbi;
6927 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6928 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6929 tp->link_ok = rtl8169_tbi_link_ok;
6930 tp->do_ioctl = rtl_tbi_ioctl;
6931 } else {
6932 tp->set_speed = rtl8169_set_speed_xmii;
6933 tp->get_settings = rtl8169_gset_xmii;
6934 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6935 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6936 tp->link_ok = rtl8169_xmii_link_ok;
6937 tp->do_ioctl = rtl_xmii_ioctl;
6938 }
6939
6940 mutex_init(&tp->wk.mutex);
6941
6942 /* Get MAC address */
6943 for (i = 0; i < ETH_ALEN; i++)
6944 dev->dev_addr[i] = RTL_R8(MAC0 + i);
6945 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6946
6947 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6948 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006949
6950 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6951
6952 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6953 * properly for all devices */
6954 dev->features |= NETIF_F_RXCSUM |
6955 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6956
6957 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6958 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6959 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6960 NETIF_F_HIGHDMA;
6961
6962 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6963 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6964 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6965
6966 dev->hw_features |= NETIF_F_RXALL;
6967 dev->hw_features |= NETIF_F_RXFCS;
6968
6969 tp->hw_start = cfg->hw_start;
6970 tp->event_slow = cfg->event_slow;
6971
6972 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6973 ~(RxBOVF | RxFOVF) : ~0;
6974
6975 init_timer(&tp->timer);
6976 tp->timer.data = (unsigned long) dev;
6977 tp->timer.function = rtl8169_phy_timer;
6978
6979 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6980
6981 rc = register_netdev(dev);
6982 if (rc < 0)
6983 goto err_out_msi_4;
6984
6985 pci_set_drvdata(pdev, dev);
6986
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006987 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6988 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6989 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006990 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6991 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6992 "tx checksumming: %s]\n",
6993 rtl_chip_infos[chipset].jumbo_max,
6994 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6995 }
6996
6997 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6998 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6999 tp->mac_version == RTL_GIGA_MAC_VER_31) {
7000 rtl8168_driver_start(tp);
7001 }
7002
7003 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
7004
7005 if (pci_dev_run_wake(pdev))
7006 pm_runtime_put_noidle(&pdev->dev);
7007
7008 netif_carrier_off(dev);
7009
7010out:
7011 return rc;
7012
7013err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007014 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007015 rtl_disable_msi(pdev, tp);
7016 iounmap(ioaddr);
7017err_out_free_res_3:
7018 pci_release_regions(pdev);
7019err_out_mwi_2:
7020 pci_clear_mwi(pdev);
7021 pci_disable_device(pdev);
7022err_out_free_dev_1:
7023 free_netdev(dev);
7024 goto out;
7025}
7026
Linus Torvalds1da177e2005-04-16 15:20:36 -07007027static struct pci_driver rtl8169_pci_driver = {
7028 .name = MODULENAME,
7029 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007030 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05007031 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02007032 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007033 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034};
7035
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007036module_pci_driver(rtl8169_pci_driver);