blob: d6c6cfb6863133f24f231decc0ce77127c4d335b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Francois Romieu07d3f512007-02-21 22:40:46 +01002 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/pci.h>
14#include <linux/netdevice.h>
15#include <linux/etherdevice.h>
16#include <linux/delay.h>
17#include <linux/ethtool.h>
18#include <linux/mii.h>
19#include <linux/if_vlan.h>
20#include <linux/crc32.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/tcp.h>
24#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000025#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000027#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000028#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000029#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040030#include <linux/prefetch.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/io.h>
33#include <asm/irq.h>
34
Francois Romieu865c6522008-05-11 14:51:00 +020035#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MODULENAME "r8169"
37#define PFX MODULENAME ": "
38
françois romieubca03d52011-01-03 15:07:31 +000039#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
40#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000041#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
42#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080043#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080044#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
45#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080046#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080047#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080048#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080049#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
Hayes Wangc5583862012-07-02 17:23:22 +080050#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw"
françois romieubca03d52011-01-03 15:07:31 +000051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#ifdef RTL8169_DEBUG
53#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020054 if (!(expr)) { \
55 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070056 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020057 }
Joe Perches06fa7352007-10-18 21:15:00 +020058#define dprintk(fmt, args...) \
59 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
61#define assert(expr) do {} while (0)
62#define dprintk(fmt, args...) do {} while (0)
63#endif /* RTL8169_DEBUG */
64
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020065#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
86#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
87#define RX_BUF_SIZE 1536 /* Rx Buffer size */
88#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
89#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
90
91#define RTL8169_TX_TIMEOUT (6*HZ)
92#define RTL8169_PHY_TIMEOUT (10*HZ)
93
françois romieuea8dbdd2009-03-15 01:10:50 +000094#define RTL_EEPROM_SIG cpu_to_le32(0x8129)
95#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff)
Francois Romieue1564ec2008-10-16 22:46:13 +020096#define RTL_EEPROM_SIG_ADDR 0x0000
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098/* write/read MMIO register */
99#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
100#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
101#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
102#define RTL_R8(reg) readb (ioaddr + (reg))
103#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +0000104#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200107 RTL_GIGA_MAC_VER_01 = 0,
108 RTL_GIGA_MAC_VER_02,
109 RTL_GIGA_MAC_VER_03,
110 RTL_GIGA_MAC_VER_04,
111 RTL_GIGA_MAC_VER_05,
112 RTL_GIGA_MAC_VER_06,
113 RTL_GIGA_MAC_VER_07,
114 RTL_GIGA_MAC_VER_08,
115 RTL_GIGA_MAC_VER_09,
116 RTL_GIGA_MAC_VER_10,
117 RTL_GIGA_MAC_VER_11,
118 RTL_GIGA_MAC_VER_12,
119 RTL_GIGA_MAC_VER_13,
120 RTL_GIGA_MAC_VER_14,
121 RTL_GIGA_MAC_VER_15,
122 RTL_GIGA_MAC_VER_16,
123 RTL_GIGA_MAC_VER_17,
124 RTL_GIGA_MAC_VER_18,
125 RTL_GIGA_MAC_VER_19,
126 RTL_GIGA_MAC_VER_20,
127 RTL_GIGA_MAC_VER_21,
128 RTL_GIGA_MAC_VER_22,
129 RTL_GIGA_MAC_VER_23,
130 RTL_GIGA_MAC_VER_24,
131 RTL_GIGA_MAC_VER_25,
132 RTL_GIGA_MAC_VER_26,
133 RTL_GIGA_MAC_VER_27,
134 RTL_GIGA_MAC_VER_28,
135 RTL_GIGA_MAC_VER_29,
136 RTL_GIGA_MAC_VER_30,
137 RTL_GIGA_MAC_VER_31,
138 RTL_GIGA_MAC_VER_32,
139 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800140 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800141 RTL_GIGA_MAC_VER_35,
142 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800143 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800144 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800145 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800146 RTL_GIGA_MAC_VER_40,
147 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200148 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149};
150
Francois Romieu2b7b4312011-04-18 22:53:24 -0700151enum rtl_tx_desc_version {
152 RTL_TD_0 = 0,
153 RTL_TD_1 = 1,
154};
155
Francois Romieud58d46b2011-05-03 16:38:29 +0200156#define JUMBO_1K ETH_DATA_LEN
157#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
158#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
159#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
160#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
161
162#define _R(NAME,TD,FW,SZ,B) { \
163 .name = NAME, \
164 .txd_version = TD, \
165 .fw_name = FW, \
166 .jumbo_max = SZ, \
167 .jumbo_tx_csum = B \
168}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800170static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700172 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200173 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 u16 jumbo_max;
175 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200176} rtl_chip_infos[] = {
177 /* PCI devices. */
178 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200179 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200180 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200181 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200182 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200183 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200184 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200185 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200186 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 /* PCI-E devices. */
191 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200192 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200193 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200194 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200195 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200196 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200197 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200198 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200199 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200200 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200201 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200202 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200203 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200204 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200205 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200206 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200207 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200208 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200209 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200210 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200211 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200212 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200213 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200214 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200215 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200216 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200217 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200218 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200219 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200220 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200221 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200222 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200223 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200224 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200227 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200228 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
229 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
232 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200233 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200234 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200237 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200238 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
239 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
242 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200245 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200246 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
247 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200248 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200249 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
250 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800251 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200252 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
253 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800254 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200255 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
256 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800257 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200258 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
259 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800260 [RTL_GIGA_MAC_VER_37] =
261 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
262 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800263 [RTL_GIGA_MAC_VER_38] =
264 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
265 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800266 [RTL_GIGA_MAC_VER_39] =
267 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
268 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800269 [RTL_GIGA_MAC_VER_40] =
270 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
271 JUMBO_9K, false),
272 [RTL_GIGA_MAC_VER_41] =
273 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274};
275#undef _R
276
Francois Romieubcf0bf92006-07-26 23:14:13 +0200277enum cfg_version {
278 RTL_CFG_0 = 0x00,
279 RTL_CFG_1,
280 RTL_CFG_2
281};
282
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000283static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200284 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200285 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100287 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200289 { PCI_VENDOR_ID_DLINK, 0x4300,
290 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200291 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000292 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200293 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200294 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
295 { PCI_VENDOR_ID_LINKSYS, 0x1032,
296 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100297 { 0x0001, 0x8168,
298 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 {0,},
300};
301
302MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
303
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000304static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700305static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200306static struct {
307 u32 msg_enable;
308} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Francois Romieu07d3f512007-02-21 22:40:46 +0100310enum rtl_registers {
311 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100312 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100313 MAR0 = 8, /* Multicast filter. */
314 CounterAddrLow = 0x10,
315 CounterAddrHigh = 0x14,
316 TxDescStartAddrLow = 0x20,
317 TxDescStartAddrHigh = 0x24,
318 TxHDescStartAddrLow = 0x28,
319 TxHDescStartAddrHigh = 0x2c,
320 FLASH = 0x30,
321 ERSR = 0x36,
322 ChipCmd = 0x37,
323 TxPoll = 0x38,
324 IntrMask = 0x3c,
325 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700326
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800327 TxConfig = 0x40,
328#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
329#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
330
331 RxConfig = 0x44,
332#define RX128_INT_EN (1 << 15) /* 8111c and later */
333#define RX_MULTI_EN (1 << 14) /* 8111c only */
334#define RXCFG_FIFO_SHIFT 13
335 /* No threshold before first PCI xfer */
336#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
337#define RXCFG_DMA_SHIFT 8
338 /* Unlimited maximum PCI burst. */
339#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700340
Francois Romieu07d3f512007-02-21 22:40:46 +0100341 RxMissed = 0x4c,
342 Cfg9346 = 0x50,
343 Config0 = 0x51,
344 Config1 = 0x52,
345 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200346#define PME_SIGNAL (1 << 5) /* 8168c and later */
347
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 Config3 = 0x54,
349 Config4 = 0x55,
350 Config5 = 0x56,
351 MultiIntr = 0x5c,
352 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100353 PHYstatus = 0x6c,
354 RxMaxSize = 0xda,
355 CPlusCmd = 0xe0,
356 IntrMitigate = 0xe2,
357 RxDescAddrLow = 0xe4,
358 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000359 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
360
361#define NoEarlyTx 0x3f /* Max value : no early transmit. */
362
363 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
364
365#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800366#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000367
Francois Romieu07d3f512007-02-21 22:40:46 +0100368 FuncEvent = 0xf0,
369 FuncEventMask = 0xf4,
370 FuncPresetState = 0xf8,
371 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372};
373
Francois Romieuf162a5d2008-06-01 22:37:49 +0200374enum rtl8110_registers {
375 TBICSR = 0x64,
376 TBI_ANAR = 0x68,
377 TBI_LPAR = 0x6a,
378};
379
380enum rtl8168_8101_registers {
381 CSIDR = 0x64,
382 CSIAR = 0x68,
383#define CSIAR_FLAG 0x80000000
384#define CSIAR_WRITE_CMD 0x80000000
385#define CSIAR_BYTE_ENABLE 0x0f
386#define CSIAR_BYTE_ENABLE_SHIFT 12
387#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800388#define CSIAR_FUNC_CARD 0x00000000
389#define CSIAR_FUNC_SDIO 0x00010000
390#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000391 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200392 EPHYAR = 0x80,
393#define EPHYAR_FLAG 0x80000000
394#define EPHYAR_WRITE_CMD 0x80000000
395#define EPHYAR_REG_MASK 0x1f
396#define EPHYAR_REG_SHIFT 16
397#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800399#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200400 DBG_REG = 0xd1,
401#define FIX_NAK_1 (1 << 4)
402#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800403 TWSI = 0xd2,
404 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800405#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define TX_EMPTY (1 << 5)
407#define RX_EMPTY (1 << 4)
408#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800409#define EN_NDP (1 << 3)
410#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800411#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000412 EFUSEAR = 0xdc,
413#define EFUSEAR_FLAG 0x80000000
414#define EFUSEAR_WRITE_CMD 0x80000000
415#define EFUSEAR_READ_CMD 0x00000000
416#define EFUSEAR_REG_MASK 0x03ff
417#define EFUSEAR_REG_SHIFT 8
418#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200419};
420
françois romieuc0e45c12011-01-03 15:08:04 +0000421enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800422 LED_FREQ = 0x1a,
423 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000424 ERIDR = 0x70,
425 ERIAR = 0x74,
426#define ERIAR_FLAG 0x80000000
427#define ERIAR_WRITE_CMD 0x80000000
428#define ERIAR_READ_CMD 0x00000000
429#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000430#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800431#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
432#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
433#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
434#define ERIAR_MASK_SHIFT 12
435#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
436#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800437#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800438#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000439 EPHY_RXER_NUM = 0x7c,
440 OCPDR = 0xb0, /* OCP GPHY access */
441#define OCPDR_WRITE_CMD 0x80000000
442#define OCPDR_READ_CMD 0x00000000
443#define OCPDR_REG_MASK 0x7f
444#define OCPDR_GPHY_REG_SHIFT 16
445#define OCPDR_DATA_MASK 0xffff
446 OCPAR = 0xb4,
447#define OCPAR_FLAG 0x80000000
448#define OCPAR_GPHY_WRITE_CMD 0x8000f060
449#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800450 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000451 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
452 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200453#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800454#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800455#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800456#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800457#define EARLY_TALLY_EN (1 << 16)
hayeswangd64ec842012-11-01 16:46:28 +0000458#define FORCE_CLK (1 << 15) /* force clock request */
françois romieuc0e45c12011-01-03 15:08:04 +0000459};
460
Francois Romieu07d3f512007-02-21 22:40:46 +0100461enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100463 SYSErr = 0x8000,
464 PCSTimeout = 0x4000,
465 SWInt = 0x0100,
466 TxDescUnavail = 0x0080,
467 RxFIFOOver = 0x0040,
468 LinkChg = 0x0020,
469 RxOverflow = 0x0010,
470 TxErr = 0x0008,
471 TxOK = 0x0004,
472 RxErr = 0x0002,
473 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
475 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400476 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200477 RxFOVF = (1 << 23),
478 RxRWT = (1 << 22),
479 RxRES = (1 << 21),
480 RxRUNT = (1 << 20),
481 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800484 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100485 CmdReset = 0x10,
486 CmdRxEnb = 0x08,
487 CmdTxEnb = 0x04,
488 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Francois Romieu275391a2007-02-23 23:50:28 +0100490 /* TXPoll register p.5 */
491 HPQ = 0x80, /* Poll cmd on the high prio queue */
492 NPQ = 0x40, /* Poll cmd on the low prio queue */
493 FSWInt = 0x01, /* Forced software interrupt */
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100496 Cfg9346_Lock = 0x00,
497 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100500 AcceptErr = 0x20,
501 AcceptRunt = 0x10,
502 AcceptBroadcast = 0x08,
503 AcceptMulticast = 0x04,
504 AcceptMyPhys = 0x02,
505 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200506#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 /* TxConfigBits */
509 TxInterFrameGapShift = 24,
510 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
511
Francois Romieu5d06a992006-02-23 00:47:58 +0100512 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200513 LEDS1 = (1 << 7),
514 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200515 Speed_down = (1 << 4),
516 MEMMAP = (1 << 3),
517 IOMAP = (1 << 2),
518 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100519 PMEnable = (1 << 0), /* Power Management Enable */
520
Francois Romieu6dccd162007-02-13 23:38:05 +0100521 /* Config2 register p. 25 */
hayeswangd64ec842012-11-01 16:46:28 +0000522 ClkReqEn = (1 << 7), /* Clock Request Enable */
françois romieu2ca6cf02011-12-15 08:37:43 +0000523 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100524 PCI_Clock_66MHz = 0x01,
525 PCI_Clock_33MHz = 0x00,
526
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100527 /* Config3 register p.25 */
528 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
529 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200530 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200531 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100532
Francois Romieud58d46b2011-05-03 16:38:29 +0200533 /* Config4 register */
534 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
535
Francois Romieu5d06a992006-02-23 00:47:58 +0100536 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100537 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
538 MWF = (1 << 5), /* Accept Multicast wakeup frame */
539 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200540 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100541 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100542 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
hayeswangd64ec842012-11-01 16:46:28 +0000543 ASPM_en = (1 << 0), /* ASPM enable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 /* TBICSR p.28 */
546 TBIReset = 0x80000000,
547 TBILoopback = 0x40000000,
548 TBINwEnable = 0x20000000,
549 TBINwRestart = 0x10000000,
550 TBILinkOk = 0x02000000,
551 TBINwComplete = 0x01000000,
552
553 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200554 EnableBist = (1 << 15), // 8168 8101
555 Mac_dbgo_oe = (1 << 14), // 8168 8101
556 Normal_mode = (1 << 13), // unused
557 Force_half_dup = (1 << 12), // 8168 8101
558 Force_rxflow_en = (1 << 11), // 8168 8101
559 Force_txflow_en = (1 << 10), // 8168 8101
560 Cxpl_dbg_sel = (1 << 9), // 8168 8101
561 ASF = (1 << 8), // 8168 8101
562 PktCntrDisable = (1 << 7), // 8168 8101
563 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 RxVlan = (1 << 6),
565 RxChkSum = (1 << 5),
566 PCIDAC = (1 << 4),
567 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100568 INTT_0 = 0x0000, // 8168
569 INTT_1 = 0x0001, // 8168
570 INTT_2 = 0x0002, // 8168
571 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
573 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100574 TBI_Enable = 0x80,
575 TxFlowCtrl = 0x40,
576 RxFlowCtrl = 0x20,
577 _1000bpsF = 0x10,
578 _100bps = 0x08,
579 _10bps = 0x04,
580 LinkStatus = 0x02,
581 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100584 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200585
586 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100587 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588};
589
Francois Romieu2b7b4312011-04-18 22:53:24 -0700590enum rtl_desc_bit {
591 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
593 RingEnd = (1 << 30), /* End of descriptor ring */
594 FirstFrag = (1 << 29), /* First segment of a packet */
595 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700596};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Francois Romieu2b7b4312011-04-18 22:53:24 -0700598/* Generic case. */
599enum rtl_tx_desc_bit {
600 /* First doubleword. */
601 TD_LSO = (1 << 27), /* Large Send Offload */
602#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Francois Romieu2b7b4312011-04-18 22:53:24 -0700604 /* Second doubleword. */
605 TxVlanTag = (1 << 17), /* Add VLAN tag */
606};
607
608/* 8169, 8168b and 810x except 8102e. */
609enum rtl_tx_desc_bit_0 {
610 /* First doubleword. */
611#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
612 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
613 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
614 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
615};
616
617/* 8102e, 8168c and beyond. */
618enum rtl_tx_desc_bit_1 {
619 /* Second doubleword. */
620#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
621 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
622 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
623 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
624};
625
626static const struct rtl_tx_desc_info {
627 struct {
628 u32 udp;
629 u32 tcp;
630 } checksum;
631 u16 mss_shift;
632 u16 opts_offset;
633} tx_desc_info [] = {
634 [RTL_TD_0] = {
635 .checksum = {
636 .udp = TD0_IP_CS | TD0_UDP_CS,
637 .tcp = TD0_IP_CS | TD0_TCP_CS
638 },
639 .mss_shift = TD0_MSS_SHIFT,
640 .opts_offset = 0
641 },
642 [RTL_TD_1] = {
643 .checksum = {
644 .udp = TD1_IP_CS | TD1_UDP_CS,
645 .tcp = TD1_IP_CS | TD1_TCP_CS
646 },
647 .mss_shift = TD1_MSS_SHIFT,
648 .opts_offset = 1
649 }
650};
651
652enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 /* Rx private */
654 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
655 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
656
657#define RxProtoUDP (PID1)
658#define RxProtoTCP (PID0)
659#define RxProtoIP (PID1 | PID0)
660#define RxProtoMask RxProtoIP
661
662 IPFail = (1 << 16), /* IP checksum failed */
663 UDPFail = (1 << 15), /* UDP/IP checksum failed */
664 TCPFail = (1 << 14), /* TCP/IP checksum failed */
665 RxVlanTag = (1 << 16), /* VLAN tag available */
666};
667
668#define RsvdMask 0x3fffc000
669
670struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200671 __le32 opts1;
672 __le32 opts2;
673 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674};
675
676struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200677 __le32 opts1;
678 __le32 opts2;
679 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680};
681
682struct ring_info {
683 struct sk_buff *skb;
684 u32 len;
685 u8 __pad[sizeof(void *) - sizeof(u32)];
686};
687
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200688enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200689 RTL_FEATURE_WOL = (1 << 0),
690 RTL_FEATURE_MSI = (1 << 1),
691 RTL_FEATURE_GMII = (1 << 2),
hayeswange0c07552012-10-23 20:24:03 +0000692 RTL_FEATURE_FW_LOADED = (1 << 3),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200693};
694
Ivan Vecera355423d2009-02-06 21:49:57 -0800695struct rtl8169_counters {
696 __le64 tx_packets;
697 __le64 rx_packets;
698 __le64 tx_errors;
699 __le32 rx_errors;
700 __le16 rx_missed;
701 __le16 align_errors;
702 __le32 tx_one_collision;
703 __le32 tx_multi_collision;
704 __le64 rx_unicast;
705 __le64 rx_broadcast;
706 __le32 rx_multicast;
707 __le16 tx_aborted;
708 __le16 tx_underun;
709};
710
Francois Romieuda78dbf2012-01-26 14:18:23 +0100711enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100712 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100713 RTL_FLAG_TASK_SLOW_PENDING,
714 RTL_FLAG_TASK_RESET_PENDING,
715 RTL_FLAG_TASK_PHY_PENDING,
716 RTL_FLAG_MAX
717};
718
Junchang Wang8027aa22012-03-04 23:30:32 +0100719struct rtl8169_stats {
720 u64 packets;
721 u64 bytes;
722 struct u64_stats_sync syncp;
723};
724
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725struct rtl8169_private {
726 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200727 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000728 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700729 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200730 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700731 u16 txd_version;
732 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
734 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
735 u32 dirty_rx;
736 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100737 struct rtl8169_stats rx_stats;
738 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
740 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
741 dma_addr_t TxPhyAddr;
742 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000743 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 struct timer_list timer;
746 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100747
748 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000749
750 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200751 void (*write)(struct rtl8169_private *, int, int);
752 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000753 } mdio_ops;
754
françois romieu065c27c2011-01-03 15:08:12 +0000755 struct pll_power_ops {
756 void (*down)(struct rtl8169_private *);
757 void (*up)(struct rtl8169_private *);
758 } pll_power_ops;
759
Francois Romieud58d46b2011-05-03 16:38:29 +0200760 struct jumbo_ops {
761 void (*enable)(struct rtl8169_private *);
762 void (*disable)(struct rtl8169_private *);
763 } jumbo_ops;
764
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800765 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200766 void (*write)(struct rtl8169_private *, int, int);
767 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800768 } csi_ops;
769
Oliver Neukum54405cd2011-01-06 21:55:13 +0100770 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200771 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000772 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100773 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000774 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800776 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100777
778 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100779 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
780 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100781 struct work_struct work;
782 } wk;
783
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200784 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200785
786 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800787 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000788 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400789 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000790
Francois Romieub6ffd972011-06-17 17:00:05 +0200791 struct rtl_fw {
792 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200793
794#define RTL_VER_SIZE 32
795
796 char version[RTL_VER_SIZE];
797
798 struct rtl_fw_phy_action {
799 __le32 *code;
800 size_t size;
801 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200802 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300803#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800804
805 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806};
807
Ralf Baechle979b6c12005-06-13 14:30:40 -0700808MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700811MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200812module_param_named(debug, debug.msg_enable, int, 0);
813MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814MODULE_LICENSE("GPL");
815MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000816MODULE_FIRMWARE(FIRMWARE_8168D_1);
817MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000818MODULE_FIRMWARE(FIRMWARE_8168E_1);
819MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400820MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800821MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800822MODULE_FIRMWARE(FIRMWARE_8168F_1);
823MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800824MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800825MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800826MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800827MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Francois Romieuda78dbf2012-01-26 14:18:23 +0100829static void rtl_lock_work(struct rtl8169_private *tp)
830{
831 mutex_lock(&tp->wk.mutex);
832}
833
834static void rtl_unlock_work(struct rtl8169_private *tp)
835{
836 mutex_unlock(&tp->wk.mutex);
837}
838
Francois Romieud58d46b2011-05-03 16:38:29 +0200839static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
840{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800841 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
842 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200843}
844
Francois Romieuffc46952012-07-06 14:19:23 +0200845struct rtl_cond {
846 bool (*check)(struct rtl8169_private *);
847 const char *msg;
848};
849
850static void rtl_udelay(unsigned int d)
851{
852 udelay(d);
853}
854
855static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
856 void (*delay)(unsigned int), unsigned int d, int n,
857 bool high)
858{
859 int i;
860
861 for (i = 0; i < n; i++) {
862 delay(d);
863 if (c->check(tp) == high)
864 return true;
865 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200866 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
867 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200868 return false;
869}
870
871static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
872 const struct rtl_cond *c,
873 unsigned int d, int n)
874{
875 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
876}
877
878static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
879 const struct rtl_cond *c,
880 unsigned int d, int n)
881{
882 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
883}
884
885static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
886 const struct rtl_cond *c,
887 unsigned int d, int n)
888{
889 return rtl_loop_wait(tp, c, msleep, d, n, true);
890}
891
892static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
893 const struct rtl_cond *c,
894 unsigned int d, int n)
895{
896 return rtl_loop_wait(tp, c, msleep, d, n, false);
897}
898
899#define DECLARE_RTL_COND(name) \
900static bool name ## _check(struct rtl8169_private *); \
901 \
902static const struct rtl_cond name = { \
903 .check = name ## _check, \
904 .msg = #name \
905}; \
906 \
907static bool name ## _check(struct rtl8169_private *tp)
908
909DECLARE_RTL_COND(rtl_ocpar_cond)
910{
911 void __iomem *ioaddr = tp->mmio_addr;
912
913 return RTL_R32(OCPAR) & OCPAR_FLAG;
914}
915
françois romieub646d902011-01-03 15:08:21 +0000916static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
917{
918 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000919
920 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200921
922 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
923 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000924}
925
926static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
927{
928 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000929
930 RTL_W32(OCPDR, data);
931 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200932
933 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
934}
935
936DECLARE_RTL_COND(rtl_eriar_cond)
937{
938 void __iomem *ioaddr = tp->mmio_addr;
939
940 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000941}
942
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800943static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000944{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800945 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000946
947 RTL_W8(ERIDR, cmd);
948 RTL_W32(ERIAR, 0x800010e8);
949 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200950
951 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
952 return;
françois romieub646d902011-01-03 15:08:21 +0000953
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800954 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000955}
956
957#define OOB_CMD_RESET 0x00
958#define OOB_CMD_DRIVER_START 0x05
959#define OOB_CMD_DRIVER_STOP 0x06
960
Francois Romieucecb5fd2011-04-01 10:21:07 +0200961static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
962{
963 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
964}
965
Francois Romieuffc46952012-07-06 14:19:23 +0200966DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000967{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200968 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000969
Francois Romieucecb5fd2011-04-01 10:21:07 +0200970 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000971
Francois Romieuffc46952012-07-06 14:19:23 +0200972 return ocp_read(tp, 0x0f, reg) & 0x00000800;
973}
974
975static void rtl8168_driver_start(struct rtl8169_private *tp)
976{
977 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
978
979 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000980}
981
982static void rtl8168_driver_stop(struct rtl8169_private *tp)
983{
françois romieub646d902011-01-03 15:08:21 +0000984 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
985
Francois Romieuffc46952012-07-06 14:19:23 +0200986 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000987}
988
hayeswang4804b3b2011-03-21 01:50:29 +0000989static int r8168dp_check_dash(struct rtl8169_private *tp)
990{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200991 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000992
Francois Romieucecb5fd2011-04-01 10:21:07 +0200993 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000994}
françois romieub646d902011-01-03 15:08:21 +0000995
Hayes Wangc5583862012-07-02 17:23:22 +0800996static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
997{
998 if (reg & 0xffff0001) {
999 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
1000 return true;
1001 }
1002 return false;
1003}
1004
1005DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1006{
1007 void __iomem *ioaddr = tp->mmio_addr;
1008
1009 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1010}
1011
1012static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1013{
1014 void __iomem *ioaddr = tp->mmio_addr;
1015
1016 if (rtl_ocp_reg_failure(tp, reg))
1017 return;
1018
1019 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1020
1021 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1022}
1023
1024static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1025{
1026 void __iomem *ioaddr = tp->mmio_addr;
1027
1028 if (rtl_ocp_reg_failure(tp, reg))
1029 return 0;
1030
1031 RTL_W32(GPHY_OCP, reg << 15);
1032
1033 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1034 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1035}
1036
1037static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1038{
1039 int val;
1040
1041 val = r8168_phy_ocp_read(tp, reg);
1042 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1043}
1044
Hayes Wangc5583862012-07-02 17:23:22 +08001045static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1046{
1047 void __iomem *ioaddr = tp->mmio_addr;
1048
1049 if (rtl_ocp_reg_failure(tp, reg))
1050 return;
1051
1052 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001053}
1054
1055static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1056{
1057 void __iomem *ioaddr = tp->mmio_addr;
1058
1059 if (rtl_ocp_reg_failure(tp, reg))
1060 return 0;
1061
1062 RTL_W32(OCPDR, reg << 15);
1063
Hayes Wang3a83ad12012-07-11 20:31:56 +08001064 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001065}
1066
1067#define OCP_STD_PHY_BASE 0xa400
1068
1069static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1070{
1071 if (reg == 0x1f) {
1072 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1073 return;
1074 }
1075
1076 if (tp->ocp_base != OCP_STD_PHY_BASE)
1077 reg -= 0x10;
1078
1079 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1080}
1081
1082static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1083{
1084 if (tp->ocp_base != OCP_STD_PHY_BASE)
1085 reg -= 0x10;
1086
1087 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1088}
1089
Francois Romieuffc46952012-07-06 14:19:23 +02001090DECLARE_RTL_COND(rtl_phyar_cond)
1091{
1092 void __iomem *ioaddr = tp->mmio_addr;
1093
1094 return RTL_R32(PHYAR) & 0x80000000;
1095}
1096
Francois Romieu24192212012-07-06 20:19:42 +02001097static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
Francois Romieu24192212012-07-06 20:19:42 +02001099 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Francois Romieu24192212012-07-06 20:19:42 +02001101 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Francois Romieuffc46952012-07-06 14:19:23 +02001103 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001104 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001105 * According to hardware specs a 20us delay is required after write
1106 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001107 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001108 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
Francois Romieu24192212012-07-06 20:19:42 +02001111static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112{
Francois Romieu24192212012-07-06 20:19:42 +02001113 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001114 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Francois Romieu24192212012-07-06 20:19:42 +02001116 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Francois Romieuffc46952012-07-06 14:19:23 +02001118 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1119 RTL_R32(PHYAR) & 0xffff : ~0;
1120
Timo Teräs81a95f02010-06-09 17:31:48 -07001121 /*
1122 * According to hardware specs a 20us delay is required after read
1123 * complete indication, but before sending next command.
1124 */
1125 udelay(20);
1126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 return value;
1128}
1129
Francois Romieu24192212012-07-06 20:19:42 +02001130static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001131{
Francois Romieu24192212012-07-06 20:19:42 +02001132 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001133
Francois Romieu24192212012-07-06 20:19:42 +02001134 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001135 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1136 RTL_W32(EPHY_RXER_NUM, 0);
1137
Francois Romieuffc46952012-07-06 14:19:23 +02001138 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001139}
1140
Francois Romieu24192212012-07-06 20:19:42 +02001141static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001142{
Francois Romieu24192212012-07-06 20:19:42 +02001143 r8168dp_1_mdio_access(tp, reg,
1144 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001145}
1146
Francois Romieu24192212012-07-06 20:19:42 +02001147static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001148{
Francois Romieu24192212012-07-06 20:19:42 +02001149 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001150
Francois Romieu24192212012-07-06 20:19:42 +02001151 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001152
1153 mdelay(1);
1154 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1155 RTL_W32(EPHY_RXER_NUM, 0);
1156
Francois Romieuffc46952012-07-06 14:19:23 +02001157 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1158 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001159}
1160
françois romieue6de30d2011-01-03 15:08:37 +00001161#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1162
1163static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1164{
1165 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1166}
1167
1168static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1169{
1170 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1171}
1172
Francois Romieu24192212012-07-06 20:19:42 +02001173static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001174{
Francois Romieu24192212012-07-06 20:19:42 +02001175 void __iomem *ioaddr = tp->mmio_addr;
1176
françois romieue6de30d2011-01-03 15:08:37 +00001177 r8168dp_2_mdio_start(ioaddr);
1178
Francois Romieu24192212012-07-06 20:19:42 +02001179 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001180
1181 r8168dp_2_mdio_stop(ioaddr);
1182}
1183
Francois Romieu24192212012-07-06 20:19:42 +02001184static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001185{
Francois Romieu24192212012-07-06 20:19:42 +02001186 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001187 int value;
1188
1189 r8168dp_2_mdio_start(ioaddr);
1190
Francois Romieu24192212012-07-06 20:19:42 +02001191 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001192
1193 r8168dp_2_mdio_stop(ioaddr);
1194
1195 return value;
1196}
1197
françois romieu4da19632011-01-03 15:07:55 +00001198static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001199{
Francois Romieu24192212012-07-06 20:19:42 +02001200 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001201}
1202
françois romieu4da19632011-01-03 15:07:55 +00001203static int rtl_readphy(struct rtl8169_private *tp, int location)
1204{
Francois Romieu24192212012-07-06 20:19:42 +02001205 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001206}
1207
1208static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1209{
1210 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1211}
1212
1213static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001214{
1215 int val;
1216
françois romieu4da19632011-01-03 15:07:55 +00001217 val = rtl_readphy(tp, reg_addr);
1218 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001219}
1220
Francois Romieuccdffb92008-07-26 14:26:06 +02001221static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1222 int val)
1223{
1224 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001225
françois romieu4da19632011-01-03 15:07:55 +00001226 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001227}
1228
1229static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1230{
1231 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001232
françois romieu4da19632011-01-03 15:07:55 +00001233 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001234}
1235
Francois Romieuffc46952012-07-06 14:19:23 +02001236DECLARE_RTL_COND(rtl_ephyar_cond)
1237{
1238 void __iomem *ioaddr = tp->mmio_addr;
1239
1240 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1241}
1242
Francois Romieufdf6fc02012-07-06 22:40:38 +02001243static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001244{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001245 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001246
1247 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1248 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1249
Francois Romieuffc46952012-07-06 14:19:23 +02001250 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1251
1252 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001253}
1254
Francois Romieufdf6fc02012-07-06 22:40:38 +02001255static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001256{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001257 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001258
1259 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1260
Francois Romieuffc46952012-07-06 14:19:23 +02001261 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1262 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001263}
1264
Francois Romieufdf6fc02012-07-06 22:40:38 +02001265static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1266 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001267{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001268 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001269
1270 BUG_ON((addr & 3) || (mask == 0));
1271 RTL_W32(ERIDR, val);
1272 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1273
Francois Romieuffc46952012-07-06 14:19:23 +02001274 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001275}
1276
Francois Romieufdf6fc02012-07-06 22:40:38 +02001277static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001278{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001279 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001280
1281 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1282
Francois Romieuffc46952012-07-06 14:19:23 +02001283 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1284 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001285}
1286
Francois Romieufdf6fc02012-07-06 22:40:38 +02001287static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1288 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001289{
1290 u32 val;
1291
Francois Romieufdf6fc02012-07-06 22:40:38 +02001292 val = rtl_eri_read(tp, addr, type);
1293 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001294}
1295
françois romieuc28aa382011-08-02 03:53:43 +00001296struct exgmac_reg {
1297 u16 addr;
1298 u16 mask;
1299 u32 val;
1300};
1301
Francois Romieufdf6fc02012-07-06 22:40:38 +02001302static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001303 const struct exgmac_reg *r, int len)
1304{
1305 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001306 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001307 r++;
1308 }
1309}
1310
Francois Romieuffc46952012-07-06 14:19:23 +02001311DECLARE_RTL_COND(rtl_efusear_cond)
1312{
1313 void __iomem *ioaddr = tp->mmio_addr;
1314
1315 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1316}
1317
Francois Romieufdf6fc02012-07-06 22:40:38 +02001318static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001319{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001320 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001321
1322 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1323
Francois Romieuffc46952012-07-06 14:19:23 +02001324 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1325 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001326}
1327
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001328static u16 rtl_get_events(struct rtl8169_private *tp)
1329{
1330 void __iomem *ioaddr = tp->mmio_addr;
1331
1332 return RTL_R16(IntrStatus);
1333}
1334
1335static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1336{
1337 void __iomem *ioaddr = tp->mmio_addr;
1338
1339 RTL_W16(IntrStatus, bits);
1340 mmiowb();
1341}
1342
1343static void rtl_irq_disable(struct rtl8169_private *tp)
1344{
1345 void __iomem *ioaddr = tp->mmio_addr;
1346
1347 RTL_W16(IntrMask, 0);
1348 mmiowb();
1349}
1350
Francois Romieu3e990ff2012-01-26 12:50:01 +01001351static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1352{
1353 void __iomem *ioaddr = tp->mmio_addr;
1354
1355 RTL_W16(IntrMask, bits);
1356}
1357
Francois Romieuda78dbf2012-01-26 14:18:23 +01001358#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1359#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1360#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1361
1362static void rtl_irq_enable_all(struct rtl8169_private *tp)
1363{
1364 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1365}
1366
françois romieu811fd302011-12-04 20:30:45 +00001367static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368{
françois romieu811fd302011-12-04 20:30:45 +00001369 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001371 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001372 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001373 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374}
1375
françois romieu4da19632011-01-03 15:07:55 +00001376static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
françois romieu4da19632011-01-03 15:07:55 +00001378 void __iomem *ioaddr = tp->mmio_addr;
1379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 return RTL_R32(TBICSR) & TBIReset;
1381}
1382
françois romieu4da19632011-01-03 15:07:55 +00001383static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384{
françois romieu4da19632011-01-03 15:07:55 +00001385 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386}
1387
1388static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1389{
1390 return RTL_R32(TBICSR) & TBILinkOk;
1391}
1392
1393static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1394{
1395 return RTL_R8(PHYstatus) & LinkStatus;
1396}
1397
françois romieu4da19632011-01-03 15:07:55 +00001398static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399{
françois romieu4da19632011-01-03 15:07:55 +00001400 void __iomem *ioaddr = tp->mmio_addr;
1401
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1403}
1404
françois romieu4da19632011-01-03 15:07:55 +00001405static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406{
1407 unsigned int val;
1408
françois romieu4da19632011-01-03 15:07:55 +00001409 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1410 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411}
1412
Hayes Wang70090422011-07-06 15:58:06 +08001413static void rtl_link_chg_patch(struct rtl8169_private *tp)
1414{
1415 void __iomem *ioaddr = tp->mmio_addr;
1416 struct net_device *dev = tp->dev;
1417
1418 if (!netif_running(dev))
1419 return;
1420
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001421 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1422 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001423 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001424 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1425 ERIAR_EXGMAC);
1426 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1427 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001428 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001429 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1430 ERIAR_EXGMAC);
1431 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1432 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001433 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001434 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1435 ERIAR_EXGMAC);
1436 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1437 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001438 }
1439 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001440 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001441 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001442 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001443 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001444 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1445 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1446 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001447 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1448 ERIAR_EXGMAC);
1449 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1450 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001451 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001452 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1453 ERIAR_EXGMAC);
1454 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1455 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001456 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001457 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1458 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001459 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1460 ERIAR_EXGMAC);
1461 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1462 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001463 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001464 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1465 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001466 }
Hayes Wang70090422011-07-06 15:58:06 +08001467 }
1468}
1469
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001470static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001471 struct rtl8169_private *tp,
1472 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001475 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001476 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001477 if (pm)
1478 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001480 if (net_ratelimit())
1481 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001482 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001484 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001485 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001486 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488}
1489
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001490static void rtl8169_check_link_status(struct net_device *dev,
1491 struct rtl8169_private *tp,
1492 void __iomem *ioaddr)
1493{
1494 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1495}
1496
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001497#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1498
1499static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1500{
1501 void __iomem *ioaddr = tp->mmio_addr;
1502 u8 options;
1503 u32 wolopts = 0;
1504
1505 options = RTL_R8(Config1);
1506 if (!(options & PMEnable))
1507 return 0;
1508
1509 options = RTL_R8(Config3);
1510 if (options & LinkUp)
1511 wolopts |= WAKE_PHY;
1512 if (options & MagicPacket)
1513 wolopts |= WAKE_MAGIC;
1514
1515 options = RTL_R8(Config5);
1516 if (options & UWF)
1517 wolopts |= WAKE_UCAST;
1518 if (options & BWF)
1519 wolopts |= WAKE_BCAST;
1520 if (options & MWF)
1521 wolopts |= WAKE_MCAST;
1522
1523 return wolopts;
1524}
1525
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1527{
1528 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001529
Francois Romieuda78dbf2012-01-26 14:18:23 +01001530 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001531
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001532 wol->supported = WAKE_ANY;
1533 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534
Francois Romieuda78dbf2012-01-26 14:18:23 +01001535 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001536}
1537
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001538static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001539{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001540 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001541 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001542 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001543 u32 opt;
1544 u16 reg;
1545 u8 mask;
1546 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001547 { WAKE_PHY, Config3, LinkUp },
1548 { WAKE_MAGIC, Config3, MagicPacket },
1549 { WAKE_UCAST, Config5, UWF },
1550 { WAKE_BCAST, Config5, BWF },
1551 { WAKE_MCAST, Config5, MWF },
1552 { WAKE_ANY, Config5, LanWake }
1553 };
Francois Romieu851e6022012-04-17 11:10:11 +02001554 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001555
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001556 RTL_W8(Cfg9346, Cfg9346_Unlock);
1557
1558 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001559 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001560 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001561 options |= cfg[i].mask;
1562 RTL_W8(cfg[i].reg, options);
1563 }
1564
Francois Romieu851e6022012-04-17 11:10:11 +02001565 switch (tp->mac_version) {
1566 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1567 options = RTL_R8(Config1) & ~PMEnable;
1568 if (wolopts)
1569 options |= PMEnable;
1570 RTL_W8(Config1, options);
1571 break;
1572 default:
Francois Romieud387b422012-04-17 11:12:01 +02001573 options = RTL_R8(Config2) & ~PME_SIGNAL;
1574 if (wolopts)
1575 options |= PME_SIGNAL;
1576 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001577 break;
1578 }
1579
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001580 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001581}
1582
1583static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1584{
1585 struct rtl8169_private *tp = netdev_priv(dev);
1586
Francois Romieuda78dbf2012-01-26 14:18:23 +01001587 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001588
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001589 if (wol->wolopts)
1590 tp->features |= RTL_FEATURE_WOL;
1591 else
1592 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001593 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001594
1595 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001596
françois romieuea809072010-11-08 13:23:58 +00001597 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1598
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001599 return 0;
1600}
1601
Francois Romieu31bd2042011-04-26 18:58:59 +02001602static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1603{
Francois Romieu85bffe62011-04-27 08:22:39 +02001604 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001605}
1606
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607static void rtl8169_get_drvinfo(struct net_device *dev,
1608 struct ethtool_drvinfo *info)
1609{
1610 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001611 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Rick Jones68aad782011-11-07 13:29:27 +00001613 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1614 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1615 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001616 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001617 if (!IS_ERR_OR_NULL(rtl_fw))
1618 strlcpy(info->fw_version, rtl_fw->version,
1619 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620}
1621
1622static int rtl8169_get_regs_len(struct net_device *dev)
1623{
1624 return R8169_REGS_SIZE;
1625}
1626
1627static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001628 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629{
1630 struct rtl8169_private *tp = netdev_priv(dev);
1631 void __iomem *ioaddr = tp->mmio_addr;
1632 int ret = 0;
1633 u32 reg;
1634
1635 reg = RTL_R32(TBICSR);
1636 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1637 (duplex == DUPLEX_FULL)) {
1638 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1639 } else if (autoneg == AUTONEG_ENABLE)
1640 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1641 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001642 netif_warn(tp, link, dev,
1643 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 ret = -EOPNOTSUPP;
1645 }
1646
1647 return ret;
1648}
1649
1650static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001651 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
1653 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001654 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001655 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
Hayes Wang716b50a2011-02-22 17:26:18 +08001657 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
1659 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001660 int auto_nego;
1661
françois romieu4da19632011-01-03 15:07:55 +00001662 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001663 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1664 ADVERTISE_100HALF | ADVERTISE_100FULL);
1665
1666 if (adv & ADVERTISED_10baseT_Half)
1667 auto_nego |= ADVERTISE_10HALF;
1668 if (adv & ADVERTISED_10baseT_Full)
1669 auto_nego |= ADVERTISE_10FULL;
1670 if (adv & ADVERTISED_100baseT_Half)
1671 auto_nego |= ADVERTISE_100HALF;
1672 if (adv & ADVERTISED_100baseT_Full)
1673 auto_nego |= ADVERTISE_100FULL;
1674
françois romieu3577aa12009-05-19 10:46:48 +00001675 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1676
françois romieu4da19632011-01-03 15:07:55 +00001677 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001678 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1679
1680 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001681 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001682 if (adv & ADVERTISED_1000baseT_Half)
1683 giga_ctrl |= ADVERTISE_1000HALF;
1684 if (adv & ADVERTISED_1000baseT_Full)
1685 giga_ctrl |= ADVERTISE_1000FULL;
1686 } else if (adv & (ADVERTISED_1000baseT_Half |
1687 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001688 netif_info(tp, link, dev,
1689 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001690 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
françois romieu3577aa12009-05-19 10:46:48 +00001693 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001694
françois romieu4da19632011-01-03 15:07:55 +00001695 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1696 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001697 } else {
1698 giga_ctrl = 0;
1699
1700 if (speed == SPEED_10)
1701 bmcr = 0;
1702 else if (speed == SPEED_100)
1703 bmcr = BMCR_SPEED100;
1704 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001705 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001706
1707 if (duplex == DUPLEX_FULL)
1708 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001709 }
1710
françois romieu4da19632011-01-03 15:07:55 +00001711 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001712
Francois Romieucecb5fd2011-04-01 10:21:07 +02001713 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1714 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001715 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001716 rtl_writephy(tp, 0x17, 0x2138);
1717 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001718 } else {
françois romieu4da19632011-01-03 15:07:55 +00001719 rtl_writephy(tp, 0x17, 0x2108);
1720 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001721 }
1722 }
1723
Oliver Neukum54405cd2011-01-06 21:55:13 +01001724 rc = 0;
1725out:
1726 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727}
1728
1729static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001730 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731{
1732 struct rtl8169_private *tp = netdev_priv(dev);
1733 int ret;
1734
Oliver Neukum54405cd2011-01-06 21:55:13 +01001735 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001736 if (ret < 0)
1737 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
Francois Romieu4876cc12011-03-11 21:07:11 +01001739 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1740 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001742 }
1743out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 return ret;
1745}
1746
1747static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1748{
1749 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 int ret;
1751
Francois Romieu4876cc12011-03-11 21:07:11 +01001752 del_timer_sync(&tp->timer);
1753
Francois Romieuda78dbf2012-01-26 14:18:23 +01001754 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001755 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001756 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001757 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001758
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 return ret;
1760}
1761
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001762static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1763 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764{
Francois Romieud58d46b2011-05-03 16:38:29 +02001765 struct rtl8169_private *tp = netdev_priv(dev);
1766
Francois Romieu2b7b4312011-04-18 22:53:24 -07001767 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001768 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Francois Romieud58d46b2011-05-03 16:38:29 +02001770 if (dev->mtu > JUMBO_1K &&
1771 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1772 features &= ~NETIF_F_IP_CSUM;
1773
Michał Mirosław350fb322011-04-08 06:35:56 +00001774 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775}
1776
Francois Romieuda78dbf2012-01-26 14:18:23 +01001777static void __rtl8169_set_features(struct net_device *dev,
1778 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779{
1780 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001781 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001782 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Ben Greear6bbe0212012-02-10 15:04:33 +00001784 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1785 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
Ben Greear6bbe0212012-02-10 15:04:33 +00001787 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1788 if (features & NETIF_F_RXCSUM)
1789 tp->cp_cmd |= RxChkSum;
1790 else
1791 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001792
Ben Greear6bbe0212012-02-10 15:04:33 +00001793 if (dev->features & NETIF_F_HW_VLAN_RX)
1794 tp->cp_cmd |= RxVlan;
1795 else
1796 tp->cp_cmd &= ~RxVlan;
1797
1798 RTL_W16(CPlusCmd, tp->cp_cmd);
1799 RTL_R16(CPlusCmd);
1800 }
1801 if (changed & NETIF_F_RXALL) {
1802 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1803 if (features & NETIF_F_RXALL)
1804 tmp |= (AcceptErr | AcceptRunt);
1805 RTL_W32(RxConfig, tmp);
1806 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001807}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
Francois Romieuda78dbf2012-01-26 14:18:23 +01001809static int rtl8169_set_features(struct net_device *dev,
1810 netdev_features_t features)
1811{
1812 struct rtl8169_private *tp = netdev_priv(dev);
1813
1814 rtl_lock_work(tp);
1815 __rtl8169_set_features(dev, features);
1816 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 return 0;
1819}
1820
Francois Romieuda78dbf2012-01-26 14:18:23 +01001821
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
1823 struct sk_buff *skb)
1824{
Jesse Grosseab6d182010-10-20 13:56:03 +00001825 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1827}
1828
Francois Romieu7a8fc772011-03-01 17:18:33 +01001829static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
1831 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
Francois Romieu7a8fc772011-03-01 17:18:33 +01001833 if (opts2 & RxVlanTag)
1834 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Eric Dumazet2edae082010-09-06 18:46:39 +00001835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 desc->opts2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837}
1838
Francois Romieuccdffb92008-07-26 14:26:06 +02001839static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840{
1841 struct rtl8169_private *tp = netdev_priv(dev);
1842 void __iomem *ioaddr = tp->mmio_addr;
1843 u32 status;
1844
1845 cmd->supported =
1846 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1847 cmd->port = PORT_FIBRE;
1848 cmd->transceiver = XCVR_INTERNAL;
1849
1850 status = RTL_R32(TBICSR);
1851 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1852 cmd->autoneg = !!(status & TBINwEnable);
1853
David Decotigny70739492011-04-27 18:32:40 +00001854 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001856
1857 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
Francois Romieuccdffb92008-07-26 14:26:06 +02001860static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
1862 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Francois Romieuccdffb92008-07-26 14:26:06 +02001864 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865}
1866
1867static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1868{
1869 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001870 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Francois Romieuda78dbf2012-01-26 14:18:23 +01001872 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001873 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001874 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Francois Romieuccdffb92008-07-26 14:26:06 +02001876 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877}
1878
1879static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1880 void *p)
1881{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001882 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Francois Romieu5b0384f2006-08-16 16:00:01 +02001884 if (regs->len > R8169_REGS_SIZE)
1885 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886
Francois Romieuda78dbf2012-01-26 14:18:23 +01001887 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001888 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001889 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890}
1891
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001892static u32 rtl8169_get_msglevel(struct net_device *dev)
1893{
1894 struct rtl8169_private *tp = netdev_priv(dev);
1895
1896 return tp->msg_enable;
1897}
1898
1899static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1900{
1901 struct rtl8169_private *tp = netdev_priv(dev);
1902
1903 tp->msg_enable = value;
1904}
1905
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001906static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1907 "tx_packets",
1908 "rx_packets",
1909 "tx_errors",
1910 "rx_errors",
1911 "rx_missed",
1912 "align_errors",
1913 "tx_single_collisions",
1914 "tx_multi_collisions",
1915 "unicast",
1916 "broadcast",
1917 "multicast",
1918 "tx_aborted",
1919 "tx_underrun",
1920};
1921
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001922static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001923{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001924 switch (sset) {
1925 case ETH_SS_STATS:
1926 return ARRAY_SIZE(rtl8169_gstrings);
1927 default:
1928 return -EOPNOTSUPP;
1929 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001930}
1931
Francois Romieuffc46952012-07-06 14:19:23 +02001932DECLARE_RTL_COND(rtl_counters_cond)
1933{
1934 void __iomem *ioaddr = tp->mmio_addr;
1935
1936 return RTL_R32(CounterAddrLow) & CounterDump;
1937}
1938
Ivan Vecera355423d2009-02-06 21:49:57 -08001939static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001940{
1941 struct rtl8169_private *tp = netdev_priv(dev);
1942 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001943 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001944 struct rtl8169_counters *counters;
1945 dma_addr_t paddr;
1946 u32 cmd;
1947
Ivan Vecera355423d2009-02-06 21:49:57 -08001948 /*
1949 * Some chips are unable to dump tally counters when the receiver
1950 * is disabled.
1951 */
1952 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1953 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001954
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001955 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001956 if (!counters)
1957 return;
1958
1959 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001960 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001961 RTL_W32(CounterAddrLow, cmd);
1962 RTL_W32(CounterAddrLow, cmd | CounterDump);
1963
Francois Romieuffc46952012-07-06 14:19:23 +02001964 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1965 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001966
1967 RTL_W32(CounterAddrLow, 0);
1968 RTL_W32(CounterAddrHigh, 0);
1969
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001970 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001971}
1972
Ivan Vecera355423d2009-02-06 21:49:57 -08001973static void rtl8169_get_ethtool_stats(struct net_device *dev,
1974 struct ethtool_stats *stats, u64 *data)
1975{
1976 struct rtl8169_private *tp = netdev_priv(dev);
1977
1978 ASSERT_RTNL();
1979
1980 rtl8169_update_counters(dev);
1981
1982 data[0] = le64_to_cpu(tp->counters.tx_packets);
1983 data[1] = le64_to_cpu(tp->counters.rx_packets);
1984 data[2] = le64_to_cpu(tp->counters.tx_errors);
1985 data[3] = le32_to_cpu(tp->counters.rx_errors);
1986 data[4] = le16_to_cpu(tp->counters.rx_missed);
1987 data[5] = le16_to_cpu(tp->counters.align_errors);
1988 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1989 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1990 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1991 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1992 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1993 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1994 data[12] = le16_to_cpu(tp->counters.tx_underun);
1995}
1996
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001997static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1998{
1999 switch(stringset) {
2000 case ETH_SS_STATS:
2001 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
2002 break;
2003 }
2004}
2005
Jeff Garzik7282d492006-09-13 14:30:00 -04002006static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 .get_drvinfo = rtl8169_get_drvinfo,
2008 .get_regs_len = rtl8169_get_regs_len,
2009 .get_link = ethtool_op_get_link,
2010 .get_settings = rtl8169_get_settings,
2011 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002012 .get_msglevel = rtl8169_get_msglevel,
2013 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002015 .get_wol = rtl8169_get_wol,
2016 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002017 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002018 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002019 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002020 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021};
2022
Francois Romieu07d3f512007-02-21 22:40:46 +01002023static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002024 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025{
Francois Romieu5d320a22011-05-08 17:47:36 +02002026 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002027 /*
2028 * The driver currently handles the 8168Bf and the 8168Be identically
2029 * but they can be identified more specifically through the test below
2030 * if needed:
2031 *
2032 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002033 *
2034 * Same thing for the 8101Eb and the 8101Ec:
2035 *
2036 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002037 */
Francois Romieu37441002011-06-17 22:58:54 +02002038 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002040 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 int mac_version;
2042 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002043 /* 8168G family. */
2044 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2045 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2046
Hayes Wangc2218922011-09-06 16:55:18 +08002047 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002048 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002049 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2050 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2051
hayeswang01dc7fe2011-03-21 01:50:28 +00002052 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002053 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002054 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2055 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2056 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2057
Francois Romieu5b538df2008-07-20 16:22:45 +02002058 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002059 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2060 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002061 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002062
françois romieue6de30d2011-01-03 15:08:37 +00002063 /* 8168DP family. */
2064 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2065 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002066 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002067
Francois Romieuef808d52008-06-29 13:10:54 +02002068 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002069 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002070 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002071 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002072 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002073 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2074 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002075 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002076 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002077 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002078
2079 /* 8168B family. */
2080 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2081 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2082 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2083 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2084
2085 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002086 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2087 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002088 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002089 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002090 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2091 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2092 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002093 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2094 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2095 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2096 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2097 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2098 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002099 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002100 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002101 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002102 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2103 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002104 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2105 /* FIXME: where did these entries come from ? -- FR */
2106 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2107 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2108
2109 /* 8110 family. */
2110 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2111 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2112 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2113 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2114 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2115 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2116
Jean Delvaref21b75e2009-05-26 20:54:48 -07002117 /* Catch-all */
2118 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002119 };
2120 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 u32 reg;
2122
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002123 reg = RTL_R32(TxConfig);
2124 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 p++;
2126 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002127
2128 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2129 netif_notice(tp, probe, dev,
2130 "unknown MAC, using family default\n");
2131 tp->mac_version = default_version;
2132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133}
2134
2135static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2136{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002137 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138}
2139
Francois Romieu867763c2007-08-17 18:21:58 +02002140struct phy_reg {
2141 u16 reg;
2142 u16 val;
2143};
2144
françois romieu4da19632011-01-03 15:07:55 +00002145static void rtl_writephy_batch(struct rtl8169_private *tp,
2146 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002147{
2148 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002149 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002150 regs++;
2151 }
2152}
2153
françois romieubca03d52011-01-03 15:07:31 +00002154#define PHY_READ 0x00000000
2155#define PHY_DATA_OR 0x10000000
2156#define PHY_DATA_AND 0x20000000
2157#define PHY_BJMPN 0x30000000
2158#define PHY_READ_EFUSE 0x40000000
2159#define PHY_READ_MAC_BYTE 0x50000000
2160#define PHY_WRITE_MAC_BYTE 0x60000000
2161#define PHY_CLEAR_READCOUNT 0x70000000
2162#define PHY_WRITE 0x80000000
2163#define PHY_READCOUNT_EQ_SKIP 0x90000000
2164#define PHY_COMP_EQ_SKIPN 0xa0000000
2165#define PHY_COMP_NEQ_SKIPN 0xb0000000
2166#define PHY_WRITE_PREVIOUS 0xc0000000
2167#define PHY_SKIPN 0xd0000000
2168#define PHY_DELAY_MS 0xe0000000
2169#define PHY_WRITE_ERI_WORD 0xf0000000
2170
Hayes Wang960aee62011-06-18 11:37:48 +02002171struct fw_info {
2172 u32 magic;
2173 char version[RTL_VER_SIZE];
2174 __le32 fw_start;
2175 __le32 fw_len;
2176 u8 chksum;
2177} __packed;
2178
Francois Romieu1c361ef2011-06-17 17:16:24 +02002179#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2180
2181static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002182{
Francois Romieub6ffd972011-06-17 17:00:05 +02002183 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002184 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002185 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2186 char *version = rtl_fw->version;
2187 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002188
Francois Romieu1c361ef2011-06-17 17:16:24 +02002189 if (fw->size < FW_OPCODE_SIZE)
2190 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002191
2192 if (!fw_info->magic) {
2193 size_t i, size, start;
2194 u8 checksum = 0;
2195
2196 if (fw->size < sizeof(*fw_info))
2197 goto out;
2198
2199 for (i = 0; i < fw->size; i++)
2200 checksum += fw->data[i];
2201 if (checksum != 0)
2202 goto out;
2203
2204 start = le32_to_cpu(fw_info->fw_start);
2205 if (start > fw->size)
2206 goto out;
2207
2208 size = le32_to_cpu(fw_info->fw_len);
2209 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2210 goto out;
2211
2212 memcpy(version, fw_info->version, RTL_VER_SIZE);
2213
2214 pa->code = (__le32 *)(fw->data + start);
2215 pa->size = size;
2216 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002217 if (fw->size % FW_OPCODE_SIZE)
2218 goto out;
2219
2220 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2221
2222 pa->code = (__le32 *)fw->data;
2223 pa->size = fw->size / FW_OPCODE_SIZE;
2224 }
2225 version[RTL_VER_SIZE - 1] = 0;
2226
2227 rc = true;
2228out:
2229 return rc;
2230}
2231
Francois Romieufd112f22011-06-18 00:10:29 +02002232static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2233 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002234{
Francois Romieufd112f22011-06-18 00:10:29 +02002235 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002236 size_t index;
2237
Francois Romieu1c361ef2011-06-17 17:16:24 +02002238 for (index = 0; index < pa->size; index++) {
2239 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002240 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002241
hayeswang42b82dc2011-01-10 02:07:25 +00002242 switch(action & 0xf0000000) {
2243 case PHY_READ:
2244 case PHY_DATA_OR:
2245 case PHY_DATA_AND:
2246 case PHY_READ_EFUSE:
2247 case PHY_CLEAR_READCOUNT:
2248 case PHY_WRITE:
2249 case PHY_WRITE_PREVIOUS:
2250 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002251 break;
2252
hayeswang42b82dc2011-01-10 02:07:25 +00002253 case PHY_BJMPN:
2254 if (regno > index) {
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_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002261 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002262 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002263 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002264 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002265 }
2266 break;
2267 case PHY_COMP_EQ_SKIPN:
2268 case PHY_COMP_NEQ_SKIPN:
2269 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002270 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002271 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002272 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002273 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002274 }
2275 break;
2276
2277 case PHY_READ_MAC_BYTE:
2278 case PHY_WRITE_MAC_BYTE:
2279 case PHY_WRITE_ERI_WORD:
2280 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002281 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002282 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002283 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002284 }
2285 }
Francois Romieufd112f22011-06-18 00:10:29 +02002286 rc = true;
2287out:
2288 return rc;
2289}
françois romieubca03d52011-01-03 15:07:31 +00002290
Francois Romieufd112f22011-06-18 00:10:29 +02002291static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2292{
2293 struct net_device *dev = tp->dev;
2294 int rc = -EINVAL;
2295
2296 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2297 netif_err(tp, ifup, dev, "invalid firwmare\n");
2298 goto out;
2299 }
2300
2301 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2302 rc = 0;
2303out:
2304 return rc;
2305}
2306
2307static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2308{
2309 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2310 u32 predata, count;
2311 size_t index;
2312
2313 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002314
Francois Romieu1c361ef2011-06-17 17:16:24 +02002315 for (index = 0; index < pa->size; ) {
2316 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002317 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002318 u32 regno = (action & 0x0fff0000) >> 16;
2319
2320 if (!action)
2321 break;
françois romieubca03d52011-01-03 15:07:31 +00002322
2323 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002324 case PHY_READ:
2325 predata = rtl_readphy(tp, regno);
2326 count++;
2327 index++;
françois romieubca03d52011-01-03 15:07:31 +00002328 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002329 case PHY_DATA_OR:
2330 predata |= data;
2331 index++;
2332 break;
2333 case PHY_DATA_AND:
2334 predata &= data;
2335 index++;
2336 break;
2337 case PHY_BJMPN:
2338 index -= regno;
2339 break;
2340 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002341 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002342 index++;
2343 break;
2344 case PHY_CLEAR_READCOUNT:
2345 count = 0;
2346 index++;
2347 break;
2348 case PHY_WRITE:
2349 rtl_writephy(tp, regno, data);
2350 index++;
2351 break;
2352 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002353 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002354 break;
2355 case PHY_COMP_EQ_SKIPN:
2356 if (predata == data)
2357 index += regno;
2358 index++;
2359 break;
2360 case PHY_COMP_NEQ_SKIPN:
2361 if (predata != data)
2362 index += regno;
2363 index++;
2364 break;
2365 case PHY_WRITE_PREVIOUS:
2366 rtl_writephy(tp, regno, predata);
2367 index++;
2368 break;
2369 case PHY_SKIPN:
2370 index += regno + 1;
2371 break;
2372 case PHY_DELAY_MS:
2373 mdelay(data);
2374 index++;
2375 break;
2376
2377 case PHY_READ_MAC_BYTE:
2378 case PHY_WRITE_MAC_BYTE:
2379 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002380 default:
2381 BUG();
2382 }
2383 }
2384}
2385
françois romieuf1e02ed2011-01-13 13:07:53 +00002386static void rtl_release_firmware(struct rtl8169_private *tp)
2387{
Francois Romieub6ffd972011-06-17 17:00:05 +02002388 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2389 release_firmware(tp->rtl_fw->fw);
2390 kfree(tp->rtl_fw);
2391 }
2392 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002393}
2394
François Romieu953a12c2011-04-24 17:38:48 +02002395static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002396{
Francois Romieub6ffd972011-06-17 17:00:05 +02002397 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002398
2399 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002400 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002401 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002402 tp->features |= RTL_FEATURE_FW_LOADED;
2403 }
François Romieu953a12c2011-04-24 17:38:48 +02002404}
2405
2406static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2407{
2408 if (rtl_readphy(tp, reg) != val)
2409 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2410 else
2411 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002412}
2413
hayeswange0c07552012-10-23 20:24:03 +00002414static void r810x_aldps_disable(struct rtl8169_private *tp)
2415{
2416 rtl_writephy(tp, 0x1f, 0x0000);
2417 rtl_writephy(tp, 0x18, 0x0310);
2418 msleep(100);
2419}
2420
2421static void r810x_aldps_enable(struct rtl8169_private *tp)
2422{
2423 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2424 return;
2425
2426 rtl_writephy(tp, 0x1f, 0x0000);
2427 rtl_writephy(tp, 0x18, 0x8310);
2428}
2429
2430static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2431{
2432 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2433 return;
2434
2435 rtl_writephy(tp, 0x1f, 0x0000);
2436 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2437}
2438
françois romieu4da19632011-01-03 15:07:55 +00002439static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002441 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002442 { 0x1f, 0x0001 },
2443 { 0x06, 0x006e },
2444 { 0x08, 0x0708 },
2445 { 0x15, 0x4000 },
2446 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
françois romieu0b9b5712009-08-10 19:44:56 +00002448 { 0x1f, 0x0001 },
2449 { 0x03, 0x00a1 },
2450 { 0x02, 0x0008 },
2451 { 0x01, 0x0120 },
2452 { 0x00, 0x1000 },
2453 { 0x04, 0x0800 },
2454 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
françois romieu0b9b5712009-08-10 19:44:56 +00002456 { 0x03, 0xff41 },
2457 { 0x02, 0xdf60 },
2458 { 0x01, 0x0140 },
2459 { 0x00, 0x0077 },
2460 { 0x04, 0x7800 },
2461 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
françois romieu0b9b5712009-08-10 19:44:56 +00002463 { 0x03, 0x802f },
2464 { 0x02, 0x4f02 },
2465 { 0x01, 0x0409 },
2466 { 0x00, 0xf0f9 },
2467 { 0x04, 0x9800 },
2468 { 0x04, 0x9000 },
2469
2470 { 0x03, 0xdf01 },
2471 { 0x02, 0xdf20 },
2472 { 0x01, 0xff95 },
2473 { 0x00, 0xba00 },
2474 { 0x04, 0xa800 },
2475 { 0x04, 0xa000 },
2476
2477 { 0x03, 0xff41 },
2478 { 0x02, 0xdf20 },
2479 { 0x01, 0x0140 },
2480 { 0x00, 0x00bb },
2481 { 0x04, 0xb800 },
2482 { 0x04, 0xb000 },
2483
2484 { 0x03, 0xdf41 },
2485 { 0x02, 0xdc60 },
2486 { 0x01, 0x6340 },
2487 { 0x00, 0x007d },
2488 { 0x04, 0xd800 },
2489 { 0x04, 0xd000 },
2490
2491 { 0x03, 0xdf01 },
2492 { 0x02, 0xdf20 },
2493 { 0x01, 0x100a },
2494 { 0x00, 0xa0ff },
2495 { 0x04, 0xf800 },
2496 { 0x04, 0xf000 },
2497
2498 { 0x1f, 0x0000 },
2499 { 0x0b, 0x0000 },
2500 { 0x00, 0x9200 }
2501 };
2502
françois romieu4da19632011-01-03 15:07:55 +00002503 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504}
2505
françois romieu4da19632011-01-03 15:07:55 +00002506static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002507{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002508 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002509 { 0x1f, 0x0002 },
2510 { 0x01, 0x90d0 },
2511 { 0x1f, 0x0000 }
2512 };
2513
françois romieu4da19632011-01-03 15:07:55 +00002514 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002515}
2516
françois romieu4da19632011-01-03 15:07:55 +00002517static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002518{
2519 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002520
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002521 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2522 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002523 return;
2524
françois romieu4da19632011-01-03 15:07:55 +00002525 rtl_writephy(tp, 0x1f, 0x0001);
2526 rtl_writephy(tp, 0x10, 0xf01b);
2527 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002528}
2529
françois romieu4da19632011-01-03 15:07:55 +00002530static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002531{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002532 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002533 { 0x1f, 0x0001 },
2534 { 0x04, 0x0000 },
2535 { 0x03, 0x00a1 },
2536 { 0x02, 0x0008 },
2537 { 0x01, 0x0120 },
2538 { 0x00, 0x1000 },
2539 { 0x04, 0x0800 },
2540 { 0x04, 0x9000 },
2541 { 0x03, 0x802f },
2542 { 0x02, 0x4f02 },
2543 { 0x01, 0x0409 },
2544 { 0x00, 0xf099 },
2545 { 0x04, 0x9800 },
2546 { 0x04, 0xa000 },
2547 { 0x03, 0xdf01 },
2548 { 0x02, 0xdf20 },
2549 { 0x01, 0xff95 },
2550 { 0x00, 0xba00 },
2551 { 0x04, 0xa800 },
2552 { 0x04, 0xf000 },
2553 { 0x03, 0xdf01 },
2554 { 0x02, 0xdf20 },
2555 { 0x01, 0x101a },
2556 { 0x00, 0xa0ff },
2557 { 0x04, 0xf800 },
2558 { 0x04, 0x0000 },
2559 { 0x1f, 0x0000 },
2560
2561 { 0x1f, 0x0001 },
2562 { 0x10, 0xf41b },
2563 { 0x14, 0xfb54 },
2564 { 0x18, 0xf5c7 },
2565 { 0x1f, 0x0000 },
2566
2567 { 0x1f, 0x0001 },
2568 { 0x17, 0x0cc0 },
2569 { 0x1f, 0x0000 }
2570 };
2571
françois romieu4da19632011-01-03 15:07:55 +00002572 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002573
françois romieu4da19632011-01-03 15:07:55 +00002574 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002575}
2576
françois romieu4da19632011-01-03 15:07:55 +00002577static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002578{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002579 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002580 { 0x1f, 0x0001 },
2581 { 0x04, 0x0000 },
2582 { 0x03, 0x00a1 },
2583 { 0x02, 0x0008 },
2584 { 0x01, 0x0120 },
2585 { 0x00, 0x1000 },
2586 { 0x04, 0x0800 },
2587 { 0x04, 0x9000 },
2588 { 0x03, 0x802f },
2589 { 0x02, 0x4f02 },
2590 { 0x01, 0x0409 },
2591 { 0x00, 0xf099 },
2592 { 0x04, 0x9800 },
2593 { 0x04, 0xa000 },
2594 { 0x03, 0xdf01 },
2595 { 0x02, 0xdf20 },
2596 { 0x01, 0xff95 },
2597 { 0x00, 0xba00 },
2598 { 0x04, 0xa800 },
2599 { 0x04, 0xf000 },
2600 { 0x03, 0xdf01 },
2601 { 0x02, 0xdf20 },
2602 { 0x01, 0x101a },
2603 { 0x00, 0xa0ff },
2604 { 0x04, 0xf800 },
2605 { 0x04, 0x0000 },
2606 { 0x1f, 0x0000 },
2607
2608 { 0x1f, 0x0001 },
2609 { 0x0b, 0x8480 },
2610 { 0x1f, 0x0000 },
2611
2612 { 0x1f, 0x0001 },
2613 { 0x18, 0x67c7 },
2614 { 0x04, 0x2000 },
2615 { 0x03, 0x002f },
2616 { 0x02, 0x4360 },
2617 { 0x01, 0x0109 },
2618 { 0x00, 0x3022 },
2619 { 0x04, 0x2800 },
2620 { 0x1f, 0x0000 },
2621
2622 { 0x1f, 0x0001 },
2623 { 0x17, 0x0cc0 },
2624 { 0x1f, 0x0000 }
2625 };
2626
françois romieu4da19632011-01-03 15:07:55 +00002627 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002628}
2629
françois romieu4da19632011-01-03 15:07:55 +00002630static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002631{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002632 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002633 { 0x10, 0xf41b },
2634 { 0x1f, 0x0000 }
2635 };
2636
françois romieu4da19632011-01-03 15:07:55 +00002637 rtl_writephy(tp, 0x1f, 0x0001);
2638 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002639
françois romieu4da19632011-01-03 15:07:55 +00002640 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002641}
2642
françois romieu4da19632011-01-03 15:07:55 +00002643static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002644{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002645 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002646 { 0x1f, 0x0001 },
2647 { 0x10, 0xf41b },
2648 { 0x1f, 0x0000 }
2649 };
2650
françois romieu4da19632011-01-03 15:07:55 +00002651 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002652}
2653
françois romieu4da19632011-01-03 15:07:55 +00002654static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002655{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002656 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002657 { 0x1f, 0x0000 },
2658 { 0x1d, 0x0f00 },
2659 { 0x1f, 0x0002 },
2660 { 0x0c, 0x1ec8 },
2661 { 0x1f, 0x0000 }
2662 };
2663
françois romieu4da19632011-01-03 15:07:55 +00002664 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002665}
2666
françois romieu4da19632011-01-03 15:07:55 +00002667static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002668{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002669 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002670 { 0x1f, 0x0001 },
2671 { 0x1d, 0x3d98 },
2672 { 0x1f, 0x0000 }
2673 };
2674
françois romieu4da19632011-01-03 15:07:55 +00002675 rtl_writephy(tp, 0x1f, 0x0000);
2676 rtl_patchphy(tp, 0x14, 1 << 5);
2677 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002678
françois romieu4da19632011-01-03 15:07:55 +00002679 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002680}
2681
françois romieu4da19632011-01-03 15:07:55 +00002682static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002683{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002684 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002685 { 0x1f, 0x0001 },
2686 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002687 { 0x1f, 0x0002 },
2688 { 0x00, 0x88d4 },
2689 { 0x01, 0x82b1 },
2690 { 0x03, 0x7002 },
2691 { 0x08, 0x9e30 },
2692 { 0x09, 0x01f0 },
2693 { 0x0a, 0x5500 },
2694 { 0x0c, 0x00c8 },
2695 { 0x1f, 0x0003 },
2696 { 0x12, 0xc096 },
2697 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002698 { 0x1f, 0x0000 },
2699 { 0x1f, 0x0000 },
2700 { 0x09, 0x2000 },
2701 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002702 };
2703
françois romieu4da19632011-01-03 15:07:55 +00002704 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002705
françois romieu4da19632011-01-03 15:07:55 +00002706 rtl_patchphy(tp, 0x14, 1 << 5);
2707 rtl_patchphy(tp, 0x0d, 1 << 5);
2708 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002709}
2710
françois romieu4da19632011-01-03 15:07:55 +00002711static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002712{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002713 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002714 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002715 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002716 { 0x03, 0x802f },
2717 { 0x02, 0x4f02 },
2718 { 0x01, 0x0409 },
2719 { 0x00, 0xf099 },
2720 { 0x04, 0x9800 },
2721 { 0x04, 0x9000 },
2722 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002723 { 0x1f, 0x0002 },
2724 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002725 { 0x06, 0x0761 },
2726 { 0x1f, 0x0003 },
2727 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002728 { 0x1f, 0x0000 }
2729 };
2730
françois romieu4da19632011-01-03 15:07:55 +00002731 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002732
françois romieu4da19632011-01-03 15:07:55 +00002733 rtl_patchphy(tp, 0x16, 1 << 0);
2734 rtl_patchphy(tp, 0x14, 1 << 5);
2735 rtl_patchphy(tp, 0x0d, 1 << 5);
2736 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002737}
2738
françois romieu4da19632011-01-03 15:07:55 +00002739static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002740{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002741 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002742 { 0x1f, 0x0001 },
2743 { 0x12, 0x2300 },
2744 { 0x1d, 0x3d98 },
2745 { 0x1f, 0x0002 },
2746 { 0x0c, 0x7eb8 },
2747 { 0x06, 0x5461 },
2748 { 0x1f, 0x0003 },
2749 { 0x16, 0x0f0a },
2750 { 0x1f, 0x0000 }
2751 };
2752
françois romieu4da19632011-01-03 15:07:55 +00002753 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002754
françois romieu4da19632011-01-03 15:07:55 +00002755 rtl_patchphy(tp, 0x16, 1 << 0);
2756 rtl_patchphy(tp, 0x14, 1 << 5);
2757 rtl_patchphy(tp, 0x0d, 1 << 5);
2758 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002759}
2760
françois romieu4da19632011-01-03 15:07:55 +00002761static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002762{
françois romieu4da19632011-01-03 15:07:55 +00002763 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002764}
2765
françois romieubca03d52011-01-03 15:07:31 +00002766static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002767{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002768 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002769 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002770 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002771 { 0x06, 0x4064 },
2772 { 0x07, 0x2863 },
2773 { 0x08, 0x059c },
2774 { 0x09, 0x26b4 },
2775 { 0x0a, 0x6a19 },
2776 { 0x0b, 0xdcc8 },
2777 { 0x10, 0xf06d },
2778 { 0x14, 0x7f68 },
2779 { 0x18, 0x7fd9 },
2780 { 0x1c, 0xf0ff },
2781 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002782 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002783 { 0x12, 0xf49f },
2784 { 0x13, 0x070b },
2785 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002786 { 0x14, 0x94c0 },
2787
2788 /*
2789 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002790 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002791 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002792 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002793 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002794 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002795 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002796 { 0x06, 0x5561 },
2797
2798 /*
2799 * Can not link to 1Gbps with bad cable
2800 * Decrease SNR threshold form 21.07dB to 19.04dB
2801 */
2802 { 0x1f, 0x0001 },
2803 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002804
2805 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002806 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002807 };
2808
françois romieu4da19632011-01-03 15:07:55 +00002809 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002810
françois romieubca03d52011-01-03 15:07:31 +00002811 /*
2812 * Rx Error Issue
2813 * Fine Tune Switching regulator parameter
2814 */
françois romieu4da19632011-01-03 15:07:55 +00002815 rtl_writephy(tp, 0x1f, 0x0002);
2816 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2817 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002818
Francois Romieufdf6fc02012-07-06 22:40:38 +02002819 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002820 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002821 { 0x1f, 0x0002 },
2822 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002823 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002824 { 0x05, 0x8330 },
2825 { 0x06, 0x669a },
2826 { 0x1f, 0x0002 }
2827 };
2828 int val;
2829
françois romieu4da19632011-01-03 15:07:55 +00002830 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002831
françois romieu4da19632011-01-03 15:07:55 +00002832 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002833
2834 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002835 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002836 0x0065, 0x0066, 0x0067, 0x0068,
2837 0x0069, 0x006a, 0x006b, 0x006c
2838 };
2839 int i;
2840
françois romieu4da19632011-01-03 15:07:55 +00002841 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002842
2843 val &= 0xff00;
2844 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002845 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002846 }
2847 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002848 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002849 { 0x1f, 0x0002 },
2850 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002851 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002852 { 0x05, 0x8330 },
2853 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002854 };
2855
françois romieu4da19632011-01-03 15:07:55 +00002856 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002857 }
2858
françois romieubca03d52011-01-03 15:07:31 +00002859 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002860 rtl_writephy(tp, 0x1f, 0x0002);
2861 rtl_patchphy(tp, 0x0d, 0x0300);
2862 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002863
françois romieubca03d52011-01-03 15:07:31 +00002864 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002865 rtl_writephy(tp, 0x1f, 0x0002);
2866 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2867 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002868
françois romieu4da19632011-01-03 15:07:55 +00002869 rtl_writephy(tp, 0x1f, 0x0005);
2870 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002871
2872 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002873
françois romieu4da19632011-01-03 15:07:55 +00002874 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002875}
2876
françois romieubca03d52011-01-03 15:07:31 +00002877static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002878{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002879 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002880 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002881 { 0x1f, 0x0001 },
2882 { 0x06, 0x4064 },
2883 { 0x07, 0x2863 },
2884 { 0x08, 0x059c },
2885 { 0x09, 0x26b4 },
2886 { 0x0a, 0x6a19 },
2887 { 0x0b, 0xdcc8 },
2888 { 0x10, 0xf06d },
2889 { 0x14, 0x7f68 },
2890 { 0x18, 0x7fd9 },
2891 { 0x1c, 0xf0ff },
2892 { 0x1d, 0x3d9c },
2893 { 0x1f, 0x0003 },
2894 { 0x12, 0xf49f },
2895 { 0x13, 0x070b },
2896 { 0x1a, 0x05ad },
2897 { 0x14, 0x94c0 },
2898
françois romieubca03d52011-01-03 15:07:31 +00002899 /*
2900 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002901 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002902 */
françois romieudaf9df62009-10-07 12:44:20 +00002903 { 0x1f, 0x0002 },
2904 { 0x06, 0x5561 },
2905 { 0x1f, 0x0005 },
2906 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002907 { 0x06, 0x5561 },
2908
2909 /*
2910 * Can not link to 1Gbps with bad cable
2911 * Decrease SNR threshold form 21.07dB to 19.04dB
2912 */
2913 { 0x1f, 0x0001 },
2914 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002915
2916 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002917 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002918 };
2919
françois romieu4da19632011-01-03 15:07:55 +00002920 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002921
Francois Romieufdf6fc02012-07-06 22:40:38 +02002922 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002923 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002924 { 0x1f, 0x0002 },
2925 { 0x05, 0x669a },
2926 { 0x1f, 0x0005 },
2927 { 0x05, 0x8330 },
2928 { 0x06, 0x669a },
2929
2930 { 0x1f, 0x0002 }
2931 };
2932 int val;
2933
françois romieu4da19632011-01-03 15:07:55 +00002934 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002935
françois romieu4da19632011-01-03 15:07:55 +00002936 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002937 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002938 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002939 0x0065, 0x0066, 0x0067, 0x0068,
2940 0x0069, 0x006a, 0x006b, 0x006c
2941 };
2942 int i;
2943
françois romieu4da19632011-01-03 15:07:55 +00002944 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002945
2946 val &= 0xff00;
2947 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002948 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002949 }
2950 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002951 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002952 { 0x1f, 0x0002 },
2953 { 0x05, 0x2642 },
2954 { 0x1f, 0x0005 },
2955 { 0x05, 0x8330 },
2956 { 0x06, 0x2642 }
2957 };
2958
françois romieu4da19632011-01-03 15:07:55 +00002959 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002960 }
2961
françois romieubca03d52011-01-03 15:07:31 +00002962 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002963 rtl_writephy(tp, 0x1f, 0x0002);
2964 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2965 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002966
françois romieubca03d52011-01-03 15:07:31 +00002967 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002968 rtl_writephy(tp, 0x1f, 0x0002);
2969 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002970
françois romieu4da19632011-01-03 15:07:55 +00002971 rtl_writephy(tp, 0x1f, 0x0005);
2972 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002973
2974 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002975
françois romieu4da19632011-01-03 15:07:55 +00002976 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002977}
2978
françois romieu4da19632011-01-03 15:07:55 +00002979static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002980{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002981 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002982 { 0x1f, 0x0002 },
2983 { 0x10, 0x0008 },
2984 { 0x0d, 0x006c },
2985
2986 { 0x1f, 0x0000 },
2987 { 0x0d, 0xf880 },
2988
2989 { 0x1f, 0x0001 },
2990 { 0x17, 0x0cc0 },
2991
2992 { 0x1f, 0x0001 },
2993 { 0x0b, 0xa4d8 },
2994 { 0x09, 0x281c },
2995 { 0x07, 0x2883 },
2996 { 0x0a, 0x6b35 },
2997 { 0x1d, 0x3da4 },
2998 { 0x1c, 0xeffd },
2999 { 0x14, 0x7f52 },
3000 { 0x18, 0x7fc6 },
3001 { 0x08, 0x0601 },
3002 { 0x06, 0x4063 },
3003 { 0x10, 0xf074 },
3004 { 0x1f, 0x0003 },
3005 { 0x13, 0x0789 },
3006 { 0x12, 0xf4bd },
3007 { 0x1a, 0x04fd },
3008 { 0x14, 0x84b0 },
3009 { 0x1f, 0x0000 },
3010 { 0x00, 0x9200 },
3011
3012 { 0x1f, 0x0005 },
3013 { 0x01, 0x0340 },
3014 { 0x1f, 0x0001 },
3015 { 0x04, 0x4000 },
3016 { 0x03, 0x1d21 },
3017 { 0x02, 0x0c32 },
3018 { 0x01, 0x0200 },
3019 { 0x00, 0x5554 },
3020 { 0x04, 0x4800 },
3021 { 0x04, 0x4000 },
3022 { 0x04, 0xf000 },
3023 { 0x03, 0xdf01 },
3024 { 0x02, 0xdf20 },
3025 { 0x01, 0x101a },
3026 { 0x00, 0xa0ff },
3027 { 0x04, 0xf800 },
3028 { 0x04, 0xf000 },
3029 { 0x1f, 0x0000 },
3030
3031 { 0x1f, 0x0007 },
3032 { 0x1e, 0x0023 },
3033 { 0x16, 0x0000 },
3034 { 0x1f, 0x0000 }
3035 };
3036
françois romieu4da19632011-01-03 15:07:55 +00003037 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003038}
3039
françois romieue6de30d2011-01-03 15:08:37 +00003040static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3041{
3042 static const struct phy_reg phy_reg_init[] = {
3043 { 0x1f, 0x0001 },
3044 { 0x17, 0x0cc0 },
3045
3046 { 0x1f, 0x0007 },
3047 { 0x1e, 0x002d },
3048 { 0x18, 0x0040 },
3049 { 0x1f, 0x0000 }
3050 };
3051
3052 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3053 rtl_patchphy(tp, 0x0d, 1 << 5);
3054}
3055
Hayes Wang70090422011-07-06 15:58:06 +08003056static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003057{
3058 static const struct phy_reg phy_reg_init[] = {
3059 /* Enable Delay cap */
3060 { 0x1f, 0x0005 },
3061 { 0x05, 0x8b80 },
3062 { 0x06, 0xc896 },
3063 { 0x1f, 0x0000 },
3064
3065 /* Channel estimation fine tune */
3066 { 0x1f, 0x0001 },
3067 { 0x0b, 0x6c20 },
3068 { 0x07, 0x2872 },
3069 { 0x1c, 0xefff },
3070 { 0x1f, 0x0003 },
3071 { 0x14, 0x6420 },
3072 { 0x1f, 0x0000 },
3073
3074 /* Update PFM & 10M TX idle timer */
3075 { 0x1f, 0x0007 },
3076 { 0x1e, 0x002f },
3077 { 0x15, 0x1919 },
3078 { 0x1f, 0x0000 },
3079
3080 { 0x1f, 0x0007 },
3081 { 0x1e, 0x00ac },
3082 { 0x18, 0x0006 },
3083 { 0x1f, 0x0000 }
3084 };
3085
Francois Romieu15ecd032011-04-27 13:52:22 -07003086 rtl_apply_firmware(tp);
3087
hayeswang01dc7fe2011-03-21 01:50:28 +00003088 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3089
3090 /* DCO enable for 10M IDLE Power */
3091 rtl_writephy(tp, 0x1f, 0x0007);
3092 rtl_writephy(tp, 0x1e, 0x0023);
3093 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3094 rtl_writephy(tp, 0x1f, 0x0000);
3095
3096 /* For impedance matching */
3097 rtl_writephy(tp, 0x1f, 0x0002);
3098 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003099 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003100
3101 /* PHY auto speed down */
3102 rtl_writephy(tp, 0x1f, 0x0007);
3103 rtl_writephy(tp, 0x1e, 0x002d);
3104 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3105 rtl_writephy(tp, 0x1f, 0x0000);
3106 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3107
3108 rtl_writephy(tp, 0x1f, 0x0005);
3109 rtl_writephy(tp, 0x05, 0x8b86);
3110 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3111 rtl_writephy(tp, 0x1f, 0x0000);
3112
3113 rtl_writephy(tp, 0x1f, 0x0005);
3114 rtl_writephy(tp, 0x05, 0x8b85);
3115 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3116 rtl_writephy(tp, 0x1f, 0x0007);
3117 rtl_writephy(tp, 0x1e, 0x0020);
3118 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3119 rtl_writephy(tp, 0x1f, 0x0006);
3120 rtl_writephy(tp, 0x00, 0x5a00);
3121 rtl_writephy(tp, 0x1f, 0x0000);
3122 rtl_writephy(tp, 0x0d, 0x0007);
3123 rtl_writephy(tp, 0x0e, 0x003c);
3124 rtl_writephy(tp, 0x0d, 0x4007);
3125 rtl_writephy(tp, 0x0e, 0x0000);
3126 rtl_writephy(tp, 0x0d, 0x0000);
3127}
3128
Hayes Wang70090422011-07-06 15:58:06 +08003129static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3130{
3131 static const struct phy_reg phy_reg_init[] = {
3132 /* Enable Delay cap */
3133 { 0x1f, 0x0004 },
3134 { 0x1f, 0x0007 },
3135 { 0x1e, 0x00ac },
3136 { 0x18, 0x0006 },
3137 { 0x1f, 0x0002 },
3138 { 0x1f, 0x0000 },
3139 { 0x1f, 0x0000 },
3140
3141 /* Channel estimation fine tune */
3142 { 0x1f, 0x0003 },
3143 { 0x09, 0xa20f },
3144 { 0x1f, 0x0000 },
3145 { 0x1f, 0x0000 },
3146
3147 /* Green Setting */
3148 { 0x1f, 0x0005 },
3149 { 0x05, 0x8b5b },
3150 { 0x06, 0x9222 },
3151 { 0x05, 0x8b6d },
3152 { 0x06, 0x8000 },
3153 { 0x05, 0x8b76 },
3154 { 0x06, 0x8000 },
3155 { 0x1f, 0x0000 }
3156 };
3157
3158 rtl_apply_firmware(tp);
3159
3160 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3161
3162 /* For 4-corner performance improve */
3163 rtl_writephy(tp, 0x1f, 0x0005);
3164 rtl_writephy(tp, 0x05, 0x8b80);
3165 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3166 rtl_writephy(tp, 0x1f, 0x0000);
3167
3168 /* PHY auto speed down */
3169 rtl_writephy(tp, 0x1f, 0x0004);
3170 rtl_writephy(tp, 0x1f, 0x0007);
3171 rtl_writephy(tp, 0x1e, 0x002d);
3172 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3173 rtl_writephy(tp, 0x1f, 0x0002);
3174 rtl_writephy(tp, 0x1f, 0x0000);
3175 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3176
3177 /* improve 10M EEE waveform */
3178 rtl_writephy(tp, 0x1f, 0x0005);
3179 rtl_writephy(tp, 0x05, 0x8b86);
3180 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3181 rtl_writephy(tp, 0x1f, 0x0000);
3182
3183 /* Improve 2-pair detection performance */
3184 rtl_writephy(tp, 0x1f, 0x0005);
3185 rtl_writephy(tp, 0x05, 0x8b85);
3186 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3187 rtl_writephy(tp, 0x1f, 0x0000);
3188
3189 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003190 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003191 rtl_writephy(tp, 0x1f, 0x0005);
3192 rtl_writephy(tp, 0x05, 0x8b85);
3193 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3194 rtl_writephy(tp, 0x1f, 0x0004);
3195 rtl_writephy(tp, 0x1f, 0x0007);
3196 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003197 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003198 rtl_writephy(tp, 0x1f, 0x0002);
3199 rtl_writephy(tp, 0x1f, 0x0000);
3200 rtl_writephy(tp, 0x0d, 0x0007);
3201 rtl_writephy(tp, 0x0e, 0x003c);
3202 rtl_writephy(tp, 0x0d, 0x4007);
3203 rtl_writephy(tp, 0x0e, 0x0000);
3204 rtl_writephy(tp, 0x0d, 0x0000);
3205
3206 /* Green feature */
3207 rtl_writephy(tp, 0x1f, 0x0003);
3208 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3209 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3210 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003211
3212 r8168_aldps_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08003213}
3214
Hayes Wang5f886e02012-03-30 14:33:03 +08003215static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3216{
3217 /* For 4-corner performance improve */
3218 rtl_writephy(tp, 0x1f, 0x0005);
3219 rtl_writephy(tp, 0x05, 0x8b80);
3220 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3221 rtl_writephy(tp, 0x1f, 0x0000);
3222
3223 /* PHY auto speed down */
3224 rtl_writephy(tp, 0x1f, 0x0007);
3225 rtl_writephy(tp, 0x1e, 0x002d);
3226 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3227 rtl_writephy(tp, 0x1f, 0x0000);
3228 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3229
3230 /* Improve 10M EEE waveform */
3231 rtl_writephy(tp, 0x1f, 0x0005);
3232 rtl_writephy(tp, 0x05, 0x8b86);
3233 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3234 rtl_writephy(tp, 0x1f, 0x0000);
3235}
3236
Hayes Wangc2218922011-09-06 16:55:18 +08003237static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3238{
3239 static const struct phy_reg phy_reg_init[] = {
3240 /* Channel estimation fine tune */
3241 { 0x1f, 0x0003 },
3242 { 0x09, 0xa20f },
3243 { 0x1f, 0x0000 },
3244
3245 /* Modify green table for giga & fnet */
3246 { 0x1f, 0x0005 },
3247 { 0x05, 0x8b55 },
3248 { 0x06, 0x0000 },
3249 { 0x05, 0x8b5e },
3250 { 0x06, 0x0000 },
3251 { 0x05, 0x8b67 },
3252 { 0x06, 0x0000 },
3253 { 0x05, 0x8b70 },
3254 { 0x06, 0x0000 },
3255 { 0x1f, 0x0000 },
3256 { 0x1f, 0x0007 },
3257 { 0x1e, 0x0078 },
3258 { 0x17, 0x0000 },
3259 { 0x19, 0x00fb },
3260 { 0x1f, 0x0000 },
3261
3262 /* Modify green table for 10M */
3263 { 0x1f, 0x0005 },
3264 { 0x05, 0x8b79 },
3265 { 0x06, 0xaa00 },
3266 { 0x1f, 0x0000 },
3267
3268 /* Disable hiimpedance detection (RTCT) */
3269 { 0x1f, 0x0003 },
3270 { 0x01, 0x328a },
3271 { 0x1f, 0x0000 }
3272 };
3273
3274 rtl_apply_firmware(tp);
3275
3276 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3277
Hayes Wang5f886e02012-03-30 14:33:03 +08003278 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003279
3280 /* Improve 2-pair detection performance */
3281 rtl_writephy(tp, 0x1f, 0x0005);
3282 rtl_writephy(tp, 0x05, 0x8b85);
3283 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3284 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003285
3286 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003287}
3288
3289static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3290{
3291 rtl_apply_firmware(tp);
3292
Hayes Wang5f886e02012-03-30 14:33:03 +08003293 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003294
3295 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003296}
3297
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003298static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3299{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003300 static const struct phy_reg phy_reg_init[] = {
3301 /* Channel estimation fine tune */
3302 { 0x1f, 0x0003 },
3303 { 0x09, 0xa20f },
3304 { 0x1f, 0x0000 },
3305
3306 /* Modify green table for giga & fnet */
3307 { 0x1f, 0x0005 },
3308 { 0x05, 0x8b55 },
3309 { 0x06, 0x0000 },
3310 { 0x05, 0x8b5e },
3311 { 0x06, 0x0000 },
3312 { 0x05, 0x8b67 },
3313 { 0x06, 0x0000 },
3314 { 0x05, 0x8b70 },
3315 { 0x06, 0x0000 },
3316 { 0x1f, 0x0000 },
3317 { 0x1f, 0x0007 },
3318 { 0x1e, 0x0078 },
3319 { 0x17, 0x0000 },
3320 { 0x19, 0x00aa },
3321 { 0x1f, 0x0000 },
3322
3323 /* Modify green table for 10M */
3324 { 0x1f, 0x0005 },
3325 { 0x05, 0x8b79 },
3326 { 0x06, 0xaa00 },
3327 { 0x1f, 0x0000 },
3328
3329 /* Disable hiimpedance detection (RTCT) */
3330 { 0x1f, 0x0003 },
3331 { 0x01, 0x328a },
3332 { 0x1f, 0x0000 }
3333 };
3334
3335
3336 rtl_apply_firmware(tp);
3337
3338 rtl8168f_hw_phy_config(tp);
3339
3340 /* Improve 2-pair detection performance */
3341 rtl_writephy(tp, 0x1f, 0x0005);
3342 rtl_writephy(tp, 0x05, 0x8b85);
3343 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3344 rtl_writephy(tp, 0x1f, 0x0000);
3345
3346 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3347
3348 /* Modify green table for giga */
3349 rtl_writephy(tp, 0x1f, 0x0005);
3350 rtl_writephy(tp, 0x05, 0x8b54);
3351 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3352 rtl_writephy(tp, 0x05, 0x8b5d);
3353 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3354 rtl_writephy(tp, 0x05, 0x8a7c);
3355 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3356 rtl_writephy(tp, 0x05, 0x8a7f);
3357 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3358 rtl_writephy(tp, 0x05, 0x8a82);
3359 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3360 rtl_writephy(tp, 0x05, 0x8a85);
3361 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3362 rtl_writephy(tp, 0x05, 0x8a88);
3363 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3364 rtl_writephy(tp, 0x1f, 0x0000);
3365
3366 /* uc same-seed solution */
3367 rtl_writephy(tp, 0x1f, 0x0005);
3368 rtl_writephy(tp, 0x05, 0x8b85);
3369 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3370 rtl_writephy(tp, 0x1f, 0x0000);
3371
3372 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003373 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003374 rtl_writephy(tp, 0x1f, 0x0005);
3375 rtl_writephy(tp, 0x05, 0x8b85);
3376 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3377 rtl_writephy(tp, 0x1f, 0x0004);
3378 rtl_writephy(tp, 0x1f, 0x0007);
3379 rtl_writephy(tp, 0x1e, 0x0020);
3380 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3381 rtl_writephy(tp, 0x1f, 0x0000);
3382 rtl_writephy(tp, 0x0d, 0x0007);
3383 rtl_writephy(tp, 0x0e, 0x003c);
3384 rtl_writephy(tp, 0x0d, 0x4007);
3385 rtl_writephy(tp, 0x0e, 0x0000);
3386 rtl_writephy(tp, 0x0d, 0x0000);
3387
3388 /* Green feature */
3389 rtl_writephy(tp, 0x1f, 0x0003);
3390 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3391 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3392 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003393
3394 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003395}
3396
Hayes Wangc5583862012-07-02 17:23:22 +08003397static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3398{
3399 static const u16 mac_ocp_patch[] = {
3400 0xe008, 0xe01b, 0xe01d, 0xe01f,
3401 0xe021, 0xe023, 0xe025, 0xe027,
3402 0x49d2, 0xf10d, 0x766c, 0x49e2,
3403 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3404
3405 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3406 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3407 0xbe00, 0xb416, 0x0076, 0xe86c,
3408 0xc602, 0xbe00, 0x0000, 0xc602,
3409
3410 0xbe00, 0x0000, 0xc602, 0xbe00,
3411 0x0000, 0xc602, 0xbe00, 0x0000,
3412 0xc602, 0xbe00, 0x0000, 0xc602,
3413 0xbe00, 0x0000, 0xc602, 0xbe00,
3414
3415 0x0000, 0x0000, 0x0000, 0x0000
3416 };
3417 u32 i;
3418
3419 /* Patch code for GPHY reset */
3420 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3421 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3422 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3423 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3424
3425 rtl_apply_firmware(tp);
3426
3427 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3428 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3429 else
3430 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3431
3432 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3433 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3434 else
3435 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3436
3437 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3438 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3439
3440 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3441 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3442
3443 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3444}
3445
françois romieu4da19632011-01-03 15:07:55 +00003446static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003447{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003448 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003449 { 0x1f, 0x0003 },
3450 { 0x08, 0x441d },
3451 { 0x01, 0x9100 },
3452 { 0x1f, 0x0000 }
3453 };
3454
françois romieu4da19632011-01-03 15:07:55 +00003455 rtl_writephy(tp, 0x1f, 0x0000);
3456 rtl_patchphy(tp, 0x11, 1 << 12);
3457 rtl_patchphy(tp, 0x19, 1 << 13);
3458 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003459
françois romieu4da19632011-01-03 15:07:55 +00003460 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003461}
3462
Hayes Wang5a5e4442011-02-22 17:26:21 +08003463static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3464{
3465 static const struct phy_reg phy_reg_init[] = {
3466 { 0x1f, 0x0005 },
3467 { 0x1a, 0x0000 },
3468 { 0x1f, 0x0000 },
3469
3470 { 0x1f, 0x0004 },
3471 { 0x1c, 0x0000 },
3472 { 0x1f, 0x0000 },
3473
3474 { 0x1f, 0x0001 },
3475 { 0x15, 0x7701 },
3476 { 0x1f, 0x0000 }
3477 };
3478
3479 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003480 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003481
François Romieu953a12c2011-04-24 17:38:48 +02003482 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003483
3484 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003485
3486 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003487}
3488
Hayes Wang7e18dca2012-03-30 14:33:02 +08003489static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3490{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003491 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003492 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003493
3494 rtl_apply_firmware(tp);
3495
3496 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003497 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003498 rtl_writephy(tp, 0x1f, 0x0004);
3499 rtl_writephy(tp, 0x10, 0x401f);
3500 rtl_writephy(tp, 0x19, 0x7030);
3501 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003502
3503 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003504}
3505
Hayes Wang5598bfe2012-07-02 17:23:21 +08003506static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3507{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003508 static const struct phy_reg phy_reg_init[] = {
3509 { 0x1f, 0x0004 },
3510 { 0x10, 0xc07f },
3511 { 0x19, 0x7030 },
3512 { 0x1f, 0x0000 }
3513 };
3514
3515 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003516 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003517
3518 rtl_apply_firmware(tp);
3519
Francois Romieufdf6fc02012-07-06 22:40:38 +02003520 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003521 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3522
Francois Romieufdf6fc02012-07-06 22:40:38 +02003523 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003524
3525 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003526}
3527
Francois Romieu5615d9f2007-08-17 17:50:46 +02003528static void rtl_hw_phy_config(struct net_device *dev)
3529{
3530 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003531
3532 rtl8169_print_mac_version(tp);
3533
3534 switch (tp->mac_version) {
3535 case RTL_GIGA_MAC_VER_01:
3536 break;
3537 case RTL_GIGA_MAC_VER_02:
3538 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003539 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003540 break;
3541 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003542 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003543 break;
françois romieu2e9558562009-08-10 19:44:19 +00003544 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003545 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003546 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003547 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003548 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003549 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003550 case RTL_GIGA_MAC_VER_07:
3551 case RTL_GIGA_MAC_VER_08:
3552 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003554 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003555 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003556 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003557 break;
3558 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003559 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003560 break;
3561 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003563 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003564 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003565 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003566 break;
3567 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003568 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003569 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003570 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003571 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003572 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003573 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003574 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003575 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003576 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003577 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003578 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003579 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003580 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003581 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003582 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003583 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003584 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003585 break;
3586 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003587 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003588 break;
3589 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003590 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003591 break;
françois romieue6de30d2011-01-03 15:08:37 +00003592 case RTL_GIGA_MAC_VER_28:
3593 rtl8168d_4_hw_phy_config(tp);
3594 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003595 case RTL_GIGA_MAC_VER_29:
3596 case RTL_GIGA_MAC_VER_30:
3597 rtl8105e_hw_phy_config(tp);
3598 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003599 case RTL_GIGA_MAC_VER_31:
3600 /* None. */
3601 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003602 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003603 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003604 rtl8168e_1_hw_phy_config(tp);
3605 break;
3606 case RTL_GIGA_MAC_VER_34:
3607 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003608 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003609 case RTL_GIGA_MAC_VER_35:
3610 rtl8168f_1_hw_phy_config(tp);
3611 break;
3612 case RTL_GIGA_MAC_VER_36:
3613 rtl8168f_2_hw_phy_config(tp);
3614 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003615
Hayes Wang7e18dca2012-03-30 14:33:02 +08003616 case RTL_GIGA_MAC_VER_37:
3617 rtl8402_hw_phy_config(tp);
3618 break;
3619
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003620 case RTL_GIGA_MAC_VER_38:
3621 rtl8411_hw_phy_config(tp);
3622 break;
3623
Hayes Wang5598bfe2012-07-02 17:23:21 +08003624 case RTL_GIGA_MAC_VER_39:
3625 rtl8106e_hw_phy_config(tp);
3626 break;
3627
Hayes Wangc5583862012-07-02 17:23:22 +08003628 case RTL_GIGA_MAC_VER_40:
3629 rtl8168g_1_hw_phy_config(tp);
3630 break;
3631
3632 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003633 default:
3634 break;
3635 }
3636}
3637
Francois Romieuda78dbf2012-01-26 14:18:23 +01003638static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 struct timer_list *timer = &tp->timer;
3641 void __iomem *ioaddr = tp->mmio_addr;
3642 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3643
Francois Romieubcf0bf92006-07-26 23:14:13 +02003644 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
françois romieu4da19632011-01-03 15:07:55 +00003646 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003647 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 * A busy loop could burn quite a few cycles on nowadays CPU.
3649 * Let's delay the execution of the timer for a few ticks.
3650 */
3651 timeout = HZ/10;
3652 goto out_mod_timer;
3653 }
3654
3655 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003656 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
Francois Romieuda78dbf2012-01-26 14:18:23 +01003658 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
françois romieu4da19632011-01-03 15:07:55 +00003660 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
3662out_mod_timer:
3663 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003664}
3665
3666static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3667{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003668 if (!test_and_set_bit(flag, tp->wk.flags))
3669 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003670}
3671
3672static void rtl8169_phy_timer(unsigned long __opaque)
3673{
3674 struct net_device *dev = (struct net_device *)__opaque;
3675 struct rtl8169_private *tp = netdev_priv(dev);
3676
Francois Romieu98ddf982012-01-31 10:47:34 +01003677 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678}
3679
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3681 void __iomem *ioaddr)
3682{
3683 iounmap(ioaddr);
3684 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003685 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 pci_disable_device(pdev);
3687 free_netdev(dev);
3688}
3689
Francois Romieuffc46952012-07-06 14:19:23 +02003690DECLARE_RTL_COND(rtl_phy_reset_cond)
3691{
3692 return tp->phy_reset_pending(tp);
3693}
3694
Francois Romieubf793292006-11-01 00:53:05 +01003695static void rtl8169_phy_reset(struct net_device *dev,
3696 struct rtl8169_private *tp)
3697{
françois romieu4da19632011-01-03 15:07:55 +00003698 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003699 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003700}
3701
David S. Miller8decf862011-09-22 03:23:13 -04003702static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3703{
3704 void __iomem *ioaddr = tp->mmio_addr;
3705
3706 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3707 (RTL_R8(PHYstatus) & TBI_Enable);
3708}
3709
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003710static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003712 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003713
Francois Romieu5615d9f2007-08-17 17:50:46 +02003714 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003715
Marcus Sundberg773328942008-07-10 21:28:08 +02003716 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3717 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3718 RTL_W8(0x82, 0x01);
3719 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003720
Francois Romieu6dccd162007-02-13 23:38:05 +01003721 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3722
3723 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3724 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003725
Francois Romieubcf0bf92006-07-26 23:14:13 +02003726 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003727 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3728 RTL_W8(0x82, 0x01);
3729 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003730 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003731 }
3732
Francois Romieubf793292006-11-01 00:53:05 +01003733 rtl8169_phy_reset(dev, tp);
3734
Oliver Neukum54405cd2011-01-06 21:55:13 +01003735 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003736 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3737 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3738 (tp->mii.supports_gmii ?
3739 ADVERTISED_1000baseT_Half |
3740 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003741
David S. Miller8decf862011-09-22 03:23:13 -04003742 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003743 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003744}
3745
Francois Romieu773d2022007-01-31 23:47:43 +01003746static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3747{
3748 void __iomem *ioaddr = tp->mmio_addr;
3749 u32 high;
3750 u32 low;
3751
3752 low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
3753 high = addr[4] | (addr[5] << 8);
3754
Francois Romieuda78dbf2012-01-26 14:18:23 +01003755 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003756
3757 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003758
Francois Romieu773d2022007-01-31 23:47:43 +01003759 RTL_W32(MAC4, high);
françois romieu908ba2b2010-04-26 11:42:58 +00003760 RTL_R32(MAC4);
3761
Francois Romieu78f1cd02010-03-27 19:35:46 -07003762 RTL_W32(MAC0, low);
françois romieu908ba2b2010-04-26 11:42:58 +00003763 RTL_R32(MAC0);
3764
françois romieuc28aa382011-08-02 03:53:43 +00003765 if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
3766 const struct exgmac_reg e[] = {
3767 { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
3768 { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
3769 { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
3770 { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
3771 low >> 16 },
3772 };
3773
Francois Romieufdf6fc02012-07-06 22:40:38 +02003774 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
françois romieuc28aa382011-08-02 03:53:43 +00003775 }
3776
Francois Romieu773d2022007-01-31 23:47:43 +01003777 RTL_W8(Cfg9346, Cfg9346_Lock);
3778
Francois Romieuda78dbf2012-01-26 14:18:23 +01003779 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003780}
3781
3782static int rtl_set_mac_address(struct net_device *dev, void *p)
3783{
3784 struct rtl8169_private *tp = netdev_priv(dev);
3785 struct sockaddr *addr = p;
3786
3787 if (!is_valid_ether_addr(addr->sa_data))
3788 return -EADDRNOTAVAIL;
3789
3790 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3791
3792 rtl_rar_set(tp, dev->dev_addr);
3793
3794 return 0;
3795}
3796
Francois Romieu5f787a12006-08-17 13:02:36 +02003797static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3798{
3799 struct rtl8169_private *tp = netdev_priv(dev);
3800 struct mii_ioctl_data *data = if_mii(ifr);
3801
Francois Romieu8b4ab282008-11-19 22:05:25 -08003802 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3803}
Francois Romieu5f787a12006-08-17 13:02:36 +02003804
Francois Romieucecb5fd2011-04-01 10:21:07 +02003805static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3806 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003807{
Francois Romieu5f787a12006-08-17 13:02:36 +02003808 switch (cmd) {
3809 case SIOCGMIIPHY:
3810 data->phy_id = 32; /* Internal PHY */
3811 return 0;
3812
3813 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003814 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003815 return 0;
3816
3817 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003818 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003819 return 0;
3820 }
3821 return -EOPNOTSUPP;
3822}
3823
Francois Romieu8b4ab282008-11-19 22:05:25 -08003824static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3825{
3826 return -EOPNOTSUPP;
3827}
3828
Francois Romieufbac58f2007-10-04 22:51:38 +02003829static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3830{
3831 if (tp->features & RTL_FEATURE_MSI) {
3832 pci_disable_msi(pdev);
3833 tp->features &= ~RTL_FEATURE_MSI;
3834 }
3835}
3836
françois romieuc0e45c12011-01-03 15:08:04 +00003837static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
3838{
3839 struct mdio_ops *ops = &tp->mdio_ops;
3840
3841 switch (tp->mac_version) {
3842 case RTL_GIGA_MAC_VER_27:
3843 ops->write = r8168dp_1_mdio_write;
3844 ops->read = r8168dp_1_mdio_read;
3845 break;
françois romieue6de30d2011-01-03 15:08:37 +00003846 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003847 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003848 ops->write = r8168dp_2_mdio_write;
3849 ops->read = r8168dp_2_mdio_read;
3850 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003851 case RTL_GIGA_MAC_VER_40:
3852 case RTL_GIGA_MAC_VER_41:
3853 ops->write = r8168g_mdio_write;
3854 ops->read = r8168g_mdio_read;
3855 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003856 default:
3857 ops->write = r8169_mdio_write;
3858 ops->read = r8169_mdio_read;
3859 break;
3860 }
3861}
3862
David S. Miller1805b2f2011-10-24 18:18:09 -04003863static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3864{
3865 void __iomem *ioaddr = tp->mmio_addr;
3866
3867 switch (tp->mac_version) {
3868 case RTL_GIGA_MAC_VER_29:
3869 case RTL_GIGA_MAC_VER_30:
3870 case RTL_GIGA_MAC_VER_32:
3871 case RTL_GIGA_MAC_VER_33:
3872 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003873 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003874 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003875 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003876 case RTL_GIGA_MAC_VER_40:
3877 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003878 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3879 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3880 break;
3881 default:
3882 break;
3883 }
3884}
3885
3886static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3887{
3888 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3889 return false;
3890
3891 rtl_writephy(tp, 0x1f, 0x0000);
3892 rtl_writephy(tp, MII_BMCR, 0x0000);
3893
3894 rtl_wol_suspend_quirk(tp);
3895
3896 return true;
3897}
3898
françois romieu065c27c2011-01-03 15:08:12 +00003899static void r810x_phy_power_down(struct rtl8169_private *tp)
3900{
3901 rtl_writephy(tp, 0x1f, 0x0000);
3902 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3903}
3904
3905static void r810x_phy_power_up(struct rtl8169_private *tp)
3906{
3907 rtl_writephy(tp, 0x1f, 0x0000);
3908 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3909}
3910
3911static void r810x_pll_power_down(struct rtl8169_private *tp)
3912{
Hayes Wang00042992012-03-30 14:33:00 +08003913 void __iomem *ioaddr = tp->mmio_addr;
3914
David S. Miller1805b2f2011-10-24 18:18:09 -04003915 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003916 return;
françois romieu065c27c2011-01-03 15:08:12 +00003917
3918 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003919
3920 switch (tp->mac_version) {
3921 case RTL_GIGA_MAC_VER_07:
3922 case RTL_GIGA_MAC_VER_08:
3923 case RTL_GIGA_MAC_VER_09:
3924 case RTL_GIGA_MAC_VER_10:
3925 case RTL_GIGA_MAC_VER_13:
3926 case RTL_GIGA_MAC_VER_16:
3927 break;
3928 default:
3929 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3930 break;
3931 }
françois romieu065c27c2011-01-03 15:08:12 +00003932}
3933
3934static void r810x_pll_power_up(struct rtl8169_private *tp)
3935{
Hayes Wang00042992012-03-30 14:33:00 +08003936 void __iomem *ioaddr = tp->mmio_addr;
3937
françois romieu065c27c2011-01-03 15:08:12 +00003938 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003939
3940 switch (tp->mac_version) {
3941 case RTL_GIGA_MAC_VER_07:
3942 case RTL_GIGA_MAC_VER_08:
3943 case RTL_GIGA_MAC_VER_09:
3944 case RTL_GIGA_MAC_VER_10:
3945 case RTL_GIGA_MAC_VER_13:
3946 case RTL_GIGA_MAC_VER_16:
3947 break;
3948 default:
3949 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3950 break;
3951 }
françois romieu065c27c2011-01-03 15:08:12 +00003952}
3953
3954static void r8168_phy_power_up(struct rtl8169_private *tp)
3955{
3956 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003957 switch (tp->mac_version) {
3958 case RTL_GIGA_MAC_VER_11:
3959 case RTL_GIGA_MAC_VER_12:
3960 case RTL_GIGA_MAC_VER_17:
3961 case RTL_GIGA_MAC_VER_18:
3962 case RTL_GIGA_MAC_VER_19:
3963 case RTL_GIGA_MAC_VER_20:
3964 case RTL_GIGA_MAC_VER_21:
3965 case RTL_GIGA_MAC_VER_22:
3966 case RTL_GIGA_MAC_VER_23:
3967 case RTL_GIGA_MAC_VER_24:
3968 case RTL_GIGA_MAC_VER_25:
3969 case RTL_GIGA_MAC_VER_26:
3970 case RTL_GIGA_MAC_VER_27:
3971 case RTL_GIGA_MAC_VER_28:
3972 case RTL_GIGA_MAC_VER_31:
3973 rtl_writephy(tp, 0x0e, 0x0000);
3974 break;
3975 default:
3976 break;
3977 }
françois romieu065c27c2011-01-03 15:08:12 +00003978 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3979}
3980
3981static void r8168_phy_power_down(struct rtl8169_private *tp)
3982{
3983 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003984 switch (tp->mac_version) {
3985 case RTL_GIGA_MAC_VER_32:
3986 case RTL_GIGA_MAC_VER_33:
3987 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3988 break;
3989
3990 case RTL_GIGA_MAC_VER_11:
3991 case RTL_GIGA_MAC_VER_12:
3992 case RTL_GIGA_MAC_VER_17:
3993 case RTL_GIGA_MAC_VER_18:
3994 case RTL_GIGA_MAC_VER_19:
3995 case RTL_GIGA_MAC_VER_20:
3996 case RTL_GIGA_MAC_VER_21:
3997 case RTL_GIGA_MAC_VER_22:
3998 case RTL_GIGA_MAC_VER_23:
3999 case RTL_GIGA_MAC_VER_24:
4000 case RTL_GIGA_MAC_VER_25:
4001 case RTL_GIGA_MAC_VER_26:
4002 case RTL_GIGA_MAC_VER_27:
4003 case RTL_GIGA_MAC_VER_28:
4004 case RTL_GIGA_MAC_VER_31:
4005 rtl_writephy(tp, 0x0e, 0x0200);
4006 default:
4007 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4008 break;
4009 }
françois romieu065c27c2011-01-03 15:08:12 +00004010}
4011
4012static void r8168_pll_power_down(struct rtl8169_private *tp)
4013{
4014 void __iomem *ioaddr = tp->mmio_addr;
4015
Francois Romieucecb5fd2011-04-01 10:21:07 +02004016 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4017 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4018 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004019 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004020 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004021 }
françois romieu065c27c2011-01-03 15:08:12 +00004022
Francois Romieucecb5fd2011-04-01 10:21:07 +02004023 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4024 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004025 (RTL_R16(CPlusCmd) & ASF)) {
4026 return;
4027 }
4028
hayeswang01dc7fe2011-03-21 01:50:28 +00004029 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4030 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004031 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004032
David S. Miller1805b2f2011-10-24 18:18:09 -04004033 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004034 return;
françois romieu065c27c2011-01-03 15:08:12 +00004035
4036 r8168_phy_power_down(tp);
4037
4038 switch (tp->mac_version) {
4039 case RTL_GIGA_MAC_VER_25:
4040 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004041 case RTL_GIGA_MAC_VER_27:
4042 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004043 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004044 case RTL_GIGA_MAC_VER_32:
4045 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004046 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4047 break;
4048 }
4049}
4050
4051static void r8168_pll_power_up(struct rtl8169_private *tp)
4052{
4053 void __iomem *ioaddr = tp->mmio_addr;
4054
françois romieu065c27c2011-01-03 15:08:12 +00004055 switch (tp->mac_version) {
4056 case RTL_GIGA_MAC_VER_25:
4057 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004058 case RTL_GIGA_MAC_VER_27:
4059 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004060 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004061 case RTL_GIGA_MAC_VER_32:
4062 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004063 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4064 break;
4065 }
4066
4067 r8168_phy_power_up(tp);
4068}
4069
Francois Romieud58d46b2011-05-03 16:38:29 +02004070static void rtl_generic_op(struct rtl8169_private *tp,
4071 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004072{
4073 if (op)
4074 op(tp);
4075}
4076
4077static void rtl_pll_power_down(struct rtl8169_private *tp)
4078{
Francois Romieud58d46b2011-05-03 16:38:29 +02004079 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004080}
4081
4082static void rtl_pll_power_up(struct rtl8169_private *tp)
4083{
Francois Romieud58d46b2011-05-03 16:38:29 +02004084 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004085}
4086
4087static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
4088{
4089 struct pll_power_ops *ops = &tp->pll_power_ops;
4090
4091 switch (tp->mac_version) {
4092 case RTL_GIGA_MAC_VER_07:
4093 case RTL_GIGA_MAC_VER_08:
4094 case RTL_GIGA_MAC_VER_09:
4095 case RTL_GIGA_MAC_VER_10:
4096 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004097 case RTL_GIGA_MAC_VER_29:
4098 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004099 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004100 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004101 ops->down = r810x_pll_power_down;
4102 ops->up = r810x_pll_power_up;
4103 break;
4104
4105 case RTL_GIGA_MAC_VER_11:
4106 case RTL_GIGA_MAC_VER_12:
4107 case RTL_GIGA_MAC_VER_17:
4108 case RTL_GIGA_MAC_VER_18:
4109 case RTL_GIGA_MAC_VER_19:
4110 case RTL_GIGA_MAC_VER_20:
4111 case RTL_GIGA_MAC_VER_21:
4112 case RTL_GIGA_MAC_VER_22:
4113 case RTL_GIGA_MAC_VER_23:
4114 case RTL_GIGA_MAC_VER_24:
4115 case RTL_GIGA_MAC_VER_25:
4116 case RTL_GIGA_MAC_VER_26:
4117 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004118 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004119 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004120 case RTL_GIGA_MAC_VER_32:
4121 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004122 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004123 case RTL_GIGA_MAC_VER_35:
4124 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004125 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004126 case RTL_GIGA_MAC_VER_40:
4127 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004128 ops->down = r8168_pll_power_down;
4129 ops->up = r8168_pll_power_up;
4130 break;
4131
4132 default:
4133 ops->down = NULL;
4134 ops->up = NULL;
4135 break;
4136 }
4137}
4138
Hayes Wange542a222011-07-06 15:58:04 +08004139static void rtl_init_rxcfg(struct rtl8169_private *tp)
4140{
4141 void __iomem *ioaddr = tp->mmio_addr;
4142
4143 switch (tp->mac_version) {
4144 case RTL_GIGA_MAC_VER_01:
4145 case RTL_GIGA_MAC_VER_02:
4146 case RTL_GIGA_MAC_VER_03:
4147 case RTL_GIGA_MAC_VER_04:
4148 case RTL_GIGA_MAC_VER_05:
4149 case RTL_GIGA_MAC_VER_06:
4150 case RTL_GIGA_MAC_VER_10:
4151 case RTL_GIGA_MAC_VER_11:
4152 case RTL_GIGA_MAC_VER_12:
4153 case RTL_GIGA_MAC_VER_13:
4154 case RTL_GIGA_MAC_VER_14:
4155 case RTL_GIGA_MAC_VER_15:
4156 case RTL_GIGA_MAC_VER_16:
4157 case RTL_GIGA_MAC_VER_17:
4158 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4159 break;
4160 case RTL_GIGA_MAC_VER_18:
4161 case RTL_GIGA_MAC_VER_19:
4162 case RTL_GIGA_MAC_VER_20:
4163 case RTL_GIGA_MAC_VER_21:
4164 case RTL_GIGA_MAC_VER_22:
4165 case RTL_GIGA_MAC_VER_23:
4166 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004167 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004168 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4169 break;
4170 default:
4171 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4172 break;
4173 }
4174}
4175
Hayes Wang92fc43b2011-07-06 15:58:03 +08004176static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4177{
4178 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4179}
4180
Francois Romieud58d46b2011-05-03 16:38:29 +02004181static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4182{
françois romieu9c5028e2012-03-02 04:43:14 +00004183 void __iomem *ioaddr = tp->mmio_addr;
4184
4185 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004186 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004187 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004188}
4189
4190static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4191{
françois romieu9c5028e2012-03-02 04:43:14 +00004192 void __iomem *ioaddr = tp->mmio_addr;
4193
4194 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004195 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004196 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004197}
4198
4199static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4200{
4201 void __iomem *ioaddr = tp->mmio_addr;
4202
4203 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4204 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4205 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4206}
4207
4208static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4209{
4210 void __iomem *ioaddr = tp->mmio_addr;
4211
4212 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4213 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4214 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4215}
4216
4217static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4218{
4219 void __iomem *ioaddr = tp->mmio_addr;
4220
4221 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4222}
4223
4224static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4225{
4226 void __iomem *ioaddr = tp->mmio_addr;
4227
4228 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4229}
4230
4231static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4232{
4233 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004234
4235 RTL_W8(MaxTxPacketSize, 0x3f);
4236 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4237 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004238 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004239}
4240
4241static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4242{
4243 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004244
4245 RTL_W8(MaxTxPacketSize, 0x0c);
4246 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4247 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004248 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004249}
4250
4251static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4252{
4253 rtl_tx_performance_tweak(tp->pci_dev,
4254 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4255}
4256
4257static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4258{
4259 rtl_tx_performance_tweak(tp->pci_dev,
4260 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4261}
4262
4263static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4264{
4265 void __iomem *ioaddr = tp->mmio_addr;
4266
4267 r8168b_0_hw_jumbo_enable(tp);
4268
4269 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4270}
4271
4272static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4273{
4274 void __iomem *ioaddr = tp->mmio_addr;
4275
4276 r8168b_0_hw_jumbo_disable(tp);
4277
4278 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4279}
4280
4281static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
4282{
4283 struct jumbo_ops *ops = &tp->jumbo_ops;
4284
4285 switch (tp->mac_version) {
4286 case RTL_GIGA_MAC_VER_11:
4287 ops->disable = r8168b_0_hw_jumbo_disable;
4288 ops->enable = r8168b_0_hw_jumbo_enable;
4289 break;
4290 case RTL_GIGA_MAC_VER_12:
4291 case RTL_GIGA_MAC_VER_17:
4292 ops->disable = r8168b_1_hw_jumbo_disable;
4293 ops->enable = r8168b_1_hw_jumbo_enable;
4294 break;
4295 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4296 case RTL_GIGA_MAC_VER_19:
4297 case RTL_GIGA_MAC_VER_20:
4298 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4299 case RTL_GIGA_MAC_VER_22:
4300 case RTL_GIGA_MAC_VER_23:
4301 case RTL_GIGA_MAC_VER_24:
4302 case RTL_GIGA_MAC_VER_25:
4303 case RTL_GIGA_MAC_VER_26:
4304 ops->disable = r8168c_hw_jumbo_disable;
4305 ops->enable = r8168c_hw_jumbo_enable;
4306 break;
4307 case RTL_GIGA_MAC_VER_27:
4308 case RTL_GIGA_MAC_VER_28:
4309 ops->disable = r8168dp_hw_jumbo_disable;
4310 ops->enable = r8168dp_hw_jumbo_enable;
4311 break;
4312 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4313 case RTL_GIGA_MAC_VER_32:
4314 case RTL_GIGA_MAC_VER_33:
4315 case RTL_GIGA_MAC_VER_34:
4316 ops->disable = r8168e_hw_jumbo_disable;
4317 ops->enable = r8168e_hw_jumbo_enable;
4318 break;
4319
4320 /*
4321 * No action needed for jumbo frames with 8169.
4322 * No jumbo for 810x at all.
4323 */
Hayes Wangc5583862012-07-02 17:23:22 +08004324 case RTL_GIGA_MAC_VER_40:
4325 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004326 default:
4327 ops->disable = NULL;
4328 ops->enable = NULL;
4329 break;
4330 }
4331}
4332
Francois Romieuffc46952012-07-06 14:19:23 +02004333DECLARE_RTL_COND(rtl_chipcmd_cond)
4334{
4335 void __iomem *ioaddr = tp->mmio_addr;
4336
4337 return RTL_R8(ChipCmd) & CmdReset;
4338}
4339
Francois Romieu6f43adc2011-04-29 15:05:51 +02004340static void rtl_hw_reset(struct rtl8169_private *tp)
4341{
4342 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004343
Francois Romieu6f43adc2011-04-29 15:05:51 +02004344 RTL_W8(ChipCmd, CmdReset);
4345
Francois Romieuffc46952012-07-06 14:19:23 +02004346 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004347}
4348
Francois Romieub6ffd972011-06-17 17:00:05 +02004349static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4350{
4351 struct rtl_fw *rtl_fw;
4352 const char *name;
4353 int rc = -ENOMEM;
4354
4355 name = rtl_lookup_firmware_name(tp);
4356 if (!name)
4357 goto out_no_firmware;
4358
4359 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4360 if (!rtl_fw)
4361 goto err_warn;
4362
4363 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4364 if (rc < 0)
4365 goto err_free;
4366
Francois Romieufd112f22011-06-18 00:10:29 +02004367 rc = rtl_check_firmware(tp, rtl_fw);
4368 if (rc < 0)
4369 goto err_release_firmware;
4370
Francois Romieub6ffd972011-06-17 17:00:05 +02004371 tp->rtl_fw = rtl_fw;
4372out:
4373 return;
4374
Francois Romieufd112f22011-06-18 00:10:29 +02004375err_release_firmware:
4376 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004377err_free:
4378 kfree(rtl_fw);
4379err_warn:
4380 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4381 name, rc);
4382out_no_firmware:
4383 tp->rtl_fw = NULL;
4384 goto out;
4385}
4386
François Romieu953a12c2011-04-24 17:38:48 +02004387static void rtl_request_firmware(struct rtl8169_private *tp)
4388{
Francois Romieub6ffd972011-06-17 17:00:05 +02004389 if (IS_ERR(tp->rtl_fw))
4390 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004391}
4392
Hayes Wang92fc43b2011-07-06 15:58:03 +08004393static void rtl_rx_close(struct rtl8169_private *tp)
4394{
4395 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004396
Francois Romieu1687b562011-07-19 17:21:29 +02004397 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004398}
4399
Francois Romieuffc46952012-07-06 14:19:23 +02004400DECLARE_RTL_COND(rtl_npq_cond)
4401{
4402 void __iomem *ioaddr = tp->mmio_addr;
4403
4404 return RTL_R8(TxPoll) & NPQ;
4405}
4406
4407DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4408{
4409 void __iomem *ioaddr = tp->mmio_addr;
4410
4411 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4412}
4413
françois romieue6de30d2011-01-03 15:08:37 +00004414static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
françois romieue6de30d2011-01-03 15:08:37 +00004416 void __iomem *ioaddr = tp->mmio_addr;
4417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004419 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Hayes Wang92fc43b2011-07-06 15:58:03 +08004421 rtl_rx_close(tp);
4422
Hayes Wang5d2e1952011-02-22 17:26:22 +08004423 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004424 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4425 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004426 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004427 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4428 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004429 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004430 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004431 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4432 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004433 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004434 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004435 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004436 } else {
4437 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4438 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004439 }
4440
Hayes Wang92fc43b2011-07-06 15:58:03 +08004441 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442}
4443
Francois Romieu7f796d832007-06-11 23:04:41 +02004444static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004445{
4446 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004447
4448 /* Set DMA burst size and Interframe Gap Time */
4449 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4450 (InterFrameGap << TxInterFrameGapShift));
4451}
4452
Francois Romieu07ce4062007-02-23 23:36:39 +01004453static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454{
4455 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
Francois Romieu07ce4062007-02-23 23:36:39 +01004457 tp->hw_start(dev);
4458
Francois Romieuda78dbf2012-01-26 14:18:23 +01004459 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004460}
4461
Francois Romieu7f796d832007-06-11 23:04:41 +02004462static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4463 void __iomem *ioaddr)
4464{
4465 /*
4466 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4467 * register to be written before TxDescAddrLow to work.
4468 * Switching from MMIO to I/O access fixes the issue as well.
4469 */
4470 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004471 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004472 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004473 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004474}
4475
4476static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4477{
4478 u16 cmd;
4479
4480 cmd = RTL_R16(CPlusCmd);
4481 RTL_W16(CPlusCmd, cmd);
4482 return cmd;
4483}
4484
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004485static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004486{
4487 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004488 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004489}
4490
Francois Romieu6dccd162007-02-13 23:38:05 +01004491static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4492{
Francois Romieu37441002011-06-17 22:58:54 +02004493 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004494 u32 mac_version;
4495 u32 clk;
4496 u32 val;
4497 } cfg2_info [] = {
4498 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4499 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4500 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4501 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004502 };
4503 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004504 unsigned int i;
4505 u32 clk;
4506
4507 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004508 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004509 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4510 RTL_W32(0x7c, p->val);
4511 break;
4512 }
4513 }
4514}
4515
Francois Romieue6b763e2012-03-08 09:35:39 +01004516static void rtl_set_rx_mode(struct net_device *dev)
4517{
4518 struct rtl8169_private *tp = netdev_priv(dev);
4519 void __iomem *ioaddr = tp->mmio_addr;
4520 u32 mc_filter[2]; /* Multicast hash filter */
4521 int rx_mode;
4522 u32 tmp = 0;
4523
4524 if (dev->flags & IFF_PROMISC) {
4525 /* Unconditionally log net taps. */
4526 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4527 rx_mode =
4528 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4529 AcceptAllPhys;
4530 mc_filter[1] = mc_filter[0] = 0xffffffff;
4531 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4532 (dev->flags & IFF_ALLMULTI)) {
4533 /* Too many to filter perfectly -- accept all multicasts. */
4534 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4535 mc_filter[1] = mc_filter[0] = 0xffffffff;
4536 } else {
4537 struct netdev_hw_addr *ha;
4538
4539 rx_mode = AcceptBroadcast | AcceptMyPhys;
4540 mc_filter[1] = mc_filter[0] = 0;
4541 netdev_for_each_mc_addr(ha, dev) {
4542 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4543 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4544 rx_mode |= AcceptMulticast;
4545 }
4546 }
4547
4548 if (dev->features & NETIF_F_RXALL)
4549 rx_mode |= (AcceptErr | AcceptRunt);
4550
4551 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4552
4553 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4554 u32 data = mc_filter[0];
4555
4556 mc_filter[0] = swab32(mc_filter[1]);
4557 mc_filter[1] = swab32(data);
4558 }
4559
4560 RTL_W32(MAR0 + 4, mc_filter[1]);
4561 RTL_W32(MAR0 + 0, mc_filter[0]);
4562
4563 RTL_W32(RxConfig, tmp);
4564}
4565
Francois Romieu07ce4062007-02-23 23:36:39 +01004566static void rtl_hw_start_8169(struct net_device *dev)
4567{
4568 struct rtl8169_private *tp = netdev_priv(dev);
4569 void __iomem *ioaddr = tp->mmio_addr;
4570 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004571
Francois Romieu9cb427b2006-11-02 00:10:16 +01004572 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4573 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4574 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4575 }
4576
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004578 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4579 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4580 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4581 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004582 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4583
Hayes Wange542a222011-07-06 15:58:04 +08004584 rtl_init_rxcfg(tp);
4585
françois romieuf0298f82011-01-03 15:07:42 +00004586 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004588 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
Francois Romieucecb5fd2011-04-01 10:21:07 +02004590 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4591 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4592 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4593 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004594 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595
Francois Romieu7f796d832007-06-11 23:04:41 +02004596 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004597
Francois Romieucecb5fd2011-04-01 10:21:07 +02004598 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4599 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004600 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004602 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 }
4604
Francois Romieubcf0bf92006-07-26 23:14:13 +02004605 RTL_W16(CPlusCmd, tp->cp_cmd);
4606
Francois Romieu6dccd162007-02-13 23:38:05 +01004607 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4608
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 /*
4610 * Undocumented corner. Supposedly:
4611 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4612 */
4613 RTL_W16(IntrMitigate, 0x0000);
4614
Francois Romieu7f796d832007-06-11 23:04:41 +02004615 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004616
Francois Romieucecb5fd2011-04-01 10:21:07 +02004617 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4618 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4619 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4620 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004621 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4622 rtl_set_rx_tx_config_registers(tp);
4623 }
4624
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004626
4627 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4628 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629
4630 RTL_W32(RxMissed, 0);
4631
Francois Romieu07ce4062007-02-23 23:36:39 +01004632 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
4634 /* no early-rx interrupts */
4635 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004636}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004638static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4639{
4640 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004641 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004642}
4643
4644static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4645{
Francois Romieu52989f02012-07-06 13:37:00 +02004646 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004647}
4648
4649static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004650{
4651 u32 csi;
4652
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004653 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4654 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004655}
4656
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004657static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004658{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004659 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004660}
4661
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004662static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004663{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004664 rtl_csi_access_enable(tp, 0x27000000);
4665}
4666
Francois Romieuffc46952012-07-06 14:19:23 +02004667DECLARE_RTL_COND(rtl_csiar_cond)
4668{
4669 void __iomem *ioaddr = tp->mmio_addr;
4670
4671 return RTL_R32(CSIAR) & CSIAR_FLAG;
4672}
4673
Francois Romieu52989f02012-07-06 13:37:00 +02004674static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004675{
Francois Romieu52989f02012-07-06 13:37:00 +02004676 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004677
4678 RTL_W32(CSIDR, value);
4679 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4680 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4681
Francois Romieuffc46952012-07-06 14:19:23 +02004682 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004683}
4684
Francois Romieu52989f02012-07-06 13:37:00 +02004685static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004686{
Francois Romieu52989f02012-07-06 13:37:00 +02004687 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004688
4689 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4690 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4691
Francois Romieuffc46952012-07-06 14:19:23 +02004692 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4693 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004694}
4695
Francois Romieu52989f02012-07-06 13:37:00 +02004696static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004697{
Francois Romieu52989f02012-07-06 13:37:00 +02004698 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004699
4700 RTL_W32(CSIDR, value);
4701 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4702 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4703 CSIAR_FUNC_NIC);
4704
Francois Romieuffc46952012-07-06 14:19:23 +02004705 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004706}
4707
Francois Romieu52989f02012-07-06 13:37:00 +02004708static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004709{
Francois Romieu52989f02012-07-06 13:37:00 +02004710 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004711
4712 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4713 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4714
Francois Romieuffc46952012-07-06 14:19:23 +02004715 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4716 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004717}
4718
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004719static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
4720{
4721 struct csi_ops *ops = &tp->csi_ops;
4722
4723 switch (tp->mac_version) {
4724 case RTL_GIGA_MAC_VER_01:
4725 case RTL_GIGA_MAC_VER_02:
4726 case RTL_GIGA_MAC_VER_03:
4727 case RTL_GIGA_MAC_VER_04:
4728 case RTL_GIGA_MAC_VER_05:
4729 case RTL_GIGA_MAC_VER_06:
4730 case RTL_GIGA_MAC_VER_10:
4731 case RTL_GIGA_MAC_VER_11:
4732 case RTL_GIGA_MAC_VER_12:
4733 case RTL_GIGA_MAC_VER_13:
4734 case RTL_GIGA_MAC_VER_14:
4735 case RTL_GIGA_MAC_VER_15:
4736 case RTL_GIGA_MAC_VER_16:
4737 case RTL_GIGA_MAC_VER_17:
4738 ops->write = NULL;
4739 ops->read = NULL;
4740 break;
4741
Hayes Wang7e18dca2012-03-30 14:33:02 +08004742 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004743 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004744 ops->write = r8402_csi_write;
4745 ops->read = r8402_csi_read;
4746 break;
4747
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004748 default:
4749 ops->write = r8169_csi_write;
4750 ops->read = r8169_csi_read;
4751 break;
4752 }
Francois Romieudacf8152008-08-02 20:44:13 +02004753}
4754
4755struct ephy_info {
4756 unsigned int offset;
4757 u16 mask;
4758 u16 bits;
4759};
4760
Francois Romieufdf6fc02012-07-06 22:40:38 +02004761static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4762 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004763{
4764 u16 w;
4765
4766 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004767 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4768 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004769 e++;
4770 }
4771}
4772
Francois Romieub726e492008-06-28 12:22:59 +02004773static void rtl_disable_clock_request(struct pci_dev *pdev)
4774{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004775 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4776 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004777}
4778
françois romieue6de30d2011-01-03 15:08:37 +00004779static void rtl_enable_clock_request(struct pci_dev *pdev)
4780{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004781 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4782 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004783}
4784
Francois Romieub726e492008-06-28 12:22:59 +02004785#define R8168_CPCMD_QUIRK_MASK (\
4786 EnableBist | \
4787 Mac_dbgo_oe | \
4788 Force_half_dup | \
4789 Force_rxflow_en | \
4790 Force_txflow_en | \
4791 Cxpl_dbg_sel | \
4792 ASF | \
4793 PktCntrDisable | \
4794 Mac_dbgo_sel)
4795
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004796static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004797{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004798 void __iomem *ioaddr = tp->mmio_addr;
4799 struct pci_dev *pdev = tp->pci_dev;
4800
Francois Romieub726e492008-06-28 12:22:59 +02004801 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4802
4803 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4804
Francois Romieu2e68ae42008-06-28 12:00:55 +02004805 rtl_tx_performance_tweak(pdev,
4806 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004807}
4808
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004809static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004810{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004811 void __iomem *ioaddr = tp->mmio_addr;
4812
4813 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004814
françois romieuf0298f82011-01-03 15:07:42 +00004815 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004816
4817 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004818}
4819
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004820static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004821{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004822 void __iomem *ioaddr = tp->mmio_addr;
4823 struct pci_dev *pdev = tp->pci_dev;
4824
Francois Romieub726e492008-06-28 12:22:59 +02004825 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4826
4827 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4828
Francois Romieu219a1e92008-06-28 11:58:39 +02004829 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004830
4831 rtl_disable_clock_request(pdev);
4832
4833 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004834}
4835
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004836static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004837{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004838 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004839 { 0x01, 0, 0x0001 },
4840 { 0x02, 0x0800, 0x1000 },
4841 { 0x03, 0, 0x0042 },
4842 { 0x06, 0x0080, 0x0000 },
4843 { 0x07, 0, 0x2000 }
4844 };
4845
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004846 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004847
Francois Romieufdf6fc02012-07-06 22:40:38 +02004848 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004849
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004850 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004851}
4852
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004853static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004854{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004855 void __iomem *ioaddr = tp->mmio_addr;
4856 struct pci_dev *pdev = tp->pci_dev;
4857
4858 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004859
4860 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4861
4862 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4863
4864 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4865}
4866
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004867static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004868{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004869 void __iomem *ioaddr = tp->mmio_addr;
4870 struct pci_dev *pdev = tp->pci_dev;
4871
4872 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004873
4874 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4875
4876 /* Magic. */
4877 RTL_W8(DBG_REG, 0x20);
4878
françois romieuf0298f82011-01-03 15:07:42 +00004879 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004880
4881 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4882
4883 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4884}
4885
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004886static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004887{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004888 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004889 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004890 { 0x02, 0x0800, 0x1000 },
4891 { 0x03, 0, 0x0002 },
4892 { 0x06, 0x0080, 0x0000 }
4893 };
4894
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004895 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004896
4897 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4898
Francois Romieufdf6fc02012-07-06 22:40:38 +02004899 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004900
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004901 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004902}
4903
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004904static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004905{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004906 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004907 { 0x01, 0, 0x0001 },
4908 { 0x03, 0x0400, 0x0220 }
4909 };
4910
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004911 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004912
Francois Romieufdf6fc02012-07-06 22:40:38 +02004913 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004914
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004915 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004916}
4917
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004918static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004919{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004920 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004921}
4922
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004923static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004924{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004925 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004926
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004927 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004928}
4929
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004930static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004931{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004932 void __iomem *ioaddr = tp->mmio_addr;
4933 struct pci_dev *pdev = tp->pci_dev;
4934
4935 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004936
4937 rtl_disable_clock_request(pdev);
4938
françois romieuf0298f82011-01-03 15:07:42 +00004939 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004940
4941 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4942
4943 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4944}
4945
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004946static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004947{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004948 void __iomem *ioaddr = tp->mmio_addr;
4949 struct pci_dev *pdev = tp->pci_dev;
4950
4951 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004952
4953 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4954
4955 RTL_W8(MaxTxPacketSize, TxPacketMax);
4956
4957 rtl_disable_clock_request(pdev);
4958}
4959
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004960static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004961{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004962 void __iomem *ioaddr = tp->mmio_addr;
4963 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004964 static const struct ephy_info e_info_8168d_4[] = {
4965 { 0x0b, ~0, 0x48 },
4966 { 0x19, 0x20, 0x50 },
4967 { 0x0c, ~0, 0x20 }
4968 };
4969 int i;
4970
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004971 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004972
4973 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4974
4975 RTL_W8(MaxTxPacketSize, TxPacketMax);
4976
4977 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4978 const struct ephy_info *e = e_info_8168d_4 + i;
4979 u16 w;
4980
Francois Romieufdf6fc02012-07-06 22:40:38 +02004981 w = rtl_ephy_read(tp, e->offset);
4982 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004983 }
4984
4985 rtl_enable_clock_request(pdev);
4986}
4987
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004988static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004989{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004990 void __iomem *ioaddr = tp->mmio_addr;
4991 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004992 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004993 { 0x00, 0x0200, 0x0100 },
4994 { 0x00, 0x0000, 0x0004 },
4995 { 0x06, 0x0002, 0x0001 },
4996 { 0x06, 0x0000, 0x0030 },
4997 { 0x07, 0x0000, 0x2000 },
4998 { 0x00, 0x0000, 0x0020 },
4999 { 0x03, 0x5800, 0x2000 },
5000 { 0x03, 0x0000, 0x0001 },
5001 { 0x01, 0x0800, 0x1000 },
5002 { 0x07, 0x0000, 0x4000 },
5003 { 0x1e, 0x0000, 0x2000 },
5004 { 0x19, 0xffff, 0xfe6c },
5005 { 0x0a, 0x0000, 0x0040 }
5006 };
5007
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005008 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005009
Francois Romieufdf6fc02012-07-06 22:40:38 +02005010 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005011
5012 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5013
5014 RTL_W8(MaxTxPacketSize, TxPacketMax);
5015
5016 rtl_disable_clock_request(pdev);
5017
5018 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005019 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5020 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005021
Francois Romieucecb5fd2011-04-01 10:21:07 +02005022 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005023}
5024
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005025static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005026{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005027 void __iomem *ioaddr = tp->mmio_addr;
5028 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005029 static const struct ephy_info e_info_8168e_2[] = {
5030 { 0x09, 0x0000, 0x0080 },
5031 { 0x19, 0x0000, 0x0224 }
5032 };
5033
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005034 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005035
Francois Romieufdf6fc02012-07-06 22:40:38 +02005036 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005037
5038 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5039
Francois Romieufdf6fc02012-07-06 22:40:38 +02005040 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5041 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5042 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5043 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5044 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5045 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5046 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5047 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005048
Hayes Wang3090bd92011-09-06 16:55:15 +08005049 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005050
Hayes Wang70090422011-07-06 15:58:06 +08005051 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5052 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5053
5054 /* Adjust EEE LED frequency */
5055 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5056
5057 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5058 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005059 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5060 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005061}
5062
Hayes Wang5f886e02012-03-30 14:33:03 +08005063static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005064{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005065 void __iomem *ioaddr = tp->mmio_addr;
5066 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005067
Hayes Wang5f886e02012-03-30 14:33:03 +08005068 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005069
5070 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5071
Francois Romieufdf6fc02012-07-06 22:40:38 +02005072 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5073 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5074 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5075 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5076 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5077 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5078 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5079 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5080 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5081 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005082
5083 RTL_W8(MaxTxPacketSize, EarlySize);
5084
Hayes Wangc2218922011-09-06 16:55:18 +08005085 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5086 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005087 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005088 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5089 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5090 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005091}
5092
Hayes Wang5f886e02012-03-30 14:33:03 +08005093static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5094{
5095 void __iomem *ioaddr = tp->mmio_addr;
5096 static const struct ephy_info e_info_8168f_1[] = {
5097 { 0x06, 0x00c0, 0x0020 },
5098 { 0x08, 0x0001, 0x0002 },
5099 { 0x09, 0x0000, 0x0080 },
5100 { 0x19, 0x0000, 0x0224 }
5101 };
5102
5103 rtl_hw_start_8168f(tp);
5104
Francois Romieufdf6fc02012-07-06 22:40:38 +02005105 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005106
Francois Romieufdf6fc02012-07-06 22:40:38 +02005107 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005108
5109 /* Adjust EEE LED frequency */
5110 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5111}
5112
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005113static void rtl_hw_start_8411(struct rtl8169_private *tp)
5114{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005115 static const struct ephy_info e_info_8168f_1[] = {
5116 { 0x06, 0x00c0, 0x0020 },
5117 { 0x0f, 0xffff, 0x5200 },
5118 { 0x1e, 0x0000, 0x4000 },
5119 { 0x19, 0x0000, 0x0224 }
5120 };
5121
5122 rtl_hw_start_8168f(tp);
5123
Francois Romieufdf6fc02012-07-06 22:40:38 +02005124 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005125
Francois Romieufdf6fc02012-07-06 22:40:38 +02005126 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005127}
5128
Hayes Wangc5583862012-07-02 17:23:22 +08005129static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5130{
5131 void __iomem *ioaddr = tp->mmio_addr;
5132 struct pci_dev *pdev = tp->pci_dev;
5133
5134 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5135 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5136 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5137 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5138
5139 rtl_csi_access_enable_1(tp);
5140
5141 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5142
5143 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5144 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5145
5146 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005147 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005148 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005149 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5150 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005151
5152 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5153 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5154
5155 /* Adjust EEE LED frequency */
5156 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5157
5158 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5159}
5160
Francois Romieu07ce4062007-02-23 23:36:39 +01005161static void rtl_hw_start_8168(struct net_device *dev)
5162{
Francois Romieu2dd99532007-06-11 23:22:52 +02005163 struct rtl8169_private *tp = netdev_priv(dev);
5164 void __iomem *ioaddr = tp->mmio_addr;
5165
5166 RTL_W8(Cfg9346, Cfg9346_Unlock);
5167
françois romieuf0298f82011-01-03 15:07:42 +00005168 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005169
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005170 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005171
Francois Romieu0e485152007-02-20 00:00:26 +01005172 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005173
5174 RTL_W16(CPlusCmd, tp->cp_cmd);
5175
Francois Romieu0e485152007-02-20 00:00:26 +01005176 RTL_W16(IntrMitigate, 0x5151);
5177
5178 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005179 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005180 tp->event_slow |= RxFIFOOver | PCSTimeout;
5181 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005182 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005183
5184 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5185
Francois Romieub8363902008-06-01 12:31:57 +02005186 rtl_set_rx_mode(dev);
5187
5188 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5189 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005190
5191 RTL_R8(IntrMask);
5192
Francois Romieu219a1e92008-06-28 11:58:39 +02005193 switch (tp->mac_version) {
5194 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005195 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005196 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005197
5198 case RTL_GIGA_MAC_VER_12:
5199 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005200 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005201 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005202
5203 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005204 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005205 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005206
5207 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005208 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005209 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005210
5211 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005212 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005213 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005214
Francois Romieu197ff762008-06-28 13:16:02 +02005215 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005216 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005217 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005218
Francois Romieu6fb07052008-06-29 11:54:28 +02005219 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005220 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005221 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005222
Francois Romieuef3386f2008-06-29 12:24:30 +02005223 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005224 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005225 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005226
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005227 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005228 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005229 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005230
Francois Romieu5b538df2008-07-20 16:22:45 +02005231 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005232 case RTL_GIGA_MAC_VER_26:
5233 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005234 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005235 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005236
françois romieue6de30d2011-01-03 15:08:37 +00005237 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005238 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005239 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005240
hayeswang4804b3b2011-03-21 01:50:29 +00005241 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005242 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005243 break;
5244
hayeswang01dc7fe2011-03-21 01:50:28 +00005245 case RTL_GIGA_MAC_VER_32:
5246 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005247 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005248 break;
5249 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005250 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005251 break;
françois romieue6de30d2011-01-03 15:08:37 +00005252
Hayes Wangc2218922011-09-06 16:55:18 +08005253 case RTL_GIGA_MAC_VER_35:
5254 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005255 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005256 break;
5257
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005258 case RTL_GIGA_MAC_VER_38:
5259 rtl_hw_start_8411(tp);
5260 break;
5261
Hayes Wangc5583862012-07-02 17:23:22 +08005262 case RTL_GIGA_MAC_VER_40:
5263 case RTL_GIGA_MAC_VER_41:
5264 rtl_hw_start_8168g_1(tp);
5265 break;
5266
Francois Romieu219a1e92008-06-28 11:58:39 +02005267 default:
5268 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5269 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005270 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005271 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005272
Francois Romieu0e485152007-02-20 00:00:26 +01005273 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5274
Francois Romieub8363902008-06-01 12:31:57 +02005275 RTL_W8(Cfg9346, Cfg9346_Lock);
5276
Francois Romieu2dd99532007-06-11 23:22:52 +02005277 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005278}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279
Francois Romieu2857ffb2008-08-02 21:08:49 +02005280#define R810X_CPCMD_QUIRK_MASK (\
5281 EnableBist | \
5282 Mac_dbgo_oe | \
5283 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005284 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005285 Force_txflow_en | \
5286 Cxpl_dbg_sel | \
5287 ASF | \
5288 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005289 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005290
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005291static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005292{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005293 void __iomem *ioaddr = tp->mmio_addr;
5294 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005295 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005296 { 0x01, 0, 0x6e65 },
5297 { 0x02, 0, 0x091f },
5298 { 0x03, 0, 0xc2f9 },
5299 { 0x06, 0, 0xafb5 },
5300 { 0x07, 0, 0x0e00 },
5301 { 0x19, 0, 0xec80 },
5302 { 0x01, 0, 0x2e65 },
5303 { 0x01, 0, 0x6e65 }
5304 };
5305 u8 cfg1;
5306
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005307 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005308
5309 RTL_W8(DBG_REG, FIX_NAK_1);
5310
5311 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5312
5313 RTL_W8(Config1,
5314 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5315 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5316
5317 cfg1 = RTL_R8(Config1);
5318 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5319 RTL_W8(Config1, cfg1 & ~LEDS0);
5320
Francois Romieufdf6fc02012-07-06 22:40:38 +02005321 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005322}
5323
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005324static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005325{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005326 void __iomem *ioaddr = tp->mmio_addr;
5327 struct pci_dev *pdev = tp->pci_dev;
5328
5329 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005330
5331 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5332
5333 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5334 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005335}
5336
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005337static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005338{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005339 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005340
Francois Romieufdf6fc02012-07-06 22:40:38 +02005341 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005342}
5343
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005344static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005345{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005346 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005347 static const struct ephy_info e_info_8105e_1[] = {
5348 { 0x07, 0, 0x4000 },
5349 { 0x19, 0, 0x0200 },
5350 { 0x19, 0, 0x0020 },
5351 { 0x1e, 0, 0x2000 },
5352 { 0x03, 0, 0x0001 },
5353 { 0x19, 0, 0x0100 },
5354 { 0x19, 0, 0x0004 },
5355 { 0x0a, 0, 0x0020 }
5356 };
5357
Francois Romieucecb5fd2011-04-01 10:21:07 +02005358 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005359 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5360
Francois Romieucecb5fd2011-04-01 10:21:07 +02005361 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005362 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5363
5364 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005365 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005366 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5367 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5368 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005369
Francois Romieufdf6fc02012-07-06 22:40:38 +02005370 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005371}
5372
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005373static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005374{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005375 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005376 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005377}
5378
Hayes Wang7e18dca2012-03-30 14:33:02 +08005379static void rtl_hw_start_8402(struct rtl8169_private *tp)
5380{
5381 void __iomem *ioaddr = tp->mmio_addr;
5382 static const struct ephy_info e_info_8402[] = {
5383 { 0x19, 0xffff, 0xff64 },
5384 { 0x1e, 0, 0x4000 }
5385 };
5386
5387 rtl_csi_access_enable_2(tp);
5388
5389 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5390 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5391
5392 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5393 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005394 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5395 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5396 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005397
Francois Romieufdf6fc02012-07-06 22:40:38 +02005398 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005399
5400 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5401
Francois Romieufdf6fc02012-07-06 22:40:38 +02005402 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5403 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5404 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5405 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5406 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5407 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5408 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005409}
5410
Hayes Wang5598bfe2012-07-02 17:23:21 +08005411static void rtl_hw_start_8106(struct rtl8169_private *tp)
5412{
5413 void __iomem *ioaddr = tp->mmio_addr;
5414
5415 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5416 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5417
hayeswangd64ec842012-11-01 16:46:28 +00005418 RTL_W32(MISC,
5419 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5420 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5421 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005422 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5423 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5424}
5425
Francois Romieu07ce4062007-02-23 23:36:39 +01005426static void rtl_hw_start_8101(struct net_device *dev)
5427{
Francois Romieucdf1a602007-06-11 23:29:50 +02005428 struct rtl8169_private *tp = netdev_priv(dev);
5429 void __iomem *ioaddr = tp->mmio_addr;
5430 struct pci_dev *pdev = tp->pci_dev;
5431
Francois Romieuda78dbf2012-01-26 14:18:23 +01005432 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5433 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005434
Francois Romieucecb5fd2011-04-01 10:21:07 +02005435 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005436 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005437 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5438 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005439
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005440 RTL_W8(Cfg9346, Cfg9346_Unlock);
5441
Francois Romieu2857ffb2008-08-02 21:08:49 +02005442 switch (tp->mac_version) {
5443 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005444 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005445 break;
5446
5447 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005448 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005449 break;
5450
5451 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005452 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005453 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005454
5455 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005456 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005457 break;
5458 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005459 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005460 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005461
5462 case RTL_GIGA_MAC_VER_37:
5463 rtl_hw_start_8402(tp);
5464 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005465
5466 case RTL_GIGA_MAC_VER_39:
5467 rtl_hw_start_8106(tp);
5468 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005469 }
5470
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005471 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005472
françois romieuf0298f82011-01-03 15:07:42 +00005473 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005474
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005475 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005476
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005477 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005478 RTL_W16(CPlusCmd, tp->cp_cmd);
5479
5480 RTL_W16(IntrMitigate, 0x0000);
5481
5482 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5483
5484 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5485 rtl_set_rx_tx_config_registers(tp);
5486
Francois Romieucdf1a602007-06-11 23:29:50 +02005487 RTL_R8(IntrMask);
5488
Francois Romieucdf1a602007-06-11 23:29:50 +02005489 rtl_set_rx_mode(dev);
5490
5491 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492}
5493
5494static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5495{
Francois Romieud58d46b2011-05-03 16:38:29 +02005496 struct rtl8169_private *tp = netdev_priv(dev);
5497
5498 if (new_mtu < ETH_ZLEN ||
5499 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500 return -EINVAL;
5501
Francois Romieud58d46b2011-05-03 16:38:29 +02005502 if (new_mtu > ETH_DATA_LEN)
5503 rtl_hw_jumbo_enable(tp);
5504 else
5505 rtl_hw_jumbo_disable(tp);
5506
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005508 netdev_update_features(dev);
5509
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005510 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511}
5512
5513static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5514{
Al Viro95e09182007-12-22 18:55:39 +00005515 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5517}
5518
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005519static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5520 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005522 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005523 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005524
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005525 kfree(*data_buff);
5526 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527 rtl8169_make_unusable_by_asic(desc);
5528}
5529
5530static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5531{
5532 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5533
5534 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5535}
5536
5537static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5538 u32 rx_buf_sz)
5539{
5540 desc->addr = cpu_to_le64(mapping);
5541 wmb();
5542 rtl8169_mark_to_asic(desc, rx_buf_sz);
5543}
5544
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005545static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005547 return (void *)ALIGN((long)data, 16);
5548}
5549
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005550static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5551 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005552{
5553 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005555 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005556 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005557 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005558
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005559 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5560 if (!data)
5561 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005562
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005563 if (rtl8169_align(data) != data) {
5564 kfree(data);
5565 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5566 if (!data)
5567 return NULL;
5568 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005569
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005570 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005571 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005572 if (unlikely(dma_mapping_error(d, mapping))) {
5573 if (net_ratelimit())
5574 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005575 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577
5578 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005579 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005580
5581err_out:
5582 kfree(data);
5583 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584}
5585
5586static void rtl8169_rx_clear(struct rtl8169_private *tp)
5587{
Francois Romieu07d3f512007-02-21 22:40:46 +01005588 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
5590 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005591 if (tp->Rx_databuff[i]) {
5592 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005593 tp->RxDescArray + i);
5594 }
5595 }
5596}
5597
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005598static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005600 desc->opts1 |= cpu_to_le32(RingEnd);
5601}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005602
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005603static int rtl8169_rx_fill(struct rtl8169_private *tp)
5604{
5605 unsigned int i;
5606
5607 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005608 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005609
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005610 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005612
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005613 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005614 if (!data) {
5615 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005616 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005617 }
5618 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005621 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5622 return 0;
5623
5624err_out:
5625 rtl8169_rx_clear(tp);
5626 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627}
5628
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629static int rtl8169_init_ring(struct net_device *dev)
5630{
5631 struct rtl8169_private *tp = netdev_priv(dev);
5632
5633 rtl8169_init_ring_indexes(tp);
5634
5635 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005636 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005638 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639}
5640
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005641static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 struct TxDesc *desc)
5643{
5644 unsigned int len = tx_skb->len;
5645
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005646 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5647
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648 desc->opts1 = 0x00;
5649 desc->opts2 = 0x00;
5650 desc->addr = 0x00;
5651 tx_skb->len = 0;
5652}
5653
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005654static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5655 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656{
5657 unsigned int i;
5658
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005659 for (i = 0; i < n; i++) {
5660 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 struct ring_info *tx_skb = tp->tx_skb + entry;
5662 unsigned int len = tx_skb->len;
5663
5664 if (len) {
5665 struct sk_buff *skb = tx_skb->skb;
5666
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005667 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668 tp->TxDescArray + entry);
5669 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005670 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671 dev_kfree_skb(skb);
5672 tx_skb->skb = NULL;
5673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 }
5675 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005676}
5677
5678static void rtl8169_tx_clear(struct rtl8169_private *tp)
5679{
5680 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005681 tp->cur_tx = tp->dirty_tx = 0;
5682}
5683
Francois Romieu4422bcd2012-01-26 11:23:32 +01005684static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685{
David Howellsc4028952006-11-22 14:57:56 +00005686 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005687 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688
Francois Romieuda78dbf2012-01-26 14:18:23 +01005689 napi_disable(&tp->napi);
5690 netif_stop_queue(dev);
5691 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
françois romieuc7c2c392011-12-04 20:30:52 +00005693 rtl8169_hw_reset(tp);
5694
Francois Romieu56de4142011-03-15 17:29:31 +01005695 for (i = 0; i < NUM_RX_DESC; i++)
5696 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5697
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005699 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700
Francois Romieuda78dbf2012-01-26 14:18:23 +01005701 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005702 rtl_hw_start(dev);
5703 netif_wake_queue(dev);
5704 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705}
5706
5707static void rtl8169_tx_timeout(struct net_device *dev)
5708{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005709 struct rtl8169_private *tp = netdev_priv(dev);
5710
5711 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712}
5713
5714static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005715 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716{
5717 struct skb_shared_info *info = skb_shinfo(skb);
5718 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005719 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005720 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721
5722 entry = tp->cur_tx;
5723 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005724 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725 dma_addr_t mapping;
5726 u32 status, len;
5727 void *addr;
5728
5729 entry = (entry + 1) % NUM_TX_DESC;
5730
5731 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005732 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005733 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005734 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005735 if (unlikely(dma_mapping_error(d, mapping))) {
5736 if (net_ratelimit())
5737 netif_err(tp, drv, tp->dev,
5738 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005739 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741
Francois Romieucecb5fd2011-04-01 10:21:07 +02005742 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005743 status = opts[0] | len |
5744 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005745
5746 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005747 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748 txd->addr = cpu_to_le64(mapping);
5749
5750 tp->tx_skb[entry].len = len;
5751 }
5752
5753 if (cur_frag) {
5754 tp->tx_skb[entry].skb = skb;
5755 txd->opts1 |= cpu_to_le32(LastFrag);
5756 }
5757
5758 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005759
5760err_out:
5761 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5762 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763}
5764
Francois Romieu2b7b4312011-04-18 22:53:24 -07005765static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5766 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005768 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005769 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005770 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771
Francois Romieu2b7b4312011-04-18 22:53:24 -07005772 if (mss) {
5773 opts[0] |= TD_LSO;
5774 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5775 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005776 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777
5778 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005779 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005781 opts[offset] |= info->checksum.udp;
5782 else
5783 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785}
5786
Stephen Hemminger613573252009-08-31 19:50:58 +00005787static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5788 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789{
5790 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005791 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792 struct TxDesc *txd = tp->TxDescArray + entry;
5793 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005794 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795 dma_addr_t mapping;
5796 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005797 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005798 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005799
Julien Ducourthial477206a2012-05-09 00:00:06 +02005800 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005801 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005802 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005803 }
5804
5805 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005806 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005808 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005809 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005810 if (unlikely(dma_mapping_error(d, mapping))) {
5811 if (net_ratelimit())
5812 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005813 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815
5816 tp->tx_skb[entry].len = len;
5817 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
Francois Romieu2b7b4312011-04-18 22:53:24 -07005819 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
5820 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005821
Francois Romieu2b7b4312011-04-18 22:53:24 -07005822 rtl8169_tso_csum(tp, skb, opts);
5823
5824 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005825 if (frags < 0)
5826 goto err_dma_1;
5827 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005828 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005829 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005830 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005831 tp->tx_skb[entry].skb = skb;
5832 }
5833
Francois Romieu2b7b4312011-04-18 22:53:24 -07005834 txd->opts2 = cpu_to_le32(opts[1]);
5835
Richard Cochran5047fb52012-03-10 07:29:42 +00005836 skb_tx_timestamp(skb);
5837
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838 wmb();
5839
Francois Romieucecb5fd2011-04-01 10:21:07 +02005840 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005841 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 txd->opts1 = cpu_to_le32(status);
5843
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844 tp->cur_tx += frags + 1;
5845
David Dillow4c020a92010-03-03 16:33:10 +00005846 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847
Francois Romieucecb5fd2011-04-01 10:21:07 +02005848 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849
Francois Romieuda78dbf2012-01-26 14:18:23 +01005850 mmiowb();
5851
Julien Ducourthial477206a2012-05-09 00:00:06 +02005852 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005853 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5854 * not miss a ring update when it notices a stopped queue.
5855 */
5856 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005858 /* Sync with rtl_tx:
5859 * - publish queue status and cur_tx ring index (write barrier)
5860 * - refresh dirty_tx ring index (read barrier).
5861 * May the current thread have a pessimistic view of the ring
5862 * status and forget to wake up queue, a racing rtl_tx thread
5863 * can't.
5864 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005865 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005866 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 netif_wake_queue(dev);
5868 }
5869
Stephen Hemminger613573252009-08-31 19:50:58 +00005870 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005872err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005873 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005874err_dma_0:
5875 dev_kfree_skb(skb);
5876 dev->stats.tx_dropped++;
5877 return NETDEV_TX_OK;
5878
5879err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005881 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005882 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883}
5884
5885static void rtl8169_pcierr_interrupt(struct net_device *dev)
5886{
5887 struct rtl8169_private *tp = netdev_priv(dev);
5888 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889 u16 pci_status, pci_cmd;
5890
5891 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5892 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5893
Joe Perchesbf82c182010-02-09 11:49:50 +00005894 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5895 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896
5897 /*
5898 * The recovery sequence below admits a very elaborated explanation:
5899 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005900 * - I did not see what else could be done;
5901 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902 *
5903 * Feel free to adjust to your needs.
5904 */
Francois Romieua27993f2006-12-18 00:04:19 +01005905 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005906 pci_cmd &= ~PCI_COMMAND_PARITY;
5907 else
5908 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5909
5910 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911
5912 pci_write_config_word(pdev, PCI_STATUS,
5913 pci_status & (PCI_STATUS_DETECTED_PARITY |
5914 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5915 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5916
5917 /* The infamous DAC f*ckup only happens at boot time */
5918 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005919 void __iomem *ioaddr = tp->mmio_addr;
5920
Joe Perchesbf82c182010-02-09 11:49:50 +00005921 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922 tp->cp_cmd &= ~PCIDAC;
5923 RTL_W16(CPlusCmd, tp->cp_cmd);
5924 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 }
5926
françois romieue6de30d2011-01-03 15:08:37 +00005927 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005928
Francois Romieu98ddf982012-01-31 10:47:34 +01005929 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930}
5931
Francois Romieuda78dbf2012-01-26 14:18:23 +01005932static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933{
5934 unsigned int dirty_tx, tx_left;
5935
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936 dirty_tx = tp->dirty_tx;
5937 smp_rmb();
5938 tx_left = tp->cur_tx - dirty_tx;
5939
5940 while (tx_left > 0) {
5941 unsigned int entry = dirty_tx % NUM_TX_DESC;
5942 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943 u32 status;
5944
5945 rmb();
5946 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5947 if (status & DescOwn)
5948 break;
5949
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005950 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5951 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005953 u64_stats_update_begin(&tp->tx_stats.syncp);
5954 tp->tx_stats.packets++;
5955 tp->tx_stats.bytes += tx_skb->skb->len;
5956 u64_stats_update_end(&tp->tx_stats.syncp);
5957 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958 tx_skb->skb = NULL;
5959 }
5960 dirty_tx++;
5961 tx_left--;
5962 }
5963
5964 if (tp->dirty_tx != dirty_tx) {
5965 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005966 /* Sync with rtl8169_start_xmit:
5967 * - publish dirty_tx ring index (write barrier)
5968 * - refresh cur_tx ring index and queue status (read barrier)
5969 * May the current thread miss the stopped queue condition,
5970 * a racing xmit thread can only have a right view of the
5971 * ring status.
5972 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005973 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005975 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976 netif_wake_queue(dev);
5977 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005978 /*
5979 * 8168 hack: TxPoll requests are lost when the Tx packets are
5980 * too close. Let's kick an extra TxPoll request when a burst
5981 * of start_xmit activity is detected (if it is not detected,
5982 * it is slow enough). -- FR
5983 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005984 if (tp->cur_tx != dirty_tx) {
5985 void __iomem *ioaddr = tp->mmio_addr;
5986
Francois Romieud78ae2d2007-08-26 20:08:19 +02005987 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989 }
5990}
5991
Francois Romieu126fa4b2005-05-12 20:09:17 -04005992static inline int rtl8169_fragmented_frame(u32 status)
5993{
5994 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5995}
5996
Eric Dumazetadea1ac72010-09-05 20:04:05 -07005997static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999 u32 status = opts1 & RxProtoMask;
6000
6001 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006002 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003 skb->ip_summed = CHECKSUM_UNNECESSARY;
6004 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006005 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006}
6007
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006008static struct sk_buff *rtl8169_try_rx_copy(void *data,
6009 struct rtl8169_private *tp,
6010 int pkt_size,
6011 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006013 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006014 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006016 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006017 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006018 prefetch(data);
6019 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6020 if (skb)
6021 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006022 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6023
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006024 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025}
6026
Francois Romieuda78dbf2012-01-26 14:18:23 +01006027static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028{
6029 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006030 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032 cur_rx = tp->cur_rx;
6033 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006034 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006036 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006038 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039 u32 status;
6040
6041 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006042 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043
6044 if (status & DescOwn)
6045 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006046 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006047 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6048 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006049 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006050 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006051 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006053 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006054 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006055 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006056 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006057 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006058 if ((status & (RxRUNT | RxCRC)) &&
6059 !(status & (RxRWT | RxFOVF)) &&
6060 (dev->features & NETIF_F_RXALL))
6061 goto process_pkt;
6062
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006063 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006065 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006066 dma_addr_t addr;
6067 int pkt_size;
6068
6069process_pkt:
6070 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006071 if (likely(!(dev->features & NETIF_F_RXFCS)))
6072 pkt_size = (status & 0x00003fff) - 4;
6073 else
6074 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075
Francois Romieu126fa4b2005-05-12 20:09:17 -04006076 /*
6077 * The driver does not support incoming fragmented
6078 * frames. They are seen as a symptom of over-mtu
6079 * sized frames.
6080 */
6081 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006082 dev->stats.rx_dropped++;
6083 dev->stats.rx_length_errors++;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006084 rtl8169_mark_to_asic(desc, rx_buf_sz);
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006085 continue;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006086 }
6087
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006088 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6089 tp, pkt_size, addr);
6090 rtl8169_mark_to_asic(desc, rx_buf_sz);
6091 if (!skb) {
6092 dev->stats.rx_dropped++;
6093 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094 }
6095
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006096 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097 skb_put(skb, pkt_size);
6098 skb->protocol = eth_type_trans(skb, dev);
6099
Francois Romieu7a8fc772011-03-01 17:18:33 +01006100 rtl8169_rx_vlan_tag(desc, skb);
6101
Francois Romieu56de4142011-03-15 17:29:31 +01006102 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
Junchang Wang8027aa22012-03-04 23:30:32 +01006104 u64_stats_update_begin(&tp->rx_stats.syncp);
6105 tp->rx_stats.packets++;
6106 tp->rx_stats.bytes += pkt_size;
6107 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108 }
Francois Romieu6dccd162007-02-13 23:38:05 +01006109
6110 /* Work around for AMD plateform. */
Al Viro95e09182007-12-22 18:55:39 +00006111 if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
Francois Romieu6dccd162007-02-13 23:38:05 +01006112 (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
6113 desc->opts2 = 0;
6114 cur_rx++;
6115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116 }
6117
6118 count = cur_rx - tp->cur_rx;
6119 tp->cur_rx = cur_rx;
6120
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006121 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122
6123 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
Francois Romieue27566e2012-03-08 09:54:01 +01006614static void __devexit rtl_remove_one(struct pci_dev *pdev)
6615{
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
6734static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
6735{
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
6768static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
6769{
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
Francois Romieu3b6cf252012-03-08 09:59:04 +01006781static int __devinit
6782rtl_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);
6946 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6947
6948 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6949 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006950
6951 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6952
6953 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6954 * properly for all devices */
6955 dev->features |= NETIF_F_RXCSUM |
6956 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6957
6958 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6959 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6960 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6961 NETIF_F_HIGHDMA;
6962
6963 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6964 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6965 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6966
6967 dev->hw_features |= NETIF_F_RXALL;
6968 dev->hw_features |= NETIF_F_RXFCS;
6969
6970 tp->hw_start = cfg->hw_start;
6971 tp->event_slow = cfg->event_slow;
6972
6973 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6974 ~(RxBOVF | RxFOVF) : ~0;
6975
6976 init_timer(&tp->timer);
6977 tp->timer.data = (unsigned long) dev;
6978 tp->timer.function = rtl8169_phy_timer;
6979
6980 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6981
6982 rc = register_netdev(dev);
6983 if (rc < 0)
6984 goto err_out_msi_4;
6985
6986 pci_set_drvdata(pdev, dev);
6987
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006988 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6989 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6990 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006991 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6992 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6993 "tx checksumming: %s]\n",
6994 rtl_chip_infos[chipset].jumbo_max,
6995 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6996 }
6997
6998 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6999 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
7000 tp->mac_version == RTL_GIGA_MAC_VER_31) {
7001 rtl8168_driver_start(tp);
7002 }
7003
7004 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
7005
7006 if (pci_dev_run_wake(pdev))
7007 pm_runtime_put_noidle(&pdev->dev);
7008
7009 netif_carrier_off(dev);
7010
7011out:
7012 return rc;
7013
7014err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007015 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007016 rtl_disable_msi(pdev, tp);
7017 iounmap(ioaddr);
7018err_out_free_res_3:
7019 pci_release_regions(pdev);
7020err_out_mwi_2:
7021 pci_clear_mwi(pdev);
7022 pci_disable_device(pdev);
7023err_out_free_dev_1:
7024 free_netdev(dev);
7025 goto out;
7026}
7027
Linus Torvalds1da177e2005-04-16 15:20:36 -07007028static struct pci_driver rtl8169_pci_driver = {
7029 .name = MODULENAME,
7030 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007031 .probe = rtl_init_one,
Francois Romieue27566e2012-03-08 09:54:01 +01007032 .remove = __devexit_p(rtl_remove_one),
Francois Romieu1765f952008-09-13 17:21:40 +02007033 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007034 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035};
7036
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007037module_pci_driver(rtl8169_pci_driver);