blob: 97fdbb1d64121c90abc7e95159468327503bcd0f [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 */
Timo Teräs9fba0812013-01-15 21:01:24 +000086#define NUM_RX_DESC 256U /* 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. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100731 struct rtl8169_stats rx_stats;
732 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
734 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
735 dma_addr_t TxPhyAddr;
736 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000737 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct timer_list timer;
740 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100741
742 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000743
744 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200745 void (*write)(struct rtl8169_private *, int, int);
746 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000747 } mdio_ops;
748
françois romieu065c27c2011-01-03 15:08:12 +0000749 struct pll_power_ops {
750 void (*down)(struct rtl8169_private *);
751 void (*up)(struct rtl8169_private *);
752 } pll_power_ops;
753
Francois Romieud58d46b2011-05-03 16:38:29 +0200754 struct jumbo_ops {
755 void (*enable)(struct rtl8169_private *);
756 void (*disable)(struct rtl8169_private *);
757 } jumbo_ops;
758
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800759 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200760 void (*write)(struct rtl8169_private *, int, int);
761 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800762 } csi_ops;
763
Oliver Neukum54405cd2011-01-06 21:55:13 +0100764 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200765 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000766 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100767 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000768 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800770 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100771
772 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100773 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
774 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100775 struct work_struct work;
776 } wk;
777
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200778 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200779
780 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800781 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000782 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400783 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000784
Francois Romieub6ffd972011-06-17 17:00:05 +0200785 struct rtl_fw {
786 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200787
788#define RTL_VER_SIZE 32
789
790 char version[RTL_VER_SIZE];
791
792 struct rtl_fw_phy_action {
793 __le32 *code;
794 size_t size;
795 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200796 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300797#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800798
799 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800};
801
Ralf Baechle979b6c12005-06-13 14:30:40 -0700802MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700805MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200806module_param_named(debug, debug.msg_enable, int, 0);
807MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808MODULE_LICENSE("GPL");
809MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000810MODULE_FIRMWARE(FIRMWARE_8168D_1);
811MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000812MODULE_FIRMWARE(FIRMWARE_8168E_1);
813MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400814MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800815MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800816MODULE_FIRMWARE(FIRMWARE_8168F_1);
817MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800818MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800819MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800820MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800821MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
Francois Romieuda78dbf2012-01-26 14:18:23 +0100823static void rtl_lock_work(struct rtl8169_private *tp)
824{
825 mutex_lock(&tp->wk.mutex);
826}
827
828static void rtl_unlock_work(struct rtl8169_private *tp)
829{
830 mutex_unlock(&tp->wk.mutex);
831}
832
Francois Romieud58d46b2011-05-03 16:38:29 +0200833static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
834{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800835 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
836 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200837}
838
Francois Romieuffc46952012-07-06 14:19:23 +0200839struct rtl_cond {
840 bool (*check)(struct rtl8169_private *);
841 const char *msg;
842};
843
844static void rtl_udelay(unsigned int d)
845{
846 udelay(d);
847}
848
849static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
850 void (*delay)(unsigned int), unsigned int d, int n,
851 bool high)
852{
853 int i;
854
855 for (i = 0; i < n; i++) {
856 delay(d);
857 if (c->check(tp) == high)
858 return true;
859 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200860 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
861 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200862 return false;
863}
864
865static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
866 const struct rtl_cond *c,
867 unsigned int d, int n)
868{
869 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
870}
871
872static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
873 const struct rtl_cond *c,
874 unsigned int d, int n)
875{
876 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
877}
878
879static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
880 const struct rtl_cond *c,
881 unsigned int d, int n)
882{
883 return rtl_loop_wait(tp, c, msleep, d, n, true);
884}
885
886static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
887 const struct rtl_cond *c,
888 unsigned int d, int n)
889{
890 return rtl_loop_wait(tp, c, msleep, d, n, false);
891}
892
893#define DECLARE_RTL_COND(name) \
894static bool name ## _check(struct rtl8169_private *); \
895 \
896static const struct rtl_cond name = { \
897 .check = name ## _check, \
898 .msg = #name \
899}; \
900 \
901static bool name ## _check(struct rtl8169_private *tp)
902
903DECLARE_RTL_COND(rtl_ocpar_cond)
904{
905 void __iomem *ioaddr = tp->mmio_addr;
906
907 return RTL_R32(OCPAR) & OCPAR_FLAG;
908}
909
françois romieub646d902011-01-03 15:08:21 +0000910static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
911{
912 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000913
914 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200915
916 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
917 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000918}
919
920static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
921{
922 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000923
924 RTL_W32(OCPDR, data);
925 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200926
927 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
928}
929
930DECLARE_RTL_COND(rtl_eriar_cond)
931{
932 void __iomem *ioaddr = tp->mmio_addr;
933
934 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000935}
936
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800937static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000938{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800939 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000940
941 RTL_W8(ERIDR, cmd);
942 RTL_W32(ERIAR, 0x800010e8);
943 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200944
945 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
946 return;
françois romieub646d902011-01-03 15:08:21 +0000947
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800948 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000949}
950
951#define OOB_CMD_RESET 0x00
952#define OOB_CMD_DRIVER_START 0x05
953#define OOB_CMD_DRIVER_STOP 0x06
954
Francois Romieucecb5fd2011-04-01 10:21:07 +0200955static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
956{
957 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
958}
959
Francois Romieuffc46952012-07-06 14:19:23 +0200960DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000961{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200962 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000963
Francois Romieucecb5fd2011-04-01 10:21:07 +0200964 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000965
Francois Romieuffc46952012-07-06 14:19:23 +0200966 return ocp_read(tp, 0x0f, reg) & 0x00000800;
967}
968
969static void rtl8168_driver_start(struct rtl8169_private *tp)
970{
971 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
972
973 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000974}
975
976static void rtl8168_driver_stop(struct rtl8169_private *tp)
977{
françois romieub646d902011-01-03 15:08:21 +0000978 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
979
Francois Romieuffc46952012-07-06 14:19:23 +0200980 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000981}
982
hayeswang4804b3b2011-03-21 01:50:29 +0000983static int r8168dp_check_dash(struct rtl8169_private *tp)
984{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200985 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000986
Francois Romieucecb5fd2011-04-01 10:21:07 +0200987 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000988}
françois romieub646d902011-01-03 15:08:21 +0000989
Hayes Wangc5583862012-07-02 17:23:22 +0800990static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
991{
992 if (reg & 0xffff0001) {
993 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
994 return true;
995 }
996 return false;
997}
998
999DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1000{
1001 void __iomem *ioaddr = tp->mmio_addr;
1002
1003 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1004}
1005
1006static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1007{
1008 void __iomem *ioaddr = tp->mmio_addr;
1009
1010 if (rtl_ocp_reg_failure(tp, reg))
1011 return;
1012
1013 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1014
1015 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1016}
1017
1018static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1019{
1020 void __iomem *ioaddr = tp->mmio_addr;
1021
1022 if (rtl_ocp_reg_failure(tp, reg))
1023 return 0;
1024
1025 RTL_W32(GPHY_OCP, reg << 15);
1026
1027 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1028 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1029}
1030
1031static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1032{
1033 int val;
1034
1035 val = r8168_phy_ocp_read(tp, reg);
1036 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1037}
1038
Hayes Wangc5583862012-07-02 17:23:22 +08001039static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1040{
1041 void __iomem *ioaddr = tp->mmio_addr;
1042
1043 if (rtl_ocp_reg_failure(tp, reg))
1044 return;
1045
1046 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001047}
1048
1049static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1050{
1051 void __iomem *ioaddr = tp->mmio_addr;
1052
1053 if (rtl_ocp_reg_failure(tp, reg))
1054 return 0;
1055
1056 RTL_W32(OCPDR, reg << 15);
1057
Hayes Wang3a83ad12012-07-11 20:31:56 +08001058 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001059}
1060
1061#define OCP_STD_PHY_BASE 0xa400
1062
1063static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1064{
1065 if (reg == 0x1f) {
1066 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1067 return;
1068 }
1069
1070 if (tp->ocp_base != OCP_STD_PHY_BASE)
1071 reg -= 0x10;
1072
1073 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1074}
1075
1076static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1077{
1078 if (tp->ocp_base != OCP_STD_PHY_BASE)
1079 reg -= 0x10;
1080
1081 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1082}
1083
Francois Romieuffc46952012-07-06 14:19:23 +02001084DECLARE_RTL_COND(rtl_phyar_cond)
1085{
1086 void __iomem *ioaddr = tp->mmio_addr;
1087
1088 return RTL_R32(PHYAR) & 0x80000000;
1089}
1090
Francois Romieu24192212012-07-06 20:19:42 +02001091static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
Francois Romieu24192212012-07-06 20:19:42 +02001093 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Francois Romieu24192212012-07-06 20:19:42 +02001095 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Francois Romieuffc46952012-07-06 14:19:23 +02001097 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001098 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001099 * According to hardware specs a 20us delay is required after write
1100 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001101 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001102 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
Francois Romieu24192212012-07-06 20:19:42 +02001105static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
Francois Romieu24192212012-07-06 20:19:42 +02001107 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001108 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Francois Romieu24192212012-07-06 20:19:42 +02001110 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Francois Romieuffc46952012-07-06 14:19:23 +02001112 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1113 RTL_R32(PHYAR) & 0xffff : ~0;
1114
Timo Teräs81a95f02010-06-09 17:31:48 -07001115 /*
1116 * According to hardware specs a 20us delay is required after read
1117 * complete indication, but before sending next command.
1118 */
1119 udelay(20);
1120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return value;
1122}
1123
Francois Romieu24192212012-07-06 20:19:42 +02001124static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001125{
Francois Romieu24192212012-07-06 20:19:42 +02001126 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001127
Francois Romieu24192212012-07-06 20:19:42 +02001128 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001129 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1130 RTL_W32(EPHY_RXER_NUM, 0);
1131
Francois Romieuffc46952012-07-06 14:19:23 +02001132 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001133}
1134
Francois Romieu24192212012-07-06 20:19:42 +02001135static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001136{
Francois Romieu24192212012-07-06 20:19:42 +02001137 r8168dp_1_mdio_access(tp, reg,
1138 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001139}
1140
Francois Romieu24192212012-07-06 20:19:42 +02001141static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001142{
Francois Romieu24192212012-07-06 20:19:42 +02001143 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001144
Francois Romieu24192212012-07-06 20:19:42 +02001145 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001146
1147 mdelay(1);
1148 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1149 RTL_W32(EPHY_RXER_NUM, 0);
1150
Francois Romieuffc46952012-07-06 14:19:23 +02001151 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1152 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001153}
1154
françois romieue6de30d2011-01-03 15:08:37 +00001155#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1156
1157static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1158{
1159 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1160}
1161
1162static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1163{
1164 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1165}
1166
Francois Romieu24192212012-07-06 20:19:42 +02001167static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001168{
Francois Romieu24192212012-07-06 20:19:42 +02001169 void __iomem *ioaddr = tp->mmio_addr;
1170
françois romieue6de30d2011-01-03 15:08:37 +00001171 r8168dp_2_mdio_start(ioaddr);
1172
Francois Romieu24192212012-07-06 20:19:42 +02001173 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001174
1175 r8168dp_2_mdio_stop(ioaddr);
1176}
1177
Francois Romieu24192212012-07-06 20:19:42 +02001178static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001179{
Francois Romieu24192212012-07-06 20:19:42 +02001180 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001181 int value;
1182
1183 r8168dp_2_mdio_start(ioaddr);
1184
Francois Romieu24192212012-07-06 20:19:42 +02001185 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001186
1187 r8168dp_2_mdio_stop(ioaddr);
1188
1189 return value;
1190}
1191
françois romieu4da19632011-01-03 15:07:55 +00001192static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001193{
Francois Romieu24192212012-07-06 20:19:42 +02001194 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001195}
1196
françois romieu4da19632011-01-03 15:07:55 +00001197static int rtl_readphy(struct rtl8169_private *tp, int location)
1198{
Francois Romieu24192212012-07-06 20:19:42 +02001199 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001200}
1201
1202static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1203{
1204 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1205}
1206
1207static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001208{
1209 int val;
1210
françois romieu4da19632011-01-03 15:07:55 +00001211 val = rtl_readphy(tp, reg_addr);
1212 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001213}
1214
Francois Romieuccdffb92008-07-26 14:26:06 +02001215static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1216 int val)
1217{
1218 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001219
françois romieu4da19632011-01-03 15:07:55 +00001220 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001221}
1222
1223static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1224{
1225 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001226
françois romieu4da19632011-01-03 15:07:55 +00001227 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001228}
1229
Francois Romieuffc46952012-07-06 14:19:23 +02001230DECLARE_RTL_COND(rtl_ephyar_cond)
1231{
1232 void __iomem *ioaddr = tp->mmio_addr;
1233
1234 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1235}
1236
Francois Romieufdf6fc02012-07-06 22:40:38 +02001237static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001238{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001239 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001240
1241 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1242 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1243
Francois Romieuffc46952012-07-06 14:19:23 +02001244 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1245
1246 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001247}
1248
Francois Romieufdf6fc02012-07-06 22:40:38 +02001249static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001250{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001251 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001252
1253 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1254
Francois Romieuffc46952012-07-06 14:19:23 +02001255 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1256 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001257}
1258
Francois Romieufdf6fc02012-07-06 22:40:38 +02001259static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1260 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001261{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001262 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001263
1264 BUG_ON((addr & 3) || (mask == 0));
1265 RTL_W32(ERIDR, val);
1266 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1267
Francois Romieuffc46952012-07-06 14:19:23 +02001268 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001269}
1270
Francois Romieufdf6fc02012-07-06 22:40:38 +02001271static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001272{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001273 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001274
1275 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1276
Francois Romieuffc46952012-07-06 14:19:23 +02001277 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1278 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001279}
1280
Francois Romieufdf6fc02012-07-06 22:40:38 +02001281static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1282 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001283{
1284 u32 val;
1285
Francois Romieufdf6fc02012-07-06 22:40:38 +02001286 val = rtl_eri_read(tp, addr, type);
1287 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001288}
1289
françois romieuc28aa382011-08-02 03:53:43 +00001290struct exgmac_reg {
1291 u16 addr;
1292 u16 mask;
1293 u32 val;
1294};
1295
Francois Romieufdf6fc02012-07-06 22:40:38 +02001296static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001297 const struct exgmac_reg *r, int len)
1298{
1299 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001300 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001301 r++;
1302 }
1303}
1304
Francois Romieuffc46952012-07-06 14:19:23 +02001305DECLARE_RTL_COND(rtl_efusear_cond)
1306{
1307 void __iomem *ioaddr = tp->mmio_addr;
1308
1309 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1310}
1311
Francois Romieufdf6fc02012-07-06 22:40:38 +02001312static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001313{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001314 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001315
1316 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1317
Francois Romieuffc46952012-07-06 14:19:23 +02001318 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1319 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001320}
1321
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001322static u16 rtl_get_events(struct rtl8169_private *tp)
1323{
1324 void __iomem *ioaddr = tp->mmio_addr;
1325
1326 return RTL_R16(IntrStatus);
1327}
1328
1329static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1330{
1331 void __iomem *ioaddr = tp->mmio_addr;
1332
1333 RTL_W16(IntrStatus, bits);
1334 mmiowb();
1335}
1336
1337static void rtl_irq_disable(struct rtl8169_private *tp)
1338{
1339 void __iomem *ioaddr = tp->mmio_addr;
1340
1341 RTL_W16(IntrMask, 0);
1342 mmiowb();
1343}
1344
Francois Romieu3e990ff2012-01-26 12:50:01 +01001345static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1346{
1347 void __iomem *ioaddr = tp->mmio_addr;
1348
1349 RTL_W16(IntrMask, bits);
1350}
1351
Francois Romieuda78dbf2012-01-26 14:18:23 +01001352#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1353#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1354#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1355
1356static void rtl_irq_enable_all(struct rtl8169_private *tp)
1357{
1358 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1359}
1360
françois romieu811fd302011-12-04 20:30:45 +00001361static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
françois romieu811fd302011-12-04 20:30:45 +00001363 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001365 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001366 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001367 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368}
1369
françois romieu4da19632011-01-03 15:07:55 +00001370static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371{
françois romieu4da19632011-01-03 15:07:55 +00001372 void __iomem *ioaddr = tp->mmio_addr;
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return RTL_R32(TBICSR) & TBIReset;
1375}
1376
françois romieu4da19632011-01-03 15:07:55 +00001377static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378{
françois romieu4da19632011-01-03 15:07:55 +00001379 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380}
1381
1382static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1383{
1384 return RTL_R32(TBICSR) & TBILinkOk;
1385}
1386
1387static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1388{
1389 return RTL_R8(PHYstatus) & LinkStatus;
1390}
1391
françois romieu4da19632011-01-03 15:07:55 +00001392static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
françois romieu4da19632011-01-03 15:07:55 +00001394 void __iomem *ioaddr = tp->mmio_addr;
1395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1397}
1398
françois romieu4da19632011-01-03 15:07:55 +00001399static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
1401 unsigned int val;
1402
françois romieu4da19632011-01-03 15:07:55 +00001403 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1404 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
Hayes Wang70090422011-07-06 15:58:06 +08001407static void rtl_link_chg_patch(struct rtl8169_private *tp)
1408{
1409 void __iomem *ioaddr = tp->mmio_addr;
1410 struct net_device *dev = tp->dev;
1411
1412 if (!netif_running(dev))
1413 return;
1414
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001415 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1416 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001417 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001418 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1419 ERIAR_EXGMAC);
1420 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1421 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001422 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001423 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1424 ERIAR_EXGMAC);
1425 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1426 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001427 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001428 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1429 ERIAR_EXGMAC);
1430 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1431 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001432 }
1433 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001434 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001435 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001436 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001437 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001438 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1439 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1440 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001441 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1442 ERIAR_EXGMAC);
1443 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1444 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001445 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001446 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1447 ERIAR_EXGMAC);
1448 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1449 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001450 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001451 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1452 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001453 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1454 ERIAR_EXGMAC);
1455 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1456 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001457 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001458 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1459 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001460 }
Hayes Wang70090422011-07-06 15:58:06 +08001461 }
1462}
1463
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001464static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001465 struct rtl8169_private *tp,
1466 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001469 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001470 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001471 if (pm)
1472 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001474 if (net_ratelimit())
1475 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001476 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001478 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001479 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001480 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482}
1483
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001484static void rtl8169_check_link_status(struct net_device *dev,
1485 struct rtl8169_private *tp,
1486 void __iomem *ioaddr)
1487{
1488 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1489}
1490
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001491#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1492
1493static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1494{
1495 void __iomem *ioaddr = tp->mmio_addr;
1496 u8 options;
1497 u32 wolopts = 0;
1498
1499 options = RTL_R8(Config1);
1500 if (!(options & PMEnable))
1501 return 0;
1502
1503 options = RTL_R8(Config3);
1504 if (options & LinkUp)
1505 wolopts |= WAKE_PHY;
1506 if (options & MagicPacket)
1507 wolopts |= WAKE_MAGIC;
1508
1509 options = RTL_R8(Config5);
1510 if (options & UWF)
1511 wolopts |= WAKE_UCAST;
1512 if (options & BWF)
1513 wolopts |= WAKE_BCAST;
1514 if (options & MWF)
1515 wolopts |= WAKE_MCAST;
1516
1517 return wolopts;
1518}
1519
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001520static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1521{
1522 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001523
Francois Romieuda78dbf2012-01-26 14:18:23 +01001524 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001525
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001526 wol->supported = WAKE_ANY;
1527 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001528
Francois Romieuda78dbf2012-01-26 14:18:23 +01001529 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001530}
1531
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001532static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001533{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001535 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001536 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001537 u32 opt;
1538 u16 reg;
1539 u8 mask;
1540 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001541 { WAKE_PHY, Config3, LinkUp },
1542 { WAKE_MAGIC, Config3, MagicPacket },
1543 { WAKE_UCAST, Config5, UWF },
1544 { WAKE_BCAST, Config5, BWF },
1545 { WAKE_MCAST, Config5, MWF },
1546 { WAKE_ANY, Config5, LanWake }
1547 };
Francois Romieu851e6022012-04-17 11:10:11 +02001548 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001549
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001550 RTL_W8(Cfg9346, Cfg9346_Unlock);
1551
1552 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001553 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001554 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001555 options |= cfg[i].mask;
1556 RTL_W8(cfg[i].reg, options);
1557 }
1558
Francois Romieu851e6022012-04-17 11:10:11 +02001559 switch (tp->mac_version) {
1560 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1561 options = RTL_R8(Config1) & ~PMEnable;
1562 if (wolopts)
1563 options |= PMEnable;
1564 RTL_W8(Config1, options);
1565 break;
1566 default:
Francois Romieud387b422012-04-17 11:12:01 +02001567 options = RTL_R8(Config2) & ~PME_SIGNAL;
1568 if (wolopts)
1569 options |= PME_SIGNAL;
1570 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001571 break;
1572 }
1573
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001574 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001575}
1576
1577static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1578{
1579 struct rtl8169_private *tp = netdev_priv(dev);
1580
Francois Romieuda78dbf2012-01-26 14:18:23 +01001581 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001582
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001583 if (wol->wolopts)
1584 tp->features |= RTL_FEATURE_WOL;
1585 else
1586 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001587 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001588
1589 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001590
françois romieuea809072010-11-08 13:23:58 +00001591 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1592
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001593 return 0;
1594}
1595
Francois Romieu31bd2042011-04-26 18:58:59 +02001596static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1597{
Francois Romieu85bffe62011-04-27 08:22:39 +02001598 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001599}
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601static void rtl8169_get_drvinfo(struct net_device *dev,
1602 struct ethtool_drvinfo *info)
1603{
1604 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001605 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
Rick Jones68aad782011-11-07 13:29:27 +00001607 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1608 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1609 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001610 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001611 if (!IS_ERR_OR_NULL(rtl_fw))
1612 strlcpy(info->fw_version, rtl_fw->version,
1613 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614}
1615
1616static int rtl8169_get_regs_len(struct net_device *dev)
1617{
1618 return R8169_REGS_SIZE;
1619}
1620
1621static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001622 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct rtl8169_private *tp = netdev_priv(dev);
1625 void __iomem *ioaddr = tp->mmio_addr;
1626 int ret = 0;
1627 u32 reg;
1628
1629 reg = RTL_R32(TBICSR);
1630 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1631 (duplex == DUPLEX_FULL)) {
1632 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1633 } else if (autoneg == AUTONEG_ENABLE)
1634 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1635 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001636 netif_warn(tp, link, dev,
1637 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 ret = -EOPNOTSUPP;
1639 }
1640
1641 return ret;
1642}
1643
1644static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001645 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
1647 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001648 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001649 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Hayes Wang716b50a2011-02-22 17:26:18 +08001651 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001654 int auto_nego;
1655
françois romieu4da19632011-01-03 15:07:55 +00001656 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001657 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1658 ADVERTISE_100HALF | ADVERTISE_100FULL);
1659
1660 if (adv & ADVERTISED_10baseT_Half)
1661 auto_nego |= ADVERTISE_10HALF;
1662 if (adv & ADVERTISED_10baseT_Full)
1663 auto_nego |= ADVERTISE_10FULL;
1664 if (adv & ADVERTISED_100baseT_Half)
1665 auto_nego |= ADVERTISE_100HALF;
1666 if (adv & ADVERTISED_100baseT_Full)
1667 auto_nego |= ADVERTISE_100FULL;
1668
françois romieu3577aa12009-05-19 10:46:48 +00001669 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1670
françois romieu4da19632011-01-03 15:07:55 +00001671 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001672 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1673
1674 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001675 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001676 if (adv & ADVERTISED_1000baseT_Half)
1677 giga_ctrl |= ADVERTISE_1000HALF;
1678 if (adv & ADVERTISED_1000baseT_Full)
1679 giga_ctrl |= ADVERTISE_1000FULL;
1680 } else if (adv & (ADVERTISED_1000baseT_Half |
1681 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001682 netif_info(tp, link, dev,
1683 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001684 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
françois romieu3577aa12009-05-19 10:46:48 +00001687 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001688
françois romieu4da19632011-01-03 15:07:55 +00001689 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1690 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001691 } else {
1692 giga_ctrl = 0;
1693
1694 if (speed == SPEED_10)
1695 bmcr = 0;
1696 else if (speed == SPEED_100)
1697 bmcr = BMCR_SPEED100;
1698 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001699 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001700
1701 if (duplex == DUPLEX_FULL)
1702 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001703 }
1704
françois romieu4da19632011-01-03 15:07:55 +00001705 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001706
Francois Romieucecb5fd2011-04-01 10:21:07 +02001707 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1708 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001709 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001710 rtl_writephy(tp, 0x17, 0x2138);
1711 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001712 } else {
françois romieu4da19632011-01-03 15:07:55 +00001713 rtl_writephy(tp, 0x17, 0x2108);
1714 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001715 }
1716 }
1717
Oliver Neukum54405cd2011-01-06 21:55:13 +01001718 rc = 0;
1719out:
1720 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
1722
1723static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001724 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725{
1726 struct rtl8169_private *tp = netdev_priv(dev);
1727 int ret;
1728
Oliver Neukum54405cd2011-01-06 21:55:13 +01001729 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001730 if (ret < 0)
1731 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Francois Romieu4876cc12011-03-11 21:07:11 +01001733 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1734 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001736 }
1737out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 return ret;
1739}
1740
1741static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1742{
1743 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 int ret;
1745
Francois Romieu4876cc12011-03-11 21:07:11 +01001746 del_timer_sync(&tp->timer);
1747
Francois Romieuda78dbf2012-01-26 14:18:23 +01001748 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001749 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001750 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001751 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 return ret;
1754}
1755
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001756static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1757 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
Francois Romieud58d46b2011-05-03 16:38:29 +02001759 struct rtl8169_private *tp = netdev_priv(dev);
1760
Francois Romieu2b7b4312011-04-18 22:53:24 -07001761 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001762 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Francois Romieud58d46b2011-05-03 16:38:29 +02001764 if (dev->mtu > JUMBO_1K &&
1765 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1766 features &= ~NETIF_F_IP_CSUM;
1767
Michał Mirosław350fb322011-04-08 06:35:56 +00001768 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769}
1770
Francois Romieuda78dbf2012-01-26 14:18:23 +01001771static void __rtl8169_set_features(struct net_device *dev,
1772 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
1774 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001775 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001776 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Ben Greear6bbe0212012-02-10 15:04:33 +00001778 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1779 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Ben Greear6bbe0212012-02-10 15:04:33 +00001781 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1782 if (features & NETIF_F_RXCSUM)
1783 tp->cp_cmd |= RxChkSum;
1784 else
1785 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001786
Ben Greear6bbe0212012-02-10 15:04:33 +00001787 if (dev->features & NETIF_F_HW_VLAN_RX)
1788 tp->cp_cmd |= RxVlan;
1789 else
1790 tp->cp_cmd &= ~RxVlan;
1791
1792 RTL_W16(CPlusCmd, tp->cp_cmd);
1793 RTL_R16(CPlusCmd);
1794 }
1795 if (changed & NETIF_F_RXALL) {
1796 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1797 if (features & NETIF_F_RXALL)
1798 tmp |= (AcceptErr | AcceptRunt);
1799 RTL_W32(RxConfig, tmp);
1800 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001801}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
Francois Romieuda78dbf2012-01-26 14:18:23 +01001803static int rtl8169_set_features(struct net_device *dev,
1804 netdev_features_t features)
1805{
1806 struct rtl8169_private *tp = netdev_priv(dev);
1807
1808 rtl_lock_work(tp);
1809 __rtl8169_set_features(dev, features);
1810 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
1812 return 0;
1813}
1814
Francois Romieuda78dbf2012-01-26 14:18:23 +01001815
Kirill Smelkov810f4892012-11-10 21:11:02 +04001816static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817{
Jesse Grosseab6d182010-10-20 13:56:03 +00001818 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1820}
1821
Francois Romieu7a8fc772011-03-01 17:18:33 +01001822static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
1824 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Francois Romieu7a8fc772011-03-01 17:18:33 +01001826 if (opts2 & RxVlanTag)
1827 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Eric Dumazet2edae082010-09-06 18:46:39 +00001828
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 desc->opts2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830}
1831
Francois Romieuccdffb92008-07-26 14:26:06 +02001832static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
1834 struct rtl8169_private *tp = netdev_priv(dev);
1835 void __iomem *ioaddr = tp->mmio_addr;
1836 u32 status;
1837
1838 cmd->supported =
1839 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1840 cmd->port = PORT_FIBRE;
1841 cmd->transceiver = XCVR_INTERNAL;
1842
1843 status = RTL_R32(TBICSR);
1844 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1845 cmd->autoneg = !!(status & TBINwEnable);
1846
David Decotigny70739492011-04-27 18:32:40 +00001847 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001849
1850 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851}
1852
Francois Romieuccdffb92008-07-26 14:26:06 +02001853static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854{
1855 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
Francois Romieuccdffb92008-07-26 14:26:06 +02001857 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
1860static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1861{
1862 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001863 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Francois Romieuda78dbf2012-01-26 14:18:23 +01001865 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001866 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001867 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Francois Romieuccdffb92008-07-26 14:26:06 +02001869 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870}
1871
1872static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1873 void *p)
1874{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001875 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Francois Romieu5b0384f2006-08-16 16:00:01 +02001877 if (regs->len > R8169_REGS_SIZE)
1878 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
Francois Romieuda78dbf2012-01-26 14:18:23 +01001880 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001881 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001882 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883}
1884
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001885static u32 rtl8169_get_msglevel(struct net_device *dev)
1886{
1887 struct rtl8169_private *tp = netdev_priv(dev);
1888
1889 return tp->msg_enable;
1890}
1891
1892static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1893{
1894 struct rtl8169_private *tp = netdev_priv(dev);
1895
1896 tp->msg_enable = value;
1897}
1898
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001899static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1900 "tx_packets",
1901 "rx_packets",
1902 "tx_errors",
1903 "rx_errors",
1904 "rx_missed",
1905 "align_errors",
1906 "tx_single_collisions",
1907 "tx_multi_collisions",
1908 "unicast",
1909 "broadcast",
1910 "multicast",
1911 "tx_aborted",
1912 "tx_underrun",
1913};
1914
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001915static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001916{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001917 switch (sset) {
1918 case ETH_SS_STATS:
1919 return ARRAY_SIZE(rtl8169_gstrings);
1920 default:
1921 return -EOPNOTSUPP;
1922 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001923}
1924
Francois Romieuffc46952012-07-06 14:19:23 +02001925DECLARE_RTL_COND(rtl_counters_cond)
1926{
1927 void __iomem *ioaddr = tp->mmio_addr;
1928
1929 return RTL_R32(CounterAddrLow) & CounterDump;
1930}
1931
Ivan Vecera355423d2009-02-06 21:49:57 -08001932static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001933{
1934 struct rtl8169_private *tp = netdev_priv(dev);
1935 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001936 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001937 struct rtl8169_counters *counters;
1938 dma_addr_t paddr;
1939 u32 cmd;
1940
Ivan Vecera355423d2009-02-06 21:49:57 -08001941 /*
1942 * Some chips are unable to dump tally counters when the receiver
1943 * is disabled.
1944 */
1945 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1946 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001947
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001948 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001949 if (!counters)
1950 return;
1951
1952 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001953 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001954 RTL_W32(CounterAddrLow, cmd);
1955 RTL_W32(CounterAddrLow, cmd | CounterDump);
1956
Francois Romieuffc46952012-07-06 14:19:23 +02001957 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1958 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001959
1960 RTL_W32(CounterAddrLow, 0);
1961 RTL_W32(CounterAddrHigh, 0);
1962
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001963 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001964}
1965
Ivan Vecera355423d2009-02-06 21:49:57 -08001966static void rtl8169_get_ethtool_stats(struct net_device *dev,
1967 struct ethtool_stats *stats, u64 *data)
1968{
1969 struct rtl8169_private *tp = netdev_priv(dev);
1970
1971 ASSERT_RTNL();
1972
1973 rtl8169_update_counters(dev);
1974
1975 data[0] = le64_to_cpu(tp->counters.tx_packets);
1976 data[1] = le64_to_cpu(tp->counters.rx_packets);
1977 data[2] = le64_to_cpu(tp->counters.tx_errors);
1978 data[3] = le32_to_cpu(tp->counters.rx_errors);
1979 data[4] = le16_to_cpu(tp->counters.rx_missed);
1980 data[5] = le16_to_cpu(tp->counters.align_errors);
1981 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1982 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1983 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1984 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1985 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1986 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1987 data[12] = le16_to_cpu(tp->counters.tx_underun);
1988}
1989
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001990static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1991{
1992 switch(stringset) {
1993 case ETH_SS_STATS:
1994 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1995 break;
1996 }
1997}
1998
Jeff Garzik7282d492006-09-13 14:30:00 -04001999static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 .get_drvinfo = rtl8169_get_drvinfo,
2001 .get_regs_len = rtl8169_get_regs_len,
2002 .get_link = ethtool_op_get_link,
2003 .get_settings = rtl8169_get_settings,
2004 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002005 .get_msglevel = rtl8169_get_msglevel,
2006 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002008 .get_wol = rtl8169_get_wol,
2009 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002010 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002011 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002012 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002013 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014};
2015
Francois Romieu07d3f512007-02-21 22:40:46 +01002016static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002017 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018{
Francois Romieu5d320a22011-05-08 17:47:36 +02002019 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002020 /*
2021 * The driver currently handles the 8168Bf and the 8168Be identically
2022 * but they can be identified more specifically through the test below
2023 * if needed:
2024 *
2025 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002026 *
2027 * Same thing for the 8101Eb and the 8101Ec:
2028 *
2029 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002030 */
Francois Romieu37441002011-06-17 22:58:54 +02002031 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002033 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 int mac_version;
2035 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002036 /* 8168G family. */
2037 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2038 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2039
Hayes Wangc2218922011-09-06 16:55:18 +08002040 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002041 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002042 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2043 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2044
hayeswang01dc7fe2011-03-21 01:50:28 +00002045 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002046 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002047 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2048 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2049 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2050
Francois Romieu5b538df2008-07-20 16:22:45 +02002051 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002052 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2053 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002054 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002055
françois romieue6de30d2011-01-03 15:08:37 +00002056 /* 8168DP family. */
2057 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2058 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002059 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002060
Francois Romieuef808d52008-06-29 13:10:54 +02002061 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002062 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002063 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002064 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002065 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002066 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2067 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002068 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002069 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002070 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002071
2072 /* 8168B family. */
2073 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2074 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2075 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2076 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2077
2078 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002079 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2080 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002081 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002082 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002083 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2084 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2085 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002086 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2087 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2088 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2089 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2090 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2091 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002092 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002093 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002094 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002095 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2096 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002097 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2098 /* FIXME: where did these entries come from ? -- FR */
2099 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2100 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2101
2102 /* 8110 family. */
2103 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2104 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2105 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2106 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2107 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2108 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2109
Jean Delvaref21b75e2009-05-26 20:54:48 -07002110 /* Catch-all */
2111 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002112 };
2113 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 u32 reg;
2115
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002116 reg = RTL_R32(TxConfig);
2117 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 p++;
2119 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002120
2121 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2122 netif_notice(tp, probe, dev,
2123 "unknown MAC, using family default\n");
2124 tp->mac_version = default_version;
2125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126}
2127
2128static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2129{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002130 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131}
2132
Francois Romieu867763c2007-08-17 18:21:58 +02002133struct phy_reg {
2134 u16 reg;
2135 u16 val;
2136};
2137
françois romieu4da19632011-01-03 15:07:55 +00002138static void rtl_writephy_batch(struct rtl8169_private *tp,
2139 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002140{
2141 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002142 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002143 regs++;
2144 }
2145}
2146
françois romieubca03d52011-01-03 15:07:31 +00002147#define PHY_READ 0x00000000
2148#define PHY_DATA_OR 0x10000000
2149#define PHY_DATA_AND 0x20000000
2150#define PHY_BJMPN 0x30000000
2151#define PHY_READ_EFUSE 0x40000000
2152#define PHY_READ_MAC_BYTE 0x50000000
2153#define PHY_WRITE_MAC_BYTE 0x60000000
2154#define PHY_CLEAR_READCOUNT 0x70000000
2155#define PHY_WRITE 0x80000000
2156#define PHY_READCOUNT_EQ_SKIP 0x90000000
2157#define PHY_COMP_EQ_SKIPN 0xa0000000
2158#define PHY_COMP_NEQ_SKIPN 0xb0000000
2159#define PHY_WRITE_PREVIOUS 0xc0000000
2160#define PHY_SKIPN 0xd0000000
2161#define PHY_DELAY_MS 0xe0000000
2162#define PHY_WRITE_ERI_WORD 0xf0000000
2163
Hayes Wang960aee62011-06-18 11:37:48 +02002164struct fw_info {
2165 u32 magic;
2166 char version[RTL_VER_SIZE];
2167 __le32 fw_start;
2168 __le32 fw_len;
2169 u8 chksum;
2170} __packed;
2171
Francois Romieu1c361ef2011-06-17 17:16:24 +02002172#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2173
2174static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002175{
Francois Romieub6ffd972011-06-17 17:00:05 +02002176 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002177 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002178 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2179 char *version = rtl_fw->version;
2180 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002181
Francois Romieu1c361ef2011-06-17 17:16:24 +02002182 if (fw->size < FW_OPCODE_SIZE)
2183 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002184
2185 if (!fw_info->magic) {
2186 size_t i, size, start;
2187 u8 checksum = 0;
2188
2189 if (fw->size < sizeof(*fw_info))
2190 goto out;
2191
2192 for (i = 0; i < fw->size; i++)
2193 checksum += fw->data[i];
2194 if (checksum != 0)
2195 goto out;
2196
2197 start = le32_to_cpu(fw_info->fw_start);
2198 if (start > fw->size)
2199 goto out;
2200
2201 size = le32_to_cpu(fw_info->fw_len);
2202 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2203 goto out;
2204
2205 memcpy(version, fw_info->version, RTL_VER_SIZE);
2206
2207 pa->code = (__le32 *)(fw->data + start);
2208 pa->size = size;
2209 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002210 if (fw->size % FW_OPCODE_SIZE)
2211 goto out;
2212
2213 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2214
2215 pa->code = (__le32 *)fw->data;
2216 pa->size = fw->size / FW_OPCODE_SIZE;
2217 }
2218 version[RTL_VER_SIZE - 1] = 0;
2219
2220 rc = true;
2221out:
2222 return rc;
2223}
2224
Francois Romieufd112f22011-06-18 00:10:29 +02002225static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2226 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002227{
Francois Romieufd112f22011-06-18 00:10:29 +02002228 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002229 size_t index;
2230
Francois Romieu1c361ef2011-06-17 17:16:24 +02002231 for (index = 0; index < pa->size; index++) {
2232 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002233 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002234
hayeswang42b82dc2011-01-10 02:07:25 +00002235 switch(action & 0xf0000000) {
2236 case PHY_READ:
2237 case PHY_DATA_OR:
2238 case PHY_DATA_AND:
2239 case PHY_READ_EFUSE:
2240 case PHY_CLEAR_READCOUNT:
2241 case PHY_WRITE:
2242 case PHY_WRITE_PREVIOUS:
2243 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002244 break;
2245
hayeswang42b82dc2011-01-10 02:07:25 +00002246 case PHY_BJMPN:
2247 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002248 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002249 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002250 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002251 }
2252 break;
2253 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002254 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002255 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002256 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002257 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002258 }
2259 break;
2260 case PHY_COMP_EQ_SKIPN:
2261 case PHY_COMP_NEQ_SKIPN:
2262 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002263 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002264 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002265 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002266 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002267 }
2268 break;
2269
2270 case PHY_READ_MAC_BYTE:
2271 case PHY_WRITE_MAC_BYTE:
2272 case PHY_WRITE_ERI_WORD:
2273 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002274 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002275 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002276 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002277 }
2278 }
Francois Romieufd112f22011-06-18 00:10:29 +02002279 rc = true;
2280out:
2281 return rc;
2282}
françois romieubca03d52011-01-03 15:07:31 +00002283
Francois Romieufd112f22011-06-18 00:10:29 +02002284static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2285{
2286 struct net_device *dev = tp->dev;
2287 int rc = -EINVAL;
2288
2289 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2290 netif_err(tp, ifup, dev, "invalid firwmare\n");
2291 goto out;
2292 }
2293
2294 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2295 rc = 0;
2296out:
2297 return rc;
2298}
2299
2300static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2301{
2302 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2303 u32 predata, count;
2304 size_t index;
2305
2306 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002307
Francois Romieu1c361ef2011-06-17 17:16:24 +02002308 for (index = 0; index < pa->size; ) {
2309 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002310 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002311 u32 regno = (action & 0x0fff0000) >> 16;
2312
2313 if (!action)
2314 break;
françois romieubca03d52011-01-03 15:07:31 +00002315
2316 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002317 case PHY_READ:
2318 predata = rtl_readphy(tp, regno);
2319 count++;
2320 index++;
françois romieubca03d52011-01-03 15:07:31 +00002321 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002322 case PHY_DATA_OR:
2323 predata |= data;
2324 index++;
2325 break;
2326 case PHY_DATA_AND:
2327 predata &= data;
2328 index++;
2329 break;
2330 case PHY_BJMPN:
2331 index -= regno;
2332 break;
2333 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002334 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002335 index++;
2336 break;
2337 case PHY_CLEAR_READCOUNT:
2338 count = 0;
2339 index++;
2340 break;
2341 case PHY_WRITE:
2342 rtl_writephy(tp, regno, data);
2343 index++;
2344 break;
2345 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002346 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002347 break;
2348 case PHY_COMP_EQ_SKIPN:
2349 if (predata == data)
2350 index += regno;
2351 index++;
2352 break;
2353 case PHY_COMP_NEQ_SKIPN:
2354 if (predata != data)
2355 index += regno;
2356 index++;
2357 break;
2358 case PHY_WRITE_PREVIOUS:
2359 rtl_writephy(tp, regno, predata);
2360 index++;
2361 break;
2362 case PHY_SKIPN:
2363 index += regno + 1;
2364 break;
2365 case PHY_DELAY_MS:
2366 mdelay(data);
2367 index++;
2368 break;
2369
2370 case PHY_READ_MAC_BYTE:
2371 case PHY_WRITE_MAC_BYTE:
2372 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002373 default:
2374 BUG();
2375 }
2376 }
2377}
2378
françois romieuf1e02ed2011-01-13 13:07:53 +00002379static void rtl_release_firmware(struct rtl8169_private *tp)
2380{
Francois Romieub6ffd972011-06-17 17:00:05 +02002381 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2382 release_firmware(tp->rtl_fw->fw);
2383 kfree(tp->rtl_fw);
2384 }
2385 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002386}
2387
François Romieu953a12c2011-04-24 17:38:48 +02002388static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002389{
Francois Romieub6ffd972011-06-17 17:00:05 +02002390 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002391
2392 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002393 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002394 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002395 tp->features |= RTL_FEATURE_FW_LOADED;
2396 }
François Romieu953a12c2011-04-24 17:38:48 +02002397}
2398
2399static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2400{
2401 if (rtl_readphy(tp, reg) != val)
2402 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2403 else
2404 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002405}
2406
hayeswange0c07552012-10-23 20:24:03 +00002407static void r810x_aldps_disable(struct rtl8169_private *tp)
2408{
2409 rtl_writephy(tp, 0x1f, 0x0000);
2410 rtl_writephy(tp, 0x18, 0x0310);
2411 msleep(100);
2412}
2413
2414static void r810x_aldps_enable(struct rtl8169_private *tp)
2415{
2416 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2417 return;
2418
2419 rtl_writephy(tp, 0x1f, 0x0000);
2420 rtl_writephy(tp, 0x18, 0x8310);
2421}
2422
2423static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2424{
2425 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2426 return;
2427
2428 rtl_writephy(tp, 0x1f, 0x0000);
2429 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2430}
2431
françois romieu4da19632011-01-03 15:07:55 +00002432static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002434 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002435 { 0x1f, 0x0001 },
2436 { 0x06, 0x006e },
2437 { 0x08, 0x0708 },
2438 { 0x15, 0x4000 },
2439 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
françois romieu0b9b5712009-08-10 19:44:56 +00002441 { 0x1f, 0x0001 },
2442 { 0x03, 0x00a1 },
2443 { 0x02, 0x0008 },
2444 { 0x01, 0x0120 },
2445 { 0x00, 0x1000 },
2446 { 0x04, 0x0800 },
2447 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448
françois romieu0b9b5712009-08-10 19:44:56 +00002449 { 0x03, 0xff41 },
2450 { 0x02, 0xdf60 },
2451 { 0x01, 0x0140 },
2452 { 0x00, 0x0077 },
2453 { 0x04, 0x7800 },
2454 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
françois romieu0b9b5712009-08-10 19:44:56 +00002456 { 0x03, 0x802f },
2457 { 0x02, 0x4f02 },
2458 { 0x01, 0x0409 },
2459 { 0x00, 0xf0f9 },
2460 { 0x04, 0x9800 },
2461 { 0x04, 0x9000 },
2462
2463 { 0x03, 0xdf01 },
2464 { 0x02, 0xdf20 },
2465 { 0x01, 0xff95 },
2466 { 0x00, 0xba00 },
2467 { 0x04, 0xa800 },
2468 { 0x04, 0xa000 },
2469
2470 { 0x03, 0xff41 },
2471 { 0x02, 0xdf20 },
2472 { 0x01, 0x0140 },
2473 { 0x00, 0x00bb },
2474 { 0x04, 0xb800 },
2475 { 0x04, 0xb000 },
2476
2477 { 0x03, 0xdf41 },
2478 { 0x02, 0xdc60 },
2479 { 0x01, 0x6340 },
2480 { 0x00, 0x007d },
2481 { 0x04, 0xd800 },
2482 { 0x04, 0xd000 },
2483
2484 { 0x03, 0xdf01 },
2485 { 0x02, 0xdf20 },
2486 { 0x01, 0x100a },
2487 { 0x00, 0xa0ff },
2488 { 0x04, 0xf800 },
2489 { 0x04, 0xf000 },
2490
2491 { 0x1f, 0x0000 },
2492 { 0x0b, 0x0000 },
2493 { 0x00, 0x9200 }
2494 };
2495
françois romieu4da19632011-01-03 15:07:55 +00002496 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497}
2498
françois romieu4da19632011-01-03 15:07:55 +00002499static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002500{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002501 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002502 { 0x1f, 0x0002 },
2503 { 0x01, 0x90d0 },
2504 { 0x1f, 0x0000 }
2505 };
2506
françois romieu4da19632011-01-03 15:07:55 +00002507 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002508}
2509
françois romieu4da19632011-01-03 15:07:55 +00002510static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002511{
2512 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002513
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002514 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2515 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002516 return;
2517
françois romieu4da19632011-01-03 15:07:55 +00002518 rtl_writephy(tp, 0x1f, 0x0001);
2519 rtl_writephy(tp, 0x10, 0xf01b);
2520 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002521}
2522
françois romieu4da19632011-01-03 15:07:55 +00002523static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002524{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002525 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002526 { 0x1f, 0x0001 },
2527 { 0x04, 0x0000 },
2528 { 0x03, 0x00a1 },
2529 { 0x02, 0x0008 },
2530 { 0x01, 0x0120 },
2531 { 0x00, 0x1000 },
2532 { 0x04, 0x0800 },
2533 { 0x04, 0x9000 },
2534 { 0x03, 0x802f },
2535 { 0x02, 0x4f02 },
2536 { 0x01, 0x0409 },
2537 { 0x00, 0xf099 },
2538 { 0x04, 0x9800 },
2539 { 0x04, 0xa000 },
2540 { 0x03, 0xdf01 },
2541 { 0x02, 0xdf20 },
2542 { 0x01, 0xff95 },
2543 { 0x00, 0xba00 },
2544 { 0x04, 0xa800 },
2545 { 0x04, 0xf000 },
2546 { 0x03, 0xdf01 },
2547 { 0x02, 0xdf20 },
2548 { 0x01, 0x101a },
2549 { 0x00, 0xa0ff },
2550 { 0x04, 0xf800 },
2551 { 0x04, 0x0000 },
2552 { 0x1f, 0x0000 },
2553
2554 { 0x1f, 0x0001 },
2555 { 0x10, 0xf41b },
2556 { 0x14, 0xfb54 },
2557 { 0x18, 0xf5c7 },
2558 { 0x1f, 0x0000 },
2559
2560 { 0x1f, 0x0001 },
2561 { 0x17, 0x0cc0 },
2562 { 0x1f, 0x0000 }
2563 };
2564
françois romieu4da19632011-01-03 15:07:55 +00002565 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002566
françois romieu4da19632011-01-03 15:07:55 +00002567 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002568}
2569
françois romieu4da19632011-01-03 15:07:55 +00002570static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002571{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002572 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002573 { 0x1f, 0x0001 },
2574 { 0x04, 0x0000 },
2575 { 0x03, 0x00a1 },
2576 { 0x02, 0x0008 },
2577 { 0x01, 0x0120 },
2578 { 0x00, 0x1000 },
2579 { 0x04, 0x0800 },
2580 { 0x04, 0x9000 },
2581 { 0x03, 0x802f },
2582 { 0x02, 0x4f02 },
2583 { 0x01, 0x0409 },
2584 { 0x00, 0xf099 },
2585 { 0x04, 0x9800 },
2586 { 0x04, 0xa000 },
2587 { 0x03, 0xdf01 },
2588 { 0x02, 0xdf20 },
2589 { 0x01, 0xff95 },
2590 { 0x00, 0xba00 },
2591 { 0x04, 0xa800 },
2592 { 0x04, 0xf000 },
2593 { 0x03, 0xdf01 },
2594 { 0x02, 0xdf20 },
2595 { 0x01, 0x101a },
2596 { 0x00, 0xa0ff },
2597 { 0x04, 0xf800 },
2598 { 0x04, 0x0000 },
2599 { 0x1f, 0x0000 },
2600
2601 { 0x1f, 0x0001 },
2602 { 0x0b, 0x8480 },
2603 { 0x1f, 0x0000 },
2604
2605 { 0x1f, 0x0001 },
2606 { 0x18, 0x67c7 },
2607 { 0x04, 0x2000 },
2608 { 0x03, 0x002f },
2609 { 0x02, 0x4360 },
2610 { 0x01, 0x0109 },
2611 { 0x00, 0x3022 },
2612 { 0x04, 0x2800 },
2613 { 0x1f, 0x0000 },
2614
2615 { 0x1f, 0x0001 },
2616 { 0x17, 0x0cc0 },
2617 { 0x1f, 0x0000 }
2618 };
2619
françois romieu4da19632011-01-03 15:07:55 +00002620 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002621}
2622
françois romieu4da19632011-01-03 15:07:55 +00002623static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002624{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002625 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002626 { 0x10, 0xf41b },
2627 { 0x1f, 0x0000 }
2628 };
2629
françois romieu4da19632011-01-03 15:07:55 +00002630 rtl_writephy(tp, 0x1f, 0x0001);
2631 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002632
françois romieu4da19632011-01-03 15:07:55 +00002633 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002634}
2635
françois romieu4da19632011-01-03 15:07:55 +00002636static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002637{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002638 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002639 { 0x1f, 0x0001 },
2640 { 0x10, 0xf41b },
2641 { 0x1f, 0x0000 }
2642 };
2643
françois romieu4da19632011-01-03 15:07:55 +00002644 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002645}
2646
françois romieu4da19632011-01-03 15:07:55 +00002647static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002648{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002649 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002650 { 0x1f, 0x0000 },
2651 { 0x1d, 0x0f00 },
2652 { 0x1f, 0x0002 },
2653 { 0x0c, 0x1ec8 },
2654 { 0x1f, 0x0000 }
2655 };
2656
françois romieu4da19632011-01-03 15:07:55 +00002657 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002658}
2659
françois romieu4da19632011-01-03 15:07:55 +00002660static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002661{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002662 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002663 { 0x1f, 0x0001 },
2664 { 0x1d, 0x3d98 },
2665 { 0x1f, 0x0000 }
2666 };
2667
françois romieu4da19632011-01-03 15:07:55 +00002668 rtl_writephy(tp, 0x1f, 0x0000);
2669 rtl_patchphy(tp, 0x14, 1 << 5);
2670 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002671
françois romieu4da19632011-01-03 15:07:55 +00002672 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002673}
2674
françois romieu4da19632011-01-03 15:07:55 +00002675static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002676{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002677 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002678 { 0x1f, 0x0001 },
2679 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002680 { 0x1f, 0x0002 },
2681 { 0x00, 0x88d4 },
2682 { 0x01, 0x82b1 },
2683 { 0x03, 0x7002 },
2684 { 0x08, 0x9e30 },
2685 { 0x09, 0x01f0 },
2686 { 0x0a, 0x5500 },
2687 { 0x0c, 0x00c8 },
2688 { 0x1f, 0x0003 },
2689 { 0x12, 0xc096 },
2690 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002691 { 0x1f, 0x0000 },
2692 { 0x1f, 0x0000 },
2693 { 0x09, 0x2000 },
2694 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002695 };
2696
françois romieu4da19632011-01-03 15:07:55 +00002697 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002698
françois romieu4da19632011-01-03 15:07:55 +00002699 rtl_patchphy(tp, 0x14, 1 << 5);
2700 rtl_patchphy(tp, 0x0d, 1 << 5);
2701 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002702}
2703
françois romieu4da19632011-01-03 15:07:55 +00002704static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002705{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002706 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002707 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002708 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002709 { 0x03, 0x802f },
2710 { 0x02, 0x4f02 },
2711 { 0x01, 0x0409 },
2712 { 0x00, 0xf099 },
2713 { 0x04, 0x9800 },
2714 { 0x04, 0x9000 },
2715 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002716 { 0x1f, 0x0002 },
2717 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002718 { 0x06, 0x0761 },
2719 { 0x1f, 0x0003 },
2720 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002721 { 0x1f, 0x0000 }
2722 };
2723
françois romieu4da19632011-01-03 15:07:55 +00002724 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002725
françois romieu4da19632011-01-03 15:07:55 +00002726 rtl_patchphy(tp, 0x16, 1 << 0);
2727 rtl_patchphy(tp, 0x14, 1 << 5);
2728 rtl_patchphy(tp, 0x0d, 1 << 5);
2729 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002730}
2731
françois romieu4da19632011-01-03 15:07:55 +00002732static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002733{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002734 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002735 { 0x1f, 0x0001 },
2736 { 0x12, 0x2300 },
2737 { 0x1d, 0x3d98 },
2738 { 0x1f, 0x0002 },
2739 { 0x0c, 0x7eb8 },
2740 { 0x06, 0x5461 },
2741 { 0x1f, 0x0003 },
2742 { 0x16, 0x0f0a },
2743 { 0x1f, 0x0000 }
2744 };
2745
françois romieu4da19632011-01-03 15:07:55 +00002746 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002747
françois romieu4da19632011-01-03 15:07:55 +00002748 rtl_patchphy(tp, 0x16, 1 << 0);
2749 rtl_patchphy(tp, 0x14, 1 << 5);
2750 rtl_patchphy(tp, 0x0d, 1 << 5);
2751 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002752}
2753
françois romieu4da19632011-01-03 15:07:55 +00002754static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002755{
françois romieu4da19632011-01-03 15:07:55 +00002756 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002757}
2758
françois romieubca03d52011-01-03 15:07:31 +00002759static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002760{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002761 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002762 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002763 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002764 { 0x06, 0x4064 },
2765 { 0x07, 0x2863 },
2766 { 0x08, 0x059c },
2767 { 0x09, 0x26b4 },
2768 { 0x0a, 0x6a19 },
2769 { 0x0b, 0xdcc8 },
2770 { 0x10, 0xf06d },
2771 { 0x14, 0x7f68 },
2772 { 0x18, 0x7fd9 },
2773 { 0x1c, 0xf0ff },
2774 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002775 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002776 { 0x12, 0xf49f },
2777 { 0x13, 0x070b },
2778 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002779 { 0x14, 0x94c0 },
2780
2781 /*
2782 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002783 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002784 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002785 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002786 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002787 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002788 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002789 { 0x06, 0x5561 },
2790
2791 /*
2792 * Can not link to 1Gbps with bad cable
2793 * Decrease SNR threshold form 21.07dB to 19.04dB
2794 */
2795 { 0x1f, 0x0001 },
2796 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002797
2798 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002799 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002800 };
2801
françois romieu4da19632011-01-03 15:07:55 +00002802 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002803
françois romieubca03d52011-01-03 15:07:31 +00002804 /*
2805 * Rx Error Issue
2806 * Fine Tune Switching regulator parameter
2807 */
françois romieu4da19632011-01-03 15:07:55 +00002808 rtl_writephy(tp, 0x1f, 0x0002);
2809 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2810 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002811
Francois Romieufdf6fc02012-07-06 22:40:38 +02002812 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002813 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002814 { 0x1f, 0x0002 },
2815 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002816 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002817 { 0x05, 0x8330 },
2818 { 0x06, 0x669a },
2819 { 0x1f, 0x0002 }
2820 };
2821 int val;
2822
françois romieu4da19632011-01-03 15:07:55 +00002823 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002824
françois romieu4da19632011-01-03 15:07:55 +00002825 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002826
2827 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002828 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002829 0x0065, 0x0066, 0x0067, 0x0068,
2830 0x0069, 0x006a, 0x006b, 0x006c
2831 };
2832 int i;
2833
françois romieu4da19632011-01-03 15:07:55 +00002834 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002835
2836 val &= 0xff00;
2837 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002838 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002839 }
2840 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002841 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002842 { 0x1f, 0x0002 },
2843 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002844 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002845 { 0x05, 0x8330 },
2846 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002847 };
2848
françois romieu4da19632011-01-03 15:07:55 +00002849 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002850 }
2851
françois romieubca03d52011-01-03 15:07:31 +00002852 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002853 rtl_writephy(tp, 0x1f, 0x0002);
2854 rtl_patchphy(tp, 0x0d, 0x0300);
2855 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002856
françois romieubca03d52011-01-03 15:07:31 +00002857 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002858 rtl_writephy(tp, 0x1f, 0x0002);
2859 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2860 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002861
françois romieu4da19632011-01-03 15:07:55 +00002862 rtl_writephy(tp, 0x1f, 0x0005);
2863 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002864
2865 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002866
françois romieu4da19632011-01-03 15:07:55 +00002867 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002868}
2869
françois romieubca03d52011-01-03 15:07:31 +00002870static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002871{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002872 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002873 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002874 { 0x1f, 0x0001 },
2875 { 0x06, 0x4064 },
2876 { 0x07, 0x2863 },
2877 { 0x08, 0x059c },
2878 { 0x09, 0x26b4 },
2879 { 0x0a, 0x6a19 },
2880 { 0x0b, 0xdcc8 },
2881 { 0x10, 0xf06d },
2882 { 0x14, 0x7f68 },
2883 { 0x18, 0x7fd9 },
2884 { 0x1c, 0xf0ff },
2885 { 0x1d, 0x3d9c },
2886 { 0x1f, 0x0003 },
2887 { 0x12, 0xf49f },
2888 { 0x13, 0x070b },
2889 { 0x1a, 0x05ad },
2890 { 0x14, 0x94c0 },
2891
françois romieubca03d52011-01-03 15:07:31 +00002892 /*
2893 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002894 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002895 */
françois romieudaf9df62009-10-07 12:44:20 +00002896 { 0x1f, 0x0002 },
2897 { 0x06, 0x5561 },
2898 { 0x1f, 0x0005 },
2899 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002900 { 0x06, 0x5561 },
2901
2902 /*
2903 * Can not link to 1Gbps with bad cable
2904 * Decrease SNR threshold form 21.07dB to 19.04dB
2905 */
2906 { 0x1f, 0x0001 },
2907 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002908
2909 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002910 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002911 };
2912
françois romieu4da19632011-01-03 15:07:55 +00002913 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002914
Francois Romieufdf6fc02012-07-06 22:40:38 +02002915 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002916 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002917 { 0x1f, 0x0002 },
2918 { 0x05, 0x669a },
2919 { 0x1f, 0x0005 },
2920 { 0x05, 0x8330 },
2921 { 0x06, 0x669a },
2922
2923 { 0x1f, 0x0002 }
2924 };
2925 int val;
2926
françois romieu4da19632011-01-03 15:07:55 +00002927 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002928
françois romieu4da19632011-01-03 15:07:55 +00002929 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002930 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002931 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002932 0x0065, 0x0066, 0x0067, 0x0068,
2933 0x0069, 0x006a, 0x006b, 0x006c
2934 };
2935 int i;
2936
françois romieu4da19632011-01-03 15:07:55 +00002937 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002938
2939 val &= 0xff00;
2940 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002941 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002942 }
2943 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002944 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002945 { 0x1f, 0x0002 },
2946 { 0x05, 0x2642 },
2947 { 0x1f, 0x0005 },
2948 { 0x05, 0x8330 },
2949 { 0x06, 0x2642 }
2950 };
2951
françois romieu4da19632011-01-03 15:07:55 +00002952 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002953 }
2954
françois romieubca03d52011-01-03 15:07:31 +00002955 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002956 rtl_writephy(tp, 0x1f, 0x0002);
2957 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2958 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002959
françois romieubca03d52011-01-03 15:07:31 +00002960 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002961 rtl_writephy(tp, 0x1f, 0x0002);
2962 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002963
françois romieu4da19632011-01-03 15:07:55 +00002964 rtl_writephy(tp, 0x1f, 0x0005);
2965 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002966
2967 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002968
françois romieu4da19632011-01-03 15:07:55 +00002969 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002970}
2971
françois romieu4da19632011-01-03 15:07:55 +00002972static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002973{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002974 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002975 { 0x1f, 0x0002 },
2976 { 0x10, 0x0008 },
2977 { 0x0d, 0x006c },
2978
2979 { 0x1f, 0x0000 },
2980 { 0x0d, 0xf880 },
2981
2982 { 0x1f, 0x0001 },
2983 { 0x17, 0x0cc0 },
2984
2985 { 0x1f, 0x0001 },
2986 { 0x0b, 0xa4d8 },
2987 { 0x09, 0x281c },
2988 { 0x07, 0x2883 },
2989 { 0x0a, 0x6b35 },
2990 { 0x1d, 0x3da4 },
2991 { 0x1c, 0xeffd },
2992 { 0x14, 0x7f52 },
2993 { 0x18, 0x7fc6 },
2994 { 0x08, 0x0601 },
2995 { 0x06, 0x4063 },
2996 { 0x10, 0xf074 },
2997 { 0x1f, 0x0003 },
2998 { 0x13, 0x0789 },
2999 { 0x12, 0xf4bd },
3000 { 0x1a, 0x04fd },
3001 { 0x14, 0x84b0 },
3002 { 0x1f, 0x0000 },
3003 { 0x00, 0x9200 },
3004
3005 { 0x1f, 0x0005 },
3006 { 0x01, 0x0340 },
3007 { 0x1f, 0x0001 },
3008 { 0x04, 0x4000 },
3009 { 0x03, 0x1d21 },
3010 { 0x02, 0x0c32 },
3011 { 0x01, 0x0200 },
3012 { 0x00, 0x5554 },
3013 { 0x04, 0x4800 },
3014 { 0x04, 0x4000 },
3015 { 0x04, 0xf000 },
3016 { 0x03, 0xdf01 },
3017 { 0x02, 0xdf20 },
3018 { 0x01, 0x101a },
3019 { 0x00, 0xa0ff },
3020 { 0x04, 0xf800 },
3021 { 0x04, 0xf000 },
3022 { 0x1f, 0x0000 },
3023
3024 { 0x1f, 0x0007 },
3025 { 0x1e, 0x0023 },
3026 { 0x16, 0x0000 },
3027 { 0x1f, 0x0000 }
3028 };
3029
françois romieu4da19632011-01-03 15:07:55 +00003030 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003031}
3032
françois romieue6de30d2011-01-03 15:08:37 +00003033static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3034{
3035 static const struct phy_reg phy_reg_init[] = {
3036 { 0x1f, 0x0001 },
3037 { 0x17, 0x0cc0 },
3038
3039 { 0x1f, 0x0007 },
3040 { 0x1e, 0x002d },
3041 { 0x18, 0x0040 },
3042 { 0x1f, 0x0000 }
3043 };
3044
3045 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3046 rtl_patchphy(tp, 0x0d, 1 << 5);
3047}
3048
Hayes Wang70090422011-07-06 15:58:06 +08003049static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003050{
3051 static const struct phy_reg phy_reg_init[] = {
3052 /* Enable Delay cap */
3053 { 0x1f, 0x0005 },
3054 { 0x05, 0x8b80 },
3055 { 0x06, 0xc896 },
3056 { 0x1f, 0x0000 },
3057
3058 /* Channel estimation fine tune */
3059 { 0x1f, 0x0001 },
3060 { 0x0b, 0x6c20 },
3061 { 0x07, 0x2872 },
3062 { 0x1c, 0xefff },
3063 { 0x1f, 0x0003 },
3064 { 0x14, 0x6420 },
3065 { 0x1f, 0x0000 },
3066
3067 /* Update PFM & 10M TX idle timer */
3068 { 0x1f, 0x0007 },
3069 { 0x1e, 0x002f },
3070 { 0x15, 0x1919 },
3071 { 0x1f, 0x0000 },
3072
3073 { 0x1f, 0x0007 },
3074 { 0x1e, 0x00ac },
3075 { 0x18, 0x0006 },
3076 { 0x1f, 0x0000 }
3077 };
3078
Francois Romieu15ecd032011-04-27 13:52:22 -07003079 rtl_apply_firmware(tp);
3080
hayeswang01dc7fe2011-03-21 01:50:28 +00003081 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3082
3083 /* DCO enable for 10M IDLE Power */
3084 rtl_writephy(tp, 0x1f, 0x0007);
3085 rtl_writephy(tp, 0x1e, 0x0023);
3086 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3087 rtl_writephy(tp, 0x1f, 0x0000);
3088
3089 /* For impedance matching */
3090 rtl_writephy(tp, 0x1f, 0x0002);
3091 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003092 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003093
3094 /* PHY auto speed down */
3095 rtl_writephy(tp, 0x1f, 0x0007);
3096 rtl_writephy(tp, 0x1e, 0x002d);
3097 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3098 rtl_writephy(tp, 0x1f, 0x0000);
3099 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3100
3101 rtl_writephy(tp, 0x1f, 0x0005);
3102 rtl_writephy(tp, 0x05, 0x8b86);
3103 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3104 rtl_writephy(tp, 0x1f, 0x0000);
3105
3106 rtl_writephy(tp, 0x1f, 0x0005);
3107 rtl_writephy(tp, 0x05, 0x8b85);
3108 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3109 rtl_writephy(tp, 0x1f, 0x0007);
3110 rtl_writephy(tp, 0x1e, 0x0020);
3111 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3112 rtl_writephy(tp, 0x1f, 0x0006);
3113 rtl_writephy(tp, 0x00, 0x5a00);
3114 rtl_writephy(tp, 0x1f, 0x0000);
3115 rtl_writephy(tp, 0x0d, 0x0007);
3116 rtl_writephy(tp, 0x0e, 0x003c);
3117 rtl_writephy(tp, 0x0d, 0x4007);
3118 rtl_writephy(tp, 0x0e, 0x0000);
3119 rtl_writephy(tp, 0x0d, 0x0000);
3120}
3121
françois romieu9ecb9aa2012-12-07 11:20:21 +00003122static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3123{
3124 const u16 w[] = {
3125 addr[0] | (addr[1] << 8),
3126 addr[2] | (addr[3] << 8),
3127 addr[4] | (addr[5] << 8)
3128 };
3129 const struct exgmac_reg e[] = {
3130 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3131 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3132 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3133 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3134 };
3135
3136 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3137}
3138
Hayes Wang70090422011-07-06 15:58:06 +08003139static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3140{
3141 static const struct phy_reg phy_reg_init[] = {
3142 /* Enable Delay cap */
3143 { 0x1f, 0x0004 },
3144 { 0x1f, 0x0007 },
3145 { 0x1e, 0x00ac },
3146 { 0x18, 0x0006 },
3147 { 0x1f, 0x0002 },
3148 { 0x1f, 0x0000 },
3149 { 0x1f, 0x0000 },
3150
3151 /* Channel estimation fine tune */
3152 { 0x1f, 0x0003 },
3153 { 0x09, 0xa20f },
3154 { 0x1f, 0x0000 },
3155 { 0x1f, 0x0000 },
3156
3157 /* Green Setting */
3158 { 0x1f, 0x0005 },
3159 { 0x05, 0x8b5b },
3160 { 0x06, 0x9222 },
3161 { 0x05, 0x8b6d },
3162 { 0x06, 0x8000 },
3163 { 0x05, 0x8b76 },
3164 { 0x06, 0x8000 },
3165 { 0x1f, 0x0000 }
3166 };
3167
3168 rtl_apply_firmware(tp);
3169
3170 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3171
3172 /* For 4-corner performance improve */
3173 rtl_writephy(tp, 0x1f, 0x0005);
3174 rtl_writephy(tp, 0x05, 0x8b80);
3175 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3176 rtl_writephy(tp, 0x1f, 0x0000);
3177
3178 /* PHY auto speed down */
3179 rtl_writephy(tp, 0x1f, 0x0004);
3180 rtl_writephy(tp, 0x1f, 0x0007);
3181 rtl_writephy(tp, 0x1e, 0x002d);
3182 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3183 rtl_writephy(tp, 0x1f, 0x0002);
3184 rtl_writephy(tp, 0x1f, 0x0000);
3185 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3186
3187 /* improve 10M EEE waveform */
3188 rtl_writephy(tp, 0x1f, 0x0005);
3189 rtl_writephy(tp, 0x05, 0x8b86);
3190 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3191 rtl_writephy(tp, 0x1f, 0x0000);
3192
3193 /* Improve 2-pair detection performance */
3194 rtl_writephy(tp, 0x1f, 0x0005);
3195 rtl_writephy(tp, 0x05, 0x8b85);
3196 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3197 rtl_writephy(tp, 0x1f, 0x0000);
3198
3199 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003200 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003201 rtl_writephy(tp, 0x1f, 0x0005);
3202 rtl_writephy(tp, 0x05, 0x8b85);
3203 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3204 rtl_writephy(tp, 0x1f, 0x0004);
3205 rtl_writephy(tp, 0x1f, 0x0007);
3206 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003207 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003208 rtl_writephy(tp, 0x1f, 0x0002);
3209 rtl_writephy(tp, 0x1f, 0x0000);
3210 rtl_writephy(tp, 0x0d, 0x0007);
3211 rtl_writephy(tp, 0x0e, 0x003c);
3212 rtl_writephy(tp, 0x0d, 0x4007);
3213 rtl_writephy(tp, 0x0e, 0x0000);
3214 rtl_writephy(tp, 0x0d, 0x0000);
3215
3216 /* Green feature */
3217 rtl_writephy(tp, 0x1f, 0x0003);
3218 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3219 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3220 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003221
3222 r8168_aldps_enable_1(tp);
françois romieu9ecb9aa2012-12-07 11:20:21 +00003223
3224 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3225 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003226}
3227
Hayes Wang5f886e02012-03-30 14:33:03 +08003228static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3229{
3230 /* For 4-corner performance improve */
3231 rtl_writephy(tp, 0x1f, 0x0005);
3232 rtl_writephy(tp, 0x05, 0x8b80);
3233 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3234 rtl_writephy(tp, 0x1f, 0x0000);
3235
3236 /* PHY auto speed down */
3237 rtl_writephy(tp, 0x1f, 0x0007);
3238 rtl_writephy(tp, 0x1e, 0x002d);
3239 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3240 rtl_writephy(tp, 0x1f, 0x0000);
3241 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3242
3243 /* Improve 10M EEE waveform */
3244 rtl_writephy(tp, 0x1f, 0x0005);
3245 rtl_writephy(tp, 0x05, 0x8b86);
3246 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3247 rtl_writephy(tp, 0x1f, 0x0000);
3248}
3249
Hayes Wangc2218922011-09-06 16:55:18 +08003250static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3251{
3252 static const struct phy_reg phy_reg_init[] = {
3253 /* Channel estimation fine tune */
3254 { 0x1f, 0x0003 },
3255 { 0x09, 0xa20f },
3256 { 0x1f, 0x0000 },
3257
3258 /* Modify green table for giga & fnet */
3259 { 0x1f, 0x0005 },
3260 { 0x05, 0x8b55 },
3261 { 0x06, 0x0000 },
3262 { 0x05, 0x8b5e },
3263 { 0x06, 0x0000 },
3264 { 0x05, 0x8b67 },
3265 { 0x06, 0x0000 },
3266 { 0x05, 0x8b70 },
3267 { 0x06, 0x0000 },
3268 { 0x1f, 0x0000 },
3269 { 0x1f, 0x0007 },
3270 { 0x1e, 0x0078 },
3271 { 0x17, 0x0000 },
3272 { 0x19, 0x00fb },
3273 { 0x1f, 0x0000 },
3274
3275 /* Modify green table for 10M */
3276 { 0x1f, 0x0005 },
3277 { 0x05, 0x8b79 },
3278 { 0x06, 0xaa00 },
3279 { 0x1f, 0x0000 },
3280
3281 /* Disable hiimpedance detection (RTCT) */
3282 { 0x1f, 0x0003 },
3283 { 0x01, 0x328a },
3284 { 0x1f, 0x0000 }
3285 };
3286
3287 rtl_apply_firmware(tp);
3288
3289 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3290
Hayes Wang5f886e02012-03-30 14:33:03 +08003291 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003292
3293 /* Improve 2-pair detection performance */
3294 rtl_writephy(tp, 0x1f, 0x0005);
3295 rtl_writephy(tp, 0x05, 0x8b85);
3296 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3297 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003298
3299 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003300}
3301
3302static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3303{
3304 rtl_apply_firmware(tp);
3305
Hayes Wang5f886e02012-03-30 14:33:03 +08003306 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003307
3308 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003309}
3310
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003311static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3312{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003313 static const struct phy_reg phy_reg_init[] = {
3314 /* Channel estimation fine tune */
3315 { 0x1f, 0x0003 },
3316 { 0x09, 0xa20f },
3317 { 0x1f, 0x0000 },
3318
3319 /* Modify green table for giga & fnet */
3320 { 0x1f, 0x0005 },
3321 { 0x05, 0x8b55 },
3322 { 0x06, 0x0000 },
3323 { 0x05, 0x8b5e },
3324 { 0x06, 0x0000 },
3325 { 0x05, 0x8b67 },
3326 { 0x06, 0x0000 },
3327 { 0x05, 0x8b70 },
3328 { 0x06, 0x0000 },
3329 { 0x1f, 0x0000 },
3330 { 0x1f, 0x0007 },
3331 { 0x1e, 0x0078 },
3332 { 0x17, 0x0000 },
3333 { 0x19, 0x00aa },
3334 { 0x1f, 0x0000 },
3335
3336 /* Modify green table for 10M */
3337 { 0x1f, 0x0005 },
3338 { 0x05, 0x8b79 },
3339 { 0x06, 0xaa00 },
3340 { 0x1f, 0x0000 },
3341
3342 /* Disable hiimpedance detection (RTCT) */
3343 { 0x1f, 0x0003 },
3344 { 0x01, 0x328a },
3345 { 0x1f, 0x0000 }
3346 };
3347
3348
3349 rtl_apply_firmware(tp);
3350
3351 rtl8168f_hw_phy_config(tp);
3352
3353 /* Improve 2-pair detection performance */
3354 rtl_writephy(tp, 0x1f, 0x0005);
3355 rtl_writephy(tp, 0x05, 0x8b85);
3356 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3357 rtl_writephy(tp, 0x1f, 0x0000);
3358
3359 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3360
3361 /* Modify green table for giga */
3362 rtl_writephy(tp, 0x1f, 0x0005);
3363 rtl_writephy(tp, 0x05, 0x8b54);
3364 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3365 rtl_writephy(tp, 0x05, 0x8b5d);
3366 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3367 rtl_writephy(tp, 0x05, 0x8a7c);
3368 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3369 rtl_writephy(tp, 0x05, 0x8a7f);
3370 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3371 rtl_writephy(tp, 0x05, 0x8a82);
3372 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3373 rtl_writephy(tp, 0x05, 0x8a85);
3374 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3375 rtl_writephy(tp, 0x05, 0x8a88);
3376 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3377 rtl_writephy(tp, 0x1f, 0x0000);
3378
3379 /* uc same-seed solution */
3380 rtl_writephy(tp, 0x1f, 0x0005);
3381 rtl_writephy(tp, 0x05, 0x8b85);
3382 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3383 rtl_writephy(tp, 0x1f, 0x0000);
3384
3385 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003386 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003387 rtl_writephy(tp, 0x1f, 0x0005);
3388 rtl_writephy(tp, 0x05, 0x8b85);
3389 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3390 rtl_writephy(tp, 0x1f, 0x0004);
3391 rtl_writephy(tp, 0x1f, 0x0007);
3392 rtl_writephy(tp, 0x1e, 0x0020);
3393 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3394 rtl_writephy(tp, 0x1f, 0x0000);
3395 rtl_writephy(tp, 0x0d, 0x0007);
3396 rtl_writephy(tp, 0x0e, 0x003c);
3397 rtl_writephy(tp, 0x0d, 0x4007);
3398 rtl_writephy(tp, 0x0e, 0x0000);
3399 rtl_writephy(tp, 0x0d, 0x0000);
3400
3401 /* Green feature */
3402 rtl_writephy(tp, 0x1f, 0x0003);
3403 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3404 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3405 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003406
3407 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003408}
3409
Hayes Wangc5583862012-07-02 17:23:22 +08003410static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3411{
3412 static const u16 mac_ocp_patch[] = {
3413 0xe008, 0xe01b, 0xe01d, 0xe01f,
3414 0xe021, 0xe023, 0xe025, 0xe027,
3415 0x49d2, 0xf10d, 0x766c, 0x49e2,
3416 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3417
3418 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3419 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3420 0xbe00, 0xb416, 0x0076, 0xe86c,
3421 0xc602, 0xbe00, 0x0000, 0xc602,
3422
3423 0xbe00, 0x0000, 0xc602, 0xbe00,
3424 0x0000, 0xc602, 0xbe00, 0x0000,
3425 0xc602, 0xbe00, 0x0000, 0xc602,
3426 0xbe00, 0x0000, 0xc602, 0xbe00,
3427
3428 0x0000, 0x0000, 0x0000, 0x0000
3429 };
3430 u32 i;
3431
3432 /* Patch code for GPHY reset */
3433 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3434 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3435 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3436 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3437
3438 rtl_apply_firmware(tp);
3439
3440 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3441 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3442 else
3443 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3444
3445 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3446 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3447 else
3448 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3449
3450 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3451 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3452
3453 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3454 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3455
3456 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3457}
3458
françois romieu4da19632011-01-03 15:07:55 +00003459static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003460{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003461 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003462 { 0x1f, 0x0003 },
3463 { 0x08, 0x441d },
3464 { 0x01, 0x9100 },
3465 { 0x1f, 0x0000 }
3466 };
3467
françois romieu4da19632011-01-03 15:07:55 +00003468 rtl_writephy(tp, 0x1f, 0x0000);
3469 rtl_patchphy(tp, 0x11, 1 << 12);
3470 rtl_patchphy(tp, 0x19, 1 << 13);
3471 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003472
françois romieu4da19632011-01-03 15:07:55 +00003473 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003474}
3475
Hayes Wang5a5e4442011-02-22 17:26:21 +08003476static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3477{
3478 static const struct phy_reg phy_reg_init[] = {
3479 { 0x1f, 0x0005 },
3480 { 0x1a, 0x0000 },
3481 { 0x1f, 0x0000 },
3482
3483 { 0x1f, 0x0004 },
3484 { 0x1c, 0x0000 },
3485 { 0x1f, 0x0000 },
3486
3487 { 0x1f, 0x0001 },
3488 { 0x15, 0x7701 },
3489 { 0x1f, 0x0000 }
3490 };
3491
3492 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003493 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003494
François Romieu953a12c2011-04-24 17:38:48 +02003495 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003496
3497 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003498
3499 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003500}
3501
Hayes Wang7e18dca2012-03-30 14:33:02 +08003502static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3503{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003504 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003505 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003506
3507 rtl_apply_firmware(tp);
3508
3509 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003510 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003511 rtl_writephy(tp, 0x1f, 0x0004);
3512 rtl_writephy(tp, 0x10, 0x401f);
3513 rtl_writephy(tp, 0x19, 0x7030);
3514 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003515
3516 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003517}
3518
Hayes Wang5598bfe2012-07-02 17:23:21 +08003519static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3520{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003521 static const struct phy_reg phy_reg_init[] = {
3522 { 0x1f, 0x0004 },
3523 { 0x10, 0xc07f },
3524 { 0x19, 0x7030 },
3525 { 0x1f, 0x0000 }
3526 };
3527
3528 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003529 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003530
3531 rtl_apply_firmware(tp);
3532
Francois Romieufdf6fc02012-07-06 22:40:38 +02003533 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003534 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3535
Francois Romieufdf6fc02012-07-06 22:40:38 +02003536 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003537
3538 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003539}
3540
Francois Romieu5615d9f2007-08-17 17:50:46 +02003541static void rtl_hw_phy_config(struct net_device *dev)
3542{
3543 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003544
3545 rtl8169_print_mac_version(tp);
3546
3547 switch (tp->mac_version) {
3548 case RTL_GIGA_MAC_VER_01:
3549 break;
3550 case RTL_GIGA_MAC_VER_02:
3551 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003552 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003553 break;
3554 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003555 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003556 break;
françois romieu2e9558562009-08-10 19:44:19 +00003557 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003558 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003559 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003560 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003561 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003562 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003563 case RTL_GIGA_MAC_VER_07:
3564 case RTL_GIGA_MAC_VER_08:
3565 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003566 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003567 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003568 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003569 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003570 break;
3571 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003572 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003573 break;
3574 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003575 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003576 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003577 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003578 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003579 break;
3580 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003581 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003582 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003583 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003584 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003585 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003586 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003587 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003588 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003589 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003590 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003591 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003592 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003593 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003594 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003595 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003596 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003597 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003598 break;
3599 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003600 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003601 break;
3602 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003603 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003604 break;
françois romieue6de30d2011-01-03 15:08:37 +00003605 case RTL_GIGA_MAC_VER_28:
3606 rtl8168d_4_hw_phy_config(tp);
3607 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003608 case RTL_GIGA_MAC_VER_29:
3609 case RTL_GIGA_MAC_VER_30:
3610 rtl8105e_hw_phy_config(tp);
3611 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003612 case RTL_GIGA_MAC_VER_31:
3613 /* None. */
3614 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003615 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003616 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003617 rtl8168e_1_hw_phy_config(tp);
3618 break;
3619 case RTL_GIGA_MAC_VER_34:
3620 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003621 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003622 case RTL_GIGA_MAC_VER_35:
3623 rtl8168f_1_hw_phy_config(tp);
3624 break;
3625 case RTL_GIGA_MAC_VER_36:
3626 rtl8168f_2_hw_phy_config(tp);
3627 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003628
Hayes Wang7e18dca2012-03-30 14:33:02 +08003629 case RTL_GIGA_MAC_VER_37:
3630 rtl8402_hw_phy_config(tp);
3631 break;
3632
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003633 case RTL_GIGA_MAC_VER_38:
3634 rtl8411_hw_phy_config(tp);
3635 break;
3636
Hayes Wang5598bfe2012-07-02 17:23:21 +08003637 case RTL_GIGA_MAC_VER_39:
3638 rtl8106e_hw_phy_config(tp);
3639 break;
3640
Hayes Wangc5583862012-07-02 17:23:22 +08003641 case RTL_GIGA_MAC_VER_40:
3642 rtl8168g_1_hw_phy_config(tp);
3643 break;
3644
3645 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003646 default:
3647 break;
3648 }
3649}
3650
Francois Romieuda78dbf2012-01-26 14:18:23 +01003651static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 struct timer_list *timer = &tp->timer;
3654 void __iomem *ioaddr = tp->mmio_addr;
3655 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3656
Francois Romieubcf0bf92006-07-26 23:14:13 +02003657 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
françois romieu4da19632011-01-03 15:07:55 +00003659 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003660 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 * A busy loop could burn quite a few cycles on nowadays CPU.
3662 * Let's delay the execution of the timer for a few ticks.
3663 */
3664 timeout = HZ/10;
3665 goto out_mod_timer;
3666 }
3667
3668 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003669 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Francois Romieuda78dbf2012-01-26 14:18:23 +01003671 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
françois romieu4da19632011-01-03 15:07:55 +00003673 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675out_mod_timer:
3676 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003677}
3678
3679static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3680{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003681 if (!test_and_set_bit(flag, tp->wk.flags))
3682 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003683}
3684
3685static void rtl8169_phy_timer(unsigned long __opaque)
3686{
3687 struct net_device *dev = (struct net_device *)__opaque;
3688 struct rtl8169_private *tp = netdev_priv(dev);
3689
Francois Romieu98ddf982012-01-31 10:47:34 +01003690 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691}
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3694 void __iomem *ioaddr)
3695{
3696 iounmap(ioaddr);
3697 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003698 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 pci_disable_device(pdev);
3700 free_netdev(dev);
3701}
3702
Francois Romieuffc46952012-07-06 14:19:23 +02003703DECLARE_RTL_COND(rtl_phy_reset_cond)
3704{
3705 return tp->phy_reset_pending(tp);
3706}
3707
Francois Romieubf793292006-11-01 00:53:05 +01003708static void rtl8169_phy_reset(struct net_device *dev,
3709 struct rtl8169_private *tp)
3710{
françois romieu4da19632011-01-03 15:07:55 +00003711 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003712 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003713}
3714
David S. Miller8decf862011-09-22 03:23:13 -04003715static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3716{
3717 void __iomem *ioaddr = tp->mmio_addr;
3718
3719 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3720 (RTL_R8(PHYstatus) & TBI_Enable);
3721}
3722
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003723static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003725 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003726
Francois Romieu5615d9f2007-08-17 17:50:46 +02003727 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003728
Marcus Sundberg773328942008-07-10 21:28:08 +02003729 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3730 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3731 RTL_W8(0x82, 0x01);
3732 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003733
Francois Romieu6dccd162007-02-13 23:38:05 +01003734 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3735
3736 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3737 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003738
Francois Romieubcf0bf92006-07-26 23:14:13 +02003739 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003740 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3741 RTL_W8(0x82, 0x01);
3742 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003743 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003744 }
3745
Francois Romieubf793292006-11-01 00:53:05 +01003746 rtl8169_phy_reset(dev, tp);
3747
Oliver Neukum54405cd2011-01-06 21:55:13 +01003748 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003749 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3750 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3751 (tp->mii.supports_gmii ?
3752 ADVERTISED_1000baseT_Half |
3753 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003754
David S. Miller8decf862011-09-22 03:23:13 -04003755 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003756 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003757}
3758
Francois Romieu773d2022007-01-31 23:47:43 +01003759static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3760{
3761 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003762
Francois Romieuda78dbf2012-01-26 14:18:23 +01003763 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003764
3765 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003766
françois romieu9ecb9aa2012-12-07 11:20:21 +00003767 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2b2010-04-26 11:42:58 +00003768 RTL_R32(MAC4);
3769
françois romieu9ecb9aa2012-12-07 11:20:21 +00003770 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2b2010-04-26 11:42:58 +00003771 RTL_R32(MAC0);
3772
françois romieu9ecb9aa2012-12-07 11:20:21 +00003773 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3774 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003775
Francois Romieu773d2022007-01-31 23:47:43 +01003776 RTL_W8(Cfg9346, Cfg9346_Lock);
3777
Francois Romieuda78dbf2012-01-26 14:18:23 +01003778 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003779}
3780
3781static int rtl_set_mac_address(struct net_device *dev, void *p)
3782{
3783 struct rtl8169_private *tp = netdev_priv(dev);
3784 struct sockaddr *addr = p;
3785
3786 if (!is_valid_ether_addr(addr->sa_data))
3787 return -EADDRNOTAVAIL;
3788
3789 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3790
3791 rtl_rar_set(tp, dev->dev_addr);
3792
3793 return 0;
3794}
3795
Francois Romieu5f787a12006-08-17 13:02:36 +02003796static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3797{
3798 struct rtl8169_private *tp = netdev_priv(dev);
3799 struct mii_ioctl_data *data = if_mii(ifr);
3800
Francois Romieu8b4ab282008-11-19 22:05:25 -08003801 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3802}
Francois Romieu5f787a12006-08-17 13:02:36 +02003803
Francois Romieucecb5fd2011-04-01 10:21:07 +02003804static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3805 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003806{
Francois Romieu5f787a12006-08-17 13:02:36 +02003807 switch (cmd) {
3808 case SIOCGMIIPHY:
3809 data->phy_id = 32; /* Internal PHY */
3810 return 0;
3811
3812 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003813 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003814 return 0;
3815
3816 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003817 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003818 return 0;
3819 }
3820 return -EOPNOTSUPP;
3821}
3822
Francois Romieu8b4ab282008-11-19 22:05:25 -08003823static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3824{
3825 return -EOPNOTSUPP;
3826}
3827
Francois Romieufbac58f2007-10-04 22:51:38 +02003828static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3829{
3830 if (tp->features & RTL_FEATURE_MSI) {
3831 pci_disable_msi(pdev);
3832 tp->features &= ~RTL_FEATURE_MSI;
3833 }
3834}
3835
Bill Pembertonbaf63292012-12-03 09:23:28 -05003836static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003837{
3838 struct mdio_ops *ops = &tp->mdio_ops;
3839
3840 switch (tp->mac_version) {
3841 case RTL_GIGA_MAC_VER_27:
3842 ops->write = r8168dp_1_mdio_write;
3843 ops->read = r8168dp_1_mdio_read;
3844 break;
françois romieue6de30d2011-01-03 15:08:37 +00003845 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003846 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003847 ops->write = r8168dp_2_mdio_write;
3848 ops->read = r8168dp_2_mdio_read;
3849 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003850 case RTL_GIGA_MAC_VER_40:
3851 case RTL_GIGA_MAC_VER_41:
3852 ops->write = r8168g_mdio_write;
3853 ops->read = r8168g_mdio_read;
3854 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003855 default:
3856 ops->write = r8169_mdio_write;
3857 ops->read = r8169_mdio_read;
3858 break;
3859 }
3860}
3861
David S. Miller1805b2f2011-10-24 18:18:09 -04003862static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3863{
3864 void __iomem *ioaddr = tp->mmio_addr;
3865
3866 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003867 case RTL_GIGA_MAC_VER_25:
3868 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003869 case RTL_GIGA_MAC_VER_29:
3870 case RTL_GIGA_MAC_VER_30:
3871 case RTL_GIGA_MAC_VER_32:
3872 case RTL_GIGA_MAC_VER_33:
3873 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003874 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003875 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003876 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003877 case RTL_GIGA_MAC_VER_40:
3878 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003879 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3880 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3881 break;
3882 default:
3883 break;
3884 }
3885}
3886
3887static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3888{
3889 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3890 return false;
3891
3892 rtl_writephy(tp, 0x1f, 0x0000);
3893 rtl_writephy(tp, MII_BMCR, 0x0000);
3894
3895 rtl_wol_suspend_quirk(tp);
3896
3897 return true;
3898}
3899
françois romieu065c27c2011-01-03 15:08:12 +00003900static void r810x_phy_power_down(struct rtl8169_private *tp)
3901{
3902 rtl_writephy(tp, 0x1f, 0x0000);
3903 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3904}
3905
3906static void r810x_phy_power_up(struct rtl8169_private *tp)
3907{
3908 rtl_writephy(tp, 0x1f, 0x0000);
3909 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3910}
3911
3912static void r810x_pll_power_down(struct rtl8169_private *tp)
3913{
Hayes Wang00042992012-03-30 14:33:00 +08003914 void __iomem *ioaddr = tp->mmio_addr;
3915
David S. Miller1805b2f2011-10-24 18:18:09 -04003916 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003917 return;
françois romieu065c27c2011-01-03 15:08:12 +00003918
3919 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003920
3921 switch (tp->mac_version) {
3922 case RTL_GIGA_MAC_VER_07:
3923 case RTL_GIGA_MAC_VER_08:
3924 case RTL_GIGA_MAC_VER_09:
3925 case RTL_GIGA_MAC_VER_10:
3926 case RTL_GIGA_MAC_VER_13:
3927 case RTL_GIGA_MAC_VER_16:
3928 break;
3929 default:
3930 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3931 break;
3932 }
françois romieu065c27c2011-01-03 15:08:12 +00003933}
3934
3935static void r810x_pll_power_up(struct rtl8169_private *tp)
3936{
Hayes Wang00042992012-03-30 14:33:00 +08003937 void __iomem *ioaddr = tp->mmio_addr;
3938
françois romieu065c27c2011-01-03 15:08:12 +00003939 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003940
3941 switch (tp->mac_version) {
3942 case RTL_GIGA_MAC_VER_07:
3943 case RTL_GIGA_MAC_VER_08:
3944 case RTL_GIGA_MAC_VER_09:
3945 case RTL_GIGA_MAC_VER_10:
3946 case RTL_GIGA_MAC_VER_13:
3947 case RTL_GIGA_MAC_VER_16:
3948 break;
3949 default:
3950 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3951 break;
3952 }
françois romieu065c27c2011-01-03 15:08:12 +00003953}
3954
3955static void r8168_phy_power_up(struct rtl8169_private *tp)
3956{
3957 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003958 switch (tp->mac_version) {
3959 case RTL_GIGA_MAC_VER_11:
3960 case RTL_GIGA_MAC_VER_12:
3961 case RTL_GIGA_MAC_VER_17:
3962 case RTL_GIGA_MAC_VER_18:
3963 case RTL_GIGA_MAC_VER_19:
3964 case RTL_GIGA_MAC_VER_20:
3965 case RTL_GIGA_MAC_VER_21:
3966 case RTL_GIGA_MAC_VER_22:
3967 case RTL_GIGA_MAC_VER_23:
3968 case RTL_GIGA_MAC_VER_24:
3969 case RTL_GIGA_MAC_VER_25:
3970 case RTL_GIGA_MAC_VER_26:
3971 case RTL_GIGA_MAC_VER_27:
3972 case RTL_GIGA_MAC_VER_28:
3973 case RTL_GIGA_MAC_VER_31:
3974 rtl_writephy(tp, 0x0e, 0x0000);
3975 break;
3976 default:
3977 break;
3978 }
françois romieu065c27c2011-01-03 15:08:12 +00003979 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3980}
3981
3982static void r8168_phy_power_down(struct rtl8169_private *tp)
3983{
3984 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003985 switch (tp->mac_version) {
3986 case RTL_GIGA_MAC_VER_32:
3987 case RTL_GIGA_MAC_VER_33:
3988 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3989 break;
3990
3991 case RTL_GIGA_MAC_VER_11:
3992 case RTL_GIGA_MAC_VER_12:
3993 case RTL_GIGA_MAC_VER_17:
3994 case RTL_GIGA_MAC_VER_18:
3995 case RTL_GIGA_MAC_VER_19:
3996 case RTL_GIGA_MAC_VER_20:
3997 case RTL_GIGA_MAC_VER_21:
3998 case RTL_GIGA_MAC_VER_22:
3999 case RTL_GIGA_MAC_VER_23:
4000 case RTL_GIGA_MAC_VER_24:
4001 case RTL_GIGA_MAC_VER_25:
4002 case RTL_GIGA_MAC_VER_26:
4003 case RTL_GIGA_MAC_VER_27:
4004 case RTL_GIGA_MAC_VER_28:
4005 case RTL_GIGA_MAC_VER_31:
4006 rtl_writephy(tp, 0x0e, 0x0200);
4007 default:
4008 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4009 break;
4010 }
françois romieu065c27c2011-01-03 15:08:12 +00004011}
4012
4013static void r8168_pll_power_down(struct rtl8169_private *tp)
4014{
4015 void __iomem *ioaddr = tp->mmio_addr;
4016
Francois Romieucecb5fd2011-04-01 10:21:07 +02004017 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4018 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4019 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004020 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004021 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004022 }
françois romieu065c27c2011-01-03 15:08:12 +00004023
Francois Romieucecb5fd2011-04-01 10:21:07 +02004024 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4025 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004026 (RTL_R16(CPlusCmd) & ASF)) {
4027 return;
4028 }
4029
hayeswang01dc7fe2011-03-21 01:50:28 +00004030 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4031 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004032 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004033
David S. Miller1805b2f2011-10-24 18:18:09 -04004034 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004035 return;
françois romieu065c27c2011-01-03 15:08:12 +00004036
4037 r8168_phy_power_down(tp);
4038
4039 switch (tp->mac_version) {
4040 case RTL_GIGA_MAC_VER_25:
4041 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004042 case RTL_GIGA_MAC_VER_27:
4043 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004044 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004045 case RTL_GIGA_MAC_VER_32:
4046 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004047 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4048 break;
4049 }
4050}
4051
4052static void r8168_pll_power_up(struct rtl8169_private *tp)
4053{
4054 void __iomem *ioaddr = tp->mmio_addr;
4055
françois romieu065c27c2011-01-03 15:08:12 +00004056 switch (tp->mac_version) {
4057 case RTL_GIGA_MAC_VER_25:
4058 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004059 case RTL_GIGA_MAC_VER_27:
4060 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004061 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004062 case RTL_GIGA_MAC_VER_32:
4063 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004064 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4065 break;
4066 }
4067
4068 r8168_phy_power_up(tp);
4069}
4070
Francois Romieud58d46b2011-05-03 16:38:29 +02004071static void rtl_generic_op(struct rtl8169_private *tp,
4072 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004073{
4074 if (op)
4075 op(tp);
4076}
4077
4078static void rtl_pll_power_down(struct rtl8169_private *tp)
4079{
Francois Romieud58d46b2011-05-03 16:38:29 +02004080 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004081}
4082
4083static void rtl_pll_power_up(struct rtl8169_private *tp)
4084{
Francois Romieud58d46b2011-05-03 16:38:29 +02004085 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004086}
4087
Bill Pembertonbaf63292012-12-03 09:23:28 -05004088static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004089{
4090 struct pll_power_ops *ops = &tp->pll_power_ops;
4091
4092 switch (tp->mac_version) {
4093 case RTL_GIGA_MAC_VER_07:
4094 case RTL_GIGA_MAC_VER_08:
4095 case RTL_GIGA_MAC_VER_09:
4096 case RTL_GIGA_MAC_VER_10:
4097 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004098 case RTL_GIGA_MAC_VER_29:
4099 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004100 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004101 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004102 ops->down = r810x_pll_power_down;
4103 ops->up = r810x_pll_power_up;
4104 break;
4105
4106 case RTL_GIGA_MAC_VER_11:
4107 case RTL_GIGA_MAC_VER_12:
4108 case RTL_GIGA_MAC_VER_17:
4109 case RTL_GIGA_MAC_VER_18:
4110 case RTL_GIGA_MAC_VER_19:
4111 case RTL_GIGA_MAC_VER_20:
4112 case RTL_GIGA_MAC_VER_21:
4113 case RTL_GIGA_MAC_VER_22:
4114 case RTL_GIGA_MAC_VER_23:
4115 case RTL_GIGA_MAC_VER_24:
4116 case RTL_GIGA_MAC_VER_25:
4117 case RTL_GIGA_MAC_VER_26:
4118 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004119 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004120 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004121 case RTL_GIGA_MAC_VER_32:
4122 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004123 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004124 case RTL_GIGA_MAC_VER_35:
4125 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004126 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004127 case RTL_GIGA_MAC_VER_40:
4128 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004129 ops->down = r8168_pll_power_down;
4130 ops->up = r8168_pll_power_up;
4131 break;
4132
4133 default:
4134 ops->down = NULL;
4135 ops->up = NULL;
4136 break;
4137 }
4138}
4139
Hayes Wange542a222011-07-06 15:58:04 +08004140static void rtl_init_rxcfg(struct rtl8169_private *tp)
4141{
4142 void __iomem *ioaddr = tp->mmio_addr;
4143
4144 switch (tp->mac_version) {
4145 case RTL_GIGA_MAC_VER_01:
4146 case RTL_GIGA_MAC_VER_02:
4147 case RTL_GIGA_MAC_VER_03:
4148 case RTL_GIGA_MAC_VER_04:
4149 case RTL_GIGA_MAC_VER_05:
4150 case RTL_GIGA_MAC_VER_06:
4151 case RTL_GIGA_MAC_VER_10:
4152 case RTL_GIGA_MAC_VER_11:
4153 case RTL_GIGA_MAC_VER_12:
4154 case RTL_GIGA_MAC_VER_13:
4155 case RTL_GIGA_MAC_VER_14:
4156 case RTL_GIGA_MAC_VER_15:
4157 case RTL_GIGA_MAC_VER_16:
4158 case RTL_GIGA_MAC_VER_17:
4159 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4160 break;
4161 case RTL_GIGA_MAC_VER_18:
4162 case RTL_GIGA_MAC_VER_19:
4163 case RTL_GIGA_MAC_VER_20:
4164 case RTL_GIGA_MAC_VER_21:
4165 case RTL_GIGA_MAC_VER_22:
4166 case RTL_GIGA_MAC_VER_23:
4167 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004168 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004169 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4170 break;
4171 default:
4172 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4173 break;
4174 }
4175}
4176
Hayes Wang92fc43b2011-07-06 15:58:03 +08004177static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4178{
Timo Teräs9fba0812013-01-15 21:01:24 +00004179 tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004180}
4181
Francois Romieud58d46b2011-05-03 16:38:29 +02004182static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4183{
françois romieu9c5028e2012-03-02 04:43:14 +00004184 void __iomem *ioaddr = tp->mmio_addr;
4185
4186 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004187 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004188 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004189}
4190
4191static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4192{
françois romieu9c5028e2012-03-02 04:43:14 +00004193 void __iomem *ioaddr = tp->mmio_addr;
4194
4195 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004196 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004197 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004198}
4199
4200static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4201{
4202 void __iomem *ioaddr = tp->mmio_addr;
4203
4204 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4205 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4206 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4207}
4208
4209static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4210{
4211 void __iomem *ioaddr = tp->mmio_addr;
4212
4213 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4214 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4215 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4216}
4217
4218static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4219{
4220 void __iomem *ioaddr = tp->mmio_addr;
4221
4222 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4223}
4224
4225static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4226{
4227 void __iomem *ioaddr = tp->mmio_addr;
4228
4229 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4230}
4231
4232static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4233{
4234 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004235
4236 RTL_W8(MaxTxPacketSize, 0x3f);
4237 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4238 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004239 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004240}
4241
4242static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4243{
4244 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004245
4246 RTL_W8(MaxTxPacketSize, 0x0c);
4247 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4248 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004249 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004250}
4251
4252static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4253{
4254 rtl_tx_performance_tweak(tp->pci_dev,
4255 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4256}
4257
4258static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4259{
4260 rtl_tx_performance_tweak(tp->pci_dev,
4261 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4262}
4263
4264static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4265{
4266 void __iomem *ioaddr = tp->mmio_addr;
4267
4268 r8168b_0_hw_jumbo_enable(tp);
4269
4270 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4271}
4272
4273static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4274{
4275 void __iomem *ioaddr = tp->mmio_addr;
4276
4277 r8168b_0_hw_jumbo_disable(tp);
4278
4279 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4280}
4281
Bill Pembertonbaf63292012-12-03 09:23:28 -05004282static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004283{
4284 struct jumbo_ops *ops = &tp->jumbo_ops;
4285
4286 switch (tp->mac_version) {
4287 case RTL_GIGA_MAC_VER_11:
4288 ops->disable = r8168b_0_hw_jumbo_disable;
4289 ops->enable = r8168b_0_hw_jumbo_enable;
4290 break;
4291 case RTL_GIGA_MAC_VER_12:
4292 case RTL_GIGA_MAC_VER_17:
4293 ops->disable = r8168b_1_hw_jumbo_disable;
4294 ops->enable = r8168b_1_hw_jumbo_enable;
4295 break;
4296 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4297 case RTL_GIGA_MAC_VER_19:
4298 case RTL_GIGA_MAC_VER_20:
4299 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4300 case RTL_GIGA_MAC_VER_22:
4301 case RTL_GIGA_MAC_VER_23:
4302 case RTL_GIGA_MAC_VER_24:
4303 case RTL_GIGA_MAC_VER_25:
4304 case RTL_GIGA_MAC_VER_26:
4305 ops->disable = r8168c_hw_jumbo_disable;
4306 ops->enable = r8168c_hw_jumbo_enable;
4307 break;
4308 case RTL_GIGA_MAC_VER_27:
4309 case RTL_GIGA_MAC_VER_28:
4310 ops->disable = r8168dp_hw_jumbo_disable;
4311 ops->enable = r8168dp_hw_jumbo_enable;
4312 break;
4313 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4314 case RTL_GIGA_MAC_VER_32:
4315 case RTL_GIGA_MAC_VER_33:
4316 case RTL_GIGA_MAC_VER_34:
4317 ops->disable = r8168e_hw_jumbo_disable;
4318 ops->enable = r8168e_hw_jumbo_enable;
4319 break;
4320
4321 /*
4322 * No action needed for jumbo frames with 8169.
4323 * No jumbo for 810x at all.
4324 */
Hayes Wangc5583862012-07-02 17:23:22 +08004325 case RTL_GIGA_MAC_VER_40:
4326 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004327 default:
4328 ops->disable = NULL;
4329 ops->enable = NULL;
4330 break;
4331 }
4332}
4333
Francois Romieuffc46952012-07-06 14:19:23 +02004334DECLARE_RTL_COND(rtl_chipcmd_cond)
4335{
4336 void __iomem *ioaddr = tp->mmio_addr;
4337
4338 return RTL_R8(ChipCmd) & CmdReset;
4339}
4340
Francois Romieu6f43adc2011-04-29 15:05:51 +02004341static void rtl_hw_reset(struct rtl8169_private *tp)
4342{
4343 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004344
Francois Romieu6f43adc2011-04-29 15:05:51 +02004345 RTL_W8(ChipCmd, CmdReset);
4346
Francois Romieuffc46952012-07-06 14:19:23 +02004347 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004348}
4349
Francois Romieub6ffd972011-06-17 17:00:05 +02004350static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4351{
4352 struct rtl_fw *rtl_fw;
4353 const char *name;
4354 int rc = -ENOMEM;
4355
4356 name = rtl_lookup_firmware_name(tp);
4357 if (!name)
4358 goto out_no_firmware;
4359
4360 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4361 if (!rtl_fw)
4362 goto err_warn;
4363
4364 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4365 if (rc < 0)
4366 goto err_free;
4367
Francois Romieufd112f22011-06-18 00:10:29 +02004368 rc = rtl_check_firmware(tp, rtl_fw);
4369 if (rc < 0)
4370 goto err_release_firmware;
4371
Francois Romieub6ffd972011-06-17 17:00:05 +02004372 tp->rtl_fw = rtl_fw;
4373out:
4374 return;
4375
Francois Romieufd112f22011-06-18 00:10:29 +02004376err_release_firmware:
4377 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004378err_free:
4379 kfree(rtl_fw);
4380err_warn:
4381 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4382 name, rc);
4383out_no_firmware:
4384 tp->rtl_fw = NULL;
4385 goto out;
4386}
4387
François Romieu953a12c2011-04-24 17:38:48 +02004388static void rtl_request_firmware(struct rtl8169_private *tp)
4389{
Francois Romieub6ffd972011-06-17 17:00:05 +02004390 if (IS_ERR(tp->rtl_fw))
4391 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004392}
4393
Hayes Wang92fc43b2011-07-06 15:58:03 +08004394static void rtl_rx_close(struct rtl8169_private *tp)
4395{
4396 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004397
Francois Romieu1687b562011-07-19 17:21:29 +02004398 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004399}
4400
Francois Romieuffc46952012-07-06 14:19:23 +02004401DECLARE_RTL_COND(rtl_npq_cond)
4402{
4403 void __iomem *ioaddr = tp->mmio_addr;
4404
4405 return RTL_R8(TxPoll) & NPQ;
4406}
4407
4408DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4409{
4410 void __iomem *ioaddr = tp->mmio_addr;
4411
4412 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4413}
4414
françois romieue6de30d2011-01-03 15:08:37 +00004415static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416{
françois romieue6de30d2011-01-03 15:08:37 +00004417 void __iomem *ioaddr = tp->mmio_addr;
4418
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004420 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Hayes Wang92fc43b2011-07-06 15:58:03 +08004422 rtl_rx_close(tp);
4423
Hayes Wang5d2e1952011-02-22 17:26:22 +08004424 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004425 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4426 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004427 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004428 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4429 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004430 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004431 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004432 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4433 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004434 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004435 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004436 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004437 } else {
4438 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4439 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004440 }
4441
Hayes Wang92fc43b2011-07-06 15:58:03 +08004442 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443}
4444
Francois Romieu7f796d832007-06-11 23:04:41 +02004445static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004446{
4447 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004448
4449 /* Set DMA burst size and Interframe Gap Time */
4450 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4451 (InterFrameGap << TxInterFrameGapShift));
4452}
4453
Francois Romieu07ce4062007-02-23 23:36:39 +01004454static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455{
4456 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Francois Romieu07ce4062007-02-23 23:36:39 +01004458 tp->hw_start(dev);
4459
Francois Romieuda78dbf2012-01-26 14:18:23 +01004460 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004461}
4462
Francois Romieu7f796d832007-06-11 23:04:41 +02004463static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4464 void __iomem *ioaddr)
4465{
4466 /*
4467 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4468 * register to be written before TxDescAddrLow to work.
4469 * Switching from MMIO to I/O access fixes the issue as well.
4470 */
4471 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004472 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004473 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004474 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004475}
4476
4477static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4478{
4479 u16 cmd;
4480
4481 cmd = RTL_R16(CPlusCmd);
4482 RTL_W16(CPlusCmd, cmd);
4483 return cmd;
4484}
4485
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004486static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004487{
4488 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004489 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004490}
4491
Francois Romieu6dccd162007-02-13 23:38:05 +01004492static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4493{
Francois Romieu37441002011-06-17 22:58:54 +02004494 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004495 u32 mac_version;
4496 u32 clk;
4497 u32 val;
4498 } cfg2_info [] = {
4499 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4500 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4501 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4502 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004503 };
4504 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004505 unsigned int i;
4506 u32 clk;
4507
4508 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004509 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004510 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4511 RTL_W32(0x7c, p->val);
4512 break;
4513 }
4514 }
4515}
4516
Francois Romieue6b763e2012-03-08 09:35:39 +01004517static void rtl_set_rx_mode(struct net_device *dev)
4518{
4519 struct rtl8169_private *tp = netdev_priv(dev);
4520 void __iomem *ioaddr = tp->mmio_addr;
4521 u32 mc_filter[2]; /* Multicast hash filter */
4522 int rx_mode;
4523 u32 tmp = 0;
4524
4525 if (dev->flags & IFF_PROMISC) {
4526 /* Unconditionally log net taps. */
4527 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4528 rx_mode =
4529 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4530 AcceptAllPhys;
4531 mc_filter[1] = mc_filter[0] = 0xffffffff;
4532 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4533 (dev->flags & IFF_ALLMULTI)) {
4534 /* Too many to filter perfectly -- accept all multicasts. */
4535 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4536 mc_filter[1] = mc_filter[0] = 0xffffffff;
4537 } else {
4538 struct netdev_hw_addr *ha;
4539
4540 rx_mode = AcceptBroadcast | AcceptMyPhys;
4541 mc_filter[1] = mc_filter[0] = 0;
4542 netdev_for_each_mc_addr(ha, dev) {
4543 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4544 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4545 rx_mode |= AcceptMulticast;
4546 }
4547 }
4548
4549 if (dev->features & NETIF_F_RXALL)
4550 rx_mode |= (AcceptErr | AcceptRunt);
4551
4552 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4553
4554 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4555 u32 data = mc_filter[0];
4556
4557 mc_filter[0] = swab32(mc_filter[1]);
4558 mc_filter[1] = swab32(data);
4559 }
4560
Nathan Walp04817762012-11-01 12:08:47 +00004561 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4562 mc_filter[1] = mc_filter[0] = 0xffffffff;
4563
Francois Romieue6b763e2012-03-08 09:35:39 +01004564 RTL_W32(MAR0 + 4, mc_filter[1]);
4565 RTL_W32(MAR0 + 0, mc_filter[0]);
4566
4567 RTL_W32(RxConfig, tmp);
4568}
4569
Francois Romieu07ce4062007-02-23 23:36:39 +01004570static void rtl_hw_start_8169(struct net_device *dev)
4571{
4572 struct rtl8169_private *tp = netdev_priv(dev);
4573 void __iomem *ioaddr = tp->mmio_addr;
4574 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004575
Francois Romieu9cb427b2006-11-02 00:10:16 +01004576 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4577 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4578 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4579 }
4580
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004582 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4583 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4584 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4585 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004586 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4587
Hayes Wange542a222011-07-06 15:58:04 +08004588 rtl_init_rxcfg(tp);
4589
françois romieuf0298f82011-01-03 15:07:42 +00004590 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004592 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593
Francois Romieucecb5fd2011-04-01 10:21:07 +02004594 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4595 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4596 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4597 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004598 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599
Francois Romieu7f796d832007-06-11 23:04:41 +02004600 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004601
Francois Romieucecb5fd2011-04-01 10:21:07 +02004602 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4603 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004604 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004606 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607 }
4608
Francois Romieubcf0bf92006-07-26 23:14:13 +02004609 RTL_W16(CPlusCmd, tp->cp_cmd);
4610
Francois Romieu6dccd162007-02-13 23:38:05 +01004611 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4612
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 /*
4614 * Undocumented corner. Supposedly:
4615 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4616 */
4617 RTL_W16(IntrMitigate, 0x0000);
4618
Francois Romieu7f796d832007-06-11 23:04:41 +02004619 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004620
Francois Romieucecb5fd2011-04-01 10:21:07 +02004621 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4622 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4623 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4624 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004625 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4626 rtl_set_rx_tx_config_registers(tp);
4627 }
4628
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004630
4631 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4632 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
4634 RTL_W32(RxMissed, 0);
4635
Francois Romieu07ce4062007-02-23 23:36:39 +01004636 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637
4638 /* no early-rx interrupts */
4639 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004640}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004642static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4643{
4644 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004645 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004646}
4647
4648static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4649{
Francois Romieu52989f02012-07-06 13:37:00 +02004650 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004651}
4652
4653static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004654{
4655 u32 csi;
4656
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004657 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4658 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004659}
4660
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004661static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004662{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004663 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004664}
4665
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004666static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004667{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004668 rtl_csi_access_enable(tp, 0x27000000);
4669}
4670
Francois Romieuffc46952012-07-06 14:19:23 +02004671DECLARE_RTL_COND(rtl_csiar_cond)
4672{
4673 void __iomem *ioaddr = tp->mmio_addr;
4674
4675 return RTL_R32(CSIAR) & CSIAR_FLAG;
4676}
4677
Francois Romieu52989f02012-07-06 13:37:00 +02004678static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004679{
Francois Romieu52989f02012-07-06 13:37:00 +02004680 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004681
4682 RTL_W32(CSIDR, value);
4683 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4684 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4685
Francois Romieuffc46952012-07-06 14:19:23 +02004686 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004687}
4688
Francois Romieu52989f02012-07-06 13:37:00 +02004689static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004690{
Francois Romieu52989f02012-07-06 13:37:00 +02004691 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004692
4693 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4694 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4695
Francois Romieuffc46952012-07-06 14:19:23 +02004696 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4697 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004698}
4699
Francois Romieu52989f02012-07-06 13:37:00 +02004700static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004701{
Francois Romieu52989f02012-07-06 13:37:00 +02004702 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004703
4704 RTL_W32(CSIDR, value);
4705 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4706 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4707 CSIAR_FUNC_NIC);
4708
Francois Romieuffc46952012-07-06 14:19:23 +02004709 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004710}
4711
Francois Romieu52989f02012-07-06 13:37:00 +02004712static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004713{
Francois Romieu52989f02012-07-06 13:37:00 +02004714 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004715
4716 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4717 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4718
Francois Romieuffc46952012-07-06 14:19:23 +02004719 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4720 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004721}
4722
Bill Pembertonbaf63292012-12-03 09:23:28 -05004723static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004724{
4725 struct csi_ops *ops = &tp->csi_ops;
4726
4727 switch (tp->mac_version) {
4728 case RTL_GIGA_MAC_VER_01:
4729 case RTL_GIGA_MAC_VER_02:
4730 case RTL_GIGA_MAC_VER_03:
4731 case RTL_GIGA_MAC_VER_04:
4732 case RTL_GIGA_MAC_VER_05:
4733 case RTL_GIGA_MAC_VER_06:
4734 case RTL_GIGA_MAC_VER_10:
4735 case RTL_GIGA_MAC_VER_11:
4736 case RTL_GIGA_MAC_VER_12:
4737 case RTL_GIGA_MAC_VER_13:
4738 case RTL_GIGA_MAC_VER_14:
4739 case RTL_GIGA_MAC_VER_15:
4740 case RTL_GIGA_MAC_VER_16:
4741 case RTL_GIGA_MAC_VER_17:
4742 ops->write = NULL;
4743 ops->read = NULL;
4744 break;
4745
Hayes Wang7e18dca2012-03-30 14:33:02 +08004746 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004747 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004748 ops->write = r8402_csi_write;
4749 ops->read = r8402_csi_read;
4750 break;
4751
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004752 default:
4753 ops->write = r8169_csi_write;
4754 ops->read = r8169_csi_read;
4755 break;
4756 }
Francois Romieudacf8152008-08-02 20:44:13 +02004757}
4758
4759struct ephy_info {
4760 unsigned int offset;
4761 u16 mask;
4762 u16 bits;
4763};
4764
Francois Romieufdf6fc02012-07-06 22:40:38 +02004765static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4766 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004767{
4768 u16 w;
4769
4770 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004771 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4772 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004773 e++;
4774 }
4775}
4776
Francois Romieub726e492008-06-28 12:22:59 +02004777static void rtl_disable_clock_request(struct pci_dev *pdev)
4778{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004779 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4780 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004781}
4782
françois romieue6de30d2011-01-03 15:08:37 +00004783static void rtl_enable_clock_request(struct pci_dev *pdev)
4784{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004785 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4786 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004787}
4788
Francois Romieub726e492008-06-28 12:22:59 +02004789#define R8168_CPCMD_QUIRK_MASK (\
4790 EnableBist | \
4791 Mac_dbgo_oe | \
4792 Force_half_dup | \
4793 Force_rxflow_en | \
4794 Force_txflow_en | \
4795 Cxpl_dbg_sel | \
4796 ASF | \
4797 PktCntrDisable | \
4798 Mac_dbgo_sel)
4799
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004800static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004801{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004802 void __iomem *ioaddr = tp->mmio_addr;
4803 struct pci_dev *pdev = tp->pci_dev;
4804
Francois Romieub726e492008-06-28 12:22:59 +02004805 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4806
4807 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4808
Francois Romieu2e68ae42008-06-28 12:00:55 +02004809 rtl_tx_performance_tweak(pdev,
4810 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004811}
4812
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004813static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004814{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004815 void __iomem *ioaddr = tp->mmio_addr;
4816
4817 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004818
françois romieuf0298f82011-01-03 15:07:42 +00004819 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004820
4821 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004822}
4823
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004824static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004825{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004826 void __iomem *ioaddr = tp->mmio_addr;
4827 struct pci_dev *pdev = tp->pci_dev;
4828
Francois Romieub726e492008-06-28 12:22:59 +02004829 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4830
4831 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4832
Francois Romieu219a1e92008-06-28 11:58:39 +02004833 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004834
4835 rtl_disable_clock_request(pdev);
4836
4837 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004838}
4839
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004840static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004841{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004842 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004843 { 0x01, 0, 0x0001 },
4844 { 0x02, 0x0800, 0x1000 },
4845 { 0x03, 0, 0x0042 },
4846 { 0x06, 0x0080, 0x0000 },
4847 { 0x07, 0, 0x2000 }
4848 };
4849
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004850 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004851
Francois Romieufdf6fc02012-07-06 22:40:38 +02004852 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004853
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004854 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004855}
4856
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004857static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004858{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004859 void __iomem *ioaddr = tp->mmio_addr;
4860 struct pci_dev *pdev = tp->pci_dev;
4861
4862 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004863
4864 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4865
4866 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4867
4868 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4869}
4870
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004871static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004872{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004873 void __iomem *ioaddr = tp->mmio_addr;
4874 struct pci_dev *pdev = tp->pci_dev;
4875
4876 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004877
4878 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4879
4880 /* Magic. */
4881 RTL_W8(DBG_REG, 0x20);
4882
françois romieuf0298f82011-01-03 15:07:42 +00004883 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004884
4885 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4886
4887 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4888}
4889
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004890static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004891{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004892 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004893 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004894 { 0x02, 0x0800, 0x1000 },
4895 { 0x03, 0, 0x0002 },
4896 { 0x06, 0x0080, 0x0000 }
4897 };
4898
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004899 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004900
4901 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4902
Francois Romieufdf6fc02012-07-06 22:40:38 +02004903 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004904
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004905 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004906}
4907
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004908static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004909{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004910 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004911 { 0x01, 0, 0x0001 },
4912 { 0x03, 0x0400, 0x0220 }
4913 };
4914
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004915 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004916
Francois Romieufdf6fc02012-07-06 22:40:38 +02004917 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004918
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004919 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004920}
4921
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004922static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004923{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004924 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004925}
4926
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004927static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004928{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004929 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004930
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004931 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004932}
4933
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004934static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004935{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004936 void __iomem *ioaddr = tp->mmio_addr;
4937 struct pci_dev *pdev = tp->pci_dev;
4938
4939 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004940
4941 rtl_disable_clock_request(pdev);
4942
françois romieuf0298f82011-01-03 15:07:42 +00004943 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004944
4945 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4946
4947 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4948}
4949
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004950static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004951{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004952 void __iomem *ioaddr = tp->mmio_addr;
4953 struct pci_dev *pdev = tp->pci_dev;
4954
4955 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004956
4957 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4958
4959 RTL_W8(MaxTxPacketSize, TxPacketMax);
4960
4961 rtl_disable_clock_request(pdev);
4962}
4963
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004964static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004965{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004966 void __iomem *ioaddr = tp->mmio_addr;
4967 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004968 static const struct ephy_info e_info_8168d_4[] = {
4969 { 0x0b, ~0, 0x48 },
4970 { 0x19, 0x20, 0x50 },
4971 { 0x0c, ~0, 0x20 }
4972 };
4973 int i;
4974
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004975 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004976
4977 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4978
4979 RTL_W8(MaxTxPacketSize, TxPacketMax);
4980
4981 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4982 const struct ephy_info *e = e_info_8168d_4 + i;
4983 u16 w;
4984
Francois Romieufdf6fc02012-07-06 22:40:38 +02004985 w = rtl_ephy_read(tp, e->offset);
4986 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004987 }
4988
4989 rtl_enable_clock_request(pdev);
4990}
4991
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004992static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004993{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004994 void __iomem *ioaddr = tp->mmio_addr;
4995 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004996 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004997 { 0x00, 0x0200, 0x0100 },
4998 { 0x00, 0x0000, 0x0004 },
4999 { 0x06, 0x0002, 0x0001 },
5000 { 0x06, 0x0000, 0x0030 },
5001 { 0x07, 0x0000, 0x2000 },
5002 { 0x00, 0x0000, 0x0020 },
5003 { 0x03, 0x5800, 0x2000 },
5004 { 0x03, 0x0000, 0x0001 },
5005 { 0x01, 0x0800, 0x1000 },
5006 { 0x07, 0x0000, 0x4000 },
5007 { 0x1e, 0x0000, 0x2000 },
5008 { 0x19, 0xffff, 0xfe6c },
5009 { 0x0a, 0x0000, 0x0040 }
5010 };
5011
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005012 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005013
Francois Romieufdf6fc02012-07-06 22:40:38 +02005014 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005015
5016 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5017
5018 RTL_W8(MaxTxPacketSize, TxPacketMax);
5019
5020 rtl_disable_clock_request(pdev);
5021
5022 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005023 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5024 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005025
Francois Romieucecb5fd2011-04-01 10:21:07 +02005026 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005027}
5028
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005029static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005030{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005031 void __iomem *ioaddr = tp->mmio_addr;
5032 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005033 static const struct ephy_info e_info_8168e_2[] = {
5034 { 0x09, 0x0000, 0x0080 },
5035 { 0x19, 0x0000, 0x0224 }
5036 };
5037
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005038 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005039
Francois Romieufdf6fc02012-07-06 22:40:38 +02005040 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005041
5042 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5043
Francois Romieufdf6fc02012-07-06 22:40:38 +02005044 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5045 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5046 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5047 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5048 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5049 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5050 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5051 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005052
Hayes Wang3090bd92011-09-06 16:55:15 +08005053 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005054
Hayes Wang70090422011-07-06 15:58:06 +08005055 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5056 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5057
5058 /* Adjust EEE LED frequency */
5059 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5060
5061 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5062 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005063 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5064 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005065}
5066
Hayes Wang5f886e02012-03-30 14:33:03 +08005067static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005068{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005069 void __iomem *ioaddr = tp->mmio_addr;
5070 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005071
Hayes Wang5f886e02012-03-30 14:33:03 +08005072 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005073
5074 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5075
Francois Romieufdf6fc02012-07-06 22:40:38 +02005076 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5077 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5078 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5079 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5080 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5081 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5082 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5083 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5084 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5085 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005086
5087 RTL_W8(MaxTxPacketSize, EarlySize);
5088
Hayes Wangc2218922011-09-06 16:55:18 +08005089 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5090 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005091 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005092 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5093 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5094 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005095}
5096
Hayes Wang5f886e02012-03-30 14:33:03 +08005097static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5098{
5099 void __iomem *ioaddr = tp->mmio_addr;
5100 static const struct ephy_info e_info_8168f_1[] = {
5101 { 0x06, 0x00c0, 0x0020 },
5102 { 0x08, 0x0001, 0x0002 },
5103 { 0x09, 0x0000, 0x0080 },
5104 { 0x19, 0x0000, 0x0224 }
5105 };
5106
5107 rtl_hw_start_8168f(tp);
5108
Francois Romieufdf6fc02012-07-06 22:40:38 +02005109 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005110
Francois Romieufdf6fc02012-07-06 22:40:38 +02005111 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005112
5113 /* Adjust EEE LED frequency */
5114 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5115}
5116
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005117static void rtl_hw_start_8411(struct rtl8169_private *tp)
5118{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005119 static const struct ephy_info e_info_8168f_1[] = {
5120 { 0x06, 0x00c0, 0x0020 },
5121 { 0x0f, 0xffff, 0x5200 },
5122 { 0x1e, 0x0000, 0x4000 },
5123 { 0x19, 0x0000, 0x0224 }
5124 };
5125
5126 rtl_hw_start_8168f(tp);
5127
Francois Romieufdf6fc02012-07-06 22:40:38 +02005128 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005129
Francois Romieufdf6fc02012-07-06 22:40:38 +02005130 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005131}
5132
Hayes Wangc5583862012-07-02 17:23:22 +08005133static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5134{
5135 void __iomem *ioaddr = tp->mmio_addr;
5136 struct pci_dev *pdev = tp->pci_dev;
5137
5138 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5139 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5140 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5141 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5142
5143 rtl_csi_access_enable_1(tp);
5144
5145 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5146
5147 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5148 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5149
5150 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005151 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005152 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005153 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5154 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005155
5156 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5157 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5158
5159 /* Adjust EEE LED frequency */
5160 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5161
5162 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5163}
5164
Francois Romieu07ce4062007-02-23 23:36:39 +01005165static void rtl_hw_start_8168(struct net_device *dev)
5166{
Francois Romieu2dd99532007-06-11 23:22:52 +02005167 struct rtl8169_private *tp = netdev_priv(dev);
5168 void __iomem *ioaddr = tp->mmio_addr;
5169
5170 RTL_W8(Cfg9346, Cfg9346_Unlock);
5171
françois romieuf0298f82011-01-03 15:07:42 +00005172 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005173
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005174 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005175
Francois Romieu0e485152007-02-20 00:00:26 +01005176 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005177
5178 RTL_W16(CPlusCmd, tp->cp_cmd);
5179
Francois Romieu0e485152007-02-20 00:00:26 +01005180 RTL_W16(IntrMitigate, 0x5151);
5181
5182 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005183 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005184 tp->event_slow |= RxFIFOOver | PCSTimeout;
5185 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005186 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005187
5188 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5189
Francois Romieub8363902008-06-01 12:31:57 +02005190 rtl_set_rx_mode(dev);
5191
5192 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5193 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005194
5195 RTL_R8(IntrMask);
5196
Francois Romieu219a1e92008-06-28 11:58:39 +02005197 switch (tp->mac_version) {
5198 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005199 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005200 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005201
5202 case RTL_GIGA_MAC_VER_12:
5203 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005204 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005205 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005206
5207 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005208 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005209 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005210
5211 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005212 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005213 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005214
5215 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005216 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005217 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005218
Francois Romieu197ff762008-06-28 13:16:02 +02005219 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005220 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005221 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005222
Francois Romieu6fb07052008-06-29 11:54:28 +02005223 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005224 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005225 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005226
Francois Romieuef3386f2008-06-29 12:24:30 +02005227 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005228 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005229 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005230
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005231 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005232 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005233 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005234
Francois Romieu5b538df2008-07-20 16:22:45 +02005235 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005236 case RTL_GIGA_MAC_VER_26:
5237 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005238 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005239 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005240
françois romieue6de30d2011-01-03 15:08:37 +00005241 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005242 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005243 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005244
hayeswang4804b3b2011-03-21 01:50:29 +00005245 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005246 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005247 break;
5248
hayeswang01dc7fe2011-03-21 01:50:28 +00005249 case RTL_GIGA_MAC_VER_32:
5250 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005251 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005252 break;
5253 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005254 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005255 break;
françois romieue6de30d2011-01-03 15:08:37 +00005256
Hayes Wangc2218922011-09-06 16:55:18 +08005257 case RTL_GIGA_MAC_VER_35:
5258 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005259 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005260 break;
5261
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005262 case RTL_GIGA_MAC_VER_38:
5263 rtl_hw_start_8411(tp);
5264 break;
5265
Hayes Wangc5583862012-07-02 17:23:22 +08005266 case RTL_GIGA_MAC_VER_40:
5267 case RTL_GIGA_MAC_VER_41:
5268 rtl_hw_start_8168g_1(tp);
5269 break;
5270
Francois Romieu219a1e92008-06-28 11:58:39 +02005271 default:
5272 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5273 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005274 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005275 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005276
Francois Romieu0e485152007-02-20 00:00:26 +01005277 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5278
Francois Romieub8363902008-06-01 12:31:57 +02005279 RTL_W8(Cfg9346, Cfg9346_Lock);
5280
Francois Romieu2dd99532007-06-11 23:22:52 +02005281 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005282}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283
Francois Romieu2857ffb2008-08-02 21:08:49 +02005284#define R810X_CPCMD_QUIRK_MASK (\
5285 EnableBist | \
5286 Mac_dbgo_oe | \
5287 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005288 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005289 Force_txflow_en | \
5290 Cxpl_dbg_sel | \
5291 ASF | \
5292 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005293 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005294
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005295static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005296{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005297 void __iomem *ioaddr = tp->mmio_addr;
5298 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005299 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005300 { 0x01, 0, 0x6e65 },
5301 { 0x02, 0, 0x091f },
5302 { 0x03, 0, 0xc2f9 },
5303 { 0x06, 0, 0xafb5 },
5304 { 0x07, 0, 0x0e00 },
5305 { 0x19, 0, 0xec80 },
5306 { 0x01, 0, 0x2e65 },
5307 { 0x01, 0, 0x6e65 }
5308 };
5309 u8 cfg1;
5310
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005311 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005312
5313 RTL_W8(DBG_REG, FIX_NAK_1);
5314
5315 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5316
5317 RTL_W8(Config1,
5318 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5319 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5320
5321 cfg1 = RTL_R8(Config1);
5322 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5323 RTL_W8(Config1, cfg1 & ~LEDS0);
5324
Francois Romieufdf6fc02012-07-06 22:40:38 +02005325 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005326}
5327
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005328static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005329{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005330 void __iomem *ioaddr = tp->mmio_addr;
5331 struct pci_dev *pdev = tp->pci_dev;
5332
5333 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005334
5335 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5336
5337 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5338 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005339}
5340
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005341static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005342{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005343 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005344
Francois Romieufdf6fc02012-07-06 22:40:38 +02005345 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005346}
5347
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005348static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005349{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005350 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005351 static const struct ephy_info e_info_8105e_1[] = {
5352 { 0x07, 0, 0x4000 },
5353 { 0x19, 0, 0x0200 },
5354 { 0x19, 0, 0x0020 },
5355 { 0x1e, 0, 0x2000 },
5356 { 0x03, 0, 0x0001 },
5357 { 0x19, 0, 0x0100 },
5358 { 0x19, 0, 0x0004 },
5359 { 0x0a, 0, 0x0020 }
5360 };
5361
Francois Romieucecb5fd2011-04-01 10:21:07 +02005362 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005363 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5364
Francois Romieucecb5fd2011-04-01 10:21:07 +02005365 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005366 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5367
5368 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005369 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005370 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5371 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5372 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005373
Francois Romieufdf6fc02012-07-06 22:40:38 +02005374 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005375}
5376
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005377static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005378{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005379 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005380 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005381}
5382
Hayes Wang7e18dca2012-03-30 14:33:02 +08005383static void rtl_hw_start_8402(struct rtl8169_private *tp)
5384{
5385 void __iomem *ioaddr = tp->mmio_addr;
5386 static const struct ephy_info e_info_8402[] = {
5387 { 0x19, 0xffff, 0xff64 },
5388 { 0x1e, 0, 0x4000 }
5389 };
5390
5391 rtl_csi_access_enable_2(tp);
5392
5393 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5394 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5395
5396 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5397 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005398 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5399 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5400 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005401
Francois Romieufdf6fc02012-07-06 22:40:38 +02005402 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005403
5404 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5405
Francois Romieufdf6fc02012-07-06 22:40:38 +02005406 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5407 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5408 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5409 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5410 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5411 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5412 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005413}
5414
Hayes Wang5598bfe2012-07-02 17:23:21 +08005415static void rtl_hw_start_8106(struct rtl8169_private *tp)
5416{
5417 void __iomem *ioaddr = tp->mmio_addr;
5418
5419 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5420 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5421
hayeswangd64ec842012-11-01 16:46:28 +00005422 RTL_W32(MISC,
5423 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5424 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5425 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005426 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5427 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5428}
5429
Francois Romieu07ce4062007-02-23 23:36:39 +01005430static void rtl_hw_start_8101(struct net_device *dev)
5431{
Francois Romieucdf1a602007-06-11 23:29:50 +02005432 struct rtl8169_private *tp = netdev_priv(dev);
5433 void __iomem *ioaddr = tp->mmio_addr;
5434 struct pci_dev *pdev = tp->pci_dev;
5435
Francois Romieuda78dbf2012-01-26 14:18:23 +01005436 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5437 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005438
Francois Romieucecb5fd2011-04-01 10:21:07 +02005439 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005440 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005441 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5442 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005443
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005444 RTL_W8(Cfg9346, Cfg9346_Unlock);
5445
Francois Romieu2857ffb2008-08-02 21:08:49 +02005446 switch (tp->mac_version) {
5447 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005448 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005449 break;
5450
5451 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005452 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005453 break;
5454
5455 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005456 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005457 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005458
5459 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005460 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005461 break;
5462 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005463 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005464 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005465
5466 case RTL_GIGA_MAC_VER_37:
5467 rtl_hw_start_8402(tp);
5468 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005469
5470 case RTL_GIGA_MAC_VER_39:
5471 rtl_hw_start_8106(tp);
5472 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005473 }
5474
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005475 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005476
françois romieuf0298f82011-01-03 15:07:42 +00005477 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005478
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005479 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005480
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005481 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005482 RTL_W16(CPlusCmd, tp->cp_cmd);
5483
5484 RTL_W16(IntrMitigate, 0x0000);
5485
5486 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5487
5488 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5489 rtl_set_rx_tx_config_registers(tp);
5490
Francois Romieucdf1a602007-06-11 23:29:50 +02005491 RTL_R8(IntrMask);
5492
Francois Romieucdf1a602007-06-11 23:29:50 +02005493 rtl_set_rx_mode(dev);
5494
5495 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005496}
5497
5498static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5499{
Francois Romieud58d46b2011-05-03 16:38:29 +02005500 struct rtl8169_private *tp = netdev_priv(dev);
5501
5502 if (new_mtu < ETH_ZLEN ||
5503 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504 return -EINVAL;
5505
Francois Romieud58d46b2011-05-03 16:38:29 +02005506 if (new_mtu > ETH_DATA_LEN)
5507 rtl_hw_jumbo_enable(tp);
5508 else
5509 rtl_hw_jumbo_disable(tp);
5510
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005512 netdev_update_features(dev);
5513
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005514 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515}
5516
5517static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5518{
Al Viro95e09182007-12-22 18:55:39 +00005519 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5521}
5522
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005523static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5524 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005526 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005527 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005528
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005529 kfree(*data_buff);
5530 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531 rtl8169_make_unusable_by_asic(desc);
5532}
5533
5534static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5535{
5536 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5537
5538 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5539}
5540
5541static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5542 u32 rx_buf_sz)
5543{
5544 desc->addr = cpu_to_le64(mapping);
5545 wmb();
5546 rtl8169_mark_to_asic(desc, rx_buf_sz);
5547}
5548
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005549static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005551 return (void *)ALIGN((long)data, 16);
5552}
5553
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005554static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5555 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005556{
5557 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005558 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005559 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005560 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005561 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005563 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5564 if (!data)
5565 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005566
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005567 if (rtl8169_align(data) != data) {
5568 kfree(data);
5569 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5570 if (!data)
5571 return NULL;
5572 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005573
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005574 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005575 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005576 if (unlikely(dma_mapping_error(d, mapping))) {
5577 if (net_ratelimit())
5578 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005579 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581
5582 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005583 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005584
5585err_out:
5586 kfree(data);
5587 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588}
5589
5590static void rtl8169_rx_clear(struct rtl8169_private *tp)
5591{
Francois Romieu07d3f512007-02-21 22:40:46 +01005592 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005593
5594 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005595 if (tp->Rx_databuff[i]) {
5596 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597 tp->RxDescArray + i);
5598 }
5599 }
5600}
5601
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005602static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005604 desc->opts1 |= cpu_to_le32(RingEnd);
5605}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005606
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005607static int rtl8169_rx_fill(struct rtl8169_private *tp)
5608{
5609 unsigned int i;
5610
5611 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005612 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005613
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005614 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005616
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005617 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005618 if (!data) {
5619 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005620 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005621 }
5622 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005625 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5626 return 0;
5627
5628err_out:
5629 rtl8169_rx_clear(tp);
5630 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631}
5632
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633static int rtl8169_init_ring(struct net_device *dev)
5634{
5635 struct rtl8169_private *tp = netdev_priv(dev);
5636
5637 rtl8169_init_ring_indexes(tp);
5638
5639 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005640 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005642 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005643}
5644
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005645static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005646 struct TxDesc *desc)
5647{
5648 unsigned int len = tx_skb->len;
5649
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005650 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5651
Linus Torvalds1da177e2005-04-16 15:20:36 -07005652 desc->opts1 = 0x00;
5653 desc->opts2 = 0x00;
5654 desc->addr = 0x00;
5655 tx_skb->len = 0;
5656}
5657
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005658static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5659 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660{
5661 unsigned int i;
5662
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005663 for (i = 0; i < n; i++) {
5664 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 struct ring_info *tx_skb = tp->tx_skb + entry;
5666 unsigned int len = tx_skb->len;
5667
5668 if (len) {
5669 struct sk_buff *skb = tx_skb->skb;
5670
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005671 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672 tp->TxDescArray + entry);
5673 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005674 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675 dev_kfree_skb(skb);
5676 tx_skb->skb = NULL;
5677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678 }
5679 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005680}
5681
5682static void rtl8169_tx_clear(struct rtl8169_private *tp)
5683{
5684 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685 tp->cur_tx = tp->dirty_tx = 0;
5686}
5687
Francois Romieu4422bcd2012-01-26 11:23:32 +01005688static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689{
David Howellsc4028952006-11-22 14:57:56 +00005690 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005691 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
Francois Romieuda78dbf2012-01-26 14:18:23 +01005693 napi_disable(&tp->napi);
5694 netif_stop_queue(dev);
5695 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696
françois romieuc7c2c392011-12-04 20:30:52 +00005697 rtl8169_hw_reset(tp);
5698
Francois Romieu56de4142011-03-15 17:29:31 +01005699 for (i = 0; i < NUM_RX_DESC; i++)
5700 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5701
Linus Torvalds1da177e2005-04-16 15:20:36 -07005702 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005703 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704
Francois Romieuda78dbf2012-01-26 14:18:23 +01005705 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005706 rtl_hw_start(dev);
5707 netif_wake_queue(dev);
5708 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709}
5710
5711static void rtl8169_tx_timeout(struct net_device *dev)
5712{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005713 struct rtl8169_private *tp = netdev_priv(dev);
5714
5715 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716}
5717
5718static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005719 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720{
5721 struct skb_shared_info *info = skb_shinfo(skb);
5722 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005723 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005724 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725
5726 entry = tp->cur_tx;
5727 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005728 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 dma_addr_t mapping;
5730 u32 status, len;
5731 void *addr;
5732
5733 entry = (entry + 1) % NUM_TX_DESC;
5734
5735 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005736 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005737 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005738 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005739 if (unlikely(dma_mapping_error(d, mapping))) {
5740 if (net_ratelimit())
5741 netif_err(tp, drv, tp->dev,
5742 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005743 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005745
Francois Romieucecb5fd2011-04-01 10:21:07 +02005746 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005747 status = opts[0] | len |
5748 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005749
5750 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005751 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752 txd->addr = cpu_to_le64(mapping);
5753
5754 tp->tx_skb[entry].len = len;
5755 }
5756
5757 if (cur_frag) {
5758 tp->tx_skb[entry].skb = skb;
5759 txd->opts1 |= cpu_to_le32(LastFrag);
5760 }
5761
5762 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005763
5764err_out:
5765 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5766 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767}
5768
Francois Romieu2b7b4312011-04-18 22:53:24 -07005769static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5770 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005772 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005773 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005774 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775
Francois Romieu2b7b4312011-04-18 22:53:24 -07005776 if (mss) {
5777 opts[0] |= TD_LSO;
5778 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5779 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005780 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781
5782 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005783 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005785 opts[offset] |= info->checksum.udp;
5786 else
5787 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789}
5790
Stephen Hemminger613573252009-08-31 19:50:58 +00005791static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5792 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793{
5794 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005795 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005796 struct TxDesc *txd = tp->TxDescArray + entry;
5797 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005798 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799 dma_addr_t mapping;
5800 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005801 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005802 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005803
Julien Ducourthial477206a2012-05-09 00:00:06 +02005804 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005805 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005806 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807 }
5808
5809 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005810 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005812 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005813 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005814 if (unlikely(dma_mapping_error(d, mapping))) {
5815 if (net_ratelimit())
5816 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005817 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
5820 tp->tx_skb[entry].len = len;
5821 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822
Kirill Smelkov810f4892012-11-10 21:11:02 +04005823 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005824 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005825
Francois Romieu2b7b4312011-04-18 22:53:24 -07005826 rtl8169_tso_csum(tp, skb, opts);
5827
5828 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005829 if (frags < 0)
5830 goto err_dma_1;
5831 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005832 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005833 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005834 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005835 tp->tx_skb[entry].skb = skb;
5836 }
5837
Francois Romieu2b7b4312011-04-18 22:53:24 -07005838 txd->opts2 = cpu_to_le32(opts[1]);
5839
Richard Cochran5047fb52012-03-10 07:29:42 +00005840 skb_tx_timestamp(skb);
5841
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 wmb();
5843
Francois Romieucecb5fd2011-04-01 10:21:07 +02005844 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005845 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 txd->opts1 = cpu_to_le32(status);
5847
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848 tp->cur_tx += frags + 1;
5849
David Dillow4c020a92010-03-03 16:33:10 +00005850 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851
Francois Romieucecb5fd2011-04-01 10:21:07 +02005852 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005853
Francois Romieuda78dbf2012-01-26 14:18:23 +01005854 mmiowb();
5855
Julien Ducourthial477206a2012-05-09 00:00:06 +02005856 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005857 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5858 * not miss a ring update when it notices a stopped queue.
5859 */
5860 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005862 /* Sync with rtl_tx:
5863 * - publish queue status and cur_tx ring index (write barrier)
5864 * - refresh dirty_tx ring index (read barrier).
5865 * May the current thread have a pessimistic view of the ring
5866 * status and forget to wake up queue, a racing rtl_tx thread
5867 * can't.
5868 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005869 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005870 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871 netif_wake_queue(dev);
5872 }
5873
Stephen Hemminger613573252009-08-31 19:50:58 +00005874 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005876err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005877 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005878err_dma_0:
5879 dev_kfree_skb(skb);
5880 dev->stats.tx_dropped++;
5881 return NETDEV_TX_OK;
5882
5883err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005885 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005886 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887}
5888
5889static void rtl8169_pcierr_interrupt(struct net_device *dev)
5890{
5891 struct rtl8169_private *tp = netdev_priv(dev);
5892 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893 u16 pci_status, pci_cmd;
5894
5895 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5896 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5897
Joe Perchesbf82c182010-02-09 11:49:50 +00005898 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5899 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
5901 /*
5902 * The recovery sequence below admits a very elaborated explanation:
5903 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005904 * - I did not see what else could be done;
5905 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906 *
5907 * Feel free to adjust to your needs.
5908 */
Francois Romieua27993f2006-12-18 00:04:19 +01005909 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005910 pci_cmd &= ~PCI_COMMAND_PARITY;
5911 else
5912 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5913
5914 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915
5916 pci_write_config_word(pdev, PCI_STATUS,
5917 pci_status & (PCI_STATUS_DETECTED_PARITY |
5918 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5919 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5920
5921 /* The infamous DAC f*ckup only happens at boot time */
Timo Teräs9fba0812013-01-15 21:01:24 +00005922 if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005923 void __iomem *ioaddr = tp->mmio_addr;
5924
Joe Perchesbf82c182010-02-09 11:49:50 +00005925 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926 tp->cp_cmd &= ~PCIDAC;
5927 RTL_W16(CPlusCmd, tp->cp_cmd);
5928 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929 }
5930
françois romieue6de30d2011-01-03 15:08:37 +00005931 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005932
Francois Romieu98ddf982012-01-31 10:47:34 +01005933 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934}
5935
Francois Romieuda78dbf2012-01-26 14:18:23 +01005936static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937{
5938 unsigned int dirty_tx, tx_left;
5939
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940 dirty_tx = tp->dirty_tx;
5941 smp_rmb();
5942 tx_left = tp->cur_tx - dirty_tx;
5943
5944 while (tx_left > 0) {
5945 unsigned int entry = dirty_tx % NUM_TX_DESC;
5946 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947 u32 status;
5948
5949 rmb();
5950 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5951 if (status & DescOwn)
5952 break;
5953
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005954 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5955 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005957 u64_stats_update_begin(&tp->tx_stats.syncp);
5958 tp->tx_stats.packets++;
5959 tp->tx_stats.bytes += tx_skb->skb->len;
5960 u64_stats_update_end(&tp->tx_stats.syncp);
5961 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962 tx_skb->skb = NULL;
5963 }
5964 dirty_tx++;
5965 tx_left--;
5966 }
5967
5968 if (tp->dirty_tx != dirty_tx) {
5969 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005970 /* Sync with rtl8169_start_xmit:
5971 * - publish dirty_tx ring index (write barrier)
5972 * - refresh cur_tx ring index and queue status (read barrier)
5973 * May the current thread miss the stopped queue condition,
5974 * a racing xmit thread can only have a right view of the
5975 * ring status.
5976 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005977 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005979 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980 netif_wake_queue(dev);
5981 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005982 /*
5983 * 8168 hack: TxPoll requests are lost when the Tx packets are
5984 * too close. Let's kick an extra TxPoll request when a burst
5985 * of start_xmit activity is detected (if it is not detected,
5986 * it is slow enough). -- FR
5987 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005988 if (tp->cur_tx != dirty_tx) {
5989 void __iomem *ioaddr = tp->mmio_addr;
5990
Francois Romieud78ae2d2007-08-26 20:08:19 +02005991 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993 }
5994}
5995
Francois Romieu126fa4b2005-05-12 20:09:17 -04005996static inline int rtl8169_fragmented_frame(u32 status)
5997{
5998 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5999}
6000
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006001static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003 u32 status = opts1 & RxProtoMask;
6004
6005 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006006 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006007 skb->ip_summed = CHECKSUM_UNNECESSARY;
6008 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006009 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010}
6011
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006012static struct sk_buff *rtl8169_try_rx_copy(void *data,
6013 struct rtl8169_private *tp,
6014 int pkt_size,
6015 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006017 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006018 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006020 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006021 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006022 prefetch(data);
6023 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6024 if (skb)
6025 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006026 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6027
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006028 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029}
6030
Francois Romieuda78dbf2012-01-26 14:18:23 +01006031static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032{
6033 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006034 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036 cur_rx = tp->cur_rx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Timo Teräs9fba0812013-01-15 21:01:24 +00006038 for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006040 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041 u32 status;
6042
6043 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006044 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045
6046 if (status & DescOwn)
6047 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006048 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006049 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6050 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006051 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006053 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006055 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006056 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006057 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006058 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006059 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006060 if ((status & (RxRUNT | RxCRC)) &&
6061 !(status & (RxRWT | RxFOVF)) &&
6062 (dev->features & NETIF_F_RXALL))
6063 goto process_pkt;
6064
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006065 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006067 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006068 dma_addr_t addr;
6069 int pkt_size;
6070
6071process_pkt:
6072 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006073 if (likely(!(dev->features & NETIF_F_RXFCS)))
6074 pkt_size = (status & 0x00003fff) - 4;
6075 else
6076 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077
Francois Romieu126fa4b2005-05-12 20:09:17 -04006078 /*
6079 * The driver does not support incoming fragmented
6080 * frames. They are seen as a symptom of over-mtu
6081 * sized frames.
6082 */
6083 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006084 dev->stats.rx_dropped++;
6085 dev->stats.rx_length_errors++;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006086 rtl8169_mark_to_asic(desc, rx_buf_sz);
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006087 continue;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006088 }
6089
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006090 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6091 tp, pkt_size, addr);
6092 rtl8169_mark_to_asic(desc, rx_buf_sz);
6093 if (!skb) {
6094 dev->stats.rx_dropped++;
6095 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 }
6097
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006098 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099 skb_put(skb, pkt_size);
6100 skb->protocol = eth_type_trans(skb, dev);
6101
Francois Romieu7a8fc772011-03-01 17:18:33 +01006102 rtl8169_rx_vlan_tag(desc, skb);
6103
Francois Romieu56de4142011-03-15 17:29:31 +01006104 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105
Junchang Wang8027aa22012-03-04 23:30:32 +01006106 u64_stats_update_begin(&tp->rx_stats.syncp);
6107 tp->rx_stats.packets++;
6108 tp->rx_stats.bytes += pkt_size;
6109 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110 }
Francois Romieu6dccd162007-02-13 23:38:05 +01006111
6112 /* Work around for AMD plateform. */
Al Viro95e09182007-12-22 18:55:39 +00006113 if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
Francois Romieu6dccd162007-02-13 23:38:05 +01006114 (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
6115 desc->opts2 = 0;
6116 cur_rx++;
6117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118 }
6119
6120 count = cur_rx - tp->cur_rx;
6121 tp->cur_rx = cur_rx;
6122
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123 return count;
6124}
6125
Francois Romieu07d3f512007-02-21 22:40:46 +01006126static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127{
Francois Romieu07d3f512007-02-21 22:40:46 +01006128 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006131 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006133 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006134 if (status && status != 0xffff) {
6135 status &= RTL_EVENT_NAPI | tp->event_slow;
6136 if (status) {
6137 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006138
Francois Romieuda78dbf2012-01-26 14:18:23 +01006139 rtl_irq_disable(tp);
6140 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143 return IRQ_RETVAL(handled);
6144}
6145
Francois Romieuda78dbf2012-01-26 14:18:23 +01006146/*
6147 * Workqueue context.
6148 */
6149static void rtl_slow_event_work(struct rtl8169_private *tp)
6150{
6151 struct net_device *dev = tp->dev;
6152 u16 status;
6153
6154 status = rtl_get_events(tp) & tp->event_slow;
6155 rtl_ack_events(tp, status);
6156
6157 if (unlikely(status & RxFIFOOver)) {
6158 switch (tp->mac_version) {
6159 /* Work around for rx fifo overflow */
6160 case RTL_GIGA_MAC_VER_11:
6161 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006162 /* XXX - Hack alert. See rtl_task(). */
6163 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006164 default:
6165 break;
6166 }
6167 }
6168
6169 if (unlikely(status & SYSErr))
6170 rtl8169_pcierr_interrupt(dev);
6171
6172 if (status & LinkChg)
6173 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6174
françois romieu7dbb4912012-06-09 10:53:16 +00006175 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006176}
6177
Francois Romieu4422bcd2012-01-26 11:23:32 +01006178static void rtl_task(struct work_struct *work)
6179{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006180 static const struct {
6181 int bitnr;
6182 void (*action)(struct rtl8169_private *);
6183 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006184 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006185 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6186 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6187 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6188 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006189 struct rtl8169_private *tp =
6190 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006191 struct net_device *dev = tp->dev;
6192 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006193
Francois Romieuda78dbf2012-01-26 14:18:23 +01006194 rtl_lock_work(tp);
6195
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006196 if (!netif_running(dev) ||
6197 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006198 goto out_unlock;
6199
6200 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6201 bool pending;
6202
Francois Romieuda78dbf2012-01-26 14:18:23 +01006203 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006204 if (pending)
6205 rtl_work[i].action(tp);
6206 }
6207
6208out_unlock:
6209 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006210}
6211
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006212static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006214 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6215 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006216 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6217 int work_done= 0;
6218 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219
Francois Romieuda78dbf2012-01-26 14:18:23 +01006220 status = rtl_get_events(tp);
6221 rtl_ack_events(tp, status & ~tp->event_slow);
6222
6223 if (status & RTL_EVENT_NAPI_RX)
6224 work_done = rtl_rx(dev, tp, (u32) budget);
6225
6226 if (status & RTL_EVENT_NAPI_TX)
6227 rtl_tx(dev, tp);
6228
6229 if (status & tp->event_slow) {
6230 enable_mask &= ~tp->event_slow;
6231
6232 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006235 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006236 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006237
Francois Romieuda78dbf2012-01-26 14:18:23 +01006238 rtl_irq_enable(tp, enable_mask);
6239 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006240 }
6241
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006242 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244
Francois Romieu523a6092008-09-10 22:28:56 +02006245static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6246{
6247 struct rtl8169_private *tp = netdev_priv(dev);
6248
6249 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6250 return;
6251
6252 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6253 RTL_W32(RxMissed, 0);
6254}
6255
Linus Torvalds1da177e2005-04-16 15:20:36 -07006256static void rtl8169_down(struct net_device *dev)
6257{
6258 struct rtl8169_private *tp = netdev_priv(dev);
6259 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260
Francois Romieu4876cc12011-03-11 21:07:11 +01006261 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006263 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006264 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265
Hayes Wang92fc43b2011-07-06 15:58:03 +08006266 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006267 /*
6268 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006269 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6270 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006271 */
Francois Romieu523a6092008-09-10 22:28:56 +02006272 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006275 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277 rtl8169_tx_clear(tp);
6278
6279 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006280
6281 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282}
6283
6284static int rtl8169_close(struct net_device *dev)
6285{
6286 struct rtl8169_private *tp = netdev_priv(dev);
6287 struct pci_dev *pdev = tp->pci_dev;
6288
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006289 pm_runtime_get_sync(&pdev->dev);
6290
Francois Romieucecb5fd2011-04-01 10:21:07 +02006291 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006292 rtl8169_update_counters(dev);
6293
Francois Romieuda78dbf2012-01-26 14:18:23 +01006294 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006295 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006296
Linus Torvalds1da177e2005-04-16 15:20:36 -07006297 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006298 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006300 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006301
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006302 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6303 tp->RxPhyAddr);
6304 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6305 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306 tp->TxDescArray = NULL;
6307 tp->RxDescArray = NULL;
6308
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006309 pm_runtime_put_sync(&pdev->dev);
6310
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 return 0;
6312}
6313
Francois Romieudc1c00c2012-03-08 10:06:18 +01006314#ifdef CONFIG_NET_POLL_CONTROLLER
6315static void rtl8169_netpoll(struct net_device *dev)
6316{
6317 struct rtl8169_private *tp = netdev_priv(dev);
6318
6319 rtl8169_interrupt(tp->pci_dev->irq, dev);
6320}
6321#endif
6322
Francois Romieudf43ac72012-03-08 09:48:40 +01006323static int rtl_open(struct net_device *dev)
6324{
6325 struct rtl8169_private *tp = netdev_priv(dev);
6326 void __iomem *ioaddr = tp->mmio_addr;
6327 struct pci_dev *pdev = tp->pci_dev;
6328 int retval = -ENOMEM;
6329
6330 pm_runtime_get_sync(&pdev->dev);
6331
6332 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006333 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006334 * dma_alloc_coherent provides more.
6335 */
6336 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6337 &tp->TxPhyAddr, GFP_KERNEL);
6338 if (!tp->TxDescArray)
6339 goto err_pm_runtime_put;
6340
6341 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6342 &tp->RxPhyAddr, GFP_KERNEL);
6343 if (!tp->RxDescArray)
6344 goto err_free_tx_0;
6345
6346 retval = rtl8169_init_ring(dev);
6347 if (retval < 0)
6348 goto err_free_rx_1;
6349
6350 INIT_WORK(&tp->wk.work, rtl_task);
6351
6352 smp_mb();
6353
6354 rtl_request_firmware(tp);
6355
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006356 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006357 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6358 dev->name, dev);
6359 if (retval < 0)
6360 goto err_release_fw_2;
6361
6362 rtl_lock_work(tp);
6363
6364 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6365
6366 napi_enable(&tp->napi);
6367
6368 rtl8169_init_phy(dev, tp);
6369
6370 __rtl8169_set_features(dev, dev->features);
6371
6372 rtl_pll_power_up(tp);
6373
6374 rtl_hw_start(dev);
6375
6376 netif_start_queue(dev);
6377
6378 rtl_unlock_work(tp);
6379
6380 tp->saved_wolopts = 0;
6381 pm_runtime_put_noidle(&pdev->dev);
6382
6383 rtl8169_check_link_status(dev, tp, ioaddr);
6384out:
6385 return retval;
6386
6387err_release_fw_2:
6388 rtl_release_firmware(tp);
6389 rtl8169_rx_clear(tp);
6390err_free_rx_1:
6391 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6392 tp->RxPhyAddr);
6393 tp->RxDescArray = NULL;
6394err_free_tx_0:
6395 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6396 tp->TxPhyAddr);
6397 tp->TxDescArray = NULL;
6398err_pm_runtime_put:
6399 pm_runtime_put_noidle(&pdev->dev);
6400 goto out;
6401}
6402
Junchang Wang8027aa22012-03-04 23:30:32 +01006403static struct rtnl_link_stats64 *
6404rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006405{
6406 struct rtl8169_private *tp = netdev_priv(dev);
6407 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006408 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006409
Francois Romieuda78dbf2012-01-26 14:18:23 +01006410 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006411 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006412
Junchang Wang8027aa22012-03-04 23:30:32 +01006413 do {
6414 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6415 stats->rx_packets = tp->rx_stats.packets;
6416 stats->rx_bytes = tp->rx_stats.bytes;
6417 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6418
6419
6420 do {
6421 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6422 stats->tx_packets = tp->tx_stats.packets;
6423 stats->tx_bytes = tp->tx_stats.bytes;
6424 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6425
6426 stats->rx_dropped = dev->stats.rx_dropped;
6427 stats->tx_dropped = dev->stats.tx_dropped;
6428 stats->rx_length_errors = dev->stats.rx_length_errors;
6429 stats->rx_errors = dev->stats.rx_errors;
6430 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6431 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6432 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6433
6434 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435}
6436
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006437static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006438{
françois romieu065c27c2011-01-03 15:08:12 +00006439 struct rtl8169_private *tp = netdev_priv(dev);
6440
Francois Romieu5d06a992006-02-23 00:47:58 +01006441 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006442 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006443
6444 netif_device_detach(dev);
6445 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006446
6447 rtl_lock_work(tp);
6448 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006449 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006450 rtl_unlock_work(tp);
6451
6452 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006453}
Francois Romieu5d06a992006-02-23 00:47:58 +01006454
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006455#ifdef CONFIG_PM
6456
6457static int rtl8169_suspend(struct device *device)
6458{
6459 struct pci_dev *pdev = to_pci_dev(device);
6460 struct net_device *dev = pci_get_drvdata(pdev);
6461
6462 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006463
Francois Romieu5d06a992006-02-23 00:47:58 +01006464 return 0;
6465}
6466
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006467static void __rtl8169_resume(struct net_device *dev)
6468{
françois romieu065c27c2011-01-03 15:08:12 +00006469 struct rtl8169_private *tp = netdev_priv(dev);
6470
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006471 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006472
6473 rtl_pll_power_up(tp);
6474
Artem Savkovcff4c162012-04-03 10:29:11 +00006475 rtl_lock_work(tp);
6476 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006477 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006478 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006479
Francois Romieu98ddf982012-01-31 10:47:34 +01006480 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006481}
6482
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006483static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006484{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006485 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006486 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006487 struct rtl8169_private *tp = netdev_priv(dev);
6488
6489 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006490
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006491 if (netif_running(dev))
6492 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006493
Francois Romieu5d06a992006-02-23 00:47:58 +01006494 return 0;
6495}
6496
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006497static int rtl8169_runtime_suspend(struct device *device)
6498{
6499 struct pci_dev *pdev = to_pci_dev(device);
6500 struct net_device *dev = pci_get_drvdata(pdev);
6501 struct rtl8169_private *tp = netdev_priv(dev);
6502
6503 if (!tp->TxDescArray)
6504 return 0;
6505
Francois Romieuda78dbf2012-01-26 14:18:23 +01006506 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006507 tp->saved_wolopts = __rtl8169_get_wol(tp);
6508 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006509 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006510
6511 rtl8169_net_suspend(dev);
6512
6513 return 0;
6514}
6515
6516static int rtl8169_runtime_resume(struct device *device)
6517{
6518 struct pci_dev *pdev = to_pci_dev(device);
6519 struct net_device *dev = pci_get_drvdata(pdev);
6520 struct rtl8169_private *tp = netdev_priv(dev);
6521
6522 if (!tp->TxDescArray)
6523 return 0;
6524
Francois Romieuda78dbf2012-01-26 14:18:23 +01006525 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006526 __rtl8169_set_wol(tp, tp->saved_wolopts);
6527 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006528 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006529
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006530 rtl8169_init_phy(dev, tp);
6531
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006532 __rtl8169_resume(dev);
6533
6534 return 0;
6535}
6536
6537static int rtl8169_runtime_idle(struct device *device)
6538{
6539 struct pci_dev *pdev = to_pci_dev(device);
6540 struct net_device *dev = pci_get_drvdata(pdev);
6541 struct rtl8169_private *tp = netdev_priv(dev);
6542
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006543 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006544}
6545
Alexey Dobriyan47145212009-12-14 18:00:08 -08006546static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006547 .suspend = rtl8169_suspend,
6548 .resume = rtl8169_resume,
6549 .freeze = rtl8169_suspend,
6550 .thaw = rtl8169_resume,
6551 .poweroff = rtl8169_suspend,
6552 .restore = rtl8169_resume,
6553 .runtime_suspend = rtl8169_runtime_suspend,
6554 .runtime_resume = rtl8169_runtime_resume,
6555 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006556};
6557
6558#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6559
6560#else /* !CONFIG_PM */
6561
6562#define RTL8169_PM_OPS NULL
6563
6564#endif /* !CONFIG_PM */
6565
David S. Miller1805b2f2011-10-24 18:18:09 -04006566static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6567{
6568 void __iomem *ioaddr = tp->mmio_addr;
6569
6570 /* WoL fails with 8168b when the receiver is disabled. */
6571 switch (tp->mac_version) {
6572 case RTL_GIGA_MAC_VER_11:
6573 case RTL_GIGA_MAC_VER_12:
6574 case RTL_GIGA_MAC_VER_17:
6575 pci_clear_master(tp->pci_dev);
6576
6577 RTL_W8(ChipCmd, CmdRxEnb);
6578 /* PCI commit */
6579 RTL_R8(ChipCmd);
6580 break;
6581 default:
6582 break;
6583 }
6584}
6585
Francois Romieu1765f952008-09-13 17:21:40 +02006586static void rtl_shutdown(struct pci_dev *pdev)
6587{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006588 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006589 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006590 struct device *d = &pdev->dev;
6591
6592 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006593
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006594 rtl8169_net_suspend(dev);
6595
Francois Romieucecb5fd2011-04-01 10:21:07 +02006596 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006597 rtl_rar_set(tp, dev->perm_addr);
6598
Hayes Wang92fc43b2011-07-06 15:58:03 +08006599 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006600
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006601 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006602 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6603 rtl_wol_suspend_quirk(tp);
6604 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006605 }
6606
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006607 pci_wake_from_d3(pdev, true);
6608 pci_set_power_state(pdev, PCI_D3hot);
6609 }
françois romieu2a15cd22012-03-06 01:14:12 +00006610
6611 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006612}
Francois Romieu5d06a992006-02-23 00:47:58 +01006613
Bill Pembertonbaf63292012-12-03 09:23:28 -05006614static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006615{
6616 struct net_device *dev = pci_get_drvdata(pdev);
6617 struct rtl8169_private *tp = netdev_priv(dev);
6618
6619 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6620 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6621 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6622 rtl8168_driver_stop(tp);
6623 }
6624
6625 cancel_work_sync(&tp->wk.work);
6626
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006627 netif_napi_del(&tp->napi);
6628
Francois Romieue27566e2012-03-08 09:54:01 +01006629 unregister_netdev(dev);
6630
6631 rtl_release_firmware(tp);
6632
6633 if (pci_dev_run_wake(pdev))
6634 pm_runtime_get_noresume(&pdev->dev);
6635
6636 /* restore original MAC address */
6637 rtl_rar_set(tp, dev->perm_addr);
6638
6639 rtl_disable_msi(pdev, tp);
6640 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6641 pci_set_drvdata(pdev, NULL);
6642}
6643
Francois Romieufa9c3852012-03-08 10:01:50 +01006644static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006645 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006646 .ndo_stop = rtl8169_close,
6647 .ndo_get_stats64 = rtl8169_get_stats64,
6648 .ndo_start_xmit = rtl8169_start_xmit,
6649 .ndo_tx_timeout = rtl8169_tx_timeout,
6650 .ndo_validate_addr = eth_validate_addr,
6651 .ndo_change_mtu = rtl8169_change_mtu,
6652 .ndo_fix_features = rtl8169_fix_features,
6653 .ndo_set_features = rtl8169_set_features,
6654 .ndo_set_mac_address = rtl_set_mac_address,
6655 .ndo_do_ioctl = rtl8169_ioctl,
6656 .ndo_set_rx_mode = rtl_set_rx_mode,
6657#ifdef CONFIG_NET_POLL_CONTROLLER
6658 .ndo_poll_controller = rtl8169_netpoll,
6659#endif
6660
6661};
6662
Francois Romieu31fa8b12012-03-08 10:09:40 +01006663static const struct rtl_cfg_info {
6664 void (*hw_start)(struct net_device *);
6665 unsigned int region;
6666 unsigned int align;
6667 u16 event_slow;
6668 unsigned features;
6669 u8 default_ver;
6670} rtl_cfg_infos [] = {
6671 [RTL_CFG_0] = {
6672 .hw_start = rtl_hw_start_8169,
6673 .region = 1,
6674 .align = 0,
6675 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6676 .features = RTL_FEATURE_GMII,
6677 .default_ver = RTL_GIGA_MAC_VER_01,
6678 },
6679 [RTL_CFG_1] = {
6680 .hw_start = rtl_hw_start_8168,
6681 .region = 2,
6682 .align = 8,
6683 .event_slow = SYSErr | LinkChg | RxOverflow,
6684 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6685 .default_ver = RTL_GIGA_MAC_VER_11,
6686 },
6687 [RTL_CFG_2] = {
6688 .hw_start = rtl_hw_start_8101,
6689 .region = 2,
6690 .align = 8,
6691 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6692 PCSTimeout,
6693 .features = RTL_FEATURE_MSI,
6694 .default_ver = RTL_GIGA_MAC_VER_13,
6695 }
6696};
6697
6698/* Cfg9346_Unlock assumed. */
6699static unsigned rtl_try_msi(struct rtl8169_private *tp,
6700 const struct rtl_cfg_info *cfg)
6701{
6702 void __iomem *ioaddr = tp->mmio_addr;
6703 unsigned msi = 0;
6704 u8 cfg2;
6705
6706 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6707 if (cfg->features & RTL_FEATURE_MSI) {
6708 if (pci_enable_msi(tp->pci_dev)) {
6709 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6710 } else {
6711 cfg2 |= MSIEnable;
6712 msi = RTL_FEATURE_MSI;
6713 }
6714 }
6715 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6716 RTL_W8(Config2, cfg2);
6717 return msi;
6718}
6719
Hayes Wangc5583862012-07-02 17:23:22 +08006720DECLARE_RTL_COND(rtl_link_list_ready_cond)
6721{
6722 void __iomem *ioaddr = tp->mmio_addr;
6723
6724 return RTL_R8(MCU) & LINK_LIST_RDY;
6725}
6726
6727DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6728{
6729 void __iomem *ioaddr = tp->mmio_addr;
6730
6731 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6732}
6733
Bill Pembertonbaf63292012-12-03 09:23:28 -05006734static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006735{
6736 void __iomem *ioaddr = tp->mmio_addr;
6737 u32 data;
6738
6739 tp->ocp_base = OCP_STD_PHY_BASE;
6740
6741 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6742
6743 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6744 return;
6745
6746 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6747 return;
6748
6749 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6750 msleep(1);
6751 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6752
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006753 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006754 data &= ~(1 << 14);
6755 r8168_mac_ocp_write(tp, 0xe8de, data);
6756
6757 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6758 return;
6759
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006760 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006761 data |= (1 << 15);
6762 r8168_mac_ocp_write(tp, 0xe8de, data);
6763
6764 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6765 return;
6766}
6767
Bill Pembertonbaf63292012-12-03 09:23:28 -05006768static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006769{
6770 switch (tp->mac_version) {
6771 case RTL_GIGA_MAC_VER_40:
6772 case RTL_GIGA_MAC_VER_41:
6773 rtl_hw_init_8168g(tp);
6774 break;
6775
6776 default:
6777 break;
6778 }
6779}
6780
Bill Pembertonbaf63292012-12-03 09:23:28 -05006781static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006782rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6783{
6784 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6785 const unsigned int region = cfg->region;
6786 struct rtl8169_private *tp;
6787 struct mii_if_info *mii;
6788 struct net_device *dev;
6789 void __iomem *ioaddr;
6790 int chipset, i;
6791 int rc;
6792
6793 if (netif_msg_drv(&debug)) {
6794 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6795 MODULENAME, RTL8169_VERSION);
6796 }
6797
6798 dev = alloc_etherdev(sizeof (*tp));
6799 if (!dev) {
6800 rc = -ENOMEM;
6801 goto out;
6802 }
6803
6804 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006805 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006806 tp = netdev_priv(dev);
6807 tp->dev = dev;
6808 tp->pci_dev = pdev;
6809 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6810
6811 mii = &tp->mii;
6812 mii->dev = dev;
6813 mii->mdio_read = rtl_mdio_read;
6814 mii->mdio_write = rtl_mdio_write;
6815 mii->phy_id_mask = 0x1f;
6816 mii->reg_num_mask = 0x1f;
6817 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6818
6819 /* disable ASPM completely as that cause random device stop working
6820 * problems as well as full system hangs for some PCIe devices users */
6821 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6822 PCIE_LINK_STATE_CLKPM);
6823
6824 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6825 rc = pci_enable_device(pdev);
6826 if (rc < 0) {
6827 netif_err(tp, probe, dev, "enable failure\n");
6828 goto err_out_free_dev_1;
6829 }
6830
6831 if (pci_set_mwi(pdev) < 0)
6832 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6833
6834 /* make sure PCI base addr 1 is MMIO */
6835 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6836 netif_err(tp, probe, dev,
6837 "region #%d not an MMIO resource, aborting\n",
6838 region);
6839 rc = -ENODEV;
6840 goto err_out_mwi_2;
6841 }
6842
6843 /* check for weird/broken PCI region reporting */
6844 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6845 netif_err(tp, probe, dev,
6846 "Invalid PCI region size(s), aborting\n");
6847 rc = -ENODEV;
6848 goto err_out_mwi_2;
6849 }
6850
6851 rc = pci_request_regions(pdev, MODULENAME);
6852 if (rc < 0) {
6853 netif_err(tp, probe, dev, "could not request regions\n");
6854 goto err_out_mwi_2;
6855 }
6856
6857 tp->cp_cmd = RxChkSum;
6858
6859 if ((sizeof(dma_addr_t) > 4) &&
6860 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6861 tp->cp_cmd |= PCIDAC;
6862 dev->features |= NETIF_F_HIGHDMA;
6863 } else {
6864 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6865 if (rc < 0) {
6866 netif_err(tp, probe, dev, "DMA configuration failed\n");
6867 goto err_out_free_res_3;
6868 }
6869 }
6870
6871 /* ioremap MMIO region */
6872 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6873 if (!ioaddr) {
6874 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6875 rc = -EIO;
6876 goto err_out_free_res_3;
6877 }
6878 tp->mmio_addr = ioaddr;
6879
6880 if (!pci_is_pcie(pdev))
6881 netif_info(tp, probe, dev, "not PCI Express\n");
6882
6883 /* Identify chip attached to board */
6884 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6885
6886 rtl_init_rxcfg(tp);
6887
6888 rtl_irq_disable(tp);
6889
Hayes Wangc5583862012-07-02 17:23:22 +08006890 rtl_hw_initialize(tp);
6891
Francois Romieu3b6cf252012-03-08 09:59:04 +01006892 rtl_hw_reset(tp);
6893
6894 rtl_ack_events(tp, 0xffff);
6895
6896 pci_set_master(pdev);
6897
6898 /*
6899 * Pretend we are using VLANs; This bypasses a nasty bug where
6900 * Interrupts stop flowing on high load on 8110SCd controllers.
6901 */
6902 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6903 tp->cp_cmd |= RxVlan;
6904
6905 rtl_init_mdio_ops(tp);
6906 rtl_init_pll_power_ops(tp);
6907 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006908 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006909
6910 rtl8169_print_mac_version(tp);
6911
6912 chipset = tp->mac_version;
6913 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6914
6915 RTL_W8(Cfg9346, Cfg9346_Unlock);
6916 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6917 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6918 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6919 tp->features |= RTL_FEATURE_WOL;
6920 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6921 tp->features |= RTL_FEATURE_WOL;
6922 tp->features |= rtl_try_msi(tp, cfg);
6923 RTL_W8(Cfg9346, Cfg9346_Lock);
6924
6925 if (rtl_tbi_enabled(tp)) {
6926 tp->set_speed = rtl8169_set_speed_tbi;
6927 tp->get_settings = rtl8169_gset_tbi;
6928 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6929 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6930 tp->link_ok = rtl8169_tbi_link_ok;
6931 tp->do_ioctl = rtl_tbi_ioctl;
6932 } else {
6933 tp->set_speed = rtl8169_set_speed_xmii;
6934 tp->get_settings = rtl8169_gset_xmii;
6935 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6936 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6937 tp->link_ok = rtl8169_xmii_link_ok;
6938 tp->do_ioctl = rtl_xmii_ioctl;
6939 }
6940
6941 mutex_init(&tp->wk.mutex);
6942
6943 /* Get MAC address */
6944 for (i = 0; i < ETH_ALEN; i++)
6945 dev->dev_addr[i] = RTL_R8(MAC0 + i);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006946
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);