blob: ed96f309bca8e030a0c098df8b8e728314f04bb0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Francois Romieu07d3f512007-02-21 22:40:46 +01002 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/pci.h>
14#include <linux/netdevice.h>
15#include <linux/etherdevice.h>
16#include <linux/delay.h>
17#include <linux/ethtool.h>
18#include <linux/mii.h>
19#include <linux/if_vlan.h>
20#include <linux/crc32.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/tcp.h>
24#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000025#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000027#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000028#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000029#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040030#include <linux/prefetch.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/io.h>
33#include <asm/irq.h>
34
Francois Romieu865c6522008-05-11 14:51:00 +020035#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MODULENAME "r8169"
37#define PFX MODULENAME ": "
38
françois romieubca03d52011-01-03 15:07:31 +000039#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
40#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000041#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
42#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080043#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080044#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
45#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080046#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080047#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080048#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080049#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
Hayes Wangc5583862012-07-02 17:23:22 +080050#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw"
françois romieubca03d52011-01-03 15:07:31 +000051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#ifdef RTL8169_DEBUG
53#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020054 if (!(expr)) { \
55 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070056 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020057 }
Joe Perches06fa7352007-10-18 21:15:00 +020058#define dprintk(fmt, args...) \
59 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
61#define assert(expr) do {} while (0)
62#define dprintk(fmt, args...) do {} while (0)
63#endif /* RTL8169_DEBUG */
64
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020065#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
86#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
88#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
89
90#define RTL8169_TX_TIMEOUT (6*HZ)
91#define RTL8169_PHY_TIMEOUT (10*HZ)
92
93/* write/read MMIO register */
94#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
95#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
96#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
97#define RTL_R8(reg) readb (ioaddr + (reg))
98#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +000099#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200102 RTL_GIGA_MAC_VER_01 = 0,
103 RTL_GIGA_MAC_VER_02,
104 RTL_GIGA_MAC_VER_03,
105 RTL_GIGA_MAC_VER_04,
106 RTL_GIGA_MAC_VER_05,
107 RTL_GIGA_MAC_VER_06,
108 RTL_GIGA_MAC_VER_07,
109 RTL_GIGA_MAC_VER_08,
110 RTL_GIGA_MAC_VER_09,
111 RTL_GIGA_MAC_VER_10,
112 RTL_GIGA_MAC_VER_11,
113 RTL_GIGA_MAC_VER_12,
114 RTL_GIGA_MAC_VER_13,
115 RTL_GIGA_MAC_VER_14,
116 RTL_GIGA_MAC_VER_15,
117 RTL_GIGA_MAC_VER_16,
118 RTL_GIGA_MAC_VER_17,
119 RTL_GIGA_MAC_VER_18,
120 RTL_GIGA_MAC_VER_19,
121 RTL_GIGA_MAC_VER_20,
122 RTL_GIGA_MAC_VER_21,
123 RTL_GIGA_MAC_VER_22,
124 RTL_GIGA_MAC_VER_23,
125 RTL_GIGA_MAC_VER_24,
126 RTL_GIGA_MAC_VER_25,
127 RTL_GIGA_MAC_VER_26,
128 RTL_GIGA_MAC_VER_27,
129 RTL_GIGA_MAC_VER_28,
130 RTL_GIGA_MAC_VER_29,
131 RTL_GIGA_MAC_VER_30,
132 RTL_GIGA_MAC_VER_31,
133 RTL_GIGA_MAC_VER_32,
134 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800135 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800136 RTL_GIGA_MAC_VER_35,
137 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800138 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800139 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800140 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800141 RTL_GIGA_MAC_VER_40,
142 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200143 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
Francois Romieu2b7b4312011-04-18 22:53:24 -0700146enum rtl_tx_desc_version {
147 RTL_TD_0 = 0,
148 RTL_TD_1 = 1,
149};
150
Francois Romieud58d46b2011-05-03 16:38:29 +0200151#define JUMBO_1K ETH_DATA_LEN
152#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
153#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
154#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
155#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
156
157#define _R(NAME,TD,FW,SZ,B) { \
158 .name = NAME, \
159 .txd_version = TD, \
160 .fw_name = FW, \
161 .jumbo_max = SZ, \
162 .jumbo_tx_csum = B \
163}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800165static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700167 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200168 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200169 u16 jumbo_max;
170 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200171} rtl_chip_infos[] = {
172 /* PCI devices. */
173 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200175 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200176 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200177 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200178 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200179 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200180 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200181 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200182 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200183 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200184 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200185 /* PCI-E devices. */
186 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200191 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200192 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200193 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200194 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200195 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200196 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200197 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200198 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200199 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200200 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200201 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200202 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200203 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200204 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200205 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200206 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200207 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200208 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200209 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200210 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200211 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200212 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200213 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200214 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200215 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200216 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200217 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200218 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200219 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200220 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200221 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200222 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200223 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
224 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
227 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200228 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200229 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200232 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200233 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
234 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
237 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200238 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200239 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
242 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
245 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800246 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200247 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
248 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800249 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200250 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
251 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800252 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200253 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
254 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800255 [RTL_GIGA_MAC_VER_37] =
256 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
257 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800258 [RTL_GIGA_MAC_VER_38] =
259 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
260 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800261 [RTL_GIGA_MAC_VER_39] =
262 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
263 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800264 [RTL_GIGA_MAC_VER_40] =
265 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
266 JUMBO_9K, false),
267 [RTL_GIGA_MAC_VER_41] =
268 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269};
270#undef _R
271
Francois Romieubcf0bf92006-07-26 23:14:13 +0200272enum cfg_version {
273 RTL_CFG_0 = 0x00,
274 RTL_CFG_1,
275 RTL_CFG_2
276};
277
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000278static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200279 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200280 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200281 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100282 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200283 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200284 { PCI_VENDOR_ID_DLINK, 0x4300,
285 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000287 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200289 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
290 { PCI_VENDOR_ID_LINKSYS, 0x1032,
291 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100292 { 0x0001, 0x8168,
293 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 {0,},
295};
296
297MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
298
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000299static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700300static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200301static struct {
302 u32 msg_enable;
303} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Francois Romieu07d3f512007-02-21 22:40:46 +0100305enum rtl_registers {
306 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100307 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100308 MAR0 = 8, /* Multicast filter. */
309 CounterAddrLow = 0x10,
310 CounterAddrHigh = 0x14,
311 TxDescStartAddrLow = 0x20,
312 TxDescStartAddrHigh = 0x24,
313 TxHDescStartAddrLow = 0x28,
314 TxHDescStartAddrHigh = 0x2c,
315 FLASH = 0x30,
316 ERSR = 0x36,
317 ChipCmd = 0x37,
318 TxPoll = 0x38,
319 IntrMask = 0x3c,
320 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700321
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800322 TxConfig = 0x40,
323#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
324#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
325
326 RxConfig = 0x44,
327#define RX128_INT_EN (1 << 15) /* 8111c and later */
328#define RX_MULTI_EN (1 << 14) /* 8111c only */
329#define RXCFG_FIFO_SHIFT 13
330 /* No threshold before first PCI xfer */
331#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
332#define RXCFG_DMA_SHIFT 8
333 /* Unlimited maximum PCI burst. */
334#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700335
Francois Romieu07d3f512007-02-21 22:40:46 +0100336 RxMissed = 0x4c,
337 Cfg9346 = 0x50,
338 Config0 = 0x51,
339 Config1 = 0x52,
340 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200341#define PME_SIGNAL (1 << 5) /* 8168c and later */
342
Francois Romieu07d3f512007-02-21 22:40:46 +0100343 Config3 = 0x54,
344 Config4 = 0x55,
345 Config5 = 0x56,
346 MultiIntr = 0x5c,
347 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 PHYstatus = 0x6c,
349 RxMaxSize = 0xda,
350 CPlusCmd = 0xe0,
351 IntrMitigate = 0xe2,
352 RxDescAddrLow = 0xe4,
353 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000354 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
355
356#define NoEarlyTx 0x3f /* Max value : no early transmit. */
357
358 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
359
360#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800361#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000362
Francois Romieu07d3f512007-02-21 22:40:46 +0100363 FuncEvent = 0xf0,
364 FuncEventMask = 0xf4,
365 FuncPresetState = 0xf8,
366 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Francois Romieuf162a5d2008-06-01 22:37:49 +0200369enum rtl8110_registers {
370 TBICSR = 0x64,
371 TBI_ANAR = 0x68,
372 TBI_LPAR = 0x6a,
373};
374
375enum rtl8168_8101_registers {
376 CSIDR = 0x64,
377 CSIAR = 0x68,
378#define CSIAR_FLAG 0x80000000
379#define CSIAR_WRITE_CMD 0x80000000
380#define CSIAR_BYTE_ENABLE 0x0f
381#define CSIAR_BYTE_ENABLE_SHIFT 12
382#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800383#define CSIAR_FUNC_CARD 0x00000000
384#define CSIAR_FUNC_SDIO 0x00010000
385#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000386 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200387 EPHYAR = 0x80,
388#define EPHYAR_FLAG 0x80000000
389#define EPHYAR_WRITE_CMD 0x80000000
390#define EPHYAR_REG_MASK 0x1f
391#define EPHYAR_REG_SHIFT 16
392#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800393 DLLPR = 0xd0,
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800394#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200395 DBG_REG = 0xd1,
396#define FIX_NAK_1 (1 << 4)
397#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 TWSI = 0xd2,
399 MCU = 0xd3,
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800400#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800401#define TX_EMPTY (1 << 5)
402#define RX_EMPTY (1 << 4)
403#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800404#define EN_NDP (1 << 3)
405#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000407 EFUSEAR = 0xdc,
408#define EFUSEAR_FLAG 0x80000000
409#define EFUSEAR_WRITE_CMD 0x80000000
410#define EFUSEAR_READ_CMD 0x00000000
411#define EFUSEAR_REG_MASK 0x03ff
412#define EFUSEAR_REG_SHIFT 8
413#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200414};
415
françois romieuc0e45c12011-01-03 15:08:04 +0000416enum rtl8168_registers {
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800417 LED_FREQ = 0x1a,
418 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000419 ERIDR = 0x70,
420 ERIAR = 0x74,
421#define ERIAR_FLAG 0x80000000
422#define ERIAR_WRITE_CMD 0x80000000
423#define ERIAR_READ_CMD 0x00000000
424#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000425#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800426#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
427#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
428#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
429#define ERIAR_MASK_SHIFT 12
430#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
431#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800432#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800433#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000434 EPHY_RXER_NUM = 0x7c,
435 OCPDR = 0xb0, /* OCP GPHY access */
436#define OCPDR_WRITE_CMD 0x80000000
437#define OCPDR_READ_CMD 0x00000000
438#define OCPDR_REG_MASK 0x7f
439#define OCPDR_GPHY_REG_SHIFT 16
440#define OCPDR_DATA_MASK 0xffff
441 OCPAR = 0xb4,
442#define OCPAR_FLAG 0x80000000
443#define OCPAR_GPHY_WRITE_CMD 0x8000f060
444#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800445 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000446 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
447 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200448#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800449#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800450#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800451#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800452#define EARLY_TALLY_EN (1 << 16)
hayeswangd64ec842012-11-01 16:46:28 +0000453#define FORCE_CLK (1 << 15) /* force clock request */
françois romieuc0e45c12011-01-03 15:08:04 +0000454};
455
Francois Romieu07d3f512007-02-21 22:40:46 +0100456enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100458 SYSErr = 0x8000,
459 PCSTimeout = 0x4000,
460 SWInt = 0x0100,
461 TxDescUnavail = 0x0080,
462 RxFIFOOver = 0x0040,
463 LinkChg = 0x0020,
464 RxOverflow = 0x0010,
465 TxErr = 0x0008,
466 TxOK = 0x0004,
467 RxErr = 0x0002,
468 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400471 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200472 RxFOVF = (1 << 23),
473 RxRWT = (1 << 22),
474 RxRES = (1 << 21),
475 RxRUNT = (1 << 20),
476 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
478 /* ChipCmdBits */
Hayes Wang4f6b00e2011-07-06 15:58:02 +0800479 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100480 CmdReset = 0x10,
481 CmdRxEnb = 0x08,
482 CmdTxEnb = 0x04,
483 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Francois Romieu275391a2007-02-23 23:50:28 +0100485 /* TXPoll register p.5 */
486 HPQ = 0x80, /* Poll cmd on the high prio queue */
487 NPQ = 0x40, /* Poll cmd on the low prio queue */
488 FSWInt = 0x01, /* Forced software interrupt */
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100491 Cfg9346_Lock = 0x00,
492 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
494 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100495 AcceptErr = 0x20,
496 AcceptRunt = 0x10,
497 AcceptBroadcast = 0x08,
498 AcceptMulticast = 0x04,
499 AcceptMyPhys = 0x02,
500 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200501#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 /* TxConfigBits */
504 TxInterFrameGapShift = 24,
505 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
506
Francois Romieu5d06a992006-02-23 00:47:58 +0100507 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200508 LEDS1 = (1 << 7),
509 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200510 Speed_down = (1 << 4),
511 MEMMAP = (1 << 3),
512 IOMAP = (1 << 2),
513 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100514 PMEnable = (1 << 0), /* Power Management Enable */
515
Francois Romieu6dccd162007-02-13 23:38:05 +0100516 /* Config2 register p. 25 */
hayeswangd64ec842012-11-01 16:46:28 +0000517 ClkReqEn = (1 << 7), /* Clock Request Enable */
françois romieu2ca6cf02011-12-15 08:37:43 +0000518 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100519 PCI_Clock_66MHz = 0x01,
520 PCI_Clock_33MHz = 0x00,
521
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100522 /* Config3 register p.25 */
523 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
524 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200525 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200526 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100527
Francois Romieud58d46b2011-05-03 16:38:29 +0200528 /* Config4 register */
529 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
530
Francois Romieu5d06a992006-02-23 00:47:58 +0100531 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100532 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
533 MWF = (1 << 5), /* Accept Multicast wakeup frame */
534 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200535 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100536 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100537 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
hayeswangd64ec842012-11-01 16:46:28 +0000538 ASPM_en = (1 << 0), /* ASPM enable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* TBICSR p.28 */
541 TBIReset = 0x80000000,
542 TBILoopback = 0x40000000,
543 TBINwEnable = 0x20000000,
544 TBINwRestart = 0x10000000,
545 TBILinkOk = 0x02000000,
546 TBINwComplete = 0x01000000,
547
548 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200549 EnableBist = (1 << 15), // 8168 8101
550 Mac_dbgo_oe = (1 << 14), // 8168 8101
551 Normal_mode = (1 << 13), // unused
552 Force_half_dup = (1 << 12), // 8168 8101
553 Force_rxflow_en = (1 << 11), // 8168 8101
554 Force_txflow_en = (1 << 10), // 8168 8101
555 Cxpl_dbg_sel = (1 << 9), // 8168 8101
556 ASF = (1 << 8), // 8168 8101
557 PktCntrDisable = (1 << 7), // 8168 8101
558 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 RxVlan = (1 << 6),
560 RxChkSum = (1 << 5),
561 PCIDAC = (1 << 4),
562 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100563 INTT_0 = 0x0000, // 8168
564 INTT_1 = 0x0001, // 8168
565 INTT_2 = 0x0002, // 8168
566 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100569 TBI_Enable = 0x80,
570 TxFlowCtrl = 0x40,
571 RxFlowCtrl = 0x20,
572 _1000bpsF = 0x10,
573 _100bps = 0x08,
574 _10bps = 0x04,
575 LinkStatus = 0x02,
576 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100579 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200580
581 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100582 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583};
584
Francois Romieu2b7b4312011-04-18 22:53:24 -0700585enum rtl_desc_bit {
586 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
588 RingEnd = (1 << 30), /* End of descriptor ring */
589 FirstFrag = (1 << 29), /* First segment of a packet */
590 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700591};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Francois Romieu2b7b4312011-04-18 22:53:24 -0700593/* Generic case. */
594enum rtl_tx_desc_bit {
595 /* First doubleword. */
596 TD_LSO = (1 << 27), /* Large Send Offload */
597#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Francois Romieu2b7b4312011-04-18 22:53:24 -0700599 /* Second doubleword. */
600 TxVlanTag = (1 << 17), /* Add VLAN tag */
601};
602
603/* 8169, 8168b and 810x except 8102e. */
604enum rtl_tx_desc_bit_0 {
605 /* First doubleword. */
606#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
607 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
608 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
609 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
610};
611
612/* 8102e, 8168c and beyond. */
613enum rtl_tx_desc_bit_1 {
614 /* Second doubleword. */
615#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
616 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
617 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
618 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
619};
620
621static const struct rtl_tx_desc_info {
622 struct {
623 u32 udp;
624 u32 tcp;
625 } checksum;
626 u16 mss_shift;
627 u16 opts_offset;
628} tx_desc_info [] = {
629 [RTL_TD_0] = {
630 .checksum = {
631 .udp = TD0_IP_CS | TD0_UDP_CS,
632 .tcp = TD0_IP_CS | TD0_TCP_CS
633 },
634 .mss_shift = TD0_MSS_SHIFT,
635 .opts_offset = 0
636 },
637 [RTL_TD_1] = {
638 .checksum = {
639 .udp = TD1_IP_CS | TD1_UDP_CS,
640 .tcp = TD1_IP_CS | TD1_TCP_CS
641 },
642 .mss_shift = TD1_MSS_SHIFT,
643 .opts_offset = 1
644 }
645};
646
647enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 /* Rx private */
649 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
650 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
651
652#define RxProtoUDP (PID1)
653#define RxProtoTCP (PID0)
654#define RxProtoIP (PID1 | PID0)
655#define RxProtoMask RxProtoIP
656
657 IPFail = (1 << 16), /* IP checksum failed */
658 UDPFail = (1 << 15), /* UDP/IP checksum failed */
659 TCPFail = (1 << 14), /* TCP/IP checksum failed */
660 RxVlanTag = (1 << 16), /* VLAN tag available */
661};
662
663#define RsvdMask 0x3fffc000
664
665struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200666 __le32 opts1;
667 __le32 opts2;
668 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669};
670
671struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200672 __le32 opts1;
673 __le32 opts2;
674 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675};
676
677struct ring_info {
678 struct sk_buff *skb;
679 u32 len;
680 u8 __pad[sizeof(void *) - sizeof(u32)];
681};
682
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200683enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200684 RTL_FEATURE_WOL = (1 << 0),
685 RTL_FEATURE_MSI = (1 << 1),
686 RTL_FEATURE_GMII = (1 << 2),
hayeswange0c07552012-10-23 20:24:03 +0000687 RTL_FEATURE_FW_LOADED = (1 << 3),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200688};
689
Ivan Vecera355423d2009-02-06 21:49:57 -0800690struct rtl8169_counters {
691 __le64 tx_packets;
692 __le64 rx_packets;
693 __le64 tx_errors;
694 __le32 rx_errors;
695 __le16 rx_missed;
696 __le16 align_errors;
697 __le32 tx_one_collision;
698 __le32 tx_multi_collision;
699 __le64 rx_unicast;
700 __le64 rx_broadcast;
701 __le32 rx_multicast;
702 __le16 tx_aborted;
703 __le16 tx_underun;
704};
705
Francois Romieuda78dbf2012-01-26 14:18:23 +0100706enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100707 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100708 RTL_FLAG_TASK_SLOW_PENDING,
709 RTL_FLAG_TASK_RESET_PENDING,
710 RTL_FLAG_TASK_PHY_PENDING,
711 RTL_FLAG_MAX
712};
713
Junchang Wang8027aa22012-03-04 23:30:32 +0100714struct rtl8169_stats {
715 u64 packets;
716 u64 bytes;
717 struct u64_stats_sync syncp;
718};
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720struct rtl8169_private {
721 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200722 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000723 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700724 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200725 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700726 u16 txd_version;
727 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
729 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
730 u32 dirty_rx;
731 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100732 struct rtl8169_stats rx_stats;
733 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
735 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
736 dma_addr_t TxPhyAddr;
737 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000738 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 struct timer_list timer;
741 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100742
743 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000744
745 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200746 void (*write)(struct rtl8169_private *, int, int);
747 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000748 } mdio_ops;
749
françois romieu065c27c2011-01-03 15:08:12 +0000750 struct pll_power_ops {
751 void (*down)(struct rtl8169_private *);
752 void (*up)(struct rtl8169_private *);
753 } pll_power_ops;
754
Francois Romieud58d46b2011-05-03 16:38:29 +0200755 struct jumbo_ops {
756 void (*enable)(struct rtl8169_private *);
757 void (*disable)(struct rtl8169_private *);
758 } jumbo_ops;
759
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800760 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200761 void (*write)(struct rtl8169_private *, int, int);
762 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800763 } csi_ops;
764
Oliver Neukum54405cd2011-01-06 21:55:13 +0100765 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200766 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000767 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100768 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000769 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800771 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100772
773 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100774 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
775 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100776 struct work_struct work;
777 } wk;
778
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200779 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200780
781 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800782 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000783 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400784 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000785
Francois Romieub6ffd972011-06-17 17:00:05 +0200786 struct rtl_fw {
787 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200788
789#define RTL_VER_SIZE 32
790
791 char version[RTL_VER_SIZE];
792
793 struct rtl_fw_phy_action {
794 __le32 *code;
795 size_t size;
796 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200797 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300798#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800799
800 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801};
802
Ralf Baechle979b6c12005-06-13 14:30:40 -0700803MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700806MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200807module_param_named(debug, debug.msg_enable, int, 0);
808MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809MODULE_LICENSE("GPL");
810MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000811MODULE_FIRMWARE(FIRMWARE_8168D_1);
812MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000813MODULE_FIRMWARE(FIRMWARE_8168E_1);
814MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400815MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800816MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800817MODULE_FIRMWARE(FIRMWARE_8168F_1);
818MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800819MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800820MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800821MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800822MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Francois Romieuda78dbf2012-01-26 14:18:23 +0100824static void rtl_lock_work(struct rtl8169_private *tp)
825{
826 mutex_lock(&tp->wk.mutex);
827}
828
829static void rtl_unlock_work(struct rtl8169_private *tp)
830{
831 mutex_unlock(&tp->wk.mutex);
832}
833
Francois Romieud58d46b2011-05-03 16:38:29 +0200834static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
835{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800836 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
837 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200838}
839
Francois Romieuffc46952012-07-06 14:19:23 +0200840struct rtl_cond {
841 bool (*check)(struct rtl8169_private *);
842 const char *msg;
843};
844
845static void rtl_udelay(unsigned int d)
846{
847 udelay(d);
848}
849
850static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
851 void (*delay)(unsigned int), unsigned int d, int n,
852 bool high)
853{
854 int i;
855
856 for (i = 0; i < n; i++) {
857 delay(d);
858 if (c->check(tp) == high)
859 return true;
860 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200861 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
862 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200863 return false;
864}
865
866static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
867 const struct rtl_cond *c,
868 unsigned int d, int n)
869{
870 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
871}
872
873static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
874 const struct rtl_cond *c,
875 unsigned int d, int n)
876{
877 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
878}
879
880static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
881 const struct rtl_cond *c,
882 unsigned int d, int n)
883{
884 return rtl_loop_wait(tp, c, msleep, d, n, true);
885}
886
887static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
888 const struct rtl_cond *c,
889 unsigned int d, int n)
890{
891 return rtl_loop_wait(tp, c, msleep, d, n, false);
892}
893
894#define DECLARE_RTL_COND(name) \
895static bool name ## _check(struct rtl8169_private *); \
896 \
897static const struct rtl_cond name = { \
898 .check = name ## _check, \
899 .msg = #name \
900}; \
901 \
902static bool name ## _check(struct rtl8169_private *tp)
903
904DECLARE_RTL_COND(rtl_ocpar_cond)
905{
906 void __iomem *ioaddr = tp->mmio_addr;
907
908 return RTL_R32(OCPAR) & OCPAR_FLAG;
909}
910
françois romieub646d902011-01-03 15:08:21 +0000911static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
912{
913 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000914
915 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200916
917 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
918 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000919}
920
921static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
922{
923 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000924
925 RTL_W32(OCPDR, data);
926 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200927
928 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
929}
930
931DECLARE_RTL_COND(rtl_eriar_cond)
932{
933 void __iomem *ioaddr = tp->mmio_addr;
934
935 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000936}
937
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800938static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000939{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800940 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000941
942 RTL_W8(ERIDR, cmd);
943 RTL_W32(ERIAR, 0x800010e8);
944 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200945
946 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
947 return;
françois romieub646d902011-01-03 15:08:21 +0000948
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800949 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000950}
951
952#define OOB_CMD_RESET 0x00
953#define OOB_CMD_DRIVER_START 0x05
954#define OOB_CMD_DRIVER_STOP 0x06
955
Francois Romieucecb5fd2011-04-01 10:21:07 +0200956static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
957{
958 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
959}
960
Francois Romieuffc46952012-07-06 14:19:23 +0200961DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000962{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200963 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000964
Francois Romieucecb5fd2011-04-01 10:21:07 +0200965 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000966
Francois Romieuffc46952012-07-06 14:19:23 +0200967 return ocp_read(tp, 0x0f, reg) & 0x00000800;
968}
969
970static void rtl8168_driver_start(struct rtl8169_private *tp)
971{
972 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
973
974 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000975}
976
977static void rtl8168_driver_stop(struct rtl8169_private *tp)
978{
françois romieub646d902011-01-03 15:08:21 +0000979 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
980
Francois Romieuffc46952012-07-06 14:19:23 +0200981 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000982}
983
hayeswang4804b3b2011-03-21 01:50:29 +0000984static int r8168dp_check_dash(struct rtl8169_private *tp)
985{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200986 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000987
Francois Romieucecb5fd2011-04-01 10:21:07 +0200988 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000989}
françois romieub646d902011-01-03 15:08:21 +0000990
Hayes Wangc5583862012-07-02 17:23:22 +0800991static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
992{
993 if (reg & 0xffff0001) {
994 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
995 return true;
996 }
997 return false;
998}
999
1000DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1001{
1002 void __iomem *ioaddr = tp->mmio_addr;
1003
1004 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1005}
1006
1007static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1008{
1009 void __iomem *ioaddr = tp->mmio_addr;
1010
1011 if (rtl_ocp_reg_failure(tp, reg))
1012 return;
1013
1014 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1015
1016 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1017}
1018
1019static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1020{
1021 void __iomem *ioaddr = tp->mmio_addr;
1022
1023 if (rtl_ocp_reg_failure(tp, reg))
1024 return 0;
1025
1026 RTL_W32(GPHY_OCP, reg << 15);
1027
1028 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1029 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1030}
1031
1032static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1033{
1034 int val;
1035
1036 val = r8168_phy_ocp_read(tp, reg);
1037 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1038}
1039
Hayes Wangc5583862012-07-02 17:23:22 +08001040static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1041{
1042 void __iomem *ioaddr = tp->mmio_addr;
1043
1044 if (rtl_ocp_reg_failure(tp, reg))
1045 return;
1046
1047 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001048}
1049
1050static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1051{
1052 void __iomem *ioaddr = tp->mmio_addr;
1053
1054 if (rtl_ocp_reg_failure(tp, reg))
1055 return 0;
1056
1057 RTL_W32(OCPDR, reg << 15);
1058
Hayes Wang3a83ad12012-07-11 20:31:56 +08001059 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001060}
1061
1062#define OCP_STD_PHY_BASE 0xa400
1063
1064static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1065{
1066 if (reg == 0x1f) {
1067 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1068 return;
1069 }
1070
1071 if (tp->ocp_base != OCP_STD_PHY_BASE)
1072 reg -= 0x10;
1073
1074 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1075}
1076
1077static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1078{
1079 if (tp->ocp_base != OCP_STD_PHY_BASE)
1080 reg -= 0x10;
1081
1082 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1083}
1084
Francois Romieuffc46952012-07-06 14:19:23 +02001085DECLARE_RTL_COND(rtl_phyar_cond)
1086{
1087 void __iomem *ioaddr = tp->mmio_addr;
1088
1089 return RTL_R32(PHYAR) & 0x80000000;
1090}
1091
Francois Romieu24192212012-07-06 20:19:42 +02001092static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Francois Romieu24192212012-07-06 20:19:42 +02001094 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Francois Romieu24192212012-07-06 20:19:42 +02001096 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Francois Romieuffc46952012-07-06 14:19:23 +02001098 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001099 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001100 * According to hardware specs a 20us delay is required after write
1101 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001102 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001103 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
Francois Romieu24192212012-07-06 20:19:42 +02001106static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
Francois Romieu24192212012-07-06 20:19:42 +02001108 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001109 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Francois Romieu24192212012-07-06 20:19:42 +02001111 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Francois Romieuffc46952012-07-06 14:19:23 +02001113 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1114 RTL_R32(PHYAR) & 0xffff : ~0;
1115
Timo Teräs81a95f02010-06-09 17:31:48 -07001116 /*
1117 * According to hardware specs a 20us delay is required after read
1118 * complete indication, but before sending next command.
1119 */
1120 udelay(20);
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return value;
1123}
1124
Francois Romieu24192212012-07-06 20:19:42 +02001125static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001126{
Francois Romieu24192212012-07-06 20:19:42 +02001127 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001128
Francois Romieu24192212012-07-06 20:19:42 +02001129 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001130 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1131 RTL_W32(EPHY_RXER_NUM, 0);
1132
Francois Romieuffc46952012-07-06 14:19:23 +02001133 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001134}
1135
Francois Romieu24192212012-07-06 20:19:42 +02001136static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001137{
Francois Romieu24192212012-07-06 20:19:42 +02001138 r8168dp_1_mdio_access(tp, reg,
1139 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001140}
1141
Francois Romieu24192212012-07-06 20:19:42 +02001142static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001143{
Francois Romieu24192212012-07-06 20:19:42 +02001144 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001145
Francois Romieu24192212012-07-06 20:19:42 +02001146 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001147
1148 mdelay(1);
1149 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1150 RTL_W32(EPHY_RXER_NUM, 0);
1151
Francois Romieuffc46952012-07-06 14:19:23 +02001152 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1153 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001154}
1155
françois romieue6de30d2011-01-03 15:08:37 +00001156#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1157
1158static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1159{
1160 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1161}
1162
1163static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1164{
1165 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1166}
1167
Francois Romieu24192212012-07-06 20:19:42 +02001168static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001169{
Francois Romieu24192212012-07-06 20:19:42 +02001170 void __iomem *ioaddr = tp->mmio_addr;
1171
françois romieue6de30d2011-01-03 15:08:37 +00001172 r8168dp_2_mdio_start(ioaddr);
1173
Francois Romieu24192212012-07-06 20:19:42 +02001174 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001175
1176 r8168dp_2_mdio_stop(ioaddr);
1177}
1178
Francois Romieu24192212012-07-06 20:19:42 +02001179static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001180{
Francois Romieu24192212012-07-06 20:19:42 +02001181 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001182 int value;
1183
1184 r8168dp_2_mdio_start(ioaddr);
1185
Francois Romieu24192212012-07-06 20:19:42 +02001186 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001187
1188 r8168dp_2_mdio_stop(ioaddr);
1189
1190 return value;
1191}
1192
françois romieu4da19632011-01-03 15:07:55 +00001193static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001194{
Francois Romieu24192212012-07-06 20:19:42 +02001195 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001196}
1197
françois romieu4da19632011-01-03 15:07:55 +00001198static int rtl_readphy(struct rtl8169_private *tp, int location)
1199{
Francois Romieu24192212012-07-06 20:19:42 +02001200 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001201}
1202
1203static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1204{
1205 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1206}
1207
1208static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001209{
1210 int val;
1211
françois romieu4da19632011-01-03 15:07:55 +00001212 val = rtl_readphy(tp, reg_addr);
1213 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001214}
1215
Francois Romieuccdffb92008-07-26 14:26:06 +02001216static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1217 int val)
1218{
1219 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001220
françois romieu4da19632011-01-03 15:07:55 +00001221 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001222}
1223
1224static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1225{
1226 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001227
françois romieu4da19632011-01-03 15:07:55 +00001228 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001229}
1230
Francois Romieuffc46952012-07-06 14:19:23 +02001231DECLARE_RTL_COND(rtl_ephyar_cond)
1232{
1233 void __iomem *ioaddr = tp->mmio_addr;
1234
1235 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1236}
1237
Francois Romieufdf6fc02012-07-06 22:40:38 +02001238static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001239{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001240 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001241
1242 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1243 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1244
Francois Romieuffc46952012-07-06 14:19:23 +02001245 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1246
1247 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001248}
1249
Francois Romieufdf6fc02012-07-06 22:40:38 +02001250static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001251{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001252 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001253
1254 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1255
Francois Romieuffc46952012-07-06 14:19:23 +02001256 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1257 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001258}
1259
Francois Romieufdf6fc02012-07-06 22:40:38 +02001260static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1261 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001262{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001263 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001264
1265 BUG_ON((addr & 3) || (mask == 0));
1266 RTL_W32(ERIDR, val);
1267 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1268
Francois Romieuffc46952012-07-06 14:19:23 +02001269 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001270}
1271
Francois Romieufdf6fc02012-07-06 22:40:38 +02001272static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001273{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001274 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001275
1276 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1277
Francois Romieuffc46952012-07-06 14:19:23 +02001278 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1279 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001280}
1281
Francois Romieufdf6fc02012-07-06 22:40:38 +02001282static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1283 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001284{
1285 u32 val;
1286
Francois Romieufdf6fc02012-07-06 22:40:38 +02001287 val = rtl_eri_read(tp, addr, type);
1288 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001289}
1290
françois romieuc28aa382011-08-02 03:53:43 +00001291struct exgmac_reg {
1292 u16 addr;
1293 u16 mask;
1294 u32 val;
1295};
1296
Francois Romieufdf6fc02012-07-06 22:40:38 +02001297static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001298 const struct exgmac_reg *r, int len)
1299{
1300 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001301 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001302 r++;
1303 }
1304}
1305
Francois Romieuffc46952012-07-06 14:19:23 +02001306DECLARE_RTL_COND(rtl_efusear_cond)
1307{
1308 void __iomem *ioaddr = tp->mmio_addr;
1309
1310 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1311}
1312
Francois Romieufdf6fc02012-07-06 22:40:38 +02001313static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001314{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001315 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001316
1317 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1318
Francois Romieuffc46952012-07-06 14:19:23 +02001319 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1320 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001321}
1322
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001323static u16 rtl_get_events(struct rtl8169_private *tp)
1324{
1325 void __iomem *ioaddr = tp->mmio_addr;
1326
1327 return RTL_R16(IntrStatus);
1328}
1329
1330static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1331{
1332 void __iomem *ioaddr = tp->mmio_addr;
1333
1334 RTL_W16(IntrStatus, bits);
1335 mmiowb();
1336}
1337
1338static void rtl_irq_disable(struct rtl8169_private *tp)
1339{
1340 void __iomem *ioaddr = tp->mmio_addr;
1341
1342 RTL_W16(IntrMask, 0);
1343 mmiowb();
1344}
1345
Francois Romieu3e990ff2012-01-26 12:50:01 +01001346static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1347{
1348 void __iomem *ioaddr = tp->mmio_addr;
1349
1350 RTL_W16(IntrMask, bits);
1351}
1352
Francois Romieuda78dbf2012-01-26 14:18:23 +01001353#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1354#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1355#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1356
1357static void rtl_irq_enable_all(struct rtl8169_private *tp)
1358{
1359 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1360}
1361
françois romieu811fd302011-12-04 20:30:45 +00001362static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
françois romieu811fd302011-12-04 20:30:45 +00001364 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001366 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001367 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001368 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369}
1370
françois romieu4da19632011-01-03 15:07:55 +00001371static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
françois romieu4da19632011-01-03 15:07:55 +00001373 void __iomem *ioaddr = tp->mmio_addr;
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return RTL_R32(TBICSR) & TBIReset;
1376}
1377
françois romieu4da19632011-01-03 15:07:55 +00001378static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
françois romieu4da19632011-01-03 15:07:55 +00001380 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381}
1382
1383static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1384{
1385 return RTL_R32(TBICSR) & TBILinkOk;
1386}
1387
1388static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1389{
1390 return RTL_R8(PHYstatus) & LinkStatus;
1391}
1392
françois romieu4da19632011-01-03 15:07:55 +00001393static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
françois romieu4da19632011-01-03 15:07:55 +00001395 void __iomem *ioaddr = tp->mmio_addr;
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1398}
1399
françois romieu4da19632011-01-03 15:07:55 +00001400static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 unsigned int val;
1403
françois romieu4da19632011-01-03 15:07:55 +00001404 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1405 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Hayes Wang70090422011-07-06 15:58:06 +08001408static void rtl_link_chg_patch(struct rtl8169_private *tp)
1409{
1410 void __iomem *ioaddr = tp->mmio_addr;
1411 struct net_device *dev = tp->dev;
1412
1413 if (!netif_running(dev))
1414 return;
1415
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001416 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1417 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001418 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001419 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1420 ERIAR_EXGMAC);
1421 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1422 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001423 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001424 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1425 ERIAR_EXGMAC);
1426 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1427 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001428 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001429 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1430 ERIAR_EXGMAC);
1431 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1432 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001433 }
1434 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001435 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001436 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001437 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001438 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001439 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1440 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1441 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001442 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1443 ERIAR_EXGMAC);
1444 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1445 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001446 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001447 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1448 ERIAR_EXGMAC);
1449 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1450 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001451 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001452 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1453 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001454 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1455 ERIAR_EXGMAC);
1456 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1457 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001458 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001459 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1460 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001461 }
Hayes Wang70090422011-07-06 15:58:06 +08001462 }
1463}
1464
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001465static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001466 struct rtl8169_private *tp,
1467 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001470 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001471 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001472 if (pm)
1473 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001475 if (net_ratelimit())
1476 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001477 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001479 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001480 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001481 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483}
1484
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001485static void rtl8169_check_link_status(struct net_device *dev,
1486 struct rtl8169_private *tp,
1487 void __iomem *ioaddr)
1488{
1489 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1490}
1491
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001492#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1493
1494static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1495{
1496 void __iomem *ioaddr = tp->mmio_addr;
1497 u8 options;
1498 u32 wolopts = 0;
1499
1500 options = RTL_R8(Config1);
1501 if (!(options & PMEnable))
1502 return 0;
1503
1504 options = RTL_R8(Config3);
1505 if (options & LinkUp)
1506 wolopts |= WAKE_PHY;
1507 if (options & MagicPacket)
1508 wolopts |= WAKE_MAGIC;
1509
1510 options = RTL_R8(Config5);
1511 if (options & UWF)
1512 wolopts |= WAKE_UCAST;
1513 if (options & BWF)
1514 wolopts |= WAKE_BCAST;
1515 if (options & MWF)
1516 wolopts |= WAKE_MCAST;
1517
1518 return wolopts;
1519}
1520
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001521static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1522{
1523 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001524
Francois Romieuda78dbf2012-01-26 14:18:23 +01001525 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001527 wol->supported = WAKE_ANY;
1528 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001529
Francois Romieuda78dbf2012-01-26 14:18:23 +01001530 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001531}
1532
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001533static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001535 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001536 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001537 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001538 u32 opt;
1539 u16 reg;
1540 u8 mask;
1541 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001542 { WAKE_PHY, Config3, LinkUp },
1543 { WAKE_MAGIC, Config3, MagicPacket },
1544 { WAKE_UCAST, Config5, UWF },
1545 { WAKE_BCAST, Config5, BWF },
1546 { WAKE_MCAST, Config5, MWF },
1547 { WAKE_ANY, Config5, LanWake }
1548 };
Francois Romieu851e6022012-04-17 11:10:11 +02001549 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001550
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001551 RTL_W8(Cfg9346, Cfg9346_Unlock);
1552
1553 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001554 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001555 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001556 options |= cfg[i].mask;
1557 RTL_W8(cfg[i].reg, options);
1558 }
1559
Francois Romieu851e6022012-04-17 11:10:11 +02001560 switch (tp->mac_version) {
1561 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1562 options = RTL_R8(Config1) & ~PMEnable;
1563 if (wolopts)
1564 options |= PMEnable;
1565 RTL_W8(Config1, options);
1566 break;
1567 default:
Francois Romieud387b422012-04-17 11:12:01 +02001568 options = RTL_R8(Config2) & ~PME_SIGNAL;
1569 if (wolopts)
1570 options |= PME_SIGNAL;
1571 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001572 break;
1573 }
1574
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001575 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001576}
1577
1578static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1579{
1580 struct rtl8169_private *tp = netdev_priv(dev);
1581
Francois Romieuda78dbf2012-01-26 14:18:23 +01001582 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001583
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001584 if (wol->wolopts)
1585 tp->features |= RTL_FEATURE_WOL;
1586 else
1587 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001588 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001589
1590 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001591
françois romieuea809072010-11-08 13:23:58 +00001592 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1593
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001594 return 0;
1595}
1596
Francois Romieu31bd2042011-04-26 18:58:59 +02001597static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1598{
Francois Romieu85bffe62011-04-27 08:22:39 +02001599 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001600}
1601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602static void rtl8169_get_drvinfo(struct net_device *dev,
1603 struct ethtool_drvinfo *info)
1604{
1605 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001606 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
Rick Jones68aad782011-11-07 13:29:27 +00001608 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1609 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1610 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001611 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001612 if (!IS_ERR_OR_NULL(rtl_fw))
1613 strlcpy(info->fw_version, rtl_fw->version,
1614 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615}
1616
1617static int rtl8169_get_regs_len(struct net_device *dev)
1618{
1619 return R8169_REGS_SIZE;
1620}
1621
1622static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001623 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
1625 struct rtl8169_private *tp = netdev_priv(dev);
1626 void __iomem *ioaddr = tp->mmio_addr;
1627 int ret = 0;
1628 u32 reg;
1629
1630 reg = RTL_R32(TBICSR);
1631 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1632 (duplex == DUPLEX_FULL)) {
1633 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1634 } else if (autoneg == AUTONEG_ENABLE)
1635 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1636 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001637 netif_warn(tp, link, dev,
1638 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 ret = -EOPNOTSUPP;
1640 }
1641
1642 return ret;
1643}
1644
1645static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001646 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
1648 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001649 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001650 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Hayes Wang716b50a2011-02-22 17:26:18 +08001652 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001655 int auto_nego;
1656
françois romieu4da19632011-01-03 15:07:55 +00001657 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001658 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1659 ADVERTISE_100HALF | ADVERTISE_100FULL);
1660
1661 if (adv & ADVERTISED_10baseT_Half)
1662 auto_nego |= ADVERTISE_10HALF;
1663 if (adv & ADVERTISED_10baseT_Full)
1664 auto_nego |= ADVERTISE_10FULL;
1665 if (adv & ADVERTISED_100baseT_Half)
1666 auto_nego |= ADVERTISE_100HALF;
1667 if (adv & ADVERTISED_100baseT_Full)
1668 auto_nego |= ADVERTISE_100FULL;
1669
françois romieu3577aa12009-05-19 10:46:48 +00001670 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1671
françois romieu4da19632011-01-03 15:07:55 +00001672 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001673 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1674
1675 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001676 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001677 if (adv & ADVERTISED_1000baseT_Half)
1678 giga_ctrl |= ADVERTISE_1000HALF;
1679 if (adv & ADVERTISED_1000baseT_Full)
1680 giga_ctrl |= ADVERTISE_1000FULL;
1681 } else if (adv & (ADVERTISED_1000baseT_Half |
1682 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001683 netif_info(tp, link, dev,
1684 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001685 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
françois romieu3577aa12009-05-19 10:46:48 +00001688 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001689
françois romieu4da19632011-01-03 15:07:55 +00001690 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1691 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001692 } else {
1693 giga_ctrl = 0;
1694
1695 if (speed == SPEED_10)
1696 bmcr = 0;
1697 else if (speed == SPEED_100)
1698 bmcr = BMCR_SPEED100;
1699 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001700 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001701
1702 if (duplex == DUPLEX_FULL)
1703 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001704 }
1705
françois romieu4da19632011-01-03 15:07:55 +00001706 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001707
Francois Romieucecb5fd2011-04-01 10:21:07 +02001708 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1709 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001710 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001711 rtl_writephy(tp, 0x17, 0x2138);
1712 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001713 } else {
françois romieu4da19632011-01-03 15:07:55 +00001714 rtl_writephy(tp, 0x17, 0x2108);
1715 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001716 }
1717 }
1718
Oliver Neukum54405cd2011-01-06 21:55:13 +01001719 rc = 0;
1720out:
1721 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722}
1723
1724static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001725 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
1727 struct rtl8169_private *tp = netdev_priv(dev);
1728 int ret;
1729
Oliver Neukum54405cd2011-01-06 21:55:13 +01001730 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001731 if (ret < 0)
1732 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Francois Romieu4876cc12011-03-11 21:07:11 +01001734 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1735 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001737 }
1738out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 return ret;
1740}
1741
1742static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1743{
1744 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 int ret;
1746
Francois Romieu4876cc12011-03-11 21:07:11 +01001747 del_timer_sync(&tp->timer);
1748
Francois Romieuda78dbf2012-01-26 14:18:23 +01001749 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001750 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001751 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001752 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return ret;
1755}
1756
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001757static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1758 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
Francois Romieud58d46b2011-05-03 16:38:29 +02001760 struct rtl8169_private *tp = netdev_priv(dev);
1761
Francois Romieu2b7b4312011-04-18 22:53:24 -07001762 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001763 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
Francois Romieud58d46b2011-05-03 16:38:29 +02001765 if (dev->mtu > JUMBO_1K &&
1766 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1767 features &= ~NETIF_F_IP_CSUM;
1768
Michał Mirosław350fb322011-04-08 06:35:56 +00001769 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
Francois Romieuda78dbf2012-01-26 14:18:23 +01001772static void __rtl8169_set_features(struct net_device *dev,
1773 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774{
1775 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001776 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001777 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Ben Greear6bbe0212012-02-10 15:04:33 +00001779 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1780 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Ben Greear6bbe0212012-02-10 15:04:33 +00001782 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1783 if (features & NETIF_F_RXCSUM)
1784 tp->cp_cmd |= RxChkSum;
1785 else
1786 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001787
Ben Greear6bbe0212012-02-10 15:04:33 +00001788 if (dev->features & NETIF_F_HW_VLAN_RX)
1789 tp->cp_cmd |= RxVlan;
1790 else
1791 tp->cp_cmd &= ~RxVlan;
1792
1793 RTL_W16(CPlusCmd, tp->cp_cmd);
1794 RTL_R16(CPlusCmd);
1795 }
1796 if (changed & NETIF_F_RXALL) {
1797 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1798 if (features & NETIF_F_RXALL)
1799 tmp |= (AcceptErr | AcceptRunt);
1800 RTL_W32(RxConfig, tmp);
1801 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001802}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Francois Romieuda78dbf2012-01-26 14:18:23 +01001804static int rtl8169_set_features(struct net_device *dev,
1805 netdev_features_t features)
1806{
1807 struct rtl8169_private *tp = netdev_priv(dev);
1808
1809 rtl_lock_work(tp);
1810 __rtl8169_set_features(dev, features);
1811 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 return 0;
1814}
1815
Francois Romieuda78dbf2012-01-26 14:18:23 +01001816
Kirill Smelkov810f4892012-11-10 21:11:02 +04001817static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818{
Jesse Grosseab6d182010-10-20 13:56:03 +00001819 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1821}
1822
Francois Romieu7a8fc772011-03-01 17:18:33 +01001823static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824{
1825 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Francois Romieu7a8fc772011-03-01 17:18:33 +01001827 if (opts2 & RxVlanTag)
1828 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Eric Dumazet2edae082010-09-06 18:46:39 +00001829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 desc->opts2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831}
1832
Francois Romieuccdffb92008-07-26 14:26:06 +02001833static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
1835 struct rtl8169_private *tp = netdev_priv(dev);
1836 void __iomem *ioaddr = tp->mmio_addr;
1837 u32 status;
1838
1839 cmd->supported =
1840 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1841 cmd->port = PORT_FIBRE;
1842 cmd->transceiver = XCVR_INTERNAL;
1843
1844 status = RTL_R32(TBICSR);
1845 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1846 cmd->autoneg = !!(status & TBINwEnable);
1847
David Decotigny70739492011-04-27 18:32:40 +00001848 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001850
1851 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
Francois Romieuccdffb92008-07-26 14:26:06 +02001854static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
1856 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Francois Romieuccdffb92008-07-26 14:26:06 +02001858 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859}
1860
1861static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1862{
1863 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001864 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Francois Romieuda78dbf2012-01-26 14:18:23 +01001866 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001867 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001868 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Francois Romieuccdffb92008-07-26 14:26:06 +02001870 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}
1872
1873static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1874 void *p)
1875{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001876 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Francois Romieu5b0384f2006-08-16 16:00:01 +02001878 if (regs->len > R8169_REGS_SIZE)
1879 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Francois Romieuda78dbf2012-01-26 14:18:23 +01001881 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001882 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001883 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884}
1885
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001886static u32 rtl8169_get_msglevel(struct net_device *dev)
1887{
1888 struct rtl8169_private *tp = netdev_priv(dev);
1889
1890 return tp->msg_enable;
1891}
1892
1893static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1894{
1895 struct rtl8169_private *tp = netdev_priv(dev);
1896
1897 tp->msg_enable = value;
1898}
1899
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001900static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1901 "tx_packets",
1902 "rx_packets",
1903 "tx_errors",
1904 "rx_errors",
1905 "rx_missed",
1906 "align_errors",
1907 "tx_single_collisions",
1908 "tx_multi_collisions",
1909 "unicast",
1910 "broadcast",
1911 "multicast",
1912 "tx_aborted",
1913 "tx_underrun",
1914};
1915
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001916static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001917{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001918 switch (sset) {
1919 case ETH_SS_STATS:
1920 return ARRAY_SIZE(rtl8169_gstrings);
1921 default:
1922 return -EOPNOTSUPP;
1923 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001924}
1925
Francois Romieuffc46952012-07-06 14:19:23 +02001926DECLARE_RTL_COND(rtl_counters_cond)
1927{
1928 void __iomem *ioaddr = tp->mmio_addr;
1929
1930 return RTL_R32(CounterAddrLow) & CounterDump;
1931}
1932
Ivan Vecera355423d2009-02-06 21:49:57 -08001933static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001934{
1935 struct rtl8169_private *tp = netdev_priv(dev);
1936 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001937 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001938 struct rtl8169_counters *counters;
1939 dma_addr_t paddr;
1940 u32 cmd;
1941
Ivan Vecera355423d2009-02-06 21:49:57 -08001942 /*
1943 * Some chips are unable to dump tally counters when the receiver
1944 * is disabled.
1945 */
1946 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1947 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001948
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001949 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001950 if (!counters)
1951 return;
1952
1953 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001954 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001955 RTL_W32(CounterAddrLow, cmd);
1956 RTL_W32(CounterAddrLow, cmd | CounterDump);
1957
Francois Romieuffc46952012-07-06 14:19:23 +02001958 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1959 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001960
1961 RTL_W32(CounterAddrLow, 0);
1962 RTL_W32(CounterAddrHigh, 0);
1963
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001964 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001965}
1966
Ivan Vecera355423d2009-02-06 21:49:57 -08001967static void rtl8169_get_ethtool_stats(struct net_device *dev,
1968 struct ethtool_stats *stats, u64 *data)
1969{
1970 struct rtl8169_private *tp = netdev_priv(dev);
1971
1972 ASSERT_RTNL();
1973
1974 rtl8169_update_counters(dev);
1975
1976 data[0] = le64_to_cpu(tp->counters.tx_packets);
1977 data[1] = le64_to_cpu(tp->counters.rx_packets);
1978 data[2] = le64_to_cpu(tp->counters.tx_errors);
1979 data[3] = le32_to_cpu(tp->counters.rx_errors);
1980 data[4] = le16_to_cpu(tp->counters.rx_missed);
1981 data[5] = le16_to_cpu(tp->counters.align_errors);
1982 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1983 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1984 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1985 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1986 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1987 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1988 data[12] = le16_to_cpu(tp->counters.tx_underun);
1989}
1990
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001991static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1992{
1993 switch(stringset) {
1994 case ETH_SS_STATS:
1995 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1996 break;
1997 }
1998}
1999
Jeff Garzik7282d492006-09-13 14:30:00 -04002000static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 .get_drvinfo = rtl8169_get_drvinfo,
2002 .get_regs_len = rtl8169_get_regs_len,
2003 .get_link = ethtool_op_get_link,
2004 .get_settings = rtl8169_get_settings,
2005 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002006 .get_msglevel = rtl8169_get_msglevel,
2007 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002009 .get_wol = rtl8169_get_wol,
2010 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002011 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002012 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002013 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002014 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015};
2016
Francois Romieu07d3f512007-02-21 22:40:46 +01002017static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002018 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019{
Francois Romieu5d320a22011-05-08 17:47:36 +02002020 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002021 /*
2022 * The driver currently handles the 8168Bf and the 8168Be identically
2023 * but they can be identified more specifically through the test below
2024 * if needed:
2025 *
2026 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002027 *
2028 * Same thing for the 8101Eb and the 8101Ec:
2029 *
2030 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002031 */
Francois Romieu37441002011-06-17 22:58:54 +02002032 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002034 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 int mac_version;
2036 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002037 /* 8168G family. */
2038 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2039 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2040
Hayes Wangc2218922011-09-06 16:55:18 +08002041 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002042 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002043 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2044 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2045
hayeswang01dc7fe2011-03-21 01:50:28 +00002046 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002047 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002048 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2049 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2050 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2051
Francois Romieu5b538df2008-07-20 16:22:45 +02002052 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002053 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2054 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002055 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002056
françois romieue6de30d2011-01-03 15:08:37 +00002057 /* 8168DP family. */
2058 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2059 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002060 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002061
Francois Romieuef808d52008-06-29 13:10:54 +02002062 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002063 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002064 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002065 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002066 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002067 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2068 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002069 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002070 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002071 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002072
2073 /* 8168B family. */
2074 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2075 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2076 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2077 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2078
2079 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002080 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2081 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002082 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002083 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002084 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2085 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2086 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002087 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2088 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2089 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2090 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2091 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2092 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002093 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002094 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002095 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002096 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2097 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002098 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2099 /* FIXME: where did these entries come from ? -- FR */
2100 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2101 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2102
2103 /* 8110 family. */
2104 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2105 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2106 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2107 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2108 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2109 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2110
Jean Delvaref21b75e2009-05-26 20:54:48 -07002111 /* Catch-all */
2112 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002113 };
2114 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 u32 reg;
2116
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002117 reg = RTL_R32(TxConfig);
2118 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 p++;
2120 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002121
2122 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2123 netif_notice(tp, probe, dev,
2124 "unknown MAC, using family default\n");
2125 tp->mac_version = default_version;
2126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127}
2128
2129static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2130{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002131 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Francois Romieu867763c2007-08-17 18:21:58 +02002134struct phy_reg {
2135 u16 reg;
2136 u16 val;
2137};
2138
françois romieu4da19632011-01-03 15:07:55 +00002139static void rtl_writephy_batch(struct rtl8169_private *tp,
2140 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002141{
2142 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002143 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002144 regs++;
2145 }
2146}
2147
françois romieubca03d52011-01-03 15:07:31 +00002148#define PHY_READ 0x00000000
2149#define PHY_DATA_OR 0x10000000
2150#define PHY_DATA_AND 0x20000000
2151#define PHY_BJMPN 0x30000000
2152#define PHY_READ_EFUSE 0x40000000
2153#define PHY_READ_MAC_BYTE 0x50000000
2154#define PHY_WRITE_MAC_BYTE 0x60000000
2155#define PHY_CLEAR_READCOUNT 0x70000000
2156#define PHY_WRITE 0x80000000
2157#define PHY_READCOUNT_EQ_SKIP 0x90000000
2158#define PHY_COMP_EQ_SKIPN 0xa0000000
2159#define PHY_COMP_NEQ_SKIPN 0xb0000000
2160#define PHY_WRITE_PREVIOUS 0xc0000000
2161#define PHY_SKIPN 0xd0000000
2162#define PHY_DELAY_MS 0xe0000000
2163#define PHY_WRITE_ERI_WORD 0xf0000000
2164
Hayes Wang960aee62011-06-18 11:37:48 +02002165struct fw_info {
2166 u32 magic;
2167 char version[RTL_VER_SIZE];
2168 __le32 fw_start;
2169 __le32 fw_len;
2170 u8 chksum;
2171} __packed;
2172
Francois Romieu1c361ef2011-06-17 17:16:24 +02002173#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2174
2175static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002176{
Francois Romieub6ffd972011-06-17 17:00:05 +02002177 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002178 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002179 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2180 char *version = rtl_fw->version;
2181 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002182
Francois Romieu1c361ef2011-06-17 17:16:24 +02002183 if (fw->size < FW_OPCODE_SIZE)
2184 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002185
2186 if (!fw_info->magic) {
2187 size_t i, size, start;
2188 u8 checksum = 0;
2189
2190 if (fw->size < sizeof(*fw_info))
2191 goto out;
2192
2193 for (i = 0; i < fw->size; i++)
2194 checksum += fw->data[i];
2195 if (checksum != 0)
2196 goto out;
2197
2198 start = le32_to_cpu(fw_info->fw_start);
2199 if (start > fw->size)
2200 goto out;
2201
2202 size = le32_to_cpu(fw_info->fw_len);
2203 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2204 goto out;
2205
2206 memcpy(version, fw_info->version, RTL_VER_SIZE);
2207
2208 pa->code = (__le32 *)(fw->data + start);
2209 pa->size = size;
2210 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002211 if (fw->size % FW_OPCODE_SIZE)
2212 goto out;
2213
2214 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2215
2216 pa->code = (__le32 *)fw->data;
2217 pa->size = fw->size / FW_OPCODE_SIZE;
2218 }
2219 version[RTL_VER_SIZE - 1] = 0;
2220
2221 rc = true;
2222out:
2223 return rc;
2224}
2225
Francois Romieufd112f22011-06-18 00:10:29 +02002226static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2227 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002228{
Francois Romieufd112f22011-06-18 00:10:29 +02002229 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002230 size_t index;
2231
Francois Romieu1c361ef2011-06-17 17:16:24 +02002232 for (index = 0; index < pa->size; index++) {
2233 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002234 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002235
hayeswang42b82dc2011-01-10 02:07:25 +00002236 switch(action & 0xf0000000) {
2237 case PHY_READ:
2238 case PHY_DATA_OR:
2239 case PHY_DATA_AND:
2240 case PHY_READ_EFUSE:
2241 case PHY_CLEAR_READCOUNT:
2242 case PHY_WRITE:
2243 case PHY_WRITE_PREVIOUS:
2244 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002245 break;
2246
hayeswang42b82dc2011-01-10 02:07:25 +00002247 case PHY_BJMPN:
2248 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002249 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002250 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002251 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002252 }
2253 break;
2254 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002255 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002256 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002257 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002258 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002259 }
2260 break;
2261 case PHY_COMP_EQ_SKIPN:
2262 case PHY_COMP_NEQ_SKIPN:
2263 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002264 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002265 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002266 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002267 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002268 }
2269 break;
2270
2271 case PHY_READ_MAC_BYTE:
2272 case PHY_WRITE_MAC_BYTE:
2273 case PHY_WRITE_ERI_WORD:
2274 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002275 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002276 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002277 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002278 }
2279 }
Francois Romieufd112f22011-06-18 00:10:29 +02002280 rc = true;
2281out:
2282 return rc;
2283}
françois romieubca03d52011-01-03 15:07:31 +00002284
Francois Romieufd112f22011-06-18 00:10:29 +02002285static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2286{
2287 struct net_device *dev = tp->dev;
2288 int rc = -EINVAL;
2289
2290 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2291 netif_err(tp, ifup, dev, "invalid firwmare\n");
2292 goto out;
2293 }
2294
2295 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2296 rc = 0;
2297out:
2298 return rc;
2299}
2300
2301static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2302{
2303 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2304 u32 predata, count;
2305 size_t index;
2306
2307 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002308
Francois Romieu1c361ef2011-06-17 17:16:24 +02002309 for (index = 0; index < pa->size; ) {
2310 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002311 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002312 u32 regno = (action & 0x0fff0000) >> 16;
2313
2314 if (!action)
2315 break;
françois romieubca03d52011-01-03 15:07:31 +00002316
2317 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002318 case PHY_READ:
2319 predata = rtl_readphy(tp, regno);
2320 count++;
2321 index++;
françois romieubca03d52011-01-03 15:07:31 +00002322 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002323 case PHY_DATA_OR:
2324 predata |= data;
2325 index++;
2326 break;
2327 case PHY_DATA_AND:
2328 predata &= data;
2329 index++;
2330 break;
2331 case PHY_BJMPN:
2332 index -= regno;
2333 break;
2334 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002335 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002336 index++;
2337 break;
2338 case PHY_CLEAR_READCOUNT:
2339 count = 0;
2340 index++;
2341 break;
2342 case PHY_WRITE:
2343 rtl_writephy(tp, regno, data);
2344 index++;
2345 break;
2346 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002347 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002348 break;
2349 case PHY_COMP_EQ_SKIPN:
2350 if (predata == data)
2351 index += regno;
2352 index++;
2353 break;
2354 case PHY_COMP_NEQ_SKIPN:
2355 if (predata != data)
2356 index += regno;
2357 index++;
2358 break;
2359 case PHY_WRITE_PREVIOUS:
2360 rtl_writephy(tp, regno, predata);
2361 index++;
2362 break;
2363 case PHY_SKIPN:
2364 index += regno + 1;
2365 break;
2366 case PHY_DELAY_MS:
2367 mdelay(data);
2368 index++;
2369 break;
2370
2371 case PHY_READ_MAC_BYTE:
2372 case PHY_WRITE_MAC_BYTE:
2373 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002374 default:
2375 BUG();
2376 }
2377 }
2378}
2379
françois romieuf1e02ed2011-01-13 13:07:53 +00002380static void rtl_release_firmware(struct rtl8169_private *tp)
2381{
Francois Romieub6ffd972011-06-17 17:00:05 +02002382 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2383 release_firmware(tp->rtl_fw->fw);
2384 kfree(tp->rtl_fw);
2385 }
2386 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002387}
2388
François Romieu953a12c2011-04-24 17:38:48 +02002389static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002390{
Francois Romieub6ffd972011-06-17 17:00:05 +02002391 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002392
2393 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002394 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002395 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002396 tp->features |= RTL_FEATURE_FW_LOADED;
2397 }
François Romieu953a12c2011-04-24 17:38:48 +02002398}
2399
2400static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2401{
2402 if (rtl_readphy(tp, reg) != val)
2403 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2404 else
2405 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002406}
2407
hayeswange0c07552012-10-23 20:24:03 +00002408static void r810x_aldps_disable(struct rtl8169_private *tp)
2409{
2410 rtl_writephy(tp, 0x1f, 0x0000);
2411 rtl_writephy(tp, 0x18, 0x0310);
2412 msleep(100);
2413}
2414
2415static void r810x_aldps_enable(struct rtl8169_private *tp)
2416{
2417 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2418 return;
2419
2420 rtl_writephy(tp, 0x1f, 0x0000);
2421 rtl_writephy(tp, 0x18, 0x8310);
2422}
2423
2424static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2425{
2426 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2427 return;
2428
2429 rtl_writephy(tp, 0x1f, 0x0000);
2430 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2431}
2432
françois romieu4da19632011-01-03 15:07:55 +00002433static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002435 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002436 { 0x1f, 0x0001 },
2437 { 0x06, 0x006e },
2438 { 0x08, 0x0708 },
2439 { 0x15, 0x4000 },
2440 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
françois romieu0b9b5712009-08-10 19:44:56 +00002442 { 0x1f, 0x0001 },
2443 { 0x03, 0x00a1 },
2444 { 0x02, 0x0008 },
2445 { 0x01, 0x0120 },
2446 { 0x00, 0x1000 },
2447 { 0x04, 0x0800 },
2448 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
françois romieu0b9b5712009-08-10 19:44:56 +00002450 { 0x03, 0xff41 },
2451 { 0x02, 0xdf60 },
2452 { 0x01, 0x0140 },
2453 { 0x00, 0x0077 },
2454 { 0x04, 0x7800 },
2455 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
françois romieu0b9b5712009-08-10 19:44:56 +00002457 { 0x03, 0x802f },
2458 { 0x02, 0x4f02 },
2459 { 0x01, 0x0409 },
2460 { 0x00, 0xf0f9 },
2461 { 0x04, 0x9800 },
2462 { 0x04, 0x9000 },
2463
2464 { 0x03, 0xdf01 },
2465 { 0x02, 0xdf20 },
2466 { 0x01, 0xff95 },
2467 { 0x00, 0xba00 },
2468 { 0x04, 0xa800 },
2469 { 0x04, 0xa000 },
2470
2471 { 0x03, 0xff41 },
2472 { 0x02, 0xdf20 },
2473 { 0x01, 0x0140 },
2474 { 0x00, 0x00bb },
2475 { 0x04, 0xb800 },
2476 { 0x04, 0xb000 },
2477
2478 { 0x03, 0xdf41 },
2479 { 0x02, 0xdc60 },
2480 { 0x01, 0x6340 },
2481 { 0x00, 0x007d },
2482 { 0x04, 0xd800 },
2483 { 0x04, 0xd000 },
2484
2485 { 0x03, 0xdf01 },
2486 { 0x02, 0xdf20 },
2487 { 0x01, 0x100a },
2488 { 0x00, 0xa0ff },
2489 { 0x04, 0xf800 },
2490 { 0x04, 0xf000 },
2491
2492 { 0x1f, 0x0000 },
2493 { 0x0b, 0x0000 },
2494 { 0x00, 0x9200 }
2495 };
2496
françois romieu4da19632011-01-03 15:07:55 +00002497 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498}
2499
françois romieu4da19632011-01-03 15:07:55 +00002500static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002501{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002502 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002503 { 0x1f, 0x0002 },
2504 { 0x01, 0x90d0 },
2505 { 0x1f, 0x0000 }
2506 };
2507
françois romieu4da19632011-01-03 15:07:55 +00002508 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002509}
2510
françois romieu4da19632011-01-03 15:07:55 +00002511static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002512{
2513 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002514
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002515 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2516 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002517 return;
2518
françois romieu4da19632011-01-03 15:07:55 +00002519 rtl_writephy(tp, 0x1f, 0x0001);
2520 rtl_writephy(tp, 0x10, 0xf01b);
2521 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002522}
2523
françois romieu4da19632011-01-03 15:07:55 +00002524static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002525{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002526 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002527 { 0x1f, 0x0001 },
2528 { 0x04, 0x0000 },
2529 { 0x03, 0x00a1 },
2530 { 0x02, 0x0008 },
2531 { 0x01, 0x0120 },
2532 { 0x00, 0x1000 },
2533 { 0x04, 0x0800 },
2534 { 0x04, 0x9000 },
2535 { 0x03, 0x802f },
2536 { 0x02, 0x4f02 },
2537 { 0x01, 0x0409 },
2538 { 0x00, 0xf099 },
2539 { 0x04, 0x9800 },
2540 { 0x04, 0xa000 },
2541 { 0x03, 0xdf01 },
2542 { 0x02, 0xdf20 },
2543 { 0x01, 0xff95 },
2544 { 0x00, 0xba00 },
2545 { 0x04, 0xa800 },
2546 { 0x04, 0xf000 },
2547 { 0x03, 0xdf01 },
2548 { 0x02, 0xdf20 },
2549 { 0x01, 0x101a },
2550 { 0x00, 0xa0ff },
2551 { 0x04, 0xf800 },
2552 { 0x04, 0x0000 },
2553 { 0x1f, 0x0000 },
2554
2555 { 0x1f, 0x0001 },
2556 { 0x10, 0xf41b },
2557 { 0x14, 0xfb54 },
2558 { 0x18, 0xf5c7 },
2559 { 0x1f, 0x0000 },
2560
2561 { 0x1f, 0x0001 },
2562 { 0x17, 0x0cc0 },
2563 { 0x1f, 0x0000 }
2564 };
2565
françois romieu4da19632011-01-03 15:07:55 +00002566 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002567
françois romieu4da19632011-01-03 15:07:55 +00002568 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002569}
2570
françois romieu4da19632011-01-03 15:07:55 +00002571static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002572{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002573 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002574 { 0x1f, 0x0001 },
2575 { 0x04, 0x0000 },
2576 { 0x03, 0x00a1 },
2577 { 0x02, 0x0008 },
2578 { 0x01, 0x0120 },
2579 { 0x00, 0x1000 },
2580 { 0x04, 0x0800 },
2581 { 0x04, 0x9000 },
2582 { 0x03, 0x802f },
2583 { 0x02, 0x4f02 },
2584 { 0x01, 0x0409 },
2585 { 0x00, 0xf099 },
2586 { 0x04, 0x9800 },
2587 { 0x04, 0xa000 },
2588 { 0x03, 0xdf01 },
2589 { 0x02, 0xdf20 },
2590 { 0x01, 0xff95 },
2591 { 0x00, 0xba00 },
2592 { 0x04, 0xa800 },
2593 { 0x04, 0xf000 },
2594 { 0x03, 0xdf01 },
2595 { 0x02, 0xdf20 },
2596 { 0x01, 0x101a },
2597 { 0x00, 0xa0ff },
2598 { 0x04, 0xf800 },
2599 { 0x04, 0x0000 },
2600 { 0x1f, 0x0000 },
2601
2602 { 0x1f, 0x0001 },
2603 { 0x0b, 0x8480 },
2604 { 0x1f, 0x0000 },
2605
2606 { 0x1f, 0x0001 },
2607 { 0x18, 0x67c7 },
2608 { 0x04, 0x2000 },
2609 { 0x03, 0x002f },
2610 { 0x02, 0x4360 },
2611 { 0x01, 0x0109 },
2612 { 0x00, 0x3022 },
2613 { 0x04, 0x2800 },
2614 { 0x1f, 0x0000 },
2615
2616 { 0x1f, 0x0001 },
2617 { 0x17, 0x0cc0 },
2618 { 0x1f, 0x0000 }
2619 };
2620
françois romieu4da19632011-01-03 15:07:55 +00002621 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002622}
2623
françois romieu4da19632011-01-03 15:07:55 +00002624static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002625{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002626 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002627 { 0x10, 0xf41b },
2628 { 0x1f, 0x0000 }
2629 };
2630
françois romieu4da19632011-01-03 15:07:55 +00002631 rtl_writephy(tp, 0x1f, 0x0001);
2632 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002633
françois romieu4da19632011-01-03 15:07:55 +00002634 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002635}
2636
françois romieu4da19632011-01-03 15:07:55 +00002637static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002638{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002639 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002640 { 0x1f, 0x0001 },
2641 { 0x10, 0xf41b },
2642 { 0x1f, 0x0000 }
2643 };
2644
françois romieu4da19632011-01-03 15:07:55 +00002645 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002646}
2647
françois romieu4da19632011-01-03 15:07:55 +00002648static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002649{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002650 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002651 { 0x1f, 0x0000 },
2652 { 0x1d, 0x0f00 },
2653 { 0x1f, 0x0002 },
2654 { 0x0c, 0x1ec8 },
2655 { 0x1f, 0x0000 }
2656 };
2657
françois romieu4da19632011-01-03 15:07:55 +00002658 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002659}
2660
françois romieu4da19632011-01-03 15:07:55 +00002661static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002662{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002663 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002664 { 0x1f, 0x0001 },
2665 { 0x1d, 0x3d98 },
2666 { 0x1f, 0x0000 }
2667 };
2668
françois romieu4da19632011-01-03 15:07:55 +00002669 rtl_writephy(tp, 0x1f, 0x0000);
2670 rtl_patchphy(tp, 0x14, 1 << 5);
2671 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002672
françois romieu4da19632011-01-03 15:07:55 +00002673 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002674}
2675
françois romieu4da19632011-01-03 15:07:55 +00002676static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002677{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002678 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002679 { 0x1f, 0x0001 },
2680 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002681 { 0x1f, 0x0002 },
2682 { 0x00, 0x88d4 },
2683 { 0x01, 0x82b1 },
2684 { 0x03, 0x7002 },
2685 { 0x08, 0x9e30 },
2686 { 0x09, 0x01f0 },
2687 { 0x0a, 0x5500 },
2688 { 0x0c, 0x00c8 },
2689 { 0x1f, 0x0003 },
2690 { 0x12, 0xc096 },
2691 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002692 { 0x1f, 0x0000 },
2693 { 0x1f, 0x0000 },
2694 { 0x09, 0x2000 },
2695 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002696 };
2697
françois romieu4da19632011-01-03 15:07:55 +00002698 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002699
françois romieu4da19632011-01-03 15:07:55 +00002700 rtl_patchphy(tp, 0x14, 1 << 5);
2701 rtl_patchphy(tp, 0x0d, 1 << 5);
2702 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002703}
2704
françois romieu4da19632011-01-03 15:07:55 +00002705static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002706{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002707 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002708 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002709 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002710 { 0x03, 0x802f },
2711 { 0x02, 0x4f02 },
2712 { 0x01, 0x0409 },
2713 { 0x00, 0xf099 },
2714 { 0x04, 0x9800 },
2715 { 0x04, 0x9000 },
2716 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002717 { 0x1f, 0x0002 },
2718 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002719 { 0x06, 0x0761 },
2720 { 0x1f, 0x0003 },
2721 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002722 { 0x1f, 0x0000 }
2723 };
2724
françois romieu4da19632011-01-03 15:07:55 +00002725 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002726
françois romieu4da19632011-01-03 15:07:55 +00002727 rtl_patchphy(tp, 0x16, 1 << 0);
2728 rtl_patchphy(tp, 0x14, 1 << 5);
2729 rtl_patchphy(tp, 0x0d, 1 << 5);
2730 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002731}
2732
françois romieu4da19632011-01-03 15:07:55 +00002733static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002734{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002735 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002736 { 0x1f, 0x0001 },
2737 { 0x12, 0x2300 },
2738 { 0x1d, 0x3d98 },
2739 { 0x1f, 0x0002 },
2740 { 0x0c, 0x7eb8 },
2741 { 0x06, 0x5461 },
2742 { 0x1f, 0x0003 },
2743 { 0x16, 0x0f0a },
2744 { 0x1f, 0x0000 }
2745 };
2746
françois romieu4da19632011-01-03 15:07:55 +00002747 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002748
françois romieu4da19632011-01-03 15:07:55 +00002749 rtl_patchphy(tp, 0x16, 1 << 0);
2750 rtl_patchphy(tp, 0x14, 1 << 5);
2751 rtl_patchphy(tp, 0x0d, 1 << 5);
2752 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002753}
2754
françois romieu4da19632011-01-03 15:07:55 +00002755static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002756{
françois romieu4da19632011-01-03 15:07:55 +00002757 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002758}
2759
françois romieubca03d52011-01-03 15:07:31 +00002760static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002761{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002762 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002763 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002764 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002765 { 0x06, 0x4064 },
2766 { 0x07, 0x2863 },
2767 { 0x08, 0x059c },
2768 { 0x09, 0x26b4 },
2769 { 0x0a, 0x6a19 },
2770 { 0x0b, 0xdcc8 },
2771 { 0x10, 0xf06d },
2772 { 0x14, 0x7f68 },
2773 { 0x18, 0x7fd9 },
2774 { 0x1c, 0xf0ff },
2775 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002776 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002777 { 0x12, 0xf49f },
2778 { 0x13, 0x070b },
2779 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002780 { 0x14, 0x94c0 },
2781
2782 /*
2783 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002784 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002785 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002786 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002787 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002788 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002789 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002790 { 0x06, 0x5561 },
2791
2792 /*
2793 * Can not link to 1Gbps with bad cable
2794 * Decrease SNR threshold form 21.07dB to 19.04dB
2795 */
2796 { 0x1f, 0x0001 },
2797 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002798
2799 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002800 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002801 };
2802
françois romieu4da19632011-01-03 15:07:55 +00002803 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002804
françois romieubca03d52011-01-03 15:07:31 +00002805 /*
2806 * Rx Error Issue
2807 * Fine Tune Switching regulator parameter
2808 */
françois romieu4da19632011-01-03 15:07:55 +00002809 rtl_writephy(tp, 0x1f, 0x0002);
2810 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2811 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002812
Francois Romieufdf6fc02012-07-06 22:40:38 +02002813 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002814 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002815 { 0x1f, 0x0002 },
2816 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002817 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002818 { 0x05, 0x8330 },
2819 { 0x06, 0x669a },
2820 { 0x1f, 0x0002 }
2821 };
2822 int val;
2823
françois romieu4da19632011-01-03 15:07:55 +00002824 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002825
françois romieu4da19632011-01-03 15:07:55 +00002826 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002827
2828 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002829 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002830 0x0065, 0x0066, 0x0067, 0x0068,
2831 0x0069, 0x006a, 0x006b, 0x006c
2832 };
2833 int i;
2834
françois romieu4da19632011-01-03 15:07:55 +00002835 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002836
2837 val &= 0xff00;
2838 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002839 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002840 }
2841 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002842 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002843 { 0x1f, 0x0002 },
2844 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002845 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002846 { 0x05, 0x8330 },
2847 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002848 };
2849
françois romieu4da19632011-01-03 15:07:55 +00002850 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002851 }
2852
françois romieubca03d52011-01-03 15:07:31 +00002853 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002854 rtl_writephy(tp, 0x1f, 0x0002);
2855 rtl_patchphy(tp, 0x0d, 0x0300);
2856 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002857
françois romieubca03d52011-01-03 15:07:31 +00002858 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002859 rtl_writephy(tp, 0x1f, 0x0002);
2860 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2861 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002862
françois romieu4da19632011-01-03 15:07:55 +00002863 rtl_writephy(tp, 0x1f, 0x0005);
2864 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002865
2866 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002867
françois romieu4da19632011-01-03 15:07:55 +00002868 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002869}
2870
françois romieubca03d52011-01-03 15:07:31 +00002871static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002872{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002873 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002874 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002875 { 0x1f, 0x0001 },
2876 { 0x06, 0x4064 },
2877 { 0x07, 0x2863 },
2878 { 0x08, 0x059c },
2879 { 0x09, 0x26b4 },
2880 { 0x0a, 0x6a19 },
2881 { 0x0b, 0xdcc8 },
2882 { 0x10, 0xf06d },
2883 { 0x14, 0x7f68 },
2884 { 0x18, 0x7fd9 },
2885 { 0x1c, 0xf0ff },
2886 { 0x1d, 0x3d9c },
2887 { 0x1f, 0x0003 },
2888 { 0x12, 0xf49f },
2889 { 0x13, 0x070b },
2890 { 0x1a, 0x05ad },
2891 { 0x14, 0x94c0 },
2892
françois romieubca03d52011-01-03 15:07:31 +00002893 /*
2894 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002895 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002896 */
françois romieudaf9df62009-10-07 12:44:20 +00002897 { 0x1f, 0x0002 },
2898 { 0x06, 0x5561 },
2899 { 0x1f, 0x0005 },
2900 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002901 { 0x06, 0x5561 },
2902
2903 /*
2904 * Can not link to 1Gbps with bad cable
2905 * Decrease SNR threshold form 21.07dB to 19.04dB
2906 */
2907 { 0x1f, 0x0001 },
2908 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002909
2910 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002911 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002912 };
2913
françois romieu4da19632011-01-03 15:07:55 +00002914 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002915
Francois Romieufdf6fc02012-07-06 22:40:38 +02002916 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002917 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002918 { 0x1f, 0x0002 },
2919 { 0x05, 0x669a },
2920 { 0x1f, 0x0005 },
2921 { 0x05, 0x8330 },
2922 { 0x06, 0x669a },
2923
2924 { 0x1f, 0x0002 }
2925 };
2926 int val;
2927
françois romieu4da19632011-01-03 15:07:55 +00002928 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002929
françois romieu4da19632011-01-03 15:07:55 +00002930 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002931 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002932 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002933 0x0065, 0x0066, 0x0067, 0x0068,
2934 0x0069, 0x006a, 0x006b, 0x006c
2935 };
2936 int i;
2937
françois romieu4da19632011-01-03 15:07:55 +00002938 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002939
2940 val &= 0xff00;
2941 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002942 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002943 }
2944 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002945 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002946 { 0x1f, 0x0002 },
2947 { 0x05, 0x2642 },
2948 { 0x1f, 0x0005 },
2949 { 0x05, 0x8330 },
2950 { 0x06, 0x2642 }
2951 };
2952
françois romieu4da19632011-01-03 15:07:55 +00002953 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002954 }
2955
françois romieubca03d52011-01-03 15:07:31 +00002956 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002957 rtl_writephy(tp, 0x1f, 0x0002);
2958 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2959 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002960
françois romieubca03d52011-01-03 15:07:31 +00002961 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002962 rtl_writephy(tp, 0x1f, 0x0002);
2963 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002964
françois romieu4da19632011-01-03 15:07:55 +00002965 rtl_writephy(tp, 0x1f, 0x0005);
2966 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002967
2968 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002969
françois romieu4da19632011-01-03 15:07:55 +00002970 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002971}
2972
françois romieu4da19632011-01-03 15:07:55 +00002973static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002974{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002975 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002976 { 0x1f, 0x0002 },
2977 { 0x10, 0x0008 },
2978 { 0x0d, 0x006c },
2979
2980 { 0x1f, 0x0000 },
2981 { 0x0d, 0xf880 },
2982
2983 { 0x1f, 0x0001 },
2984 { 0x17, 0x0cc0 },
2985
2986 { 0x1f, 0x0001 },
2987 { 0x0b, 0xa4d8 },
2988 { 0x09, 0x281c },
2989 { 0x07, 0x2883 },
2990 { 0x0a, 0x6b35 },
2991 { 0x1d, 0x3da4 },
2992 { 0x1c, 0xeffd },
2993 { 0x14, 0x7f52 },
2994 { 0x18, 0x7fc6 },
2995 { 0x08, 0x0601 },
2996 { 0x06, 0x4063 },
2997 { 0x10, 0xf074 },
2998 { 0x1f, 0x0003 },
2999 { 0x13, 0x0789 },
3000 { 0x12, 0xf4bd },
3001 { 0x1a, 0x04fd },
3002 { 0x14, 0x84b0 },
3003 { 0x1f, 0x0000 },
3004 { 0x00, 0x9200 },
3005
3006 { 0x1f, 0x0005 },
3007 { 0x01, 0x0340 },
3008 { 0x1f, 0x0001 },
3009 { 0x04, 0x4000 },
3010 { 0x03, 0x1d21 },
3011 { 0x02, 0x0c32 },
3012 { 0x01, 0x0200 },
3013 { 0x00, 0x5554 },
3014 { 0x04, 0x4800 },
3015 { 0x04, 0x4000 },
3016 { 0x04, 0xf000 },
3017 { 0x03, 0xdf01 },
3018 { 0x02, 0xdf20 },
3019 { 0x01, 0x101a },
3020 { 0x00, 0xa0ff },
3021 { 0x04, 0xf800 },
3022 { 0x04, 0xf000 },
3023 { 0x1f, 0x0000 },
3024
3025 { 0x1f, 0x0007 },
3026 { 0x1e, 0x0023 },
3027 { 0x16, 0x0000 },
3028 { 0x1f, 0x0000 }
3029 };
3030
françois romieu4da19632011-01-03 15:07:55 +00003031 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003032}
3033
françois romieue6de30d2011-01-03 15:08:37 +00003034static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3035{
3036 static const struct phy_reg phy_reg_init[] = {
3037 { 0x1f, 0x0001 },
3038 { 0x17, 0x0cc0 },
3039
3040 { 0x1f, 0x0007 },
3041 { 0x1e, 0x002d },
3042 { 0x18, 0x0040 },
3043 { 0x1f, 0x0000 }
3044 };
3045
3046 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3047 rtl_patchphy(tp, 0x0d, 1 << 5);
3048}
3049
Hayes Wang70090422011-07-06 15:58:06 +08003050static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003051{
3052 static const struct phy_reg phy_reg_init[] = {
3053 /* Enable Delay cap */
3054 { 0x1f, 0x0005 },
3055 { 0x05, 0x8b80 },
3056 { 0x06, 0xc896 },
3057 { 0x1f, 0x0000 },
3058
3059 /* Channel estimation fine tune */
3060 { 0x1f, 0x0001 },
3061 { 0x0b, 0x6c20 },
3062 { 0x07, 0x2872 },
3063 { 0x1c, 0xefff },
3064 { 0x1f, 0x0003 },
3065 { 0x14, 0x6420 },
3066 { 0x1f, 0x0000 },
3067
3068 /* Update PFM & 10M TX idle timer */
3069 { 0x1f, 0x0007 },
3070 { 0x1e, 0x002f },
3071 { 0x15, 0x1919 },
3072 { 0x1f, 0x0000 },
3073
3074 { 0x1f, 0x0007 },
3075 { 0x1e, 0x00ac },
3076 { 0x18, 0x0006 },
3077 { 0x1f, 0x0000 }
3078 };
3079
Francois Romieu15ecd032011-04-27 13:52:22 -07003080 rtl_apply_firmware(tp);
3081
hayeswang01dc7fe2011-03-21 01:50:28 +00003082 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3083
3084 /* DCO enable for 10M IDLE Power */
3085 rtl_writephy(tp, 0x1f, 0x0007);
3086 rtl_writephy(tp, 0x1e, 0x0023);
3087 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3088 rtl_writephy(tp, 0x1f, 0x0000);
3089
3090 /* For impedance matching */
3091 rtl_writephy(tp, 0x1f, 0x0002);
3092 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003093 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003094
3095 /* PHY auto speed down */
3096 rtl_writephy(tp, 0x1f, 0x0007);
3097 rtl_writephy(tp, 0x1e, 0x002d);
3098 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3099 rtl_writephy(tp, 0x1f, 0x0000);
3100 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3101
3102 rtl_writephy(tp, 0x1f, 0x0005);
3103 rtl_writephy(tp, 0x05, 0x8b86);
3104 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3105 rtl_writephy(tp, 0x1f, 0x0000);
3106
3107 rtl_writephy(tp, 0x1f, 0x0005);
3108 rtl_writephy(tp, 0x05, 0x8b85);
3109 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3110 rtl_writephy(tp, 0x1f, 0x0007);
3111 rtl_writephy(tp, 0x1e, 0x0020);
3112 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3113 rtl_writephy(tp, 0x1f, 0x0006);
3114 rtl_writephy(tp, 0x00, 0x5a00);
3115 rtl_writephy(tp, 0x1f, 0x0000);
3116 rtl_writephy(tp, 0x0d, 0x0007);
3117 rtl_writephy(tp, 0x0e, 0x003c);
3118 rtl_writephy(tp, 0x0d, 0x4007);
3119 rtl_writephy(tp, 0x0e, 0x0000);
3120 rtl_writephy(tp, 0x0d, 0x0000);
3121}
3122
françois romieu9ecb9aa2012-12-07 11:20:21 +00003123static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3124{
3125 const u16 w[] = {
3126 addr[0] | (addr[1] << 8),
3127 addr[2] | (addr[3] << 8),
3128 addr[4] | (addr[5] << 8)
3129 };
3130 const struct exgmac_reg e[] = {
3131 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3132 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3133 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3134 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3135 };
3136
3137 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3138}
3139
Hayes Wang70090422011-07-06 15:58:06 +08003140static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3141{
3142 static const struct phy_reg phy_reg_init[] = {
3143 /* Enable Delay cap */
3144 { 0x1f, 0x0004 },
3145 { 0x1f, 0x0007 },
3146 { 0x1e, 0x00ac },
3147 { 0x18, 0x0006 },
3148 { 0x1f, 0x0002 },
3149 { 0x1f, 0x0000 },
3150 { 0x1f, 0x0000 },
3151
3152 /* Channel estimation fine tune */
3153 { 0x1f, 0x0003 },
3154 { 0x09, 0xa20f },
3155 { 0x1f, 0x0000 },
3156 { 0x1f, 0x0000 },
3157
3158 /* Green Setting */
3159 { 0x1f, 0x0005 },
3160 { 0x05, 0x8b5b },
3161 { 0x06, 0x9222 },
3162 { 0x05, 0x8b6d },
3163 { 0x06, 0x8000 },
3164 { 0x05, 0x8b76 },
3165 { 0x06, 0x8000 },
3166 { 0x1f, 0x0000 }
3167 };
3168
3169 rtl_apply_firmware(tp);
3170
3171 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3172
3173 /* For 4-corner performance improve */
3174 rtl_writephy(tp, 0x1f, 0x0005);
3175 rtl_writephy(tp, 0x05, 0x8b80);
3176 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3177 rtl_writephy(tp, 0x1f, 0x0000);
3178
3179 /* PHY auto speed down */
3180 rtl_writephy(tp, 0x1f, 0x0004);
3181 rtl_writephy(tp, 0x1f, 0x0007);
3182 rtl_writephy(tp, 0x1e, 0x002d);
3183 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3184 rtl_writephy(tp, 0x1f, 0x0002);
3185 rtl_writephy(tp, 0x1f, 0x0000);
3186 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3187
3188 /* improve 10M EEE waveform */
3189 rtl_writephy(tp, 0x1f, 0x0005);
3190 rtl_writephy(tp, 0x05, 0x8b86);
3191 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3192 rtl_writephy(tp, 0x1f, 0x0000);
3193
3194 /* Improve 2-pair detection performance */
3195 rtl_writephy(tp, 0x1f, 0x0005);
3196 rtl_writephy(tp, 0x05, 0x8b85);
3197 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3198 rtl_writephy(tp, 0x1f, 0x0000);
3199
3200 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003201 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003202 rtl_writephy(tp, 0x1f, 0x0005);
3203 rtl_writephy(tp, 0x05, 0x8b85);
3204 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3205 rtl_writephy(tp, 0x1f, 0x0004);
3206 rtl_writephy(tp, 0x1f, 0x0007);
3207 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003208 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003209 rtl_writephy(tp, 0x1f, 0x0002);
3210 rtl_writephy(tp, 0x1f, 0x0000);
3211 rtl_writephy(tp, 0x0d, 0x0007);
3212 rtl_writephy(tp, 0x0e, 0x003c);
3213 rtl_writephy(tp, 0x0d, 0x4007);
3214 rtl_writephy(tp, 0x0e, 0x0000);
3215 rtl_writephy(tp, 0x0d, 0x0000);
3216
3217 /* Green feature */
3218 rtl_writephy(tp, 0x1f, 0x0003);
3219 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3220 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3221 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003222
3223 r8168_aldps_enable_1(tp);
françois romieu9ecb9aa2012-12-07 11:20:21 +00003224
3225 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3226 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003227}
3228
Hayes Wang5f886e02012-03-30 14:33:03 +08003229static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3230{
3231 /* For 4-corner performance improve */
3232 rtl_writephy(tp, 0x1f, 0x0005);
3233 rtl_writephy(tp, 0x05, 0x8b80);
3234 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3235 rtl_writephy(tp, 0x1f, 0x0000);
3236
3237 /* PHY auto speed down */
3238 rtl_writephy(tp, 0x1f, 0x0007);
3239 rtl_writephy(tp, 0x1e, 0x002d);
3240 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3241 rtl_writephy(tp, 0x1f, 0x0000);
3242 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3243
3244 /* Improve 10M EEE waveform */
3245 rtl_writephy(tp, 0x1f, 0x0005);
3246 rtl_writephy(tp, 0x05, 0x8b86);
3247 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3248 rtl_writephy(tp, 0x1f, 0x0000);
3249}
3250
Hayes Wangc2218922011-09-06 16:55:18 +08003251static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3252{
3253 static const struct phy_reg phy_reg_init[] = {
3254 /* Channel estimation fine tune */
3255 { 0x1f, 0x0003 },
3256 { 0x09, 0xa20f },
3257 { 0x1f, 0x0000 },
3258
3259 /* Modify green table for giga & fnet */
3260 { 0x1f, 0x0005 },
3261 { 0x05, 0x8b55 },
3262 { 0x06, 0x0000 },
3263 { 0x05, 0x8b5e },
3264 { 0x06, 0x0000 },
3265 { 0x05, 0x8b67 },
3266 { 0x06, 0x0000 },
3267 { 0x05, 0x8b70 },
3268 { 0x06, 0x0000 },
3269 { 0x1f, 0x0000 },
3270 { 0x1f, 0x0007 },
3271 { 0x1e, 0x0078 },
3272 { 0x17, 0x0000 },
3273 { 0x19, 0x00fb },
3274 { 0x1f, 0x0000 },
3275
3276 /* Modify green table for 10M */
3277 { 0x1f, 0x0005 },
3278 { 0x05, 0x8b79 },
3279 { 0x06, 0xaa00 },
3280 { 0x1f, 0x0000 },
3281
3282 /* Disable hiimpedance detection (RTCT) */
3283 { 0x1f, 0x0003 },
3284 { 0x01, 0x328a },
3285 { 0x1f, 0x0000 }
3286 };
3287
3288 rtl_apply_firmware(tp);
3289
3290 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3291
Hayes Wang5f886e02012-03-30 14:33:03 +08003292 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003293
3294 /* Improve 2-pair detection performance */
3295 rtl_writephy(tp, 0x1f, 0x0005);
3296 rtl_writephy(tp, 0x05, 0x8b85);
3297 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3298 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003299
3300 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003301}
3302
3303static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3304{
3305 rtl_apply_firmware(tp);
3306
Hayes Wang5f886e02012-03-30 14:33:03 +08003307 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003308
3309 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003310}
3311
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003312static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3313{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003314 static const struct phy_reg phy_reg_init[] = {
3315 /* Channel estimation fine tune */
3316 { 0x1f, 0x0003 },
3317 { 0x09, 0xa20f },
3318 { 0x1f, 0x0000 },
3319
3320 /* Modify green table for giga & fnet */
3321 { 0x1f, 0x0005 },
3322 { 0x05, 0x8b55 },
3323 { 0x06, 0x0000 },
3324 { 0x05, 0x8b5e },
3325 { 0x06, 0x0000 },
3326 { 0x05, 0x8b67 },
3327 { 0x06, 0x0000 },
3328 { 0x05, 0x8b70 },
3329 { 0x06, 0x0000 },
3330 { 0x1f, 0x0000 },
3331 { 0x1f, 0x0007 },
3332 { 0x1e, 0x0078 },
3333 { 0x17, 0x0000 },
3334 { 0x19, 0x00aa },
3335 { 0x1f, 0x0000 },
3336
3337 /* Modify green table for 10M */
3338 { 0x1f, 0x0005 },
3339 { 0x05, 0x8b79 },
3340 { 0x06, 0xaa00 },
3341 { 0x1f, 0x0000 },
3342
3343 /* Disable hiimpedance detection (RTCT) */
3344 { 0x1f, 0x0003 },
3345 { 0x01, 0x328a },
3346 { 0x1f, 0x0000 }
3347 };
3348
3349
3350 rtl_apply_firmware(tp);
3351
3352 rtl8168f_hw_phy_config(tp);
3353
3354 /* Improve 2-pair detection performance */
3355 rtl_writephy(tp, 0x1f, 0x0005);
3356 rtl_writephy(tp, 0x05, 0x8b85);
3357 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3358 rtl_writephy(tp, 0x1f, 0x0000);
3359
3360 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3361
3362 /* Modify green table for giga */
3363 rtl_writephy(tp, 0x1f, 0x0005);
3364 rtl_writephy(tp, 0x05, 0x8b54);
3365 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3366 rtl_writephy(tp, 0x05, 0x8b5d);
3367 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3368 rtl_writephy(tp, 0x05, 0x8a7c);
3369 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3370 rtl_writephy(tp, 0x05, 0x8a7f);
3371 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3372 rtl_writephy(tp, 0x05, 0x8a82);
3373 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3374 rtl_writephy(tp, 0x05, 0x8a85);
3375 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3376 rtl_writephy(tp, 0x05, 0x8a88);
3377 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3378 rtl_writephy(tp, 0x1f, 0x0000);
3379
3380 /* uc same-seed solution */
3381 rtl_writephy(tp, 0x1f, 0x0005);
3382 rtl_writephy(tp, 0x05, 0x8b85);
3383 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3384 rtl_writephy(tp, 0x1f, 0x0000);
3385
3386 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003387 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003388 rtl_writephy(tp, 0x1f, 0x0005);
3389 rtl_writephy(tp, 0x05, 0x8b85);
3390 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3391 rtl_writephy(tp, 0x1f, 0x0004);
3392 rtl_writephy(tp, 0x1f, 0x0007);
3393 rtl_writephy(tp, 0x1e, 0x0020);
3394 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3395 rtl_writephy(tp, 0x1f, 0x0000);
3396 rtl_writephy(tp, 0x0d, 0x0007);
3397 rtl_writephy(tp, 0x0e, 0x003c);
3398 rtl_writephy(tp, 0x0d, 0x4007);
3399 rtl_writephy(tp, 0x0e, 0x0000);
3400 rtl_writephy(tp, 0x0d, 0x0000);
3401
3402 /* Green feature */
3403 rtl_writephy(tp, 0x1f, 0x0003);
3404 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3405 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3406 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003407
3408 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003409}
3410
Hayes Wangc5583862012-07-02 17:23:22 +08003411static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3412{
3413 static const u16 mac_ocp_patch[] = {
3414 0xe008, 0xe01b, 0xe01d, 0xe01f,
3415 0xe021, 0xe023, 0xe025, 0xe027,
3416 0x49d2, 0xf10d, 0x766c, 0x49e2,
3417 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3418
3419 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3420 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3421 0xbe00, 0xb416, 0x0076, 0xe86c,
3422 0xc602, 0xbe00, 0x0000, 0xc602,
3423
3424 0xbe00, 0x0000, 0xc602, 0xbe00,
3425 0x0000, 0xc602, 0xbe00, 0x0000,
3426 0xc602, 0xbe00, 0x0000, 0xc602,
3427 0xbe00, 0x0000, 0xc602, 0xbe00,
3428
3429 0x0000, 0x0000, 0x0000, 0x0000
3430 };
3431 u32 i;
3432
3433 /* Patch code for GPHY reset */
3434 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3435 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3436 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3437 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3438
3439 rtl_apply_firmware(tp);
3440
3441 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3442 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3443 else
3444 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3445
3446 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3447 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3448 else
3449 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3450
3451 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3452 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3453
3454 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3455 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3456
3457 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3458}
3459
françois romieu4da19632011-01-03 15:07:55 +00003460static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003461{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003462 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003463 { 0x1f, 0x0003 },
3464 { 0x08, 0x441d },
3465 { 0x01, 0x9100 },
3466 { 0x1f, 0x0000 }
3467 };
3468
françois romieu4da19632011-01-03 15:07:55 +00003469 rtl_writephy(tp, 0x1f, 0x0000);
3470 rtl_patchphy(tp, 0x11, 1 << 12);
3471 rtl_patchphy(tp, 0x19, 1 << 13);
3472 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003473
françois romieu4da19632011-01-03 15:07:55 +00003474 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003475}
3476
Hayes Wang5a5e4442011-02-22 17:26:21 +08003477static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3478{
3479 static const struct phy_reg phy_reg_init[] = {
3480 { 0x1f, 0x0005 },
3481 { 0x1a, 0x0000 },
3482 { 0x1f, 0x0000 },
3483
3484 { 0x1f, 0x0004 },
3485 { 0x1c, 0x0000 },
3486 { 0x1f, 0x0000 },
3487
3488 { 0x1f, 0x0001 },
3489 { 0x15, 0x7701 },
3490 { 0x1f, 0x0000 }
3491 };
3492
3493 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003494 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003495
François Romieu953a12c2011-04-24 17:38:48 +02003496 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003497
3498 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003499
3500 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003501}
3502
Hayes Wang7e18dca2012-03-30 14:33:02 +08003503static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3504{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003505 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003506 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003507
3508 rtl_apply_firmware(tp);
3509
3510 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003511 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003512 rtl_writephy(tp, 0x1f, 0x0004);
3513 rtl_writephy(tp, 0x10, 0x401f);
3514 rtl_writephy(tp, 0x19, 0x7030);
3515 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003516
3517 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003518}
3519
Hayes Wang5598bfe2012-07-02 17:23:21 +08003520static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3521{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003522 static const struct phy_reg phy_reg_init[] = {
3523 { 0x1f, 0x0004 },
3524 { 0x10, 0xc07f },
3525 { 0x19, 0x7030 },
3526 { 0x1f, 0x0000 }
3527 };
3528
3529 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003530 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003531
3532 rtl_apply_firmware(tp);
3533
Francois Romieufdf6fc02012-07-06 22:40:38 +02003534 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003535 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3536
Francois Romieufdf6fc02012-07-06 22:40:38 +02003537 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003538
3539 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003540}
3541
Francois Romieu5615d9f2007-08-17 17:50:46 +02003542static void rtl_hw_phy_config(struct net_device *dev)
3543{
3544 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003545
3546 rtl8169_print_mac_version(tp);
3547
3548 switch (tp->mac_version) {
3549 case RTL_GIGA_MAC_VER_01:
3550 break;
3551 case RTL_GIGA_MAC_VER_02:
3552 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003554 break;
3555 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003556 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003557 break;
françois romieu2e9558562009-08-10 19:44:19 +00003558 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003559 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003560 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003561 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003563 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003564 case RTL_GIGA_MAC_VER_07:
3565 case RTL_GIGA_MAC_VER_08:
3566 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003567 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003568 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003569 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003570 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003571 break;
3572 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003573 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003574 break;
3575 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003576 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003577 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003578 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003579 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003580 break;
3581 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003582 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003583 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003584 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003585 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003586 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003587 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003588 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003589 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003590 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003591 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003592 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003593 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003594 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003595 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003596 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003597 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003598 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003599 break;
3600 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003601 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003602 break;
3603 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003604 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003605 break;
françois romieue6de30d2011-01-03 15:08:37 +00003606 case RTL_GIGA_MAC_VER_28:
3607 rtl8168d_4_hw_phy_config(tp);
3608 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003609 case RTL_GIGA_MAC_VER_29:
3610 case RTL_GIGA_MAC_VER_30:
3611 rtl8105e_hw_phy_config(tp);
3612 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003613 case RTL_GIGA_MAC_VER_31:
3614 /* None. */
3615 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003616 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003617 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003618 rtl8168e_1_hw_phy_config(tp);
3619 break;
3620 case RTL_GIGA_MAC_VER_34:
3621 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003622 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003623 case RTL_GIGA_MAC_VER_35:
3624 rtl8168f_1_hw_phy_config(tp);
3625 break;
3626 case RTL_GIGA_MAC_VER_36:
3627 rtl8168f_2_hw_phy_config(tp);
3628 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003629
Hayes Wang7e18dca2012-03-30 14:33:02 +08003630 case RTL_GIGA_MAC_VER_37:
3631 rtl8402_hw_phy_config(tp);
3632 break;
3633
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003634 case RTL_GIGA_MAC_VER_38:
3635 rtl8411_hw_phy_config(tp);
3636 break;
3637
Hayes Wang5598bfe2012-07-02 17:23:21 +08003638 case RTL_GIGA_MAC_VER_39:
3639 rtl8106e_hw_phy_config(tp);
3640 break;
3641
Hayes Wangc5583862012-07-02 17:23:22 +08003642 case RTL_GIGA_MAC_VER_40:
3643 rtl8168g_1_hw_phy_config(tp);
3644 break;
3645
3646 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003647 default:
3648 break;
3649 }
3650}
3651
Francois Romieuda78dbf2012-01-26 14:18:23 +01003652static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 struct timer_list *timer = &tp->timer;
3655 void __iomem *ioaddr = tp->mmio_addr;
3656 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3657
Francois Romieubcf0bf92006-07-26 23:14:13 +02003658 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
françois romieu4da19632011-01-03 15:07:55 +00003660 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003661 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 * A busy loop could burn quite a few cycles on nowadays CPU.
3663 * Let's delay the execution of the timer for a few ticks.
3664 */
3665 timeout = HZ/10;
3666 goto out_mod_timer;
3667 }
3668
3669 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003670 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671
Francois Romieuda78dbf2012-01-26 14:18:23 +01003672 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673
françois romieu4da19632011-01-03 15:07:55 +00003674 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675
3676out_mod_timer:
3677 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003678}
3679
3680static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3681{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003682 if (!test_and_set_bit(flag, tp->wk.flags))
3683 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003684}
3685
3686static void rtl8169_phy_timer(unsigned long __opaque)
3687{
3688 struct net_device *dev = (struct net_device *)__opaque;
3689 struct rtl8169_private *tp = netdev_priv(dev);
3690
Francois Romieu98ddf982012-01-31 10:47:34 +01003691 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692}
3693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3695 void __iomem *ioaddr)
3696{
3697 iounmap(ioaddr);
3698 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003699 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 pci_disable_device(pdev);
3701 free_netdev(dev);
3702}
3703
Francois Romieuffc46952012-07-06 14:19:23 +02003704DECLARE_RTL_COND(rtl_phy_reset_cond)
3705{
3706 return tp->phy_reset_pending(tp);
3707}
3708
Francois Romieubf793292006-11-01 00:53:05 +01003709static void rtl8169_phy_reset(struct net_device *dev,
3710 struct rtl8169_private *tp)
3711{
françois romieu4da19632011-01-03 15:07:55 +00003712 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003713 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003714}
3715
David S. Miller8decf862011-09-22 03:23:13 -04003716static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3717{
3718 void __iomem *ioaddr = tp->mmio_addr;
3719
3720 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3721 (RTL_R8(PHYstatus) & TBI_Enable);
3722}
3723
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003724static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003726 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003727
Francois Romieu5615d9f2007-08-17 17:50:46 +02003728 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003729
Marcus Sundberg773328942008-07-10 21:28:08 +02003730 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3731 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3732 RTL_W8(0x82, 0x01);
3733 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003734
Francois Romieu6dccd162007-02-13 23:38:05 +01003735 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3736
3737 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3738 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003739
Francois Romieubcf0bf92006-07-26 23:14:13 +02003740 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003741 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3742 RTL_W8(0x82, 0x01);
3743 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003744 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003745 }
3746
Francois Romieubf793292006-11-01 00:53:05 +01003747 rtl8169_phy_reset(dev, tp);
3748
Oliver Neukum54405cd2011-01-06 21:55:13 +01003749 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003750 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3751 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3752 (tp->mii.supports_gmii ?
3753 ADVERTISED_1000baseT_Half |
3754 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003755
David S. Miller8decf862011-09-22 03:23:13 -04003756 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003757 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003758}
3759
Francois Romieu773d2022007-01-31 23:47:43 +01003760static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3761{
3762 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003763
Francois Romieuda78dbf2012-01-26 14:18:23 +01003764 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003765
3766 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003767
françois romieu9ecb9aa2012-12-07 11:20:21 +00003768 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2b2010-04-26 11:42:58 +00003769 RTL_R32(MAC4);
3770
françois romieu9ecb9aa2012-12-07 11:20:21 +00003771 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2b2010-04-26 11:42:58 +00003772 RTL_R32(MAC0);
3773
françois romieu9ecb9aa2012-12-07 11:20:21 +00003774 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3775 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003776
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
Bill Pembertonbaf63292012-12-03 09:23:28 -05003837static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003838{
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) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003868 case RTL_GIGA_MAC_VER_25:
3869 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003870 case RTL_GIGA_MAC_VER_29:
3871 case RTL_GIGA_MAC_VER_30:
3872 case RTL_GIGA_MAC_VER_32:
3873 case RTL_GIGA_MAC_VER_33:
3874 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003875 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003876 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003877 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003878 case RTL_GIGA_MAC_VER_40:
3879 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003880 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3881 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3882 break;
3883 default:
3884 break;
3885 }
3886}
3887
3888static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3889{
3890 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3891 return false;
3892
3893 rtl_writephy(tp, 0x1f, 0x0000);
3894 rtl_writephy(tp, MII_BMCR, 0x0000);
3895
3896 rtl_wol_suspend_quirk(tp);
3897
3898 return true;
3899}
3900
françois romieu065c27c2011-01-03 15:08:12 +00003901static void r810x_phy_power_down(struct rtl8169_private *tp)
3902{
3903 rtl_writephy(tp, 0x1f, 0x0000);
3904 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3905}
3906
3907static void r810x_phy_power_up(struct rtl8169_private *tp)
3908{
3909 rtl_writephy(tp, 0x1f, 0x0000);
3910 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3911}
3912
3913static void r810x_pll_power_down(struct rtl8169_private *tp)
3914{
Hayes Wang00042992012-03-30 14:33:00 +08003915 void __iomem *ioaddr = tp->mmio_addr;
3916
David S. Miller1805b2f2011-10-24 18:18:09 -04003917 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003918 return;
françois romieu065c27c2011-01-03 15:08:12 +00003919
3920 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003921
3922 switch (tp->mac_version) {
3923 case RTL_GIGA_MAC_VER_07:
3924 case RTL_GIGA_MAC_VER_08:
3925 case RTL_GIGA_MAC_VER_09:
3926 case RTL_GIGA_MAC_VER_10:
3927 case RTL_GIGA_MAC_VER_13:
3928 case RTL_GIGA_MAC_VER_16:
3929 break;
3930 default:
3931 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3932 break;
3933 }
françois romieu065c27c2011-01-03 15:08:12 +00003934}
3935
3936static void r810x_pll_power_up(struct rtl8169_private *tp)
3937{
Hayes Wang00042992012-03-30 14:33:00 +08003938 void __iomem *ioaddr = tp->mmio_addr;
3939
françois romieu065c27c2011-01-03 15:08:12 +00003940 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003941
3942 switch (tp->mac_version) {
3943 case RTL_GIGA_MAC_VER_07:
3944 case RTL_GIGA_MAC_VER_08:
3945 case RTL_GIGA_MAC_VER_09:
3946 case RTL_GIGA_MAC_VER_10:
3947 case RTL_GIGA_MAC_VER_13:
3948 case RTL_GIGA_MAC_VER_16:
3949 break;
3950 default:
3951 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3952 break;
3953 }
françois romieu065c27c2011-01-03 15:08:12 +00003954}
3955
3956static void r8168_phy_power_up(struct rtl8169_private *tp)
3957{
3958 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003959 switch (tp->mac_version) {
3960 case RTL_GIGA_MAC_VER_11:
3961 case RTL_GIGA_MAC_VER_12:
3962 case RTL_GIGA_MAC_VER_17:
3963 case RTL_GIGA_MAC_VER_18:
3964 case RTL_GIGA_MAC_VER_19:
3965 case RTL_GIGA_MAC_VER_20:
3966 case RTL_GIGA_MAC_VER_21:
3967 case RTL_GIGA_MAC_VER_22:
3968 case RTL_GIGA_MAC_VER_23:
3969 case RTL_GIGA_MAC_VER_24:
3970 case RTL_GIGA_MAC_VER_25:
3971 case RTL_GIGA_MAC_VER_26:
3972 case RTL_GIGA_MAC_VER_27:
3973 case RTL_GIGA_MAC_VER_28:
3974 case RTL_GIGA_MAC_VER_31:
3975 rtl_writephy(tp, 0x0e, 0x0000);
3976 break;
3977 default:
3978 break;
3979 }
françois romieu065c27c2011-01-03 15:08:12 +00003980 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3981}
3982
3983static void r8168_phy_power_down(struct rtl8169_private *tp)
3984{
3985 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003986 switch (tp->mac_version) {
3987 case RTL_GIGA_MAC_VER_32:
3988 case RTL_GIGA_MAC_VER_33:
3989 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3990 break;
3991
3992 case RTL_GIGA_MAC_VER_11:
3993 case RTL_GIGA_MAC_VER_12:
3994 case RTL_GIGA_MAC_VER_17:
3995 case RTL_GIGA_MAC_VER_18:
3996 case RTL_GIGA_MAC_VER_19:
3997 case RTL_GIGA_MAC_VER_20:
3998 case RTL_GIGA_MAC_VER_21:
3999 case RTL_GIGA_MAC_VER_22:
4000 case RTL_GIGA_MAC_VER_23:
4001 case RTL_GIGA_MAC_VER_24:
4002 case RTL_GIGA_MAC_VER_25:
4003 case RTL_GIGA_MAC_VER_26:
4004 case RTL_GIGA_MAC_VER_27:
4005 case RTL_GIGA_MAC_VER_28:
4006 case RTL_GIGA_MAC_VER_31:
4007 rtl_writephy(tp, 0x0e, 0x0200);
4008 default:
4009 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4010 break;
4011 }
françois romieu065c27c2011-01-03 15:08:12 +00004012}
4013
4014static void r8168_pll_power_down(struct rtl8169_private *tp)
4015{
4016 void __iomem *ioaddr = tp->mmio_addr;
4017
Francois Romieucecb5fd2011-04-01 10:21:07 +02004018 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4019 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4020 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004021 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004022 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004023 }
françois romieu065c27c2011-01-03 15:08:12 +00004024
Francois Romieucecb5fd2011-04-01 10:21:07 +02004025 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4026 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004027 (RTL_R16(CPlusCmd) & ASF)) {
4028 return;
4029 }
4030
hayeswang01dc7fe2011-03-21 01:50:28 +00004031 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4032 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004033 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004034
David S. Miller1805b2f2011-10-24 18:18:09 -04004035 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004036 return;
françois romieu065c27c2011-01-03 15:08:12 +00004037
4038 r8168_phy_power_down(tp);
4039
4040 switch (tp->mac_version) {
4041 case RTL_GIGA_MAC_VER_25:
4042 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004043 case RTL_GIGA_MAC_VER_27:
4044 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004045 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004046 case RTL_GIGA_MAC_VER_32:
4047 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004048 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4049 break;
4050 }
4051}
4052
4053static void r8168_pll_power_up(struct rtl8169_private *tp)
4054{
4055 void __iomem *ioaddr = tp->mmio_addr;
4056
françois romieu065c27c2011-01-03 15:08:12 +00004057 switch (tp->mac_version) {
4058 case RTL_GIGA_MAC_VER_25:
4059 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004060 case RTL_GIGA_MAC_VER_27:
4061 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004062 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004063 case RTL_GIGA_MAC_VER_32:
4064 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004065 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4066 break;
4067 }
4068
4069 r8168_phy_power_up(tp);
4070}
4071
Francois Romieud58d46b2011-05-03 16:38:29 +02004072static void rtl_generic_op(struct rtl8169_private *tp,
4073 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004074{
4075 if (op)
4076 op(tp);
4077}
4078
4079static void rtl_pll_power_down(struct rtl8169_private *tp)
4080{
Francois Romieud58d46b2011-05-03 16:38:29 +02004081 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004082}
4083
4084static void rtl_pll_power_up(struct rtl8169_private *tp)
4085{
Francois Romieud58d46b2011-05-03 16:38:29 +02004086 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004087}
4088
Bill Pembertonbaf63292012-12-03 09:23:28 -05004089static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004090{
4091 struct pll_power_ops *ops = &tp->pll_power_ops;
4092
4093 switch (tp->mac_version) {
4094 case RTL_GIGA_MAC_VER_07:
4095 case RTL_GIGA_MAC_VER_08:
4096 case RTL_GIGA_MAC_VER_09:
4097 case RTL_GIGA_MAC_VER_10:
4098 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004099 case RTL_GIGA_MAC_VER_29:
4100 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004101 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004102 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004103 ops->down = r810x_pll_power_down;
4104 ops->up = r810x_pll_power_up;
4105 break;
4106
4107 case RTL_GIGA_MAC_VER_11:
4108 case RTL_GIGA_MAC_VER_12:
4109 case RTL_GIGA_MAC_VER_17:
4110 case RTL_GIGA_MAC_VER_18:
4111 case RTL_GIGA_MAC_VER_19:
4112 case RTL_GIGA_MAC_VER_20:
4113 case RTL_GIGA_MAC_VER_21:
4114 case RTL_GIGA_MAC_VER_22:
4115 case RTL_GIGA_MAC_VER_23:
4116 case RTL_GIGA_MAC_VER_24:
4117 case RTL_GIGA_MAC_VER_25:
4118 case RTL_GIGA_MAC_VER_26:
4119 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004120 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004121 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004122 case RTL_GIGA_MAC_VER_32:
4123 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004124 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004125 case RTL_GIGA_MAC_VER_35:
4126 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004127 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004128 case RTL_GIGA_MAC_VER_40:
4129 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004130 ops->down = r8168_pll_power_down;
4131 ops->up = r8168_pll_power_up;
4132 break;
4133
4134 default:
4135 ops->down = NULL;
4136 ops->up = NULL;
4137 break;
4138 }
4139}
4140
Hayes Wange542a222011-07-06 15:58:04 +08004141static void rtl_init_rxcfg(struct rtl8169_private *tp)
4142{
4143 void __iomem *ioaddr = tp->mmio_addr;
4144
4145 switch (tp->mac_version) {
4146 case RTL_GIGA_MAC_VER_01:
4147 case RTL_GIGA_MAC_VER_02:
4148 case RTL_GIGA_MAC_VER_03:
4149 case RTL_GIGA_MAC_VER_04:
4150 case RTL_GIGA_MAC_VER_05:
4151 case RTL_GIGA_MAC_VER_06:
4152 case RTL_GIGA_MAC_VER_10:
4153 case RTL_GIGA_MAC_VER_11:
4154 case RTL_GIGA_MAC_VER_12:
4155 case RTL_GIGA_MAC_VER_13:
4156 case RTL_GIGA_MAC_VER_14:
4157 case RTL_GIGA_MAC_VER_15:
4158 case RTL_GIGA_MAC_VER_16:
4159 case RTL_GIGA_MAC_VER_17:
4160 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4161 break;
4162 case RTL_GIGA_MAC_VER_18:
4163 case RTL_GIGA_MAC_VER_19:
4164 case RTL_GIGA_MAC_VER_20:
4165 case RTL_GIGA_MAC_VER_21:
4166 case RTL_GIGA_MAC_VER_22:
4167 case RTL_GIGA_MAC_VER_23:
4168 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004169 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004170 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4171 break;
4172 default:
4173 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4174 break;
4175 }
4176}
4177
Hayes Wang92fc43b2011-07-06 15:58:03 +08004178static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4179{
4180 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4181}
4182
Francois Romieud58d46b2011-05-03 16:38:29 +02004183static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4184{
françois romieu9c5028e2012-03-02 04:43:14 +00004185 void __iomem *ioaddr = tp->mmio_addr;
4186
4187 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004188 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004189 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004190}
4191
4192static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4193{
françois romieu9c5028e2012-03-02 04:43:14 +00004194 void __iomem *ioaddr = tp->mmio_addr;
4195
4196 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004197 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004198 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004199}
4200
4201static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4202{
4203 void __iomem *ioaddr = tp->mmio_addr;
4204
4205 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4206 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4207 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4208}
4209
4210static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4211{
4212 void __iomem *ioaddr = tp->mmio_addr;
4213
4214 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4215 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4216 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4217}
4218
4219static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4220{
4221 void __iomem *ioaddr = tp->mmio_addr;
4222
4223 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4224}
4225
4226static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4227{
4228 void __iomem *ioaddr = tp->mmio_addr;
4229
4230 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4231}
4232
4233static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4234{
4235 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004236
4237 RTL_W8(MaxTxPacketSize, 0x3f);
4238 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4239 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004240 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004241}
4242
4243static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4244{
4245 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004246
4247 RTL_W8(MaxTxPacketSize, 0x0c);
4248 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4249 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004250 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004251}
4252
4253static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4254{
4255 rtl_tx_performance_tweak(tp->pci_dev,
4256 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4257}
4258
4259static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4260{
4261 rtl_tx_performance_tweak(tp->pci_dev,
4262 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4263}
4264
4265static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4266{
4267 void __iomem *ioaddr = tp->mmio_addr;
4268
4269 r8168b_0_hw_jumbo_enable(tp);
4270
4271 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4272}
4273
4274static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4275{
4276 void __iomem *ioaddr = tp->mmio_addr;
4277
4278 r8168b_0_hw_jumbo_disable(tp);
4279
4280 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4281}
4282
Bill Pembertonbaf63292012-12-03 09:23:28 -05004283static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004284{
4285 struct jumbo_ops *ops = &tp->jumbo_ops;
4286
4287 switch (tp->mac_version) {
4288 case RTL_GIGA_MAC_VER_11:
4289 ops->disable = r8168b_0_hw_jumbo_disable;
4290 ops->enable = r8168b_0_hw_jumbo_enable;
4291 break;
4292 case RTL_GIGA_MAC_VER_12:
4293 case RTL_GIGA_MAC_VER_17:
4294 ops->disable = r8168b_1_hw_jumbo_disable;
4295 ops->enable = r8168b_1_hw_jumbo_enable;
4296 break;
4297 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4298 case RTL_GIGA_MAC_VER_19:
4299 case RTL_GIGA_MAC_VER_20:
4300 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4301 case RTL_GIGA_MAC_VER_22:
4302 case RTL_GIGA_MAC_VER_23:
4303 case RTL_GIGA_MAC_VER_24:
4304 case RTL_GIGA_MAC_VER_25:
4305 case RTL_GIGA_MAC_VER_26:
4306 ops->disable = r8168c_hw_jumbo_disable;
4307 ops->enable = r8168c_hw_jumbo_enable;
4308 break;
4309 case RTL_GIGA_MAC_VER_27:
4310 case RTL_GIGA_MAC_VER_28:
4311 ops->disable = r8168dp_hw_jumbo_disable;
4312 ops->enable = r8168dp_hw_jumbo_enable;
4313 break;
4314 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4315 case RTL_GIGA_MAC_VER_32:
4316 case RTL_GIGA_MAC_VER_33:
4317 case RTL_GIGA_MAC_VER_34:
4318 ops->disable = r8168e_hw_jumbo_disable;
4319 ops->enable = r8168e_hw_jumbo_enable;
4320 break;
4321
4322 /*
4323 * No action needed for jumbo frames with 8169.
4324 * No jumbo for 810x at all.
4325 */
Hayes Wangc5583862012-07-02 17:23:22 +08004326 case RTL_GIGA_MAC_VER_40:
4327 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004328 default:
4329 ops->disable = NULL;
4330 ops->enable = NULL;
4331 break;
4332 }
4333}
4334
Francois Romieuffc46952012-07-06 14:19:23 +02004335DECLARE_RTL_COND(rtl_chipcmd_cond)
4336{
4337 void __iomem *ioaddr = tp->mmio_addr;
4338
4339 return RTL_R8(ChipCmd) & CmdReset;
4340}
4341
Francois Romieu6f43adc2011-04-29 15:05:51 +02004342static void rtl_hw_reset(struct rtl8169_private *tp)
4343{
4344 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004345
Francois Romieu6f43adc2011-04-29 15:05:51 +02004346 RTL_W8(ChipCmd, CmdReset);
4347
Francois Romieuffc46952012-07-06 14:19:23 +02004348 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004349}
4350
Francois Romieub6ffd972011-06-17 17:00:05 +02004351static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4352{
4353 struct rtl_fw *rtl_fw;
4354 const char *name;
4355 int rc = -ENOMEM;
4356
4357 name = rtl_lookup_firmware_name(tp);
4358 if (!name)
4359 goto out_no_firmware;
4360
4361 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4362 if (!rtl_fw)
4363 goto err_warn;
4364
4365 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4366 if (rc < 0)
4367 goto err_free;
4368
Francois Romieufd112f22011-06-18 00:10:29 +02004369 rc = rtl_check_firmware(tp, rtl_fw);
4370 if (rc < 0)
4371 goto err_release_firmware;
4372
Francois Romieub6ffd972011-06-17 17:00:05 +02004373 tp->rtl_fw = rtl_fw;
4374out:
4375 return;
4376
Francois Romieufd112f22011-06-18 00:10:29 +02004377err_release_firmware:
4378 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004379err_free:
4380 kfree(rtl_fw);
4381err_warn:
4382 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4383 name, rc);
4384out_no_firmware:
4385 tp->rtl_fw = NULL;
4386 goto out;
4387}
4388
François Romieu953a12c2011-04-24 17:38:48 +02004389static void rtl_request_firmware(struct rtl8169_private *tp)
4390{
Francois Romieub6ffd972011-06-17 17:00:05 +02004391 if (IS_ERR(tp->rtl_fw))
4392 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004393}
4394
Hayes Wang92fc43b2011-07-06 15:58:03 +08004395static void rtl_rx_close(struct rtl8169_private *tp)
4396{
4397 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004398
Francois Romieu1687b562011-07-19 17:21:29 +02004399 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004400}
4401
Francois Romieuffc46952012-07-06 14:19:23 +02004402DECLARE_RTL_COND(rtl_npq_cond)
4403{
4404 void __iomem *ioaddr = tp->mmio_addr;
4405
4406 return RTL_R8(TxPoll) & NPQ;
4407}
4408
4409DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4410{
4411 void __iomem *ioaddr = tp->mmio_addr;
4412
4413 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4414}
4415
françois romieue6de30d2011-01-03 15:08:37 +00004416static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417{
françois romieue6de30d2011-01-03 15:08:37 +00004418 void __iomem *ioaddr = tp->mmio_addr;
4419
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004421 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Hayes Wang92fc43b2011-07-06 15:58:03 +08004423 rtl_rx_close(tp);
4424
Hayes Wang5d2e1952011-02-22 17:26:22 +08004425 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004426 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4427 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004428 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004429 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4430 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004431 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004432 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004433 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4434 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004435 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004436 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004437 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004438 } else {
4439 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4440 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004441 }
4442
Hayes Wang92fc43b2011-07-06 15:58:03 +08004443 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444}
4445
Francois Romieu7f796d832007-06-11 23:04:41 +02004446static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004447{
4448 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004449
4450 /* Set DMA burst size and Interframe Gap Time */
4451 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4452 (InterFrameGap << TxInterFrameGapShift));
4453}
4454
Francois Romieu07ce4062007-02-23 23:36:39 +01004455static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456{
4457 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458
Francois Romieu07ce4062007-02-23 23:36:39 +01004459 tp->hw_start(dev);
4460
Francois Romieuda78dbf2012-01-26 14:18:23 +01004461 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004462}
4463
Francois Romieu7f796d832007-06-11 23:04:41 +02004464static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4465 void __iomem *ioaddr)
4466{
4467 /*
4468 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4469 * register to be written before TxDescAddrLow to work.
4470 * Switching from MMIO to I/O access fixes the issue as well.
4471 */
4472 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004473 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004474 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004475 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004476}
4477
4478static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4479{
4480 u16 cmd;
4481
4482 cmd = RTL_R16(CPlusCmd);
4483 RTL_W16(CPlusCmd, cmd);
4484 return cmd;
4485}
4486
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004487static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004488{
4489 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e82009-10-26 10:52:37 +00004490 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004491}
4492
Francois Romieu6dccd162007-02-13 23:38:05 +01004493static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4494{
Francois Romieu37441002011-06-17 22:58:54 +02004495 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004496 u32 mac_version;
4497 u32 clk;
4498 u32 val;
4499 } cfg2_info [] = {
4500 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4501 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4502 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4503 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004504 };
4505 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004506 unsigned int i;
4507 u32 clk;
4508
4509 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004510 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004511 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4512 RTL_W32(0x7c, p->val);
4513 break;
4514 }
4515 }
4516}
4517
Francois Romieue6b763e2012-03-08 09:35:39 +01004518static void rtl_set_rx_mode(struct net_device *dev)
4519{
4520 struct rtl8169_private *tp = netdev_priv(dev);
4521 void __iomem *ioaddr = tp->mmio_addr;
4522 u32 mc_filter[2]; /* Multicast hash filter */
4523 int rx_mode;
4524 u32 tmp = 0;
4525
4526 if (dev->flags & IFF_PROMISC) {
4527 /* Unconditionally log net taps. */
4528 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4529 rx_mode =
4530 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4531 AcceptAllPhys;
4532 mc_filter[1] = mc_filter[0] = 0xffffffff;
4533 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4534 (dev->flags & IFF_ALLMULTI)) {
4535 /* Too many to filter perfectly -- accept all multicasts. */
4536 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4537 mc_filter[1] = mc_filter[0] = 0xffffffff;
4538 } else {
4539 struct netdev_hw_addr *ha;
4540
4541 rx_mode = AcceptBroadcast | AcceptMyPhys;
4542 mc_filter[1] = mc_filter[0] = 0;
4543 netdev_for_each_mc_addr(ha, dev) {
4544 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4545 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4546 rx_mode |= AcceptMulticast;
4547 }
4548 }
4549
4550 if (dev->features & NETIF_F_RXALL)
4551 rx_mode |= (AcceptErr | AcceptRunt);
4552
4553 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4554
4555 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4556 u32 data = mc_filter[0];
4557
4558 mc_filter[0] = swab32(mc_filter[1]);
4559 mc_filter[1] = swab32(data);
4560 }
4561
Nathan Walp04817762012-11-01 12:08:47 +00004562 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4563 mc_filter[1] = mc_filter[0] = 0xffffffff;
4564
Francois Romieue6b763e2012-03-08 09:35:39 +01004565 RTL_W32(MAR0 + 4, mc_filter[1]);
4566 RTL_W32(MAR0 + 0, mc_filter[0]);
4567
4568 RTL_W32(RxConfig, tmp);
4569}
4570
Francois Romieu07ce4062007-02-23 23:36:39 +01004571static void rtl_hw_start_8169(struct net_device *dev)
4572{
4573 struct rtl8169_private *tp = netdev_priv(dev);
4574 void __iomem *ioaddr = tp->mmio_addr;
4575 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004576
Francois Romieu9cb427b2006-11-02 00:10:16 +01004577 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4578 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4579 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4580 }
4581
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004583 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4584 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4585 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4586 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004587 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4588
Hayes Wange542a222011-07-06 15:58:04 +08004589 rtl_init_rxcfg(tp);
4590
françois romieuf0298f82011-01-03 15:07:42 +00004591 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004593 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
Francois Romieucecb5fd2011-04-01 10:21:07 +02004595 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4596 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4597 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4598 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004599 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600
Francois Romieu7f796d832007-06-11 23:04:41 +02004601 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004602
Francois Romieucecb5fd2011-04-01 10:21:07 +02004603 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4604 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004605 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004607 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 }
4609
Francois Romieubcf0bf92006-07-26 23:14:13 +02004610 RTL_W16(CPlusCmd, tp->cp_cmd);
4611
Francois Romieu6dccd162007-02-13 23:38:05 +01004612 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4613
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 /*
4615 * Undocumented corner. Supposedly:
4616 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4617 */
4618 RTL_W16(IntrMitigate, 0x0000);
4619
Francois Romieu7f796d832007-06-11 23:04:41 +02004620 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004621
Francois Romieucecb5fd2011-04-01 10:21:07 +02004622 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4623 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4624 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4625 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004626 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4627 rtl_set_rx_tx_config_registers(tp);
4628 }
4629
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004631
4632 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4633 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634
4635 RTL_W32(RxMissed, 0);
4636
Francois Romieu07ce4062007-02-23 23:36:39 +01004637 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638
4639 /* no early-rx interrupts */
4640 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004641}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004643static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4644{
4645 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004646 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004647}
4648
4649static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4650{
Francois Romieu52989f02012-07-06 13:37:00 +02004651 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004652}
4653
4654static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004655{
4656 u32 csi;
4657
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004658 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4659 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004660}
4661
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004662static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004663{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004664 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004665}
4666
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004667static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004668{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004669 rtl_csi_access_enable(tp, 0x27000000);
4670}
4671
Francois Romieuffc46952012-07-06 14:19:23 +02004672DECLARE_RTL_COND(rtl_csiar_cond)
4673{
4674 void __iomem *ioaddr = tp->mmio_addr;
4675
4676 return RTL_R32(CSIAR) & CSIAR_FLAG;
4677}
4678
Francois Romieu52989f02012-07-06 13:37:00 +02004679static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004680{
Francois Romieu52989f02012-07-06 13:37:00 +02004681 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004682
4683 RTL_W32(CSIDR, value);
4684 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4685 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4686
Francois Romieuffc46952012-07-06 14:19:23 +02004687 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004688}
4689
Francois Romieu52989f02012-07-06 13:37:00 +02004690static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004691{
Francois Romieu52989f02012-07-06 13:37:00 +02004692 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004693
4694 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4695 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4696
Francois Romieuffc46952012-07-06 14:19:23 +02004697 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4698 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004699}
4700
Francois Romieu52989f02012-07-06 13:37:00 +02004701static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004702{
Francois Romieu52989f02012-07-06 13:37:00 +02004703 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004704
4705 RTL_W32(CSIDR, value);
4706 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4707 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4708 CSIAR_FUNC_NIC);
4709
Francois Romieuffc46952012-07-06 14:19:23 +02004710 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004711}
4712
Francois Romieu52989f02012-07-06 13:37:00 +02004713static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004714{
Francois Romieu52989f02012-07-06 13:37:00 +02004715 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004716
4717 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4718 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4719
Francois Romieuffc46952012-07-06 14:19:23 +02004720 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4721 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004722}
4723
Bill Pembertonbaf63292012-12-03 09:23:28 -05004724static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004725{
4726 struct csi_ops *ops = &tp->csi_ops;
4727
4728 switch (tp->mac_version) {
4729 case RTL_GIGA_MAC_VER_01:
4730 case RTL_GIGA_MAC_VER_02:
4731 case RTL_GIGA_MAC_VER_03:
4732 case RTL_GIGA_MAC_VER_04:
4733 case RTL_GIGA_MAC_VER_05:
4734 case RTL_GIGA_MAC_VER_06:
4735 case RTL_GIGA_MAC_VER_10:
4736 case RTL_GIGA_MAC_VER_11:
4737 case RTL_GIGA_MAC_VER_12:
4738 case RTL_GIGA_MAC_VER_13:
4739 case RTL_GIGA_MAC_VER_14:
4740 case RTL_GIGA_MAC_VER_15:
4741 case RTL_GIGA_MAC_VER_16:
4742 case RTL_GIGA_MAC_VER_17:
4743 ops->write = NULL;
4744 ops->read = NULL;
4745 break;
4746
Hayes Wang7e18dca2012-03-30 14:33:02 +08004747 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004748 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004749 ops->write = r8402_csi_write;
4750 ops->read = r8402_csi_read;
4751 break;
4752
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004753 default:
4754 ops->write = r8169_csi_write;
4755 ops->read = r8169_csi_read;
4756 break;
4757 }
Francois Romieudacf8152008-08-02 20:44:13 +02004758}
4759
4760struct ephy_info {
4761 unsigned int offset;
4762 u16 mask;
4763 u16 bits;
4764};
4765
Francois Romieufdf6fc02012-07-06 22:40:38 +02004766static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4767 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004768{
4769 u16 w;
4770
4771 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004772 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4773 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004774 e++;
4775 }
4776}
4777
Francois Romieub726e492008-06-28 12:22:59 +02004778static void rtl_disable_clock_request(struct pci_dev *pdev)
4779{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004780 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4781 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004782}
4783
françois romieue6de30d2011-01-03 15:08:37 +00004784static void rtl_enable_clock_request(struct pci_dev *pdev)
4785{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004786 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4787 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004788}
4789
Francois Romieub726e492008-06-28 12:22:59 +02004790#define R8168_CPCMD_QUIRK_MASK (\
4791 EnableBist | \
4792 Mac_dbgo_oe | \
4793 Force_half_dup | \
4794 Force_rxflow_en | \
4795 Force_txflow_en | \
4796 Cxpl_dbg_sel | \
4797 ASF | \
4798 PktCntrDisable | \
4799 Mac_dbgo_sel)
4800
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004801static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004802{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004803 void __iomem *ioaddr = tp->mmio_addr;
4804 struct pci_dev *pdev = tp->pci_dev;
4805
Francois Romieub726e492008-06-28 12:22:59 +02004806 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4807
4808 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4809
Francois Romieu2e68ae42008-06-28 12:00:55 +02004810 rtl_tx_performance_tweak(pdev,
4811 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004812}
4813
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004814static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004815{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004816 void __iomem *ioaddr = tp->mmio_addr;
4817
4818 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004819
françois romieuf0298f82011-01-03 15:07:42 +00004820 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004821
4822 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004823}
4824
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004825static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004826{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004827 void __iomem *ioaddr = tp->mmio_addr;
4828 struct pci_dev *pdev = tp->pci_dev;
4829
Francois Romieub726e492008-06-28 12:22:59 +02004830 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4831
4832 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4833
Francois Romieu219a1e92008-06-28 11:58:39 +02004834 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004835
4836 rtl_disable_clock_request(pdev);
4837
4838 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004839}
4840
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004841static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004842{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004843 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004844 { 0x01, 0, 0x0001 },
4845 { 0x02, 0x0800, 0x1000 },
4846 { 0x03, 0, 0x0042 },
4847 { 0x06, 0x0080, 0x0000 },
4848 { 0x07, 0, 0x2000 }
4849 };
4850
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004851 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004852
Francois Romieufdf6fc02012-07-06 22:40:38 +02004853 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004854
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004855 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004856}
4857
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004858static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004859{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004860 void __iomem *ioaddr = tp->mmio_addr;
4861 struct pci_dev *pdev = tp->pci_dev;
4862
4863 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004864
4865 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4866
4867 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4868
4869 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4870}
4871
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004872static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004873{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004874 void __iomem *ioaddr = tp->mmio_addr;
4875 struct pci_dev *pdev = tp->pci_dev;
4876
4877 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004878
4879 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4880
4881 /* Magic. */
4882 RTL_W8(DBG_REG, 0x20);
4883
françois romieuf0298f82011-01-03 15:07:42 +00004884 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004885
4886 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4887
4888 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4889}
4890
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004891static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004892{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004893 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004894 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004895 { 0x02, 0x0800, 0x1000 },
4896 { 0x03, 0, 0x0002 },
4897 { 0x06, 0x0080, 0x0000 }
4898 };
4899
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004900 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004901
4902 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4903
Francois Romieufdf6fc02012-07-06 22:40:38 +02004904 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004905
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004906 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004907}
4908
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004909static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004910{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004911 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004912 { 0x01, 0, 0x0001 },
4913 { 0x03, 0x0400, 0x0220 }
4914 };
4915
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004916 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004917
Francois Romieufdf6fc02012-07-06 22:40:38 +02004918 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004919
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004920 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004921}
4922
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004923static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004924{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004925 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004926}
4927
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004928static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004929{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004930 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004931
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004932 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004933}
4934
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004935static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004936{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004937 void __iomem *ioaddr = tp->mmio_addr;
4938 struct pci_dev *pdev = tp->pci_dev;
4939
4940 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004941
4942 rtl_disable_clock_request(pdev);
4943
françois romieuf0298f82011-01-03 15:07:42 +00004944 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004945
4946 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4947
4948 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4949}
4950
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004951static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004952{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004953 void __iomem *ioaddr = tp->mmio_addr;
4954 struct pci_dev *pdev = tp->pci_dev;
4955
4956 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004957
4958 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4959
4960 RTL_W8(MaxTxPacketSize, TxPacketMax);
4961
4962 rtl_disable_clock_request(pdev);
4963}
4964
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004965static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004966{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004967 void __iomem *ioaddr = tp->mmio_addr;
4968 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004969 static const struct ephy_info e_info_8168d_4[] = {
4970 { 0x0b, ~0, 0x48 },
4971 { 0x19, 0x20, 0x50 },
4972 { 0x0c, ~0, 0x20 }
4973 };
4974 int i;
4975
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004976 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004977
4978 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4979
4980 RTL_W8(MaxTxPacketSize, TxPacketMax);
4981
4982 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4983 const struct ephy_info *e = e_info_8168d_4 + i;
4984 u16 w;
4985
Francois Romieufdf6fc02012-07-06 22:40:38 +02004986 w = rtl_ephy_read(tp, e->offset);
4987 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004988 }
4989
4990 rtl_enable_clock_request(pdev);
4991}
4992
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004993static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004994{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004995 void __iomem *ioaddr = tp->mmio_addr;
4996 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004997 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004998 { 0x00, 0x0200, 0x0100 },
4999 { 0x00, 0x0000, 0x0004 },
5000 { 0x06, 0x0002, 0x0001 },
5001 { 0x06, 0x0000, 0x0030 },
5002 { 0x07, 0x0000, 0x2000 },
5003 { 0x00, 0x0000, 0x0020 },
5004 { 0x03, 0x5800, 0x2000 },
5005 { 0x03, 0x0000, 0x0001 },
5006 { 0x01, 0x0800, 0x1000 },
5007 { 0x07, 0x0000, 0x4000 },
5008 { 0x1e, 0x0000, 0x2000 },
5009 { 0x19, 0xffff, 0xfe6c },
5010 { 0x0a, 0x0000, 0x0040 }
5011 };
5012
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005013 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005014
Francois Romieufdf6fc02012-07-06 22:40:38 +02005015 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005016
5017 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5018
5019 RTL_W8(MaxTxPacketSize, TxPacketMax);
5020
5021 rtl_disable_clock_request(pdev);
5022
5023 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005024 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5025 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005026
Francois Romieucecb5fd2011-04-01 10:21:07 +02005027 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005028}
5029
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005030static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005031{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005032 void __iomem *ioaddr = tp->mmio_addr;
5033 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005034 static const struct ephy_info e_info_8168e_2[] = {
5035 { 0x09, 0x0000, 0x0080 },
5036 { 0x19, 0x0000, 0x0224 }
5037 };
5038
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005039 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005040
Francois Romieufdf6fc02012-07-06 22:40:38 +02005041 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005042
5043 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5044
Francois Romieufdf6fc02012-07-06 22:40:38 +02005045 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5046 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5047 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5048 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5049 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5050 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5051 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5052 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005053
Hayes Wang3090bd92011-09-06 16:55:15 +08005054 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005055
Hayes Wang70090422011-07-06 15:58:06 +08005056 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5057 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5058
5059 /* Adjust EEE LED frequency */
5060 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5061
5062 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5063 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005064 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5065 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005066}
5067
Hayes Wang5f886e02012-03-30 14:33:03 +08005068static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005069{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005070 void __iomem *ioaddr = tp->mmio_addr;
5071 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005072
Hayes Wang5f886e02012-03-30 14:33:03 +08005073 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005074
5075 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5076
Francois Romieufdf6fc02012-07-06 22:40:38 +02005077 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5078 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5079 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5080 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5081 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5082 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5083 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5084 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5085 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5086 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005087
5088 RTL_W8(MaxTxPacketSize, EarlySize);
5089
Hayes Wangc2218922011-09-06 16:55:18 +08005090 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5091 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005092 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005093 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5094 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5095 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005096}
5097
Hayes Wang5f886e02012-03-30 14:33:03 +08005098static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5099{
5100 void __iomem *ioaddr = tp->mmio_addr;
5101 static const struct ephy_info e_info_8168f_1[] = {
5102 { 0x06, 0x00c0, 0x0020 },
5103 { 0x08, 0x0001, 0x0002 },
5104 { 0x09, 0x0000, 0x0080 },
5105 { 0x19, 0x0000, 0x0224 }
5106 };
5107
5108 rtl_hw_start_8168f(tp);
5109
Francois Romieufdf6fc02012-07-06 22:40:38 +02005110 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005111
Francois Romieufdf6fc02012-07-06 22:40:38 +02005112 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005113
5114 /* Adjust EEE LED frequency */
5115 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5116}
5117
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005118static void rtl_hw_start_8411(struct rtl8169_private *tp)
5119{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005120 static const struct ephy_info e_info_8168f_1[] = {
5121 { 0x06, 0x00c0, 0x0020 },
5122 { 0x0f, 0xffff, 0x5200 },
5123 { 0x1e, 0x0000, 0x4000 },
5124 { 0x19, 0x0000, 0x0224 }
5125 };
5126
5127 rtl_hw_start_8168f(tp);
5128
Francois Romieufdf6fc02012-07-06 22:40:38 +02005129 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005130
Francois Romieufdf6fc02012-07-06 22:40:38 +02005131 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005132}
5133
Hayes Wangc5583862012-07-02 17:23:22 +08005134static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5135{
5136 void __iomem *ioaddr = tp->mmio_addr;
5137 struct pci_dev *pdev = tp->pci_dev;
5138
5139 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5140 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5141 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5142 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5143
5144 rtl_csi_access_enable_1(tp);
5145
5146 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5147
5148 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5149 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5150
5151 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005152 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005153 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005154 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5155 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005156
5157 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5158 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5159
5160 /* Adjust EEE LED frequency */
5161 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5162
5163 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5164}
5165
Francois Romieu07ce4062007-02-23 23:36:39 +01005166static void rtl_hw_start_8168(struct net_device *dev)
5167{
Francois Romieu2dd99532007-06-11 23:22:52 +02005168 struct rtl8169_private *tp = netdev_priv(dev);
5169 void __iomem *ioaddr = tp->mmio_addr;
5170
5171 RTL_W8(Cfg9346, Cfg9346_Unlock);
5172
françois romieuf0298f82011-01-03 15:07:42 +00005173 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005174
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005175 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005176
Francois Romieu0e485152007-02-20 00:00:26 +01005177 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005178
5179 RTL_W16(CPlusCmd, tp->cp_cmd);
5180
Francois Romieu0e485152007-02-20 00:00:26 +01005181 RTL_W16(IntrMitigate, 0x5151);
5182
5183 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005184 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005185 tp->event_slow |= RxFIFOOver | PCSTimeout;
5186 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005187 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005188
5189 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5190
Francois Romieub8363902008-06-01 12:31:57 +02005191 rtl_set_rx_mode(dev);
5192
5193 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5194 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005195
5196 RTL_R8(IntrMask);
5197
Francois Romieu219a1e92008-06-28 11:58:39 +02005198 switch (tp->mac_version) {
5199 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005200 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005201 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005202
5203 case RTL_GIGA_MAC_VER_12:
5204 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005205 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005206 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005207
5208 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005209 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005210 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005211
5212 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005213 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005214 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005215
5216 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005217 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005218 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005219
Francois Romieu197ff762008-06-28 13:16:02 +02005220 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005221 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005222 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005223
Francois Romieu6fb07052008-06-29 11:54:28 +02005224 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005225 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005226 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005227
Francois Romieuef3386f2008-06-29 12:24:30 +02005228 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005229 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005230 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005231
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005232 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005233 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005234 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005235
Francois Romieu5b538df2008-07-20 16:22:45 +02005236 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005237 case RTL_GIGA_MAC_VER_26:
5238 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005239 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005240 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005241
françois romieue6de30d2011-01-03 15:08:37 +00005242 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005243 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005244 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005245
hayeswang4804b3b2011-03-21 01:50:29 +00005246 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005247 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005248 break;
5249
hayeswang01dc7fe2011-03-21 01:50:28 +00005250 case RTL_GIGA_MAC_VER_32:
5251 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005252 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005253 break;
5254 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005255 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005256 break;
françois romieue6de30d2011-01-03 15:08:37 +00005257
Hayes Wangc2218922011-09-06 16:55:18 +08005258 case RTL_GIGA_MAC_VER_35:
5259 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005260 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005261 break;
5262
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005263 case RTL_GIGA_MAC_VER_38:
5264 rtl_hw_start_8411(tp);
5265 break;
5266
Hayes Wangc5583862012-07-02 17:23:22 +08005267 case RTL_GIGA_MAC_VER_40:
5268 case RTL_GIGA_MAC_VER_41:
5269 rtl_hw_start_8168g_1(tp);
5270 break;
5271
Francois Romieu219a1e92008-06-28 11:58:39 +02005272 default:
5273 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5274 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005275 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005276 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005277
Francois Romieu0e485152007-02-20 00:00:26 +01005278 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5279
Francois Romieub8363902008-06-01 12:31:57 +02005280 RTL_W8(Cfg9346, Cfg9346_Lock);
5281
Francois Romieu2dd99532007-06-11 23:22:52 +02005282 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005283}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284
Francois Romieu2857ffb2008-08-02 21:08:49 +02005285#define R810X_CPCMD_QUIRK_MASK (\
5286 EnableBist | \
5287 Mac_dbgo_oe | \
5288 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005289 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005290 Force_txflow_en | \
5291 Cxpl_dbg_sel | \
5292 ASF | \
5293 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005294 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005295
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005296static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005297{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005298 void __iomem *ioaddr = tp->mmio_addr;
5299 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005300 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005301 { 0x01, 0, 0x6e65 },
5302 { 0x02, 0, 0x091f },
5303 { 0x03, 0, 0xc2f9 },
5304 { 0x06, 0, 0xafb5 },
5305 { 0x07, 0, 0x0e00 },
5306 { 0x19, 0, 0xec80 },
5307 { 0x01, 0, 0x2e65 },
5308 { 0x01, 0, 0x6e65 }
5309 };
5310 u8 cfg1;
5311
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005312 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005313
5314 RTL_W8(DBG_REG, FIX_NAK_1);
5315
5316 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5317
5318 RTL_W8(Config1,
5319 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5320 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5321
5322 cfg1 = RTL_R8(Config1);
5323 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5324 RTL_W8(Config1, cfg1 & ~LEDS0);
5325
Francois Romieufdf6fc02012-07-06 22:40:38 +02005326 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005327}
5328
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005329static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005330{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005331 void __iomem *ioaddr = tp->mmio_addr;
5332 struct pci_dev *pdev = tp->pci_dev;
5333
5334 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005335
5336 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5337
5338 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5339 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005340}
5341
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005342static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005343{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005344 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005345
Francois Romieufdf6fc02012-07-06 22:40:38 +02005346 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005347}
5348
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005349static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005350{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005351 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005352 static const struct ephy_info e_info_8105e_1[] = {
5353 { 0x07, 0, 0x4000 },
5354 { 0x19, 0, 0x0200 },
5355 { 0x19, 0, 0x0020 },
5356 { 0x1e, 0, 0x2000 },
5357 { 0x03, 0, 0x0001 },
5358 { 0x19, 0, 0x0100 },
5359 { 0x19, 0, 0x0004 },
5360 { 0x0a, 0, 0x0020 }
5361 };
5362
Francois Romieucecb5fd2011-04-01 10:21:07 +02005363 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005364 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5365
Francois Romieucecb5fd2011-04-01 10:21:07 +02005366 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005367 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5368
5369 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e2011-07-06 15:58:02 +08005370 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005371 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5372 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5373 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005374
Francois Romieufdf6fc02012-07-06 22:40:38 +02005375 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005376}
5377
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005378static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005379{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005380 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005381 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005382}
5383
Hayes Wang7e18dca2012-03-30 14:33:02 +08005384static void rtl_hw_start_8402(struct rtl8169_private *tp)
5385{
5386 void __iomem *ioaddr = tp->mmio_addr;
5387 static const struct ephy_info e_info_8402[] = {
5388 { 0x19, 0xffff, 0xff64 },
5389 { 0x1e, 0, 0x4000 }
5390 };
5391
5392 rtl_csi_access_enable_2(tp);
5393
5394 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5395 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5396
5397 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5398 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005399 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5400 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5401 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005402
Francois Romieufdf6fc02012-07-06 22:40:38 +02005403 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005404
5405 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5406
Francois Romieufdf6fc02012-07-06 22:40:38 +02005407 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5408 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5409 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5410 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5411 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5412 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5413 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005414}
5415
Hayes Wang5598bfe2012-07-02 17:23:21 +08005416static void rtl_hw_start_8106(struct rtl8169_private *tp)
5417{
5418 void __iomem *ioaddr = tp->mmio_addr;
5419
5420 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5421 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5422
hayeswangd64ec842012-11-01 16:46:28 +00005423 RTL_W32(MISC,
5424 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5425 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5426 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005427 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5428 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5429}
5430
Francois Romieu07ce4062007-02-23 23:36:39 +01005431static void rtl_hw_start_8101(struct net_device *dev)
5432{
Francois Romieucdf1a602007-06-11 23:29:50 +02005433 struct rtl8169_private *tp = netdev_priv(dev);
5434 void __iomem *ioaddr = tp->mmio_addr;
5435 struct pci_dev *pdev = tp->pci_dev;
5436
Francois Romieuda78dbf2012-01-26 14:18:23 +01005437 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5438 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005439
Francois Romieucecb5fd2011-04-01 10:21:07 +02005440 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005441 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005442 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5443 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005444
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005445 RTL_W8(Cfg9346, Cfg9346_Unlock);
5446
Francois Romieu2857ffb2008-08-02 21:08:49 +02005447 switch (tp->mac_version) {
5448 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005449 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005450 break;
5451
5452 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005453 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005454 break;
5455
5456 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005457 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005458 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005459
5460 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005461 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005462 break;
5463 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005464 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005465 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005466
5467 case RTL_GIGA_MAC_VER_37:
5468 rtl_hw_start_8402(tp);
5469 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005470
5471 case RTL_GIGA_MAC_VER_39:
5472 rtl_hw_start_8106(tp);
5473 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005474 }
5475
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005476 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005477
françois romieuf0298f82011-01-03 15:07:42 +00005478 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005479
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005480 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005481
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005482 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005483 RTL_W16(CPlusCmd, tp->cp_cmd);
5484
5485 RTL_W16(IntrMitigate, 0x0000);
5486
5487 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5488
5489 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5490 rtl_set_rx_tx_config_registers(tp);
5491
Francois Romieucdf1a602007-06-11 23:29:50 +02005492 RTL_R8(IntrMask);
5493
Francois Romieucdf1a602007-06-11 23:29:50 +02005494 rtl_set_rx_mode(dev);
5495
5496 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497}
5498
5499static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5500{
Francois Romieud58d46b2011-05-03 16:38:29 +02005501 struct rtl8169_private *tp = netdev_priv(dev);
5502
5503 if (new_mtu < ETH_ZLEN ||
5504 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505 return -EINVAL;
5506
Francois Romieud58d46b2011-05-03 16:38:29 +02005507 if (new_mtu > ETH_DATA_LEN)
5508 rtl_hw_jumbo_enable(tp);
5509 else
5510 rtl_hw_jumbo_disable(tp);
5511
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005513 netdev_update_features(dev);
5514
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005515 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516}
5517
5518static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5519{
Al Viro95e09182007-12-22 18:55:39 +00005520 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5522}
5523
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005524static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5525 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005527 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005528 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005529
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005530 kfree(*data_buff);
5531 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532 rtl8169_make_unusable_by_asic(desc);
5533}
5534
5535static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5536{
5537 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5538
5539 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5540}
5541
5542static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5543 u32 rx_buf_sz)
5544{
5545 desc->addr = cpu_to_le64(mapping);
5546 wmb();
5547 rtl8169_mark_to_asic(desc, rx_buf_sz);
5548}
5549
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005550static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005551{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005552 return (void *)ALIGN((long)data, 16);
5553}
5554
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005555static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5556 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005557{
5558 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005560 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005561 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005562 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005564 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5565 if (!data)
5566 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005567
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005568 if (rtl8169_align(data) != data) {
5569 kfree(data);
5570 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5571 if (!data)
5572 return NULL;
5573 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005574
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005575 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005576 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005577 if (unlikely(dma_mapping_error(d, mapping))) {
5578 if (net_ratelimit())
5579 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005580 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582
5583 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005584 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005585
5586err_out:
5587 kfree(data);
5588 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589}
5590
5591static void rtl8169_rx_clear(struct rtl8169_private *tp)
5592{
Francois Romieu07d3f512007-02-21 22:40:46 +01005593 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594
5595 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005596 if (tp->Rx_databuff[i]) {
5597 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598 tp->RxDescArray + i);
5599 }
5600 }
5601}
5602
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005603static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005604{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005605 desc->opts1 |= cpu_to_le32(RingEnd);
5606}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005607
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005608static int rtl8169_rx_fill(struct rtl8169_private *tp)
5609{
5610 unsigned int i;
5611
5612 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005613 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005614
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005615 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005617
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005618 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005619 if (!data) {
5620 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005621 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005622 }
5623 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005626 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5627 return 0;
5628
5629err_out:
5630 rtl8169_rx_clear(tp);
5631 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005632}
5633
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634static int rtl8169_init_ring(struct net_device *dev)
5635{
5636 struct rtl8169_private *tp = netdev_priv(dev);
5637
5638 rtl8169_init_ring_indexes(tp);
5639
5640 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005641 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005643 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644}
5645
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005646static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647 struct TxDesc *desc)
5648{
5649 unsigned int len = tx_skb->len;
5650
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005651 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5652
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653 desc->opts1 = 0x00;
5654 desc->opts2 = 0x00;
5655 desc->addr = 0x00;
5656 tx_skb->len = 0;
5657}
5658
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005659static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5660 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661{
5662 unsigned int i;
5663
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005664 for (i = 0; i < n; i++) {
5665 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666 struct ring_info *tx_skb = tp->tx_skb + entry;
5667 unsigned int len = tx_skb->len;
5668
5669 if (len) {
5670 struct sk_buff *skb = tx_skb->skb;
5671
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005672 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673 tp->TxDescArray + entry);
5674 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005675 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005676 dev_kfree_skb(skb);
5677 tx_skb->skb = NULL;
5678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679 }
5680 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005681}
5682
5683static void rtl8169_tx_clear(struct rtl8169_private *tp)
5684{
5685 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686 tp->cur_tx = tp->dirty_tx = 0;
5687}
5688
Francois Romieu4422bcd2012-01-26 11:23:32 +01005689static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690{
David Howellsc4028952006-11-22 14:57:56 +00005691 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005692 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693
Francois Romieuda78dbf2012-01-26 14:18:23 +01005694 napi_disable(&tp->napi);
5695 netif_stop_queue(dev);
5696 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697
françois romieuc7c2c392011-12-04 20:30:52 +00005698 rtl8169_hw_reset(tp);
5699
Francois Romieu56de4142011-03-15 17:29:31 +01005700 for (i = 0; i < NUM_RX_DESC; i++)
5701 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5702
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005704 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
Francois Romieuda78dbf2012-01-26 14:18:23 +01005706 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005707 rtl_hw_start(dev);
5708 netif_wake_queue(dev);
5709 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710}
5711
5712static void rtl8169_tx_timeout(struct net_device *dev)
5713{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005714 struct rtl8169_private *tp = netdev_priv(dev);
5715
5716 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717}
5718
5719static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005720 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721{
5722 struct skb_shared_info *info = skb_shinfo(skb);
5723 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005724 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005725 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726
5727 entry = tp->cur_tx;
5728 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005729 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730 dma_addr_t mapping;
5731 u32 status, len;
5732 void *addr;
5733
5734 entry = (entry + 1) % NUM_TX_DESC;
5735
5736 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005737 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005738 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005739 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005740 if (unlikely(dma_mapping_error(d, mapping))) {
5741 if (net_ratelimit())
5742 netif_err(tp, drv, tp->dev,
5743 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005744 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005745 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746
Francois Romieucecb5fd2011-04-01 10:21:07 +02005747 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005748 status = opts[0] | len |
5749 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750
5751 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005752 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753 txd->addr = cpu_to_le64(mapping);
5754
5755 tp->tx_skb[entry].len = len;
5756 }
5757
5758 if (cur_frag) {
5759 tp->tx_skb[entry].skb = skb;
5760 txd->opts1 |= cpu_to_le32(LastFrag);
5761 }
5762
5763 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005764
5765err_out:
5766 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5767 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768}
5769
Francois Romieu2b7b4312011-04-18 22:53:24 -07005770static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5771 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005773 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005774 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005775 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776
Francois Romieu2b7b4312011-04-18 22:53:24 -07005777 if (mss) {
5778 opts[0] |= TD_LSO;
5779 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5780 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005781 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005782
5783 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005784 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005786 opts[offset] |= info->checksum.udp;
5787 else
5788 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005790}
5791
Stephen Hemminger613573252009-08-31 19:50:58 +00005792static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5793 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794{
5795 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005796 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797 struct TxDesc *txd = tp->TxDescArray + entry;
5798 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005799 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800 dma_addr_t mapping;
5801 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005802 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005803 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005804
Julien Ducourthial477206a2012-05-09 00:00:06 +02005805 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005806 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005807 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808 }
5809
5810 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005811 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005813 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005814 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005815 if (unlikely(dma_mapping_error(d, mapping))) {
5816 if (net_ratelimit())
5817 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005818 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820
5821 tp->tx_skb[entry].len = len;
5822 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823
Kirill Smelkov810f4892012-11-10 21:11:02 +04005824 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005825 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005826
Francois Romieu2b7b4312011-04-18 22:53:24 -07005827 rtl8169_tso_csum(tp, skb, opts);
5828
5829 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005830 if (frags < 0)
5831 goto err_dma_1;
5832 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005833 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005834 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005835 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005836 tp->tx_skb[entry].skb = skb;
5837 }
5838
Francois Romieu2b7b4312011-04-18 22:53:24 -07005839 txd->opts2 = cpu_to_le32(opts[1]);
5840
Richard Cochran5047fb52012-03-10 07:29:42 +00005841 skb_tx_timestamp(skb);
5842
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843 wmb();
5844
Francois Romieucecb5fd2011-04-01 10:21:07 +02005845 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005846 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847 txd->opts1 = cpu_to_le32(status);
5848
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849 tp->cur_tx += frags + 1;
5850
David Dillow4c020a92010-03-03 16:33:10 +00005851 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852
Francois Romieucecb5fd2011-04-01 10:21:07 +02005853 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
Francois Romieuda78dbf2012-01-26 14:18:23 +01005855 mmiowb();
5856
Julien Ducourthial477206a2012-05-09 00:00:06 +02005857 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005858 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5859 * not miss a ring update when it notices a stopped queue.
5860 */
5861 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005863 /* Sync with rtl_tx:
5864 * - publish queue status and cur_tx ring index (write barrier)
5865 * - refresh dirty_tx ring index (read barrier).
5866 * May the current thread have a pessimistic view of the ring
5867 * status and forget to wake up queue, a racing rtl_tx thread
5868 * can't.
5869 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005870 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005871 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872 netif_wake_queue(dev);
5873 }
5874
Stephen Hemminger613573252009-08-31 19:50:58 +00005875 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005877err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005878 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005879err_dma_0:
5880 dev_kfree_skb(skb);
5881 dev->stats.tx_dropped++;
5882 return NETDEV_TX_OK;
5883
5884err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005886 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005887 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888}
5889
5890static void rtl8169_pcierr_interrupt(struct net_device *dev)
5891{
5892 struct rtl8169_private *tp = netdev_priv(dev);
5893 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894 u16 pci_status, pci_cmd;
5895
5896 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5897 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5898
Joe Perchesbf82c182010-02-09 11:49:50 +00005899 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5900 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901
5902 /*
5903 * The recovery sequence below admits a very elaborated explanation:
5904 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005905 * - I did not see what else could be done;
5906 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907 *
5908 * Feel free to adjust to your needs.
5909 */
Francois Romieua27993f2006-12-18 00:04:19 +01005910 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005911 pci_cmd &= ~PCI_COMMAND_PARITY;
5912 else
5913 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5914
5915 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916
5917 pci_write_config_word(pdev, PCI_STATUS,
5918 pci_status & (PCI_STATUS_DETECTED_PARITY |
5919 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5920 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5921
5922 /* The infamous DAC f*ckup only happens at boot time */
5923 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005924 void __iomem *ioaddr = tp->mmio_addr;
5925
Joe Perchesbf82c182010-02-09 11:49:50 +00005926 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927 tp->cp_cmd &= ~PCIDAC;
5928 RTL_W16(CPlusCmd, tp->cp_cmd);
5929 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930 }
5931
françois romieue6de30d2011-01-03 15:08:37 +00005932 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005933
Francois Romieu98ddf982012-01-31 10:47:34 +01005934 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935}
5936
Francois Romieuda78dbf2012-01-26 14:18:23 +01005937static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005938{
5939 unsigned int dirty_tx, tx_left;
5940
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941 dirty_tx = tp->dirty_tx;
5942 smp_rmb();
5943 tx_left = tp->cur_tx - dirty_tx;
5944
5945 while (tx_left > 0) {
5946 unsigned int entry = dirty_tx % NUM_TX_DESC;
5947 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948 u32 status;
5949
5950 rmb();
5951 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5952 if (status & DescOwn)
5953 break;
5954
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005955 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5956 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005958 u64_stats_update_begin(&tp->tx_stats.syncp);
5959 tp->tx_stats.packets++;
5960 tp->tx_stats.bytes += tx_skb->skb->len;
5961 u64_stats_update_end(&tp->tx_stats.syncp);
5962 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963 tx_skb->skb = NULL;
5964 }
5965 dirty_tx++;
5966 tx_left--;
5967 }
5968
5969 if (tp->dirty_tx != dirty_tx) {
5970 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005971 /* Sync with rtl8169_start_xmit:
5972 * - publish dirty_tx ring index (write barrier)
5973 * - refresh cur_tx ring index and queue status (read barrier)
5974 * May the current thread miss the stopped queue condition,
5975 * a racing xmit thread can only have a right view of the
5976 * ring status.
5977 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005978 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005980 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981 netif_wake_queue(dev);
5982 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005983 /*
5984 * 8168 hack: TxPoll requests are lost when the Tx packets are
5985 * too close. Let's kick an extra TxPoll request when a burst
5986 * of start_xmit activity is detected (if it is not detected,
5987 * it is slow enough). -- FR
5988 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005989 if (tp->cur_tx != dirty_tx) {
5990 void __iomem *ioaddr = tp->mmio_addr;
5991
Francois Romieud78ae2d2007-08-26 20:08:19 +02005992 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994 }
5995}
5996
Francois Romieu126fa4b2005-05-12 20:09:17 -04005997static inline int rtl8169_fragmented_frame(u32 status)
5998{
5999 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
6000}
6001
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006002static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004 u32 status = opts1 & RxProtoMask;
6005
6006 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006007 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008 skb->ip_summed = CHECKSUM_UNNECESSARY;
6009 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006010 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011}
6012
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006013static struct sk_buff *rtl8169_try_rx_copy(void *data,
6014 struct rtl8169_private *tp,
6015 int pkt_size,
6016 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006018 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006019 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006020
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006021 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006022 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006023 prefetch(data);
6024 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6025 if (skb)
6026 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006027 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6028
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006029 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030}
6031
Francois Romieuda78dbf2012-01-26 14:18:23 +01006032static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033{
6034 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006035 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037 cur_rx = tp->cur_rx;
6038 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006039 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006041 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006043 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044 u32 status;
6045
6046 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006047 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048
6049 if (status & DescOwn)
6050 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006051 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006052 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6053 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006054 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006056 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006058 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006059 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006060 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006061 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006062 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006063 if ((status & (RxRUNT | RxCRC)) &&
6064 !(status & (RxRWT | RxFOVF)) &&
6065 (dev->features & NETIF_F_RXALL))
6066 goto process_pkt;
6067
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006068 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006070 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006071 dma_addr_t addr;
6072 int pkt_size;
6073
6074process_pkt:
6075 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006076 if (likely(!(dev->features & NETIF_F_RXFCS)))
6077 pkt_size = (status & 0x00003fff) - 4;
6078 else
6079 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006080
Francois Romieu126fa4b2005-05-12 20:09:17 -04006081 /*
6082 * The driver does not support incoming fragmented
6083 * frames. They are seen as a symptom of over-mtu
6084 * sized frames.
6085 */
6086 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006087 dev->stats.rx_dropped++;
6088 dev->stats.rx_length_errors++;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006089 rtl8169_mark_to_asic(desc, rx_buf_sz);
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006090 continue;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006091 }
6092
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006093 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6094 tp, pkt_size, addr);
6095 rtl8169_mark_to_asic(desc, rx_buf_sz);
6096 if (!skb) {
6097 dev->stats.rx_dropped++;
6098 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099 }
6100
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006101 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102 skb_put(skb, pkt_size);
6103 skb->protocol = eth_type_trans(skb, dev);
6104
Francois Romieu7a8fc772011-03-01 17:18:33 +01006105 rtl8169_rx_vlan_tag(desc, skb);
6106
Francois Romieu56de4142011-03-15 17:29:31 +01006107 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Junchang Wang8027aa22012-03-04 23:30:32 +01006109 u64_stats_update_begin(&tp->rx_stats.syncp);
6110 tp->rx_stats.packets++;
6111 tp->rx_stats.bytes += pkt_size;
6112 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113 }
Francois Romieu6dccd162007-02-13 23:38:05 +01006114
6115 /* Work around for AMD plateform. */
Al Viro95e09182007-12-22 18:55:39 +00006116 if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
Francois Romieu6dccd162007-02-13 23:38:05 +01006117 (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
6118 desc->opts2 = 0;
6119 cur_rx++;
6120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121 }
6122
6123 count = cur_rx - tp->cur_rx;
6124 tp->cur_rx = cur_rx;
6125
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006126 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127
6128 return count;
6129}
6130
Francois Romieu07d3f512007-02-21 22:40:46 +01006131static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132{
Francois Romieu07d3f512007-02-21 22:40:46 +01006133 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006136 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006138 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006139 if (status && status != 0xffff) {
6140 status &= RTL_EVENT_NAPI | tp->event_slow;
6141 if (status) {
6142 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006143
Francois Romieuda78dbf2012-01-26 14:18:23 +01006144 rtl_irq_disable(tp);
6145 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148 return IRQ_RETVAL(handled);
6149}
6150
Francois Romieuda78dbf2012-01-26 14:18:23 +01006151/*
6152 * Workqueue context.
6153 */
6154static void rtl_slow_event_work(struct rtl8169_private *tp)
6155{
6156 struct net_device *dev = tp->dev;
6157 u16 status;
6158
6159 status = rtl_get_events(tp) & tp->event_slow;
6160 rtl_ack_events(tp, status);
6161
6162 if (unlikely(status & RxFIFOOver)) {
6163 switch (tp->mac_version) {
6164 /* Work around for rx fifo overflow */
6165 case RTL_GIGA_MAC_VER_11:
6166 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006167 /* XXX - Hack alert. See rtl_task(). */
6168 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006169 default:
6170 break;
6171 }
6172 }
6173
6174 if (unlikely(status & SYSErr))
6175 rtl8169_pcierr_interrupt(dev);
6176
6177 if (status & LinkChg)
6178 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6179
françois romieu7dbb4912012-06-09 10:53:16 +00006180 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006181}
6182
Francois Romieu4422bcd2012-01-26 11:23:32 +01006183static void rtl_task(struct work_struct *work)
6184{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006185 static const struct {
6186 int bitnr;
6187 void (*action)(struct rtl8169_private *);
6188 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006189 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006190 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6191 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6192 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6193 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006194 struct rtl8169_private *tp =
6195 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006196 struct net_device *dev = tp->dev;
6197 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006198
Francois Romieuda78dbf2012-01-26 14:18:23 +01006199 rtl_lock_work(tp);
6200
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006201 if (!netif_running(dev) ||
6202 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006203 goto out_unlock;
6204
6205 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6206 bool pending;
6207
Francois Romieuda78dbf2012-01-26 14:18:23 +01006208 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006209 if (pending)
6210 rtl_work[i].action(tp);
6211 }
6212
6213out_unlock:
6214 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006215}
6216
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006217static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006219 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6220 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006221 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6222 int work_done= 0;
6223 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224
Francois Romieuda78dbf2012-01-26 14:18:23 +01006225 status = rtl_get_events(tp);
6226 rtl_ack_events(tp, status & ~tp->event_slow);
6227
6228 if (status & RTL_EVENT_NAPI_RX)
6229 work_done = rtl_rx(dev, tp, (u32) budget);
6230
6231 if (status & RTL_EVENT_NAPI_TX)
6232 rtl_tx(dev, tp);
6233
6234 if (status & tp->event_slow) {
6235 enable_mask &= ~tp->event_slow;
6236
6237 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006239
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006240 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006241 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006242
Francois Romieuda78dbf2012-01-26 14:18:23 +01006243 rtl_irq_enable(tp, enable_mask);
6244 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245 }
6246
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006247 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Francois Romieu523a6092008-09-10 22:28:56 +02006250static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6251{
6252 struct rtl8169_private *tp = netdev_priv(dev);
6253
6254 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6255 return;
6256
6257 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6258 RTL_W32(RxMissed, 0);
6259}
6260
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261static void rtl8169_down(struct net_device *dev)
6262{
6263 struct rtl8169_private *tp = netdev_priv(dev);
6264 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265
Francois Romieu4876cc12011-03-11 21:07:11 +01006266 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006268 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006269 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270
Hayes Wang92fc43b2011-07-06 15:58:03 +08006271 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006272 /*
6273 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006274 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6275 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006276 */
Francois Romieu523a6092008-09-10 22:28:56 +02006277 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006280 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282 rtl8169_tx_clear(tp);
6283
6284 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006285
6286 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287}
6288
6289static int rtl8169_close(struct net_device *dev)
6290{
6291 struct rtl8169_private *tp = netdev_priv(dev);
6292 struct pci_dev *pdev = tp->pci_dev;
6293
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006294 pm_runtime_get_sync(&pdev->dev);
6295
Francois Romieucecb5fd2011-04-01 10:21:07 +02006296 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006297 rtl8169_update_counters(dev);
6298
Francois Romieuda78dbf2012-01-26 14:18:23 +01006299 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006300 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006301
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006303 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006304
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006305 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006307 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6308 tp->RxPhyAddr);
6309 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6310 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 tp->TxDescArray = NULL;
6312 tp->RxDescArray = NULL;
6313
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006314 pm_runtime_put_sync(&pdev->dev);
6315
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316 return 0;
6317}
6318
Francois Romieudc1c00c2012-03-08 10:06:18 +01006319#ifdef CONFIG_NET_POLL_CONTROLLER
6320static void rtl8169_netpoll(struct net_device *dev)
6321{
6322 struct rtl8169_private *tp = netdev_priv(dev);
6323
6324 rtl8169_interrupt(tp->pci_dev->irq, dev);
6325}
6326#endif
6327
Francois Romieudf43ac72012-03-08 09:48:40 +01006328static int rtl_open(struct net_device *dev)
6329{
6330 struct rtl8169_private *tp = netdev_priv(dev);
6331 void __iomem *ioaddr = tp->mmio_addr;
6332 struct pci_dev *pdev = tp->pci_dev;
6333 int retval = -ENOMEM;
6334
6335 pm_runtime_get_sync(&pdev->dev);
6336
6337 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006338 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006339 * dma_alloc_coherent provides more.
6340 */
6341 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6342 &tp->TxPhyAddr, GFP_KERNEL);
6343 if (!tp->TxDescArray)
6344 goto err_pm_runtime_put;
6345
6346 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6347 &tp->RxPhyAddr, GFP_KERNEL);
6348 if (!tp->RxDescArray)
6349 goto err_free_tx_0;
6350
6351 retval = rtl8169_init_ring(dev);
6352 if (retval < 0)
6353 goto err_free_rx_1;
6354
6355 INIT_WORK(&tp->wk.work, rtl_task);
6356
6357 smp_mb();
6358
6359 rtl_request_firmware(tp);
6360
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006361 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006362 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6363 dev->name, dev);
6364 if (retval < 0)
6365 goto err_release_fw_2;
6366
6367 rtl_lock_work(tp);
6368
6369 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6370
6371 napi_enable(&tp->napi);
6372
6373 rtl8169_init_phy(dev, tp);
6374
6375 __rtl8169_set_features(dev, dev->features);
6376
6377 rtl_pll_power_up(tp);
6378
6379 rtl_hw_start(dev);
6380
6381 netif_start_queue(dev);
6382
6383 rtl_unlock_work(tp);
6384
6385 tp->saved_wolopts = 0;
6386 pm_runtime_put_noidle(&pdev->dev);
6387
6388 rtl8169_check_link_status(dev, tp, ioaddr);
6389out:
6390 return retval;
6391
6392err_release_fw_2:
6393 rtl_release_firmware(tp);
6394 rtl8169_rx_clear(tp);
6395err_free_rx_1:
6396 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6397 tp->RxPhyAddr);
6398 tp->RxDescArray = NULL;
6399err_free_tx_0:
6400 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6401 tp->TxPhyAddr);
6402 tp->TxDescArray = NULL;
6403err_pm_runtime_put:
6404 pm_runtime_put_noidle(&pdev->dev);
6405 goto out;
6406}
6407
Junchang Wang8027aa22012-03-04 23:30:32 +01006408static struct rtnl_link_stats64 *
6409rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006410{
6411 struct rtl8169_private *tp = netdev_priv(dev);
6412 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006413 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006414
Francois Romieuda78dbf2012-01-26 14:18:23 +01006415 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006416 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006417
Junchang Wang8027aa22012-03-04 23:30:32 +01006418 do {
6419 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6420 stats->rx_packets = tp->rx_stats.packets;
6421 stats->rx_bytes = tp->rx_stats.bytes;
6422 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6423
6424
6425 do {
6426 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6427 stats->tx_packets = tp->tx_stats.packets;
6428 stats->tx_bytes = tp->tx_stats.bytes;
6429 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6430
6431 stats->rx_dropped = dev->stats.rx_dropped;
6432 stats->tx_dropped = dev->stats.tx_dropped;
6433 stats->rx_length_errors = dev->stats.rx_length_errors;
6434 stats->rx_errors = dev->stats.rx_errors;
6435 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6436 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6437 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6438
6439 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006440}
6441
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006442static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006443{
françois romieu065c27c2011-01-03 15:08:12 +00006444 struct rtl8169_private *tp = netdev_priv(dev);
6445
Francois Romieu5d06a992006-02-23 00:47:58 +01006446 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006447 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006448
6449 netif_device_detach(dev);
6450 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006451
6452 rtl_lock_work(tp);
6453 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006454 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006455 rtl_unlock_work(tp);
6456
6457 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006458}
Francois Romieu5d06a992006-02-23 00:47:58 +01006459
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006460#ifdef CONFIG_PM
6461
6462static int rtl8169_suspend(struct device *device)
6463{
6464 struct pci_dev *pdev = to_pci_dev(device);
6465 struct net_device *dev = pci_get_drvdata(pdev);
6466
6467 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006468
Francois Romieu5d06a992006-02-23 00:47:58 +01006469 return 0;
6470}
6471
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006472static void __rtl8169_resume(struct net_device *dev)
6473{
françois romieu065c27c2011-01-03 15:08:12 +00006474 struct rtl8169_private *tp = netdev_priv(dev);
6475
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006476 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006477
6478 rtl_pll_power_up(tp);
6479
Artem Savkovcff4c162012-04-03 10:29:11 +00006480 rtl_lock_work(tp);
6481 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006482 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006483 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006484
Francois Romieu98ddf982012-01-31 10:47:34 +01006485 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006486}
6487
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006488static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006489{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006490 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006491 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006492 struct rtl8169_private *tp = netdev_priv(dev);
6493
6494 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006495
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006496 if (netif_running(dev))
6497 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006498
Francois Romieu5d06a992006-02-23 00:47:58 +01006499 return 0;
6500}
6501
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006502static int rtl8169_runtime_suspend(struct device *device)
6503{
6504 struct pci_dev *pdev = to_pci_dev(device);
6505 struct net_device *dev = pci_get_drvdata(pdev);
6506 struct rtl8169_private *tp = netdev_priv(dev);
6507
6508 if (!tp->TxDescArray)
6509 return 0;
6510
Francois Romieuda78dbf2012-01-26 14:18:23 +01006511 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006512 tp->saved_wolopts = __rtl8169_get_wol(tp);
6513 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006514 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006515
6516 rtl8169_net_suspend(dev);
6517
6518 return 0;
6519}
6520
6521static int rtl8169_runtime_resume(struct device *device)
6522{
6523 struct pci_dev *pdev = to_pci_dev(device);
6524 struct net_device *dev = pci_get_drvdata(pdev);
6525 struct rtl8169_private *tp = netdev_priv(dev);
6526
6527 if (!tp->TxDescArray)
6528 return 0;
6529
Francois Romieuda78dbf2012-01-26 14:18:23 +01006530 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006531 __rtl8169_set_wol(tp, tp->saved_wolopts);
6532 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006533 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006534
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006535 rtl8169_init_phy(dev, tp);
6536
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006537 __rtl8169_resume(dev);
6538
6539 return 0;
6540}
6541
6542static int rtl8169_runtime_idle(struct device *device)
6543{
6544 struct pci_dev *pdev = to_pci_dev(device);
6545 struct net_device *dev = pci_get_drvdata(pdev);
6546 struct rtl8169_private *tp = netdev_priv(dev);
6547
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006548 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006549}
6550
Alexey Dobriyan47145212009-12-14 18:00:08 -08006551static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006552 .suspend = rtl8169_suspend,
6553 .resume = rtl8169_resume,
6554 .freeze = rtl8169_suspend,
6555 .thaw = rtl8169_resume,
6556 .poweroff = rtl8169_suspend,
6557 .restore = rtl8169_resume,
6558 .runtime_suspend = rtl8169_runtime_suspend,
6559 .runtime_resume = rtl8169_runtime_resume,
6560 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006561};
6562
6563#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6564
6565#else /* !CONFIG_PM */
6566
6567#define RTL8169_PM_OPS NULL
6568
6569#endif /* !CONFIG_PM */
6570
David S. Miller1805b2f2011-10-24 18:18:09 -04006571static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6572{
6573 void __iomem *ioaddr = tp->mmio_addr;
6574
6575 /* WoL fails with 8168b when the receiver is disabled. */
6576 switch (tp->mac_version) {
6577 case RTL_GIGA_MAC_VER_11:
6578 case RTL_GIGA_MAC_VER_12:
6579 case RTL_GIGA_MAC_VER_17:
6580 pci_clear_master(tp->pci_dev);
6581
6582 RTL_W8(ChipCmd, CmdRxEnb);
6583 /* PCI commit */
6584 RTL_R8(ChipCmd);
6585 break;
6586 default:
6587 break;
6588 }
6589}
6590
Francois Romieu1765f952008-09-13 17:21:40 +02006591static void rtl_shutdown(struct pci_dev *pdev)
6592{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006593 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006594 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006595 struct device *d = &pdev->dev;
6596
6597 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006598
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006599 rtl8169_net_suspend(dev);
6600
Francois Romieucecb5fd2011-04-01 10:21:07 +02006601 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006602 rtl_rar_set(tp, dev->perm_addr);
6603
Hayes Wang92fc43b2011-07-06 15:58:03 +08006604 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006605
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006606 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006607 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6608 rtl_wol_suspend_quirk(tp);
6609 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006610 }
6611
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006612 pci_wake_from_d3(pdev, true);
6613 pci_set_power_state(pdev, PCI_D3hot);
6614 }
françois romieu2a15cd22012-03-06 01:14:12 +00006615
6616 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006617}
Francois Romieu5d06a992006-02-23 00:47:58 +01006618
Bill Pembertonbaf63292012-12-03 09:23:28 -05006619static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006620{
6621 struct net_device *dev = pci_get_drvdata(pdev);
6622 struct rtl8169_private *tp = netdev_priv(dev);
6623
6624 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6625 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6626 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6627 rtl8168_driver_stop(tp);
6628 }
6629
6630 cancel_work_sync(&tp->wk.work);
6631
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006632 netif_napi_del(&tp->napi);
6633
Francois Romieue27566e2012-03-08 09:54:01 +01006634 unregister_netdev(dev);
6635
6636 rtl_release_firmware(tp);
6637
6638 if (pci_dev_run_wake(pdev))
6639 pm_runtime_get_noresume(&pdev->dev);
6640
6641 /* restore original MAC address */
6642 rtl_rar_set(tp, dev->perm_addr);
6643
6644 rtl_disable_msi(pdev, tp);
6645 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6646 pci_set_drvdata(pdev, NULL);
6647}
6648
Francois Romieufa9c3852012-03-08 10:01:50 +01006649static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006650 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006651 .ndo_stop = rtl8169_close,
6652 .ndo_get_stats64 = rtl8169_get_stats64,
6653 .ndo_start_xmit = rtl8169_start_xmit,
6654 .ndo_tx_timeout = rtl8169_tx_timeout,
6655 .ndo_validate_addr = eth_validate_addr,
6656 .ndo_change_mtu = rtl8169_change_mtu,
6657 .ndo_fix_features = rtl8169_fix_features,
6658 .ndo_set_features = rtl8169_set_features,
6659 .ndo_set_mac_address = rtl_set_mac_address,
6660 .ndo_do_ioctl = rtl8169_ioctl,
6661 .ndo_set_rx_mode = rtl_set_rx_mode,
6662#ifdef CONFIG_NET_POLL_CONTROLLER
6663 .ndo_poll_controller = rtl8169_netpoll,
6664#endif
6665
6666};
6667
Francois Romieu31fa8b12012-03-08 10:09:40 +01006668static const struct rtl_cfg_info {
6669 void (*hw_start)(struct net_device *);
6670 unsigned int region;
6671 unsigned int align;
6672 u16 event_slow;
6673 unsigned features;
6674 u8 default_ver;
6675} rtl_cfg_infos [] = {
6676 [RTL_CFG_0] = {
6677 .hw_start = rtl_hw_start_8169,
6678 .region = 1,
6679 .align = 0,
6680 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6681 .features = RTL_FEATURE_GMII,
6682 .default_ver = RTL_GIGA_MAC_VER_01,
6683 },
6684 [RTL_CFG_1] = {
6685 .hw_start = rtl_hw_start_8168,
6686 .region = 2,
6687 .align = 8,
6688 .event_slow = SYSErr | LinkChg | RxOverflow,
6689 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6690 .default_ver = RTL_GIGA_MAC_VER_11,
6691 },
6692 [RTL_CFG_2] = {
6693 .hw_start = rtl_hw_start_8101,
6694 .region = 2,
6695 .align = 8,
6696 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6697 PCSTimeout,
6698 .features = RTL_FEATURE_MSI,
6699 .default_ver = RTL_GIGA_MAC_VER_13,
6700 }
6701};
6702
6703/* Cfg9346_Unlock assumed. */
6704static unsigned rtl_try_msi(struct rtl8169_private *tp,
6705 const struct rtl_cfg_info *cfg)
6706{
6707 void __iomem *ioaddr = tp->mmio_addr;
6708 unsigned msi = 0;
6709 u8 cfg2;
6710
6711 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6712 if (cfg->features & RTL_FEATURE_MSI) {
6713 if (pci_enable_msi(tp->pci_dev)) {
6714 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6715 } else {
6716 cfg2 |= MSIEnable;
6717 msi = RTL_FEATURE_MSI;
6718 }
6719 }
6720 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6721 RTL_W8(Config2, cfg2);
6722 return msi;
6723}
6724
Hayes Wangc5583862012-07-02 17:23:22 +08006725DECLARE_RTL_COND(rtl_link_list_ready_cond)
6726{
6727 void __iomem *ioaddr = tp->mmio_addr;
6728
6729 return RTL_R8(MCU) & LINK_LIST_RDY;
6730}
6731
6732DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6733{
6734 void __iomem *ioaddr = tp->mmio_addr;
6735
6736 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6737}
6738
Bill Pembertonbaf63292012-12-03 09:23:28 -05006739static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006740{
6741 void __iomem *ioaddr = tp->mmio_addr;
6742 u32 data;
6743
6744 tp->ocp_base = OCP_STD_PHY_BASE;
6745
6746 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6747
6748 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6749 return;
6750
6751 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6752 return;
6753
6754 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6755 msleep(1);
6756 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6757
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006758 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006759 data &= ~(1 << 14);
6760 r8168_mac_ocp_write(tp, 0xe8de, data);
6761
6762 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6763 return;
6764
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006765 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006766 data |= (1 << 15);
6767 r8168_mac_ocp_write(tp, 0xe8de, data);
6768
6769 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6770 return;
6771}
6772
Bill Pembertonbaf63292012-12-03 09:23:28 -05006773static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006774{
6775 switch (tp->mac_version) {
6776 case RTL_GIGA_MAC_VER_40:
6777 case RTL_GIGA_MAC_VER_41:
6778 rtl_hw_init_8168g(tp);
6779 break;
6780
6781 default:
6782 break;
6783 }
6784}
6785
Bill Pembertonbaf63292012-12-03 09:23:28 -05006786static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006787rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6788{
6789 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6790 const unsigned int region = cfg->region;
6791 struct rtl8169_private *tp;
6792 struct mii_if_info *mii;
6793 struct net_device *dev;
6794 void __iomem *ioaddr;
6795 int chipset, i;
6796 int rc;
6797
6798 if (netif_msg_drv(&debug)) {
6799 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6800 MODULENAME, RTL8169_VERSION);
6801 }
6802
6803 dev = alloc_etherdev(sizeof (*tp));
6804 if (!dev) {
6805 rc = -ENOMEM;
6806 goto out;
6807 }
6808
6809 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006810 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006811 tp = netdev_priv(dev);
6812 tp->dev = dev;
6813 tp->pci_dev = pdev;
6814 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6815
6816 mii = &tp->mii;
6817 mii->dev = dev;
6818 mii->mdio_read = rtl_mdio_read;
6819 mii->mdio_write = rtl_mdio_write;
6820 mii->phy_id_mask = 0x1f;
6821 mii->reg_num_mask = 0x1f;
6822 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6823
6824 /* disable ASPM completely as that cause random device stop working
6825 * problems as well as full system hangs for some PCIe devices users */
6826 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6827 PCIE_LINK_STATE_CLKPM);
6828
6829 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6830 rc = pci_enable_device(pdev);
6831 if (rc < 0) {
6832 netif_err(tp, probe, dev, "enable failure\n");
6833 goto err_out_free_dev_1;
6834 }
6835
6836 if (pci_set_mwi(pdev) < 0)
6837 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6838
6839 /* make sure PCI base addr 1 is MMIO */
6840 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6841 netif_err(tp, probe, dev,
6842 "region #%d not an MMIO resource, aborting\n",
6843 region);
6844 rc = -ENODEV;
6845 goto err_out_mwi_2;
6846 }
6847
6848 /* check for weird/broken PCI region reporting */
6849 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6850 netif_err(tp, probe, dev,
6851 "Invalid PCI region size(s), aborting\n");
6852 rc = -ENODEV;
6853 goto err_out_mwi_2;
6854 }
6855
6856 rc = pci_request_regions(pdev, MODULENAME);
6857 if (rc < 0) {
6858 netif_err(tp, probe, dev, "could not request regions\n");
6859 goto err_out_mwi_2;
6860 }
6861
6862 tp->cp_cmd = RxChkSum;
6863
6864 if ((sizeof(dma_addr_t) > 4) &&
6865 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6866 tp->cp_cmd |= PCIDAC;
6867 dev->features |= NETIF_F_HIGHDMA;
6868 } else {
6869 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6870 if (rc < 0) {
6871 netif_err(tp, probe, dev, "DMA configuration failed\n");
6872 goto err_out_free_res_3;
6873 }
6874 }
6875
6876 /* ioremap MMIO region */
6877 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6878 if (!ioaddr) {
6879 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6880 rc = -EIO;
6881 goto err_out_free_res_3;
6882 }
6883 tp->mmio_addr = ioaddr;
6884
6885 if (!pci_is_pcie(pdev))
6886 netif_info(tp, probe, dev, "not PCI Express\n");
6887
6888 /* Identify chip attached to board */
6889 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6890
6891 rtl_init_rxcfg(tp);
6892
6893 rtl_irq_disable(tp);
6894
Hayes Wangc5583862012-07-02 17:23:22 +08006895 rtl_hw_initialize(tp);
6896
Francois Romieu3b6cf252012-03-08 09:59:04 +01006897 rtl_hw_reset(tp);
6898
6899 rtl_ack_events(tp, 0xffff);
6900
6901 pci_set_master(pdev);
6902
6903 /*
6904 * Pretend we are using VLANs; This bypasses a nasty bug where
6905 * Interrupts stop flowing on high load on 8110SCd controllers.
6906 */
6907 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6908 tp->cp_cmd |= RxVlan;
6909
6910 rtl_init_mdio_ops(tp);
6911 rtl_init_pll_power_ops(tp);
6912 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006913 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006914
6915 rtl8169_print_mac_version(tp);
6916
6917 chipset = tp->mac_version;
6918 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6919
6920 RTL_W8(Cfg9346, Cfg9346_Unlock);
6921 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6922 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6923 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6924 tp->features |= RTL_FEATURE_WOL;
6925 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6926 tp->features |= RTL_FEATURE_WOL;
6927 tp->features |= rtl_try_msi(tp, cfg);
6928 RTL_W8(Cfg9346, Cfg9346_Lock);
6929
6930 if (rtl_tbi_enabled(tp)) {
6931 tp->set_speed = rtl8169_set_speed_tbi;
6932 tp->get_settings = rtl8169_gset_tbi;
6933 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6934 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6935 tp->link_ok = rtl8169_tbi_link_ok;
6936 tp->do_ioctl = rtl_tbi_ioctl;
6937 } else {
6938 tp->set_speed = rtl8169_set_speed_xmii;
6939 tp->get_settings = rtl8169_gset_xmii;
6940 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6941 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6942 tp->link_ok = rtl8169_xmii_link_ok;
6943 tp->do_ioctl = rtl_xmii_ioctl;
6944 }
6945
6946 mutex_init(&tp->wk.mutex);
6947
6948 /* Get MAC address */
6949 for (i = 0; i < ETH_ALEN; i++)
6950 dev->dev_addr[i] = RTL_R8(MAC0 + i);
6951 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6952
6953 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6954 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006955
6956 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6957
6958 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6959 * properly for all devices */
6960 dev->features |= NETIF_F_RXCSUM |
6961 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6962
6963 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6964 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6965 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6966 NETIF_F_HIGHDMA;
6967
6968 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6969 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6970 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6971
6972 dev->hw_features |= NETIF_F_RXALL;
6973 dev->hw_features |= NETIF_F_RXFCS;
6974
6975 tp->hw_start = cfg->hw_start;
6976 tp->event_slow = cfg->event_slow;
6977
6978 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6979 ~(RxBOVF | RxFOVF) : ~0;
6980
6981 init_timer(&tp->timer);
6982 tp->timer.data = (unsigned long) dev;
6983 tp->timer.function = rtl8169_phy_timer;
6984
6985 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6986
6987 rc = register_netdev(dev);
6988 if (rc < 0)
6989 goto err_out_msi_4;
6990
6991 pci_set_drvdata(pdev, dev);
6992
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006993 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6994 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6995 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006996 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6997 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6998 "tx checksumming: %s]\n",
6999 rtl_chip_infos[chipset].jumbo_max,
7000 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
7001 }
7002
7003 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
7004 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
7005 tp->mac_version == RTL_GIGA_MAC_VER_31) {
7006 rtl8168_driver_start(tp);
7007 }
7008
7009 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
7010
7011 if (pci_dev_run_wake(pdev))
7012 pm_runtime_put_noidle(&pdev->dev);
7013
7014 netif_carrier_off(dev);
7015
7016out:
7017 return rc;
7018
7019err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007020 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007021 rtl_disable_msi(pdev, tp);
7022 iounmap(ioaddr);
7023err_out_free_res_3:
7024 pci_release_regions(pdev);
7025err_out_mwi_2:
7026 pci_clear_mwi(pdev);
7027 pci_disable_device(pdev);
7028err_out_free_dev_1:
7029 free_netdev(dev);
7030 goto out;
7031}
7032
Linus Torvalds1da177e2005-04-16 15:20:36 -07007033static struct pci_driver rtl8169_pci_driver = {
7034 .name = MODULENAME,
7035 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007036 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05007037 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02007038 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007039 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007040};
7041
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007042module_pci_driver(rtl8169_pci_driver);