blob: 11702324a071b87deff9ef13f919be57e99b024b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Francois Romieu07d3f512007-02-21 22:40:46 +01002 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/pci.h>
14#include <linux/netdevice.h>
15#include <linux/etherdevice.h>
16#include <linux/delay.h>
17#include <linux/ethtool.h>
18#include <linux/mii.h>
19#include <linux/if_vlan.h>
20#include <linux/crc32.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/tcp.h>
24#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000025#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000027#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000028#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000029#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040030#include <linux/prefetch.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/io.h>
33#include <asm/irq.h>
34
Francois Romieu865c6522008-05-11 14:51:00 +020035#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MODULENAME "r8169"
37#define PFX MODULENAME ": "
38
françois romieubca03d52011-01-03 15:07:31 +000039#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
40#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000041#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
42#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080043#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080044#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
45#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080046#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080047#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080048#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080049#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
Hayes Wangc5583862012-07-02 17:23:22 +080050#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw"
françois romieubca03d52011-01-03 15:07:31 +000051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#ifdef RTL8169_DEBUG
53#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020054 if (!(expr)) { \
55 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070056 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020057 }
Joe Perches06fa7352007-10-18 21:15:00 +020058#define dprintk(fmt, args...) \
59 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
61#define assert(expr) do {} while (0)
62#define dprintk(fmt, args...) do {} while (0)
63#endif /* RTL8169_DEBUG */
64
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020065#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
86#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
88#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
89
90#define RTL8169_TX_TIMEOUT (6*HZ)
91#define RTL8169_PHY_TIMEOUT (10*HZ)
92
93/* write/read MMIO register */
94#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
95#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
96#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
97#define RTL_R8(reg) readb (ioaddr + (reg))
98#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +000099#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200102 RTL_GIGA_MAC_VER_01 = 0,
103 RTL_GIGA_MAC_VER_02,
104 RTL_GIGA_MAC_VER_03,
105 RTL_GIGA_MAC_VER_04,
106 RTL_GIGA_MAC_VER_05,
107 RTL_GIGA_MAC_VER_06,
108 RTL_GIGA_MAC_VER_07,
109 RTL_GIGA_MAC_VER_08,
110 RTL_GIGA_MAC_VER_09,
111 RTL_GIGA_MAC_VER_10,
112 RTL_GIGA_MAC_VER_11,
113 RTL_GIGA_MAC_VER_12,
114 RTL_GIGA_MAC_VER_13,
115 RTL_GIGA_MAC_VER_14,
116 RTL_GIGA_MAC_VER_15,
117 RTL_GIGA_MAC_VER_16,
118 RTL_GIGA_MAC_VER_17,
119 RTL_GIGA_MAC_VER_18,
120 RTL_GIGA_MAC_VER_19,
121 RTL_GIGA_MAC_VER_20,
122 RTL_GIGA_MAC_VER_21,
123 RTL_GIGA_MAC_VER_22,
124 RTL_GIGA_MAC_VER_23,
125 RTL_GIGA_MAC_VER_24,
126 RTL_GIGA_MAC_VER_25,
127 RTL_GIGA_MAC_VER_26,
128 RTL_GIGA_MAC_VER_27,
129 RTL_GIGA_MAC_VER_28,
130 RTL_GIGA_MAC_VER_29,
131 RTL_GIGA_MAC_VER_30,
132 RTL_GIGA_MAC_VER_31,
133 RTL_GIGA_MAC_VER_32,
134 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800135 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800136 RTL_GIGA_MAC_VER_35,
137 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800138 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800139 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800140 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800141 RTL_GIGA_MAC_VER_40,
142 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200143 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
Francois Romieu2b7b4312011-04-18 22:53:24 -0700146enum rtl_tx_desc_version {
147 RTL_TD_0 = 0,
148 RTL_TD_1 = 1,
149};
150
Francois Romieud58d46b2011-05-03 16:38:29 +0200151#define JUMBO_1K ETH_DATA_LEN
152#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
153#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
154#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
155#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
156
157#define _R(NAME,TD,FW,SZ,B) { \
158 .name = NAME, \
159 .txd_version = TD, \
160 .fw_name = FW, \
161 .jumbo_max = SZ, \
162 .jumbo_tx_csum = B \
163}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800165static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700167 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200168 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200169 u16 jumbo_max;
170 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200171} rtl_chip_infos[] = {
172 /* PCI devices. */
173 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200175 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200176 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200177 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200178 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200179 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200180 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200181 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200182 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200183 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200184 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200185 /* PCI-E devices. */
186 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200191 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200192 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200193 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200194 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200195 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200196 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200197 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200198 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200199 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200200 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200201 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200202 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200203 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200204 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200205 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200206 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200207 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200208 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200209 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200210 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200211 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200212 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200213 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200214 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200215 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200216 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200217 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200218 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200219 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200220 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200221 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200222 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200223 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
224 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
227 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200228 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200229 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200232 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200233 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
234 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
237 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200238 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200239 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
242 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
245 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800246 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200247 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
248 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800249 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200250 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
251 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800252 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200253 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
254 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800255 [RTL_GIGA_MAC_VER_37] =
256 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
257 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800258 [RTL_GIGA_MAC_VER_38] =
259 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
260 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800261 [RTL_GIGA_MAC_VER_39] =
262 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
263 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800264 [RTL_GIGA_MAC_VER_40] =
265 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
266 JUMBO_9K, false),
267 [RTL_GIGA_MAC_VER_41] =
268 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269};
270#undef _R
271
Francois Romieubcf0bf92006-07-26 23:14:13 +0200272enum cfg_version {
273 RTL_CFG_0 = 0x00,
274 RTL_CFG_1,
275 RTL_CFG_2
276};
277
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000278static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200279 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200280 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200281 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100282 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200283 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200284 { PCI_VENDOR_ID_DLINK, 0x4300,
285 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000287 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200289 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
290 { PCI_VENDOR_ID_LINKSYS, 0x1032,
291 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100292 { 0x0001, 0x8168,
293 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 {0,},
295};
296
297MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
298
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000299static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700300static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200301static struct {
302 u32 msg_enable;
303} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Francois Romieu07d3f512007-02-21 22:40:46 +0100305enum rtl_registers {
306 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100307 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100308 MAR0 = 8, /* Multicast filter. */
309 CounterAddrLow = 0x10,
310 CounterAddrHigh = 0x14,
311 TxDescStartAddrLow = 0x20,
312 TxDescStartAddrHigh = 0x24,
313 TxHDescStartAddrLow = 0x28,
314 TxHDescStartAddrHigh = 0x2c,
315 FLASH = 0x30,
316 ERSR = 0x36,
317 ChipCmd = 0x37,
318 TxPoll = 0x38,
319 IntrMask = 0x3c,
320 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700321
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800322 TxConfig = 0x40,
323#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
324#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
325
326 RxConfig = 0x44,
327#define RX128_INT_EN (1 << 15) /* 8111c and later */
328#define RX_MULTI_EN (1 << 14) /* 8111c only */
329#define RXCFG_FIFO_SHIFT 13
330 /* No threshold before first PCI xfer */
331#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
332#define RXCFG_DMA_SHIFT 8
333 /* Unlimited maximum PCI burst. */
334#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700335
Francois Romieu07d3f512007-02-21 22:40:46 +0100336 RxMissed = 0x4c,
337 Cfg9346 = 0x50,
338 Config0 = 0x51,
339 Config1 = 0x52,
340 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200341#define PME_SIGNAL (1 << 5) /* 8168c and later */
342
Francois Romieu07d3f512007-02-21 22:40:46 +0100343 Config3 = 0x54,
344 Config4 = 0x55,
345 Config5 = 0x56,
346 MultiIntr = 0x5c,
347 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 PHYstatus = 0x6c,
349 RxMaxSize = 0xda,
350 CPlusCmd = 0xe0,
351 IntrMitigate = 0xe2,
352 RxDescAddrLow = 0xe4,
353 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000354 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
355
356#define NoEarlyTx 0x3f /* Max value : no early transmit. */
357
358 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
359
360#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800361#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000362
Francois Romieu07d3f512007-02-21 22:40:46 +0100363 FuncEvent = 0xf0,
364 FuncEventMask = 0xf4,
365 FuncPresetState = 0xf8,
366 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Francois Romieuf162a5d2008-06-01 22:37:49 +0200369enum rtl8110_registers {
370 TBICSR = 0x64,
371 TBI_ANAR = 0x68,
372 TBI_LPAR = 0x6a,
373};
374
375enum rtl8168_8101_registers {
376 CSIDR = 0x64,
377 CSIAR = 0x68,
378#define CSIAR_FLAG 0x80000000
379#define CSIAR_WRITE_CMD 0x80000000
380#define CSIAR_BYTE_ENABLE 0x0f
381#define CSIAR_BYTE_ENABLE_SHIFT 12
382#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800383#define CSIAR_FUNC_CARD 0x00000000
384#define CSIAR_FUNC_SDIO 0x00010000
385#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000386 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200387 EPHYAR = 0x80,
388#define EPHYAR_FLAG 0x80000000
389#define EPHYAR_WRITE_CMD 0x80000000
390#define EPHYAR_REG_MASK 0x1f
391#define EPHYAR_REG_SHIFT 16
392#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800393 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800394#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200395 DBG_REG = 0xd1,
396#define FIX_NAK_1 (1 << 4)
397#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 TWSI = 0xd2,
399 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800400#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800401#define TX_EMPTY (1 << 5)
402#define RX_EMPTY (1 << 4)
403#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800404#define EN_NDP (1 << 3)
405#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000407 EFUSEAR = 0xdc,
408#define EFUSEAR_FLAG 0x80000000
409#define EFUSEAR_WRITE_CMD 0x80000000
410#define EFUSEAR_READ_CMD 0x00000000
411#define EFUSEAR_REG_MASK 0x03ff
412#define EFUSEAR_REG_SHIFT 8
413#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200414};
415
françois romieuc0e45c12011-01-03 15:08:04 +0000416enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800417 LED_FREQ = 0x1a,
418 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000419 ERIDR = 0x70,
420 ERIAR = 0x74,
421#define ERIAR_FLAG 0x80000000
422#define ERIAR_WRITE_CMD 0x80000000
423#define ERIAR_READ_CMD 0x00000000
424#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000425#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800426#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
427#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
428#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
429#define ERIAR_MASK_SHIFT 12
430#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
431#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800432#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800433#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000434 EPHY_RXER_NUM = 0x7c,
435 OCPDR = 0xb0, /* OCP GPHY access */
436#define OCPDR_WRITE_CMD 0x80000000
437#define OCPDR_READ_CMD 0x00000000
438#define OCPDR_REG_MASK 0x7f
439#define OCPDR_GPHY_REG_SHIFT 16
440#define OCPDR_DATA_MASK 0xffff
441 OCPAR = 0xb4,
442#define OCPAR_FLAG 0x80000000
443#define OCPAR_GPHY_WRITE_CMD 0x8000f060
444#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800445 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000446 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
447 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200448#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800449#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800450#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800451#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800452#define EARLY_TALLY_EN (1 << 16)
hayeswangd64ec842012-11-01 16:46:28 +0000453#define FORCE_CLK (1 << 15) /* force clock request */
françois romieuc0e45c12011-01-03 15:08:04 +0000454};
455
Francois Romieu07d3f512007-02-21 22:40:46 +0100456enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100458 SYSErr = 0x8000,
459 PCSTimeout = 0x4000,
460 SWInt = 0x0100,
461 TxDescUnavail = 0x0080,
462 RxFIFOOver = 0x0040,
463 LinkChg = 0x0020,
464 RxOverflow = 0x0010,
465 TxErr = 0x0008,
466 TxOK = 0x0004,
467 RxErr = 0x0002,
468 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400471 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200472 RxFOVF = (1 << 23),
473 RxRWT = (1 << 22),
474 RxRES = (1 << 21),
475 RxRUNT = (1 << 20),
476 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
478 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800479 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100480 CmdReset = 0x10,
481 CmdRxEnb = 0x08,
482 CmdTxEnb = 0x04,
483 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Francois Romieu275391a2007-02-23 23:50:28 +0100485 /* TXPoll register p.5 */
486 HPQ = 0x80, /* Poll cmd on the high prio queue */
487 NPQ = 0x40, /* Poll cmd on the low prio queue */
488 FSWInt = 0x01, /* Forced software interrupt */
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100491 Cfg9346_Lock = 0x00,
492 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
494 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100495 AcceptErr = 0x20,
496 AcceptRunt = 0x10,
497 AcceptBroadcast = 0x08,
498 AcceptMulticast = 0x04,
499 AcceptMyPhys = 0x02,
500 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200501#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 /* TxConfigBits */
504 TxInterFrameGapShift = 24,
505 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
506
Francois Romieu5d06a992006-02-23 00:47:58 +0100507 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200508 LEDS1 = (1 << 7),
509 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200510 Speed_down = (1 << 4),
511 MEMMAP = (1 << 3),
512 IOMAP = (1 << 2),
513 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100514 PMEnable = (1 << 0), /* Power Management Enable */
515
Francois Romieu6dccd162007-02-13 23:38:05 +0100516 /* Config2 register p. 25 */
hayeswangd64ec842012-11-01 16:46:28 +0000517 ClkReqEn = (1 << 7), /* Clock Request Enable */
françois romieu2ca6cf02011-12-15 08:37:43 +0000518 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100519 PCI_Clock_66MHz = 0x01,
520 PCI_Clock_33MHz = 0x00,
521
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100522 /* Config3 register p.25 */
523 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
524 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200525 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200526 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100527
Francois Romieud58d46b2011-05-03 16:38:29 +0200528 /* Config4 register */
529 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
530
Francois Romieu5d06a992006-02-23 00:47:58 +0100531 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100532 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
533 MWF = (1 << 5), /* Accept Multicast wakeup frame */
534 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200535 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100536 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100537 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
hayeswangd64ec842012-11-01 16:46:28 +0000538 ASPM_en = (1 << 0), /* ASPM enable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* TBICSR p.28 */
541 TBIReset = 0x80000000,
542 TBILoopback = 0x40000000,
543 TBINwEnable = 0x20000000,
544 TBINwRestart = 0x10000000,
545 TBILinkOk = 0x02000000,
546 TBINwComplete = 0x01000000,
547
548 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200549 EnableBist = (1 << 15), // 8168 8101
550 Mac_dbgo_oe = (1 << 14), // 8168 8101
551 Normal_mode = (1 << 13), // unused
552 Force_half_dup = (1 << 12), // 8168 8101
553 Force_rxflow_en = (1 << 11), // 8168 8101
554 Force_txflow_en = (1 << 10), // 8168 8101
555 Cxpl_dbg_sel = (1 << 9), // 8168 8101
556 ASF = (1 << 8), // 8168 8101
557 PktCntrDisable = (1 << 7), // 8168 8101
558 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 RxVlan = (1 << 6),
560 RxChkSum = (1 << 5),
561 PCIDAC = (1 << 4),
562 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100563 INTT_0 = 0x0000, // 8168
564 INTT_1 = 0x0001, // 8168
565 INTT_2 = 0x0002, // 8168
566 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100569 TBI_Enable = 0x80,
570 TxFlowCtrl = 0x40,
571 RxFlowCtrl = 0x20,
572 _1000bpsF = 0x10,
573 _100bps = 0x08,
574 _10bps = 0x04,
575 LinkStatus = 0x02,
576 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100579 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200580
581 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100582 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583};
584
Francois Romieu2b7b4312011-04-18 22:53:24 -0700585enum rtl_desc_bit {
586 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
588 RingEnd = (1 << 30), /* End of descriptor ring */
589 FirstFrag = (1 << 29), /* First segment of a packet */
590 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700591};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Francois Romieu2b7b4312011-04-18 22:53:24 -0700593/* Generic case. */
594enum rtl_tx_desc_bit {
595 /* First doubleword. */
596 TD_LSO = (1 << 27), /* Large Send Offload */
597#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Francois Romieu2b7b4312011-04-18 22:53:24 -0700599 /* Second doubleword. */
600 TxVlanTag = (1 << 17), /* Add VLAN tag */
601};
602
603/* 8169, 8168b and 810x except 8102e. */
604enum rtl_tx_desc_bit_0 {
605 /* First doubleword. */
606#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
607 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
608 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
609 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
610};
611
612/* 8102e, 8168c and beyond. */
613enum rtl_tx_desc_bit_1 {
614 /* Second doubleword. */
615#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
616 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
617 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
618 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
619};
620
621static const struct rtl_tx_desc_info {
622 struct {
623 u32 udp;
624 u32 tcp;
625 } checksum;
626 u16 mss_shift;
627 u16 opts_offset;
628} tx_desc_info [] = {
629 [RTL_TD_0] = {
630 .checksum = {
631 .udp = TD0_IP_CS | TD0_UDP_CS,
632 .tcp = TD0_IP_CS | TD0_TCP_CS
633 },
634 .mss_shift = TD0_MSS_SHIFT,
635 .opts_offset = 0
636 },
637 [RTL_TD_1] = {
638 .checksum = {
639 .udp = TD1_IP_CS | TD1_UDP_CS,
640 .tcp = TD1_IP_CS | TD1_TCP_CS
641 },
642 .mss_shift = TD1_MSS_SHIFT,
643 .opts_offset = 1
644 }
645};
646
647enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 /* Rx private */
649 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
650 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
651
652#define RxProtoUDP (PID1)
653#define RxProtoTCP (PID0)
654#define RxProtoIP (PID1 | PID0)
655#define RxProtoMask RxProtoIP
656
657 IPFail = (1 << 16), /* IP checksum failed */
658 UDPFail = (1 << 15), /* UDP/IP checksum failed */
659 TCPFail = (1 << 14), /* TCP/IP checksum failed */
660 RxVlanTag = (1 << 16), /* VLAN tag available */
661};
662
663#define RsvdMask 0x3fffc000
664
665struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200666 __le32 opts1;
667 __le32 opts2;
668 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669};
670
671struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200672 __le32 opts1;
673 __le32 opts2;
674 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675};
676
677struct ring_info {
678 struct sk_buff *skb;
679 u32 len;
680 u8 __pad[sizeof(void *) - sizeof(u32)];
681};
682
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200683enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200684 RTL_FEATURE_WOL = (1 << 0),
685 RTL_FEATURE_MSI = (1 << 1),
686 RTL_FEATURE_GMII = (1 << 2),
hayeswange0c07552012-10-23 20:24:03 +0000687 RTL_FEATURE_FW_LOADED = (1 << 3),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200688};
689
Ivan Vecera355423d2009-02-06 21:49:57 -0800690struct rtl8169_counters {
691 __le64 tx_packets;
692 __le64 rx_packets;
693 __le64 tx_errors;
694 __le32 rx_errors;
695 __le16 rx_missed;
696 __le16 align_errors;
697 __le32 tx_one_collision;
698 __le32 tx_multi_collision;
699 __le64 rx_unicast;
700 __le64 rx_broadcast;
701 __le32 rx_multicast;
702 __le16 tx_aborted;
703 __le16 tx_underun;
704};
705
Francois Romieuda78dbf2012-01-26 14:18:23 +0100706enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100707 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100708 RTL_FLAG_TASK_SLOW_PENDING,
709 RTL_FLAG_TASK_RESET_PENDING,
710 RTL_FLAG_TASK_PHY_PENDING,
711 RTL_FLAG_MAX
712};
713
Junchang Wang8027aa22012-03-04 23:30:32 +0100714struct rtl8169_stats {
715 u64 packets;
716 u64 bytes;
717 struct u64_stats_sync syncp;
718};
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720struct rtl8169_private {
721 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200722 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000723 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700724 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200725 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700726 u16 txd_version;
727 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
729 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
730 u32 dirty_rx;
731 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100732 struct rtl8169_stats rx_stats;
733 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
735 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
736 dma_addr_t TxPhyAddr;
737 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000738 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 struct timer_list timer;
741 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100742
743 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000744
745 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200746 void (*write)(struct rtl8169_private *, int, int);
747 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000748 } mdio_ops;
749
françois romieu065c27c2011-01-03 15:08:12 +0000750 struct pll_power_ops {
751 void (*down)(struct rtl8169_private *);
752 void (*up)(struct rtl8169_private *);
753 } pll_power_ops;
754
Francois Romieud58d46b2011-05-03 16:38:29 +0200755 struct jumbo_ops {
756 void (*enable)(struct rtl8169_private *);
757 void (*disable)(struct rtl8169_private *);
758 } jumbo_ops;
759
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800760 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200761 void (*write)(struct rtl8169_private *, int, int);
762 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800763 } csi_ops;
764
Oliver Neukum54405cd2011-01-06 21:55:13 +0100765 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200766 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000767 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100768 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000769 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800771 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100772
773 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100774 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
775 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100776 struct work_struct work;
777 } wk;
778
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200779 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200780
781 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800782 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000783 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400784 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000785
Francois Romieub6ffd972011-06-17 17:00:05 +0200786 struct rtl_fw {
787 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200788
789#define RTL_VER_SIZE 32
790
791 char version[RTL_VER_SIZE];
792
793 struct rtl_fw_phy_action {
794 __le32 *code;
795 size_t size;
796 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200797 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300798#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800799
800 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801};
802
Ralf Baechle979b6c12005-06-13 14:30:40 -0700803MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700806MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200807module_param_named(debug, debug.msg_enable, int, 0);
808MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809MODULE_LICENSE("GPL");
810MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000811MODULE_FIRMWARE(FIRMWARE_8168D_1);
812MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000813MODULE_FIRMWARE(FIRMWARE_8168E_1);
814MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400815MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800816MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800817MODULE_FIRMWARE(FIRMWARE_8168F_1);
818MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800819MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800820MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800821MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800822MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Francois Romieuda78dbf2012-01-26 14:18:23 +0100824static void rtl_lock_work(struct rtl8169_private *tp)
825{
826 mutex_lock(&tp->wk.mutex);
827}
828
829static void rtl_unlock_work(struct rtl8169_private *tp)
830{
831 mutex_unlock(&tp->wk.mutex);
832}
833
Francois Romieud58d46b2011-05-03 16:38:29 +0200834static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
835{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800836 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
837 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200838}
839
Francois Romieuffc46952012-07-06 14:19:23 +0200840struct rtl_cond {
841 bool (*check)(struct rtl8169_private *);
842 const char *msg;
843};
844
845static void rtl_udelay(unsigned int d)
846{
847 udelay(d);
848}
849
850static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
851 void (*delay)(unsigned int), unsigned int d, int n,
852 bool high)
853{
854 int i;
855
856 for (i = 0; i < n; i++) {
857 delay(d);
858 if (c->check(tp) == high)
859 return true;
860 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200861 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
862 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200863 return false;
864}
865
866static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
867 const struct rtl_cond *c,
868 unsigned int d, int n)
869{
870 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
871}
872
873static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
874 const struct rtl_cond *c,
875 unsigned int d, int n)
876{
877 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
878}
879
880static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
881 const struct rtl_cond *c,
882 unsigned int d, int n)
883{
884 return rtl_loop_wait(tp, c, msleep, d, n, true);
885}
886
887static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
888 const struct rtl_cond *c,
889 unsigned int d, int n)
890{
891 return rtl_loop_wait(tp, c, msleep, d, n, false);
892}
893
894#define DECLARE_RTL_COND(name) \
895static bool name ## _check(struct rtl8169_private *); \
896 \
897static const struct rtl_cond name = { \
898 .check = name ## _check, \
899 .msg = #name \
900}; \
901 \
902static bool name ## _check(struct rtl8169_private *tp)
903
904DECLARE_RTL_COND(rtl_ocpar_cond)
905{
906 void __iomem *ioaddr = tp->mmio_addr;
907
908 return RTL_R32(OCPAR) & OCPAR_FLAG;
909}
910
françois romieub646d902011-01-03 15:08:21 +0000911static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
912{
913 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000914
915 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200916
917 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
918 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000919}
920
921static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
922{
923 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000924
925 RTL_W32(OCPDR, data);
926 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200927
928 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
929}
930
931DECLARE_RTL_COND(rtl_eriar_cond)
932{
933 void __iomem *ioaddr = tp->mmio_addr;
934
935 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000936}
937
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800938static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000939{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800940 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000941
942 RTL_W8(ERIDR, cmd);
943 RTL_W32(ERIAR, 0x800010e8);
944 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200945
946 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
947 return;
françois romieub646d902011-01-03 15:08:21 +0000948
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800949 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000950}
951
952#define OOB_CMD_RESET 0x00
953#define OOB_CMD_DRIVER_START 0x05
954#define OOB_CMD_DRIVER_STOP 0x06
955
Francois Romieucecb5fd2011-04-01 10:21:07 +0200956static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
957{
958 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
959}
960
Francois Romieuffc46952012-07-06 14:19:23 +0200961DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000962{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200963 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000964
Francois Romieucecb5fd2011-04-01 10:21:07 +0200965 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000966
Francois Romieuffc46952012-07-06 14:19:23 +0200967 return ocp_read(tp, 0x0f, reg) & 0x00000800;
968}
969
970static void rtl8168_driver_start(struct rtl8169_private *tp)
971{
972 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
973
974 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000975}
976
977static void rtl8168_driver_stop(struct rtl8169_private *tp)
978{
françois romieub646d902011-01-03 15:08:21 +0000979 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
980
Francois Romieuffc46952012-07-06 14:19:23 +0200981 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000982}
983
hayeswang4804b3b2011-03-21 01:50:29 +0000984static int r8168dp_check_dash(struct rtl8169_private *tp)
985{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200986 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000987
Francois Romieucecb5fd2011-04-01 10:21:07 +0200988 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000989}
françois romieub646d902011-01-03 15:08:21 +0000990
Hayes Wangc5583862012-07-02 17:23:22 +0800991static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
992{
993 if (reg & 0xffff0001) {
994 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
995 return true;
996 }
997 return false;
998}
999
1000DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1001{
1002 void __iomem *ioaddr = tp->mmio_addr;
1003
1004 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1005}
1006
1007static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1008{
1009 void __iomem *ioaddr = tp->mmio_addr;
1010
1011 if (rtl_ocp_reg_failure(tp, reg))
1012 return;
1013
1014 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1015
1016 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1017}
1018
1019static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1020{
1021 void __iomem *ioaddr = tp->mmio_addr;
1022
1023 if (rtl_ocp_reg_failure(tp, reg))
1024 return 0;
1025
1026 RTL_W32(GPHY_OCP, reg << 15);
1027
1028 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1029 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1030}
1031
1032static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1033{
1034 int val;
1035
1036 val = r8168_phy_ocp_read(tp, reg);
1037 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1038}
1039
Hayes Wangc5583862012-07-02 17:23:22 +08001040static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1041{
1042 void __iomem *ioaddr = tp->mmio_addr;
1043
1044 if (rtl_ocp_reg_failure(tp, reg))
1045 return;
1046
1047 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001048}
1049
1050static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1051{
1052 void __iomem *ioaddr = tp->mmio_addr;
1053
1054 if (rtl_ocp_reg_failure(tp, reg))
1055 return 0;
1056
1057 RTL_W32(OCPDR, reg << 15);
1058
Hayes Wang3a83ad12012-07-11 20:31:56 +08001059 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001060}
1061
1062#define OCP_STD_PHY_BASE 0xa400
1063
1064static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1065{
1066 if (reg == 0x1f) {
1067 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1068 return;
1069 }
1070
1071 if (tp->ocp_base != OCP_STD_PHY_BASE)
1072 reg -= 0x10;
1073
1074 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1075}
1076
1077static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1078{
1079 if (tp->ocp_base != OCP_STD_PHY_BASE)
1080 reg -= 0x10;
1081
1082 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1083}
1084
Francois Romieuffc46952012-07-06 14:19:23 +02001085DECLARE_RTL_COND(rtl_phyar_cond)
1086{
1087 void __iomem *ioaddr = tp->mmio_addr;
1088
1089 return RTL_R32(PHYAR) & 0x80000000;
1090}
1091
Francois Romieu24192212012-07-06 20:19:42 +02001092static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Francois Romieu24192212012-07-06 20:19:42 +02001094 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Francois Romieu24192212012-07-06 20:19:42 +02001096 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Francois Romieuffc46952012-07-06 14:19:23 +02001098 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001099 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001100 * According to hardware specs a 20us delay is required after write
1101 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001102 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001103 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
Francois Romieu24192212012-07-06 20:19:42 +02001106static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
Francois Romieu24192212012-07-06 20:19:42 +02001108 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001109 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Francois Romieu24192212012-07-06 20:19:42 +02001111 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Francois Romieuffc46952012-07-06 14:19:23 +02001113 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1114 RTL_R32(PHYAR) & 0xffff : ~0;
1115
Timo Teräs81a95f02010-06-09 17:31:48 -07001116 /*
1117 * According to hardware specs a 20us delay is required after read
1118 * complete indication, but before sending next command.
1119 */
1120 udelay(20);
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return value;
1123}
1124
Francois Romieu24192212012-07-06 20:19:42 +02001125static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001126{
Francois Romieu24192212012-07-06 20:19:42 +02001127 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001128
Francois Romieu24192212012-07-06 20:19:42 +02001129 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001130 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1131 RTL_W32(EPHY_RXER_NUM, 0);
1132
Francois Romieuffc46952012-07-06 14:19:23 +02001133 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001134}
1135
Francois Romieu24192212012-07-06 20:19:42 +02001136static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001137{
Francois Romieu24192212012-07-06 20:19:42 +02001138 r8168dp_1_mdio_access(tp, reg,
1139 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001140}
1141
Francois Romieu24192212012-07-06 20:19:42 +02001142static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001143{
Francois Romieu24192212012-07-06 20:19:42 +02001144 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001145
Francois Romieu24192212012-07-06 20:19:42 +02001146 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001147
1148 mdelay(1);
1149 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1150 RTL_W32(EPHY_RXER_NUM, 0);
1151
Francois Romieuffc46952012-07-06 14:19:23 +02001152 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1153 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001154}
1155
françois romieue6de30d2011-01-03 15:08:37 +00001156#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1157
1158static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1159{
1160 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1161}
1162
1163static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1164{
1165 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1166}
1167
Francois Romieu24192212012-07-06 20:19:42 +02001168static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001169{
Francois Romieu24192212012-07-06 20:19:42 +02001170 void __iomem *ioaddr = tp->mmio_addr;
1171
françois romieue6de30d2011-01-03 15:08:37 +00001172 r8168dp_2_mdio_start(ioaddr);
1173
Francois Romieu24192212012-07-06 20:19:42 +02001174 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001175
1176 r8168dp_2_mdio_stop(ioaddr);
1177}
1178
Francois Romieu24192212012-07-06 20:19:42 +02001179static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001180{
Francois Romieu24192212012-07-06 20:19:42 +02001181 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001182 int value;
1183
1184 r8168dp_2_mdio_start(ioaddr);
1185
Francois Romieu24192212012-07-06 20:19:42 +02001186 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001187
1188 r8168dp_2_mdio_stop(ioaddr);
1189
1190 return value;
1191}
1192
françois romieu4da19632011-01-03 15:07:55 +00001193static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001194{
Francois Romieu24192212012-07-06 20:19:42 +02001195 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001196}
1197
françois romieu4da19632011-01-03 15:07:55 +00001198static int rtl_readphy(struct rtl8169_private *tp, int location)
1199{
Francois Romieu24192212012-07-06 20:19:42 +02001200 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001201}
1202
1203static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1204{
1205 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1206}
1207
1208static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001209{
1210 int val;
1211
françois romieu4da19632011-01-03 15:07:55 +00001212 val = rtl_readphy(tp, reg_addr);
1213 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001214}
1215
Francois Romieuccdffb92008-07-26 14:26:06 +02001216static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1217 int val)
1218{
1219 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001220
françois romieu4da19632011-01-03 15:07:55 +00001221 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001222}
1223
1224static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1225{
1226 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001227
françois romieu4da19632011-01-03 15:07:55 +00001228 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001229}
1230
Francois Romieuffc46952012-07-06 14:19:23 +02001231DECLARE_RTL_COND(rtl_ephyar_cond)
1232{
1233 void __iomem *ioaddr = tp->mmio_addr;
1234
1235 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1236}
1237
Francois Romieufdf6fc02012-07-06 22:40:38 +02001238static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001239{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001240 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001241
1242 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1243 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1244
Francois Romieuffc46952012-07-06 14:19:23 +02001245 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1246
1247 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001248}
1249
Francois Romieufdf6fc02012-07-06 22:40:38 +02001250static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001251{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001252 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001253
1254 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1255
Francois Romieuffc46952012-07-06 14:19:23 +02001256 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1257 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001258}
1259
Francois Romieufdf6fc02012-07-06 22:40:38 +02001260static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1261 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001262{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001263 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001264
1265 BUG_ON((addr & 3) || (mask == 0));
1266 RTL_W32(ERIDR, val);
1267 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1268
Francois Romieuffc46952012-07-06 14:19:23 +02001269 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001270}
1271
Francois Romieufdf6fc02012-07-06 22:40:38 +02001272static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001273{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001274 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001275
1276 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1277
Francois Romieuffc46952012-07-06 14:19:23 +02001278 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1279 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001280}
1281
Francois Romieufdf6fc02012-07-06 22:40:38 +02001282static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1283 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001284{
1285 u32 val;
1286
Francois Romieufdf6fc02012-07-06 22:40:38 +02001287 val = rtl_eri_read(tp, addr, type);
1288 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001289}
1290
françois romieuc28aa382011-08-02 03:53:43 +00001291struct exgmac_reg {
1292 u16 addr;
1293 u16 mask;
1294 u32 val;
1295};
1296
Francois Romieufdf6fc02012-07-06 22:40:38 +02001297static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001298 const struct exgmac_reg *r, int len)
1299{
1300 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001301 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001302 r++;
1303 }
1304}
1305
Francois Romieuffc46952012-07-06 14:19:23 +02001306DECLARE_RTL_COND(rtl_efusear_cond)
1307{
1308 void __iomem *ioaddr = tp->mmio_addr;
1309
1310 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1311}
1312
Francois Romieufdf6fc02012-07-06 22:40:38 +02001313static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001314{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001315 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001316
1317 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1318
Francois Romieuffc46952012-07-06 14:19:23 +02001319 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1320 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001321}
1322
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001323static u16 rtl_get_events(struct rtl8169_private *tp)
1324{
1325 void __iomem *ioaddr = tp->mmio_addr;
1326
1327 return RTL_R16(IntrStatus);
1328}
1329
1330static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1331{
1332 void __iomem *ioaddr = tp->mmio_addr;
1333
1334 RTL_W16(IntrStatus, bits);
1335 mmiowb();
1336}
1337
1338static void rtl_irq_disable(struct rtl8169_private *tp)
1339{
1340 void __iomem *ioaddr = tp->mmio_addr;
1341
1342 RTL_W16(IntrMask, 0);
1343 mmiowb();
1344}
1345
Francois Romieu3e990ff2012-01-26 12:50:01 +01001346static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1347{
1348 void __iomem *ioaddr = tp->mmio_addr;
1349
1350 RTL_W16(IntrMask, bits);
1351}
1352
Francois Romieuda78dbf2012-01-26 14:18:23 +01001353#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1354#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1355#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1356
1357static void rtl_irq_enable_all(struct rtl8169_private *tp)
1358{
1359 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1360}
1361
françois romieu811fd302011-12-04 20:30:45 +00001362static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
françois romieu811fd302011-12-04 20:30:45 +00001364 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001366 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001367 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001368 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369}
1370
françois romieu4da19632011-01-03 15:07:55 +00001371static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
françois romieu4da19632011-01-03 15:07:55 +00001373 void __iomem *ioaddr = tp->mmio_addr;
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return RTL_R32(TBICSR) & TBIReset;
1376}
1377
françois romieu4da19632011-01-03 15:07:55 +00001378static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
françois romieu4da19632011-01-03 15:07:55 +00001380 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381}
1382
1383static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1384{
1385 return RTL_R32(TBICSR) & TBILinkOk;
1386}
1387
1388static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1389{
1390 return RTL_R8(PHYstatus) & LinkStatus;
1391}
1392
françois romieu4da19632011-01-03 15:07:55 +00001393static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
françois romieu4da19632011-01-03 15:07:55 +00001395 void __iomem *ioaddr = tp->mmio_addr;
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1398}
1399
françois romieu4da19632011-01-03 15:07:55 +00001400static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 unsigned int val;
1403
françois romieu4da19632011-01-03 15:07:55 +00001404 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1405 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Hayes Wang70090422011-07-06 15:58:06 +08001408static void rtl_link_chg_patch(struct rtl8169_private *tp)
1409{
1410 void __iomem *ioaddr = tp->mmio_addr;
1411 struct net_device *dev = tp->dev;
1412
1413 if (!netif_running(dev))
1414 return;
1415
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001416 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1417 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001418 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001419 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1420 ERIAR_EXGMAC);
1421 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1422 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001423 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001424 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1425 ERIAR_EXGMAC);
1426 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1427 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001428 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001429 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1430 ERIAR_EXGMAC);
1431 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1432 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001433 }
1434 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001435 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001436 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001437 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001438 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001439 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1440 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1441 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001442 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1443 ERIAR_EXGMAC);
1444 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1445 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001446 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001447 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1448 ERIAR_EXGMAC);
1449 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1450 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001451 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001452 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1453 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001454 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1455 ERIAR_EXGMAC);
1456 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1457 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001458 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001459 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1460 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001461 }
Hayes Wang70090422011-07-06 15:58:06 +08001462 }
1463}
1464
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001465static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001466 struct rtl8169_private *tp,
1467 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001470 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001471 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001472 if (pm)
1473 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001475 if (net_ratelimit())
1476 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001477 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001479 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001480 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001481 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483}
1484
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001485static void rtl8169_check_link_status(struct net_device *dev,
1486 struct rtl8169_private *tp,
1487 void __iomem *ioaddr)
1488{
1489 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1490}
1491
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001492#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1493
1494static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1495{
1496 void __iomem *ioaddr = tp->mmio_addr;
1497 u8 options;
1498 u32 wolopts = 0;
1499
1500 options = RTL_R8(Config1);
1501 if (!(options & PMEnable))
1502 return 0;
1503
1504 options = RTL_R8(Config3);
1505 if (options & LinkUp)
1506 wolopts |= WAKE_PHY;
1507 if (options & MagicPacket)
1508 wolopts |= WAKE_MAGIC;
1509
1510 options = RTL_R8(Config5);
1511 if (options & UWF)
1512 wolopts |= WAKE_UCAST;
1513 if (options & BWF)
1514 wolopts |= WAKE_BCAST;
1515 if (options & MWF)
1516 wolopts |= WAKE_MCAST;
1517
1518 return wolopts;
1519}
1520
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001521static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1522{
1523 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001524
Francois Romieuda78dbf2012-01-26 14:18:23 +01001525 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001527 wol->supported = WAKE_ANY;
1528 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001529
Francois Romieuda78dbf2012-01-26 14:18:23 +01001530 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001531}
1532
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001533static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001535 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001536 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001537 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001538 u32 opt;
1539 u16 reg;
1540 u8 mask;
1541 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001542 { WAKE_PHY, Config3, LinkUp },
1543 { WAKE_MAGIC, Config3, MagicPacket },
1544 { WAKE_UCAST, Config5, UWF },
1545 { WAKE_BCAST, Config5, BWF },
1546 { WAKE_MCAST, Config5, MWF },
1547 { WAKE_ANY, Config5, LanWake }
1548 };
Francois Romieu851e6022012-04-17 11:10:11 +02001549 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001550
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001551 RTL_W8(Cfg9346, Cfg9346_Unlock);
1552
1553 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001554 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001555 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001556 options |= cfg[i].mask;
1557 RTL_W8(cfg[i].reg, options);
1558 }
1559
Francois Romieu851e6022012-04-17 11:10:11 +02001560 switch (tp->mac_version) {
1561 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1562 options = RTL_R8(Config1) & ~PMEnable;
1563 if (wolopts)
1564 options |= PMEnable;
1565 RTL_W8(Config1, options);
1566 break;
1567 default:
Francois Romieud387b422012-04-17 11:12:01 +02001568 options = RTL_R8(Config2) & ~PME_SIGNAL;
1569 if (wolopts)
1570 options |= PME_SIGNAL;
1571 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001572 break;
1573 }
1574
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001575 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001576}
1577
1578static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1579{
1580 struct rtl8169_private *tp = netdev_priv(dev);
1581
Francois Romieuda78dbf2012-01-26 14:18:23 +01001582 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001583
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001584 if (wol->wolopts)
1585 tp->features |= RTL_FEATURE_WOL;
1586 else
1587 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001588 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001589
1590 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001591
françois romieuea809072010-11-08 13:23:58 +00001592 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1593
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001594 return 0;
1595}
1596
Francois Romieu31bd2042011-04-26 18:58:59 +02001597static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1598{
Francois Romieu85bffe62011-04-27 08:22:39 +02001599 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001600}
1601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602static void rtl8169_get_drvinfo(struct net_device *dev,
1603 struct ethtool_drvinfo *info)
1604{
1605 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001606 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
Rick Jones68aad782011-11-07 13:29:27 +00001608 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1609 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1610 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001611 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001612 if (!IS_ERR_OR_NULL(rtl_fw))
1613 strlcpy(info->fw_version, rtl_fw->version,
1614 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615}
1616
1617static int rtl8169_get_regs_len(struct net_device *dev)
1618{
1619 return R8169_REGS_SIZE;
1620}
1621
1622static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001623 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
1625 struct rtl8169_private *tp = netdev_priv(dev);
1626 void __iomem *ioaddr = tp->mmio_addr;
1627 int ret = 0;
1628 u32 reg;
1629
1630 reg = RTL_R32(TBICSR);
1631 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1632 (duplex == DUPLEX_FULL)) {
1633 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1634 } else if (autoneg == AUTONEG_ENABLE)
1635 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1636 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001637 netif_warn(tp, link, dev,
1638 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 ret = -EOPNOTSUPP;
1640 }
1641
1642 return ret;
1643}
1644
1645static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001646 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
1648 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001649 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001650 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Hayes Wang716b50a2011-02-22 17:26:18 +08001652 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001655 int auto_nego;
1656
françois romieu4da19632011-01-03 15:07:55 +00001657 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001658 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1659 ADVERTISE_100HALF | ADVERTISE_100FULL);
1660
1661 if (adv & ADVERTISED_10baseT_Half)
1662 auto_nego |= ADVERTISE_10HALF;
1663 if (adv & ADVERTISED_10baseT_Full)
1664 auto_nego |= ADVERTISE_10FULL;
1665 if (adv & ADVERTISED_100baseT_Half)
1666 auto_nego |= ADVERTISE_100HALF;
1667 if (adv & ADVERTISED_100baseT_Full)
1668 auto_nego |= ADVERTISE_100FULL;
1669
françois romieu3577aa12009-05-19 10:46:48 +00001670 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1671
françois romieu4da19632011-01-03 15:07:55 +00001672 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001673 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1674
1675 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001676 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001677 if (adv & ADVERTISED_1000baseT_Half)
1678 giga_ctrl |= ADVERTISE_1000HALF;
1679 if (adv & ADVERTISED_1000baseT_Full)
1680 giga_ctrl |= ADVERTISE_1000FULL;
1681 } else if (adv & (ADVERTISED_1000baseT_Half |
1682 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001683 netif_info(tp, link, dev,
1684 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001685 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
françois romieu3577aa12009-05-19 10:46:48 +00001688 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001689
françois romieu4da19632011-01-03 15:07:55 +00001690 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1691 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001692 } else {
1693 giga_ctrl = 0;
1694
1695 if (speed == SPEED_10)
1696 bmcr = 0;
1697 else if (speed == SPEED_100)
1698 bmcr = BMCR_SPEED100;
1699 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001700 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001701
1702 if (duplex == DUPLEX_FULL)
1703 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001704 }
1705
françois romieu4da19632011-01-03 15:07:55 +00001706 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001707
Francois Romieucecb5fd2011-04-01 10:21:07 +02001708 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1709 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001710 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001711 rtl_writephy(tp, 0x17, 0x2138);
1712 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001713 } else {
françois romieu4da19632011-01-03 15:07:55 +00001714 rtl_writephy(tp, 0x17, 0x2108);
1715 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001716 }
1717 }
1718
Oliver Neukum54405cd2011-01-06 21:55:13 +01001719 rc = 0;
1720out:
1721 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722}
1723
1724static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001725 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
1727 struct rtl8169_private *tp = netdev_priv(dev);
1728 int ret;
1729
Oliver Neukum54405cd2011-01-06 21:55:13 +01001730 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001731 if (ret < 0)
1732 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Francois Romieu4876cc12011-03-11 21:07:11 +01001734 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1735 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001737 }
1738out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 return ret;
1740}
1741
1742static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1743{
1744 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 int ret;
1746
Francois Romieu4876cc12011-03-11 21:07:11 +01001747 del_timer_sync(&tp->timer);
1748
Francois Romieuda78dbf2012-01-26 14:18:23 +01001749 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001750 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001751 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001752 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return ret;
1755}
1756
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001757static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1758 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
Francois Romieud58d46b2011-05-03 16:38:29 +02001760 struct rtl8169_private *tp = netdev_priv(dev);
1761
Francois Romieu2b7b4312011-04-18 22:53:24 -07001762 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001763 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
Francois Romieud58d46b2011-05-03 16:38:29 +02001765 if (dev->mtu > JUMBO_1K &&
1766 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1767 features &= ~NETIF_F_IP_CSUM;
1768
Michał Mirosław350fb322011-04-08 06:35:56 +00001769 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
Francois Romieuda78dbf2012-01-26 14:18:23 +01001772static void __rtl8169_set_features(struct net_device *dev,
1773 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774{
1775 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001776 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001777 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Ben Greear6bbe0212012-02-10 15:04:33 +00001779 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1780 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Ben Greear6bbe0212012-02-10 15:04:33 +00001782 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1783 if (features & NETIF_F_RXCSUM)
1784 tp->cp_cmd |= RxChkSum;
1785 else
1786 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001787
Ben Greear6bbe0212012-02-10 15:04:33 +00001788 if (dev->features & NETIF_F_HW_VLAN_RX)
1789 tp->cp_cmd |= RxVlan;
1790 else
1791 tp->cp_cmd &= ~RxVlan;
1792
1793 RTL_W16(CPlusCmd, tp->cp_cmd);
1794 RTL_R16(CPlusCmd);
1795 }
1796 if (changed & NETIF_F_RXALL) {
1797 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1798 if (features & NETIF_F_RXALL)
1799 tmp |= (AcceptErr | AcceptRunt);
1800 RTL_W32(RxConfig, tmp);
1801 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001802}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Francois Romieuda78dbf2012-01-26 14:18:23 +01001804static int rtl8169_set_features(struct net_device *dev,
1805 netdev_features_t features)
1806{
1807 struct rtl8169_private *tp = netdev_priv(dev);
1808
1809 rtl_lock_work(tp);
1810 __rtl8169_set_features(dev, features);
1811 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 return 0;
1814}
1815
Francois Romieuda78dbf2012-01-26 14:18:23 +01001816
Kirill Smelkov810f4892012-11-10 21:11:02 +04001817static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818{
Jesse Grosseab6d182010-10-20 13:56:03 +00001819 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1821}
1822
Francois Romieu7a8fc772011-03-01 17:18:33 +01001823static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824{
1825 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Francois Romieu7a8fc772011-03-01 17:18:33 +01001827 if (opts2 & RxVlanTag)
1828 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829}
1830
Francois Romieuccdffb92008-07-26 14:26:06 +02001831static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832{
1833 struct rtl8169_private *tp = netdev_priv(dev);
1834 void __iomem *ioaddr = tp->mmio_addr;
1835 u32 status;
1836
1837 cmd->supported =
1838 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1839 cmd->port = PORT_FIBRE;
1840 cmd->transceiver = XCVR_INTERNAL;
1841
1842 status = RTL_R32(TBICSR);
1843 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1844 cmd->autoneg = !!(status & TBINwEnable);
1845
David Decotigny70739492011-04-27 18:32:40 +00001846 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001848
1849 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850}
1851
Francois Romieuccdffb92008-07-26 14:26:06 +02001852static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853{
1854 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855
Francois Romieuccdffb92008-07-26 14:26:06 +02001856 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857}
1858
1859static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1860{
1861 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001862 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Francois Romieuda78dbf2012-01-26 14:18:23 +01001864 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001865 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001866 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
Francois Romieuccdffb92008-07-26 14:26:06 +02001868 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869}
1870
1871static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1872 void *p)
1873{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001874 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Francois Romieu5b0384f2006-08-16 16:00:01 +02001876 if (regs->len > R8169_REGS_SIZE)
1877 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
Francois Romieuda78dbf2012-01-26 14:18:23 +01001879 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001880 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001881 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882}
1883
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001884static u32 rtl8169_get_msglevel(struct net_device *dev)
1885{
1886 struct rtl8169_private *tp = netdev_priv(dev);
1887
1888 return tp->msg_enable;
1889}
1890
1891static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1892{
1893 struct rtl8169_private *tp = netdev_priv(dev);
1894
1895 tp->msg_enable = value;
1896}
1897
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001898static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1899 "tx_packets",
1900 "rx_packets",
1901 "tx_errors",
1902 "rx_errors",
1903 "rx_missed",
1904 "align_errors",
1905 "tx_single_collisions",
1906 "tx_multi_collisions",
1907 "unicast",
1908 "broadcast",
1909 "multicast",
1910 "tx_aborted",
1911 "tx_underrun",
1912};
1913
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001914static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001915{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001916 switch (sset) {
1917 case ETH_SS_STATS:
1918 return ARRAY_SIZE(rtl8169_gstrings);
1919 default:
1920 return -EOPNOTSUPP;
1921 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001922}
1923
Francois Romieuffc46952012-07-06 14:19:23 +02001924DECLARE_RTL_COND(rtl_counters_cond)
1925{
1926 void __iomem *ioaddr = tp->mmio_addr;
1927
1928 return RTL_R32(CounterAddrLow) & CounterDump;
1929}
1930
Ivan Vecera355423d2009-02-06 21:49:57 -08001931static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001932{
1933 struct rtl8169_private *tp = netdev_priv(dev);
1934 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001935 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001936 struct rtl8169_counters *counters;
1937 dma_addr_t paddr;
1938 u32 cmd;
1939
Ivan Vecera355423d2009-02-06 21:49:57 -08001940 /*
1941 * Some chips are unable to dump tally counters when the receiver
1942 * is disabled.
1943 */
1944 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1945 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001946
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001947 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001948 if (!counters)
1949 return;
1950
1951 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001952 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001953 RTL_W32(CounterAddrLow, cmd);
1954 RTL_W32(CounterAddrLow, cmd | CounterDump);
1955
Francois Romieuffc46952012-07-06 14:19:23 +02001956 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1957 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001958
1959 RTL_W32(CounterAddrLow, 0);
1960 RTL_W32(CounterAddrHigh, 0);
1961
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001962 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001963}
1964
Ivan Vecera355423d2009-02-06 21:49:57 -08001965static void rtl8169_get_ethtool_stats(struct net_device *dev,
1966 struct ethtool_stats *stats, u64 *data)
1967{
1968 struct rtl8169_private *tp = netdev_priv(dev);
1969
1970 ASSERT_RTNL();
1971
1972 rtl8169_update_counters(dev);
1973
1974 data[0] = le64_to_cpu(tp->counters.tx_packets);
1975 data[1] = le64_to_cpu(tp->counters.rx_packets);
1976 data[2] = le64_to_cpu(tp->counters.tx_errors);
1977 data[3] = le32_to_cpu(tp->counters.rx_errors);
1978 data[4] = le16_to_cpu(tp->counters.rx_missed);
1979 data[5] = le16_to_cpu(tp->counters.align_errors);
1980 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1981 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1982 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1983 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1984 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1985 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1986 data[12] = le16_to_cpu(tp->counters.tx_underun);
1987}
1988
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001989static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1990{
1991 switch(stringset) {
1992 case ETH_SS_STATS:
1993 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1994 break;
1995 }
1996}
1997
Jeff Garzik7282d492006-09-13 14:30:00 -04001998static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 .get_drvinfo = rtl8169_get_drvinfo,
2000 .get_regs_len = rtl8169_get_regs_len,
2001 .get_link = ethtool_op_get_link,
2002 .get_settings = rtl8169_get_settings,
2003 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002004 .get_msglevel = rtl8169_get_msglevel,
2005 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002007 .get_wol = rtl8169_get_wol,
2008 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002009 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002010 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002011 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002012 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013};
2014
Francois Romieu07d3f512007-02-21 22:40:46 +01002015static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002016 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017{
Francois Romieu5d320a22011-05-08 17:47:36 +02002018 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002019 /*
2020 * The driver currently handles the 8168Bf and the 8168Be identically
2021 * but they can be identified more specifically through the test below
2022 * if needed:
2023 *
2024 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002025 *
2026 * Same thing for the 8101Eb and the 8101Ec:
2027 *
2028 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002029 */
Francois Romieu37441002011-06-17 22:58:54 +02002030 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002032 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 int mac_version;
2034 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002035 /* 8168G family. */
2036 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2037 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2038
Hayes Wangc2218922011-09-06 16:55:18 +08002039 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002040 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002041 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2042 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2043
hayeswang01dc7fe2011-03-21 01:50:28 +00002044 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002045 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002046 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2047 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2048 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2049
Francois Romieu5b538df2008-07-20 16:22:45 +02002050 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002051 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2052 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002053 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002054
françois romieue6de30d2011-01-03 15:08:37 +00002055 /* 8168DP family. */
2056 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2057 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002058 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002059
Francois Romieuef808d52008-06-29 13:10:54 +02002060 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002061 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002062 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002063 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002064 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002065 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2066 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002067 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002068 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002069 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002070
2071 /* 8168B family. */
2072 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2073 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2074 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2075 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2076
2077 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002078 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2079 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002080 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002081 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002082 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2083 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2084 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002085 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2086 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2087 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2088 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2089 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2090 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002091 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002092 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002093 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002094 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2095 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002096 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2097 /* FIXME: where did these entries come from ? -- FR */
2098 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2099 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2100
2101 /* 8110 family. */
2102 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2103 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2104 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2105 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2106 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2107 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2108
Jean Delvaref21b75e2009-05-26 20:54:48 -07002109 /* Catch-all */
2110 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002111 };
2112 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 u32 reg;
2114
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002115 reg = RTL_R32(TxConfig);
2116 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 p++;
2118 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002119
2120 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2121 netif_notice(tp, probe, dev,
2122 "unknown MAC, using family default\n");
2123 tp->mac_version = default_version;
2124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125}
2126
2127static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2128{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002129 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130}
2131
Francois Romieu867763c2007-08-17 18:21:58 +02002132struct phy_reg {
2133 u16 reg;
2134 u16 val;
2135};
2136
françois romieu4da19632011-01-03 15:07:55 +00002137static void rtl_writephy_batch(struct rtl8169_private *tp,
2138 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002139{
2140 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002141 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002142 regs++;
2143 }
2144}
2145
françois romieubca03d52011-01-03 15:07:31 +00002146#define PHY_READ 0x00000000
2147#define PHY_DATA_OR 0x10000000
2148#define PHY_DATA_AND 0x20000000
2149#define PHY_BJMPN 0x30000000
2150#define PHY_READ_EFUSE 0x40000000
2151#define PHY_READ_MAC_BYTE 0x50000000
2152#define PHY_WRITE_MAC_BYTE 0x60000000
2153#define PHY_CLEAR_READCOUNT 0x70000000
2154#define PHY_WRITE 0x80000000
2155#define PHY_READCOUNT_EQ_SKIP 0x90000000
2156#define PHY_COMP_EQ_SKIPN 0xa0000000
2157#define PHY_COMP_NEQ_SKIPN 0xb0000000
2158#define PHY_WRITE_PREVIOUS 0xc0000000
2159#define PHY_SKIPN 0xd0000000
2160#define PHY_DELAY_MS 0xe0000000
2161#define PHY_WRITE_ERI_WORD 0xf0000000
2162
Hayes Wang960aee62011-06-18 11:37:48 +02002163struct fw_info {
2164 u32 magic;
2165 char version[RTL_VER_SIZE];
2166 __le32 fw_start;
2167 __le32 fw_len;
2168 u8 chksum;
2169} __packed;
2170
Francois Romieu1c361ef2011-06-17 17:16:24 +02002171#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2172
2173static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002174{
Francois Romieub6ffd972011-06-17 17:00:05 +02002175 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002176 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002177 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2178 char *version = rtl_fw->version;
2179 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002180
Francois Romieu1c361ef2011-06-17 17:16:24 +02002181 if (fw->size < FW_OPCODE_SIZE)
2182 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002183
2184 if (!fw_info->magic) {
2185 size_t i, size, start;
2186 u8 checksum = 0;
2187
2188 if (fw->size < sizeof(*fw_info))
2189 goto out;
2190
2191 for (i = 0; i < fw->size; i++)
2192 checksum += fw->data[i];
2193 if (checksum != 0)
2194 goto out;
2195
2196 start = le32_to_cpu(fw_info->fw_start);
2197 if (start > fw->size)
2198 goto out;
2199
2200 size = le32_to_cpu(fw_info->fw_len);
2201 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2202 goto out;
2203
2204 memcpy(version, fw_info->version, RTL_VER_SIZE);
2205
2206 pa->code = (__le32 *)(fw->data + start);
2207 pa->size = size;
2208 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002209 if (fw->size % FW_OPCODE_SIZE)
2210 goto out;
2211
2212 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2213
2214 pa->code = (__le32 *)fw->data;
2215 pa->size = fw->size / FW_OPCODE_SIZE;
2216 }
2217 version[RTL_VER_SIZE - 1] = 0;
2218
2219 rc = true;
2220out:
2221 return rc;
2222}
2223
Francois Romieufd112f22011-06-18 00:10:29 +02002224static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2225 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002226{
Francois Romieufd112f22011-06-18 00:10:29 +02002227 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002228 size_t index;
2229
Francois Romieu1c361ef2011-06-17 17:16:24 +02002230 for (index = 0; index < pa->size; index++) {
2231 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002232 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002233
hayeswang42b82dc2011-01-10 02:07:25 +00002234 switch(action & 0xf0000000) {
2235 case PHY_READ:
2236 case PHY_DATA_OR:
2237 case PHY_DATA_AND:
2238 case PHY_READ_EFUSE:
2239 case PHY_CLEAR_READCOUNT:
2240 case PHY_WRITE:
2241 case PHY_WRITE_PREVIOUS:
2242 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002243 break;
2244
hayeswang42b82dc2011-01-10 02:07:25 +00002245 case PHY_BJMPN:
2246 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002247 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002248 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002249 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002250 }
2251 break;
2252 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002253 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002254 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002255 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002256 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002257 }
2258 break;
2259 case PHY_COMP_EQ_SKIPN:
2260 case PHY_COMP_NEQ_SKIPN:
2261 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002262 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002263 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002264 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002265 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002266 }
2267 break;
2268
2269 case PHY_READ_MAC_BYTE:
2270 case PHY_WRITE_MAC_BYTE:
2271 case PHY_WRITE_ERI_WORD:
2272 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002273 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002274 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002275 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002276 }
2277 }
Francois Romieufd112f22011-06-18 00:10:29 +02002278 rc = true;
2279out:
2280 return rc;
2281}
françois romieubca03d52011-01-03 15:07:31 +00002282
Francois Romieufd112f22011-06-18 00:10:29 +02002283static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2284{
2285 struct net_device *dev = tp->dev;
2286 int rc = -EINVAL;
2287
2288 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2289 netif_err(tp, ifup, dev, "invalid firwmare\n");
2290 goto out;
2291 }
2292
2293 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2294 rc = 0;
2295out:
2296 return rc;
2297}
2298
2299static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2300{
2301 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2302 u32 predata, count;
2303 size_t index;
2304
2305 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002306
Francois Romieu1c361ef2011-06-17 17:16:24 +02002307 for (index = 0; index < pa->size; ) {
2308 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002309 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002310 u32 regno = (action & 0x0fff0000) >> 16;
2311
2312 if (!action)
2313 break;
françois romieubca03d52011-01-03 15:07:31 +00002314
2315 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002316 case PHY_READ:
2317 predata = rtl_readphy(tp, regno);
2318 count++;
2319 index++;
françois romieubca03d52011-01-03 15:07:31 +00002320 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002321 case PHY_DATA_OR:
2322 predata |= data;
2323 index++;
2324 break;
2325 case PHY_DATA_AND:
2326 predata &= data;
2327 index++;
2328 break;
2329 case PHY_BJMPN:
2330 index -= regno;
2331 break;
2332 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002333 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002334 index++;
2335 break;
2336 case PHY_CLEAR_READCOUNT:
2337 count = 0;
2338 index++;
2339 break;
2340 case PHY_WRITE:
2341 rtl_writephy(tp, regno, data);
2342 index++;
2343 break;
2344 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002345 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002346 break;
2347 case PHY_COMP_EQ_SKIPN:
2348 if (predata == data)
2349 index += regno;
2350 index++;
2351 break;
2352 case PHY_COMP_NEQ_SKIPN:
2353 if (predata != data)
2354 index += regno;
2355 index++;
2356 break;
2357 case PHY_WRITE_PREVIOUS:
2358 rtl_writephy(tp, regno, predata);
2359 index++;
2360 break;
2361 case PHY_SKIPN:
2362 index += regno + 1;
2363 break;
2364 case PHY_DELAY_MS:
2365 mdelay(data);
2366 index++;
2367 break;
2368
2369 case PHY_READ_MAC_BYTE:
2370 case PHY_WRITE_MAC_BYTE:
2371 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002372 default:
2373 BUG();
2374 }
2375 }
2376}
2377
françois romieuf1e02ed2011-01-13 13:07:53 +00002378static void rtl_release_firmware(struct rtl8169_private *tp)
2379{
Francois Romieub6ffd972011-06-17 17:00:05 +02002380 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2381 release_firmware(tp->rtl_fw->fw);
2382 kfree(tp->rtl_fw);
2383 }
2384 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002385}
2386
François Romieu953a12c2011-04-24 17:38:48 +02002387static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002388{
Francois Romieub6ffd972011-06-17 17:00:05 +02002389 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002390
2391 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002392 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002393 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002394 tp->features |= RTL_FEATURE_FW_LOADED;
2395 }
François Romieu953a12c2011-04-24 17:38:48 +02002396}
2397
2398static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2399{
2400 if (rtl_readphy(tp, reg) != val)
2401 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2402 else
2403 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002404}
2405
hayeswange0c07552012-10-23 20:24:03 +00002406static void r810x_aldps_disable(struct rtl8169_private *tp)
2407{
2408 rtl_writephy(tp, 0x1f, 0x0000);
2409 rtl_writephy(tp, 0x18, 0x0310);
2410 msleep(100);
2411}
2412
2413static void r810x_aldps_enable(struct rtl8169_private *tp)
2414{
2415 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2416 return;
2417
2418 rtl_writephy(tp, 0x1f, 0x0000);
2419 rtl_writephy(tp, 0x18, 0x8310);
2420}
2421
2422static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2423{
2424 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2425 return;
2426
2427 rtl_writephy(tp, 0x1f, 0x0000);
2428 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2429}
2430
françois romieu4da19632011-01-03 15:07:55 +00002431static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002433 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002434 { 0x1f, 0x0001 },
2435 { 0x06, 0x006e },
2436 { 0x08, 0x0708 },
2437 { 0x15, 0x4000 },
2438 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
françois romieu0b9b5712009-08-10 19:44:56 +00002440 { 0x1f, 0x0001 },
2441 { 0x03, 0x00a1 },
2442 { 0x02, 0x0008 },
2443 { 0x01, 0x0120 },
2444 { 0x00, 0x1000 },
2445 { 0x04, 0x0800 },
2446 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
françois romieu0b9b5712009-08-10 19:44:56 +00002448 { 0x03, 0xff41 },
2449 { 0x02, 0xdf60 },
2450 { 0x01, 0x0140 },
2451 { 0x00, 0x0077 },
2452 { 0x04, 0x7800 },
2453 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
françois romieu0b9b5712009-08-10 19:44:56 +00002455 { 0x03, 0x802f },
2456 { 0x02, 0x4f02 },
2457 { 0x01, 0x0409 },
2458 { 0x00, 0xf0f9 },
2459 { 0x04, 0x9800 },
2460 { 0x04, 0x9000 },
2461
2462 { 0x03, 0xdf01 },
2463 { 0x02, 0xdf20 },
2464 { 0x01, 0xff95 },
2465 { 0x00, 0xba00 },
2466 { 0x04, 0xa800 },
2467 { 0x04, 0xa000 },
2468
2469 { 0x03, 0xff41 },
2470 { 0x02, 0xdf20 },
2471 { 0x01, 0x0140 },
2472 { 0x00, 0x00bb },
2473 { 0x04, 0xb800 },
2474 { 0x04, 0xb000 },
2475
2476 { 0x03, 0xdf41 },
2477 { 0x02, 0xdc60 },
2478 { 0x01, 0x6340 },
2479 { 0x00, 0x007d },
2480 { 0x04, 0xd800 },
2481 { 0x04, 0xd000 },
2482
2483 { 0x03, 0xdf01 },
2484 { 0x02, 0xdf20 },
2485 { 0x01, 0x100a },
2486 { 0x00, 0xa0ff },
2487 { 0x04, 0xf800 },
2488 { 0x04, 0xf000 },
2489
2490 { 0x1f, 0x0000 },
2491 { 0x0b, 0x0000 },
2492 { 0x00, 0x9200 }
2493 };
2494
françois romieu4da19632011-01-03 15:07:55 +00002495 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496}
2497
françois romieu4da19632011-01-03 15:07:55 +00002498static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002499{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002500 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002501 { 0x1f, 0x0002 },
2502 { 0x01, 0x90d0 },
2503 { 0x1f, 0x0000 }
2504 };
2505
françois romieu4da19632011-01-03 15:07:55 +00002506 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002507}
2508
françois romieu4da19632011-01-03 15:07:55 +00002509static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002510{
2511 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002512
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002513 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2514 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002515 return;
2516
françois romieu4da19632011-01-03 15:07:55 +00002517 rtl_writephy(tp, 0x1f, 0x0001);
2518 rtl_writephy(tp, 0x10, 0xf01b);
2519 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002520}
2521
françois romieu4da19632011-01-03 15:07:55 +00002522static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002523{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002524 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002525 { 0x1f, 0x0001 },
2526 { 0x04, 0x0000 },
2527 { 0x03, 0x00a1 },
2528 { 0x02, 0x0008 },
2529 { 0x01, 0x0120 },
2530 { 0x00, 0x1000 },
2531 { 0x04, 0x0800 },
2532 { 0x04, 0x9000 },
2533 { 0x03, 0x802f },
2534 { 0x02, 0x4f02 },
2535 { 0x01, 0x0409 },
2536 { 0x00, 0xf099 },
2537 { 0x04, 0x9800 },
2538 { 0x04, 0xa000 },
2539 { 0x03, 0xdf01 },
2540 { 0x02, 0xdf20 },
2541 { 0x01, 0xff95 },
2542 { 0x00, 0xba00 },
2543 { 0x04, 0xa800 },
2544 { 0x04, 0xf000 },
2545 { 0x03, 0xdf01 },
2546 { 0x02, 0xdf20 },
2547 { 0x01, 0x101a },
2548 { 0x00, 0xa0ff },
2549 { 0x04, 0xf800 },
2550 { 0x04, 0x0000 },
2551 { 0x1f, 0x0000 },
2552
2553 { 0x1f, 0x0001 },
2554 { 0x10, 0xf41b },
2555 { 0x14, 0xfb54 },
2556 { 0x18, 0xf5c7 },
2557 { 0x1f, 0x0000 },
2558
2559 { 0x1f, 0x0001 },
2560 { 0x17, 0x0cc0 },
2561 { 0x1f, 0x0000 }
2562 };
2563
françois romieu4da19632011-01-03 15:07:55 +00002564 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002565
françois romieu4da19632011-01-03 15:07:55 +00002566 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002567}
2568
françois romieu4da19632011-01-03 15:07:55 +00002569static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002570{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002571 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002572 { 0x1f, 0x0001 },
2573 { 0x04, 0x0000 },
2574 { 0x03, 0x00a1 },
2575 { 0x02, 0x0008 },
2576 { 0x01, 0x0120 },
2577 { 0x00, 0x1000 },
2578 { 0x04, 0x0800 },
2579 { 0x04, 0x9000 },
2580 { 0x03, 0x802f },
2581 { 0x02, 0x4f02 },
2582 { 0x01, 0x0409 },
2583 { 0x00, 0xf099 },
2584 { 0x04, 0x9800 },
2585 { 0x04, 0xa000 },
2586 { 0x03, 0xdf01 },
2587 { 0x02, 0xdf20 },
2588 { 0x01, 0xff95 },
2589 { 0x00, 0xba00 },
2590 { 0x04, 0xa800 },
2591 { 0x04, 0xf000 },
2592 { 0x03, 0xdf01 },
2593 { 0x02, 0xdf20 },
2594 { 0x01, 0x101a },
2595 { 0x00, 0xa0ff },
2596 { 0x04, 0xf800 },
2597 { 0x04, 0x0000 },
2598 { 0x1f, 0x0000 },
2599
2600 { 0x1f, 0x0001 },
2601 { 0x0b, 0x8480 },
2602 { 0x1f, 0x0000 },
2603
2604 { 0x1f, 0x0001 },
2605 { 0x18, 0x67c7 },
2606 { 0x04, 0x2000 },
2607 { 0x03, 0x002f },
2608 { 0x02, 0x4360 },
2609 { 0x01, 0x0109 },
2610 { 0x00, 0x3022 },
2611 { 0x04, 0x2800 },
2612 { 0x1f, 0x0000 },
2613
2614 { 0x1f, 0x0001 },
2615 { 0x17, 0x0cc0 },
2616 { 0x1f, 0x0000 }
2617 };
2618
françois romieu4da19632011-01-03 15:07:55 +00002619 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002620}
2621
françois romieu4da19632011-01-03 15:07:55 +00002622static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002623{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002624 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002625 { 0x10, 0xf41b },
2626 { 0x1f, 0x0000 }
2627 };
2628
françois romieu4da19632011-01-03 15:07:55 +00002629 rtl_writephy(tp, 0x1f, 0x0001);
2630 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002631
françois romieu4da19632011-01-03 15:07:55 +00002632 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002633}
2634
françois romieu4da19632011-01-03 15:07:55 +00002635static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002636{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002637 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002638 { 0x1f, 0x0001 },
2639 { 0x10, 0xf41b },
2640 { 0x1f, 0x0000 }
2641 };
2642
françois romieu4da19632011-01-03 15:07:55 +00002643 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002644}
2645
françois romieu4da19632011-01-03 15:07:55 +00002646static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002647{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002648 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002649 { 0x1f, 0x0000 },
2650 { 0x1d, 0x0f00 },
2651 { 0x1f, 0x0002 },
2652 { 0x0c, 0x1ec8 },
2653 { 0x1f, 0x0000 }
2654 };
2655
françois romieu4da19632011-01-03 15:07:55 +00002656 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002657}
2658
françois romieu4da19632011-01-03 15:07:55 +00002659static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002660{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002661 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002662 { 0x1f, 0x0001 },
2663 { 0x1d, 0x3d98 },
2664 { 0x1f, 0x0000 }
2665 };
2666
françois romieu4da19632011-01-03 15:07:55 +00002667 rtl_writephy(tp, 0x1f, 0x0000);
2668 rtl_patchphy(tp, 0x14, 1 << 5);
2669 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002670
françois romieu4da19632011-01-03 15:07:55 +00002671 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002672}
2673
françois romieu4da19632011-01-03 15:07:55 +00002674static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002675{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002676 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002677 { 0x1f, 0x0001 },
2678 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002679 { 0x1f, 0x0002 },
2680 { 0x00, 0x88d4 },
2681 { 0x01, 0x82b1 },
2682 { 0x03, 0x7002 },
2683 { 0x08, 0x9e30 },
2684 { 0x09, 0x01f0 },
2685 { 0x0a, 0x5500 },
2686 { 0x0c, 0x00c8 },
2687 { 0x1f, 0x0003 },
2688 { 0x12, 0xc096 },
2689 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002690 { 0x1f, 0x0000 },
2691 { 0x1f, 0x0000 },
2692 { 0x09, 0x2000 },
2693 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002694 };
2695
françois romieu4da19632011-01-03 15:07:55 +00002696 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002697
françois romieu4da19632011-01-03 15:07:55 +00002698 rtl_patchphy(tp, 0x14, 1 << 5);
2699 rtl_patchphy(tp, 0x0d, 1 << 5);
2700 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002701}
2702
françois romieu4da19632011-01-03 15:07:55 +00002703static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002704{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002705 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002706 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002707 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002708 { 0x03, 0x802f },
2709 { 0x02, 0x4f02 },
2710 { 0x01, 0x0409 },
2711 { 0x00, 0xf099 },
2712 { 0x04, 0x9800 },
2713 { 0x04, 0x9000 },
2714 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002715 { 0x1f, 0x0002 },
2716 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002717 { 0x06, 0x0761 },
2718 { 0x1f, 0x0003 },
2719 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002720 { 0x1f, 0x0000 }
2721 };
2722
françois romieu4da19632011-01-03 15:07:55 +00002723 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002724
françois romieu4da19632011-01-03 15:07:55 +00002725 rtl_patchphy(tp, 0x16, 1 << 0);
2726 rtl_patchphy(tp, 0x14, 1 << 5);
2727 rtl_patchphy(tp, 0x0d, 1 << 5);
2728 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002729}
2730
françois romieu4da19632011-01-03 15:07:55 +00002731static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002732{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002733 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002734 { 0x1f, 0x0001 },
2735 { 0x12, 0x2300 },
2736 { 0x1d, 0x3d98 },
2737 { 0x1f, 0x0002 },
2738 { 0x0c, 0x7eb8 },
2739 { 0x06, 0x5461 },
2740 { 0x1f, 0x0003 },
2741 { 0x16, 0x0f0a },
2742 { 0x1f, 0x0000 }
2743 };
2744
françois romieu4da19632011-01-03 15:07:55 +00002745 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002746
françois romieu4da19632011-01-03 15:07:55 +00002747 rtl_patchphy(tp, 0x16, 1 << 0);
2748 rtl_patchphy(tp, 0x14, 1 << 5);
2749 rtl_patchphy(tp, 0x0d, 1 << 5);
2750 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002751}
2752
françois romieu4da19632011-01-03 15:07:55 +00002753static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002754{
françois romieu4da19632011-01-03 15:07:55 +00002755 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002756}
2757
françois romieubca03d52011-01-03 15:07:31 +00002758static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002759{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002760 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002761 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002762 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002763 { 0x06, 0x4064 },
2764 { 0x07, 0x2863 },
2765 { 0x08, 0x059c },
2766 { 0x09, 0x26b4 },
2767 { 0x0a, 0x6a19 },
2768 { 0x0b, 0xdcc8 },
2769 { 0x10, 0xf06d },
2770 { 0x14, 0x7f68 },
2771 { 0x18, 0x7fd9 },
2772 { 0x1c, 0xf0ff },
2773 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002774 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002775 { 0x12, 0xf49f },
2776 { 0x13, 0x070b },
2777 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002778 { 0x14, 0x94c0 },
2779
2780 /*
2781 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002782 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002783 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002784 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002785 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002786 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002787 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002788 { 0x06, 0x5561 },
2789
2790 /*
2791 * Can not link to 1Gbps with bad cable
2792 * Decrease SNR threshold form 21.07dB to 19.04dB
2793 */
2794 { 0x1f, 0x0001 },
2795 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002796
2797 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002798 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002799 };
2800
françois romieu4da19632011-01-03 15:07:55 +00002801 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002802
françois romieubca03d52011-01-03 15:07:31 +00002803 /*
2804 * Rx Error Issue
2805 * Fine Tune Switching regulator parameter
2806 */
françois romieu4da19632011-01-03 15:07:55 +00002807 rtl_writephy(tp, 0x1f, 0x0002);
2808 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2809 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002810
Francois Romieufdf6fc02012-07-06 22:40:38 +02002811 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002812 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002813 { 0x1f, 0x0002 },
2814 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002815 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002816 { 0x05, 0x8330 },
2817 { 0x06, 0x669a },
2818 { 0x1f, 0x0002 }
2819 };
2820 int val;
2821
françois romieu4da19632011-01-03 15:07:55 +00002822 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002823
françois romieu4da19632011-01-03 15:07:55 +00002824 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002825
2826 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002827 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002828 0x0065, 0x0066, 0x0067, 0x0068,
2829 0x0069, 0x006a, 0x006b, 0x006c
2830 };
2831 int i;
2832
françois romieu4da19632011-01-03 15:07:55 +00002833 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002834
2835 val &= 0xff00;
2836 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002837 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002838 }
2839 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002840 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002841 { 0x1f, 0x0002 },
2842 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002843 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002844 { 0x05, 0x8330 },
2845 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002846 };
2847
françois romieu4da19632011-01-03 15:07:55 +00002848 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002849 }
2850
françois romieubca03d52011-01-03 15:07:31 +00002851 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002852 rtl_writephy(tp, 0x1f, 0x0002);
2853 rtl_patchphy(tp, 0x0d, 0x0300);
2854 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002855
françois romieubca03d52011-01-03 15:07:31 +00002856 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002857 rtl_writephy(tp, 0x1f, 0x0002);
2858 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2859 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002860
françois romieu4da19632011-01-03 15:07:55 +00002861 rtl_writephy(tp, 0x1f, 0x0005);
2862 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002863
2864 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002865
françois romieu4da19632011-01-03 15:07:55 +00002866 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002867}
2868
françois romieubca03d52011-01-03 15:07:31 +00002869static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002870{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002871 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002872 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002873 { 0x1f, 0x0001 },
2874 { 0x06, 0x4064 },
2875 { 0x07, 0x2863 },
2876 { 0x08, 0x059c },
2877 { 0x09, 0x26b4 },
2878 { 0x0a, 0x6a19 },
2879 { 0x0b, 0xdcc8 },
2880 { 0x10, 0xf06d },
2881 { 0x14, 0x7f68 },
2882 { 0x18, 0x7fd9 },
2883 { 0x1c, 0xf0ff },
2884 { 0x1d, 0x3d9c },
2885 { 0x1f, 0x0003 },
2886 { 0x12, 0xf49f },
2887 { 0x13, 0x070b },
2888 { 0x1a, 0x05ad },
2889 { 0x14, 0x94c0 },
2890
françois romieubca03d52011-01-03 15:07:31 +00002891 /*
2892 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002893 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002894 */
françois romieudaf9df62009-10-07 12:44:20 +00002895 { 0x1f, 0x0002 },
2896 { 0x06, 0x5561 },
2897 { 0x1f, 0x0005 },
2898 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002899 { 0x06, 0x5561 },
2900
2901 /*
2902 * Can not link to 1Gbps with bad cable
2903 * Decrease SNR threshold form 21.07dB to 19.04dB
2904 */
2905 { 0x1f, 0x0001 },
2906 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002907
2908 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002909 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002910 };
2911
françois romieu4da19632011-01-03 15:07:55 +00002912 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002913
Francois Romieufdf6fc02012-07-06 22:40:38 +02002914 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002915 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002916 { 0x1f, 0x0002 },
2917 { 0x05, 0x669a },
2918 { 0x1f, 0x0005 },
2919 { 0x05, 0x8330 },
2920 { 0x06, 0x669a },
2921
2922 { 0x1f, 0x0002 }
2923 };
2924 int val;
2925
françois romieu4da19632011-01-03 15:07:55 +00002926 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002927
françois romieu4da19632011-01-03 15:07:55 +00002928 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002929 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002930 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002931 0x0065, 0x0066, 0x0067, 0x0068,
2932 0x0069, 0x006a, 0x006b, 0x006c
2933 };
2934 int i;
2935
françois romieu4da19632011-01-03 15:07:55 +00002936 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002937
2938 val &= 0xff00;
2939 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002940 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002941 }
2942 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002943 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002944 { 0x1f, 0x0002 },
2945 { 0x05, 0x2642 },
2946 { 0x1f, 0x0005 },
2947 { 0x05, 0x8330 },
2948 { 0x06, 0x2642 }
2949 };
2950
françois romieu4da19632011-01-03 15:07:55 +00002951 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002952 }
2953
françois romieubca03d52011-01-03 15:07:31 +00002954 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002955 rtl_writephy(tp, 0x1f, 0x0002);
2956 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2957 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002958
françois romieubca03d52011-01-03 15:07:31 +00002959 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002960 rtl_writephy(tp, 0x1f, 0x0002);
2961 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002962
françois romieu4da19632011-01-03 15:07:55 +00002963 rtl_writephy(tp, 0x1f, 0x0005);
2964 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002965
2966 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002967
françois romieu4da19632011-01-03 15:07:55 +00002968 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002969}
2970
françois romieu4da19632011-01-03 15:07:55 +00002971static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002972{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002973 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002974 { 0x1f, 0x0002 },
2975 { 0x10, 0x0008 },
2976 { 0x0d, 0x006c },
2977
2978 { 0x1f, 0x0000 },
2979 { 0x0d, 0xf880 },
2980
2981 { 0x1f, 0x0001 },
2982 { 0x17, 0x0cc0 },
2983
2984 { 0x1f, 0x0001 },
2985 { 0x0b, 0xa4d8 },
2986 { 0x09, 0x281c },
2987 { 0x07, 0x2883 },
2988 { 0x0a, 0x6b35 },
2989 { 0x1d, 0x3da4 },
2990 { 0x1c, 0xeffd },
2991 { 0x14, 0x7f52 },
2992 { 0x18, 0x7fc6 },
2993 { 0x08, 0x0601 },
2994 { 0x06, 0x4063 },
2995 { 0x10, 0xf074 },
2996 { 0x1f, 0x0003 },
2997 { 0x13, 0x0789 },
2998 { 0x12, 0xf4bd },
2999 { 0x1a, 0x04fd },
3000 { 0x14, 0x84b0 },
3001 { 0x1f, 0x0000 },
3002 { 0x00, 0x9200 },
3003
3004 { 0x1f, 0x0005 },
3005 { 0x01, 0x0340 },
3006 { 0x1f, 0x0001 },
3007 { 0x04, 0x4000 },
3008 { 0x03, 0x1d21 },
3009 { 0x02, 0x0c32 },
3010 { 0x01, 0x0200 },
3011 { 0x00, 0x5554 },
3012 { 0x04, 0x4800 },
3013 { 0x04, 0x4000 },
3014 { 0x04, 0xf000 },
3015 { 0x03, 0xdf01 },
3016 { 0x02, 0xdf20 },
3017 { 0x01, 0x101a },
3018 { 0x00, 0xa0ff },
3019 { 0x04, 0xf800 },
3020 { 0x04, 0xf000 },
3021 { 0x1f, 0x0000 },
3022
3023 { 0x1f, 0x0007 },
3024 { 0x1e, 0x0023 },
3025 { 0x16, 0x0000 },
3026 { 0x1f, 0x0000 }
3027 };
3028
françois romieu4da19632011-01-03 15:07:55 +00003029 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003030}
3031
françois romieue6de30d2011-01-03 15:08:37 +00003032static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3033{
3034 static const struct phy_reg phy_reg_init[] = {
3035 { 0x1f, 0x0001 },
3036 { 0x17, 0x0cc0 },
3037
3038 { 0x1f, 0x0007 },
3039 { 0x1e, 0x002d },
3040 { 0x18, 0x0040 },
3041 { 0x1f, 0x0000 }
3042 };
3043
3044 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3045 rtl_patchphy(tp, 0x0d, 1 << 5);
3046}
3047
Hayes Wang70090422011-07-06 15:58:06 +08003048static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003049{
3050 static const struct phy_reg phy_reg_init[] = {
3051 /* Enable Delay cap */
3052 { 0x1f, 0x0005 },
3053 { 0x05, 0x8b80 },
3054 { 0x06, 0xc896 },
3055 { 0x1f, 0x0000 },
3056
3057 /* Channel estimation fine tune */
3058 { 0x1f, 0x0001 },
3059 { 0x0b, 0x6c20 },
3060 { 0x07, 0x2872 },
3061 { 0x1c, 0xefff },
3062 { 0x1f, 0x0003 },
3063 { 0x14, 0x6420 },
3064 { 0x1f, 0x0000 },
3065
3066 /* Update PFM & 10M TX idle timer */
3067 { 0x1f, 0x0007 },
3068 { 0x1e, 0x002f },
3069 { 0x15, 0x1919 },
3070 { 0x1f, 0x0000 },
3071
3072 { 0x1f, 0x0007 },
3073 { 0x1e, 0x00ac },
3074 { 0x18, 0x0006 },
3075 { 0x1f, 0x0000 }
3076 };
3077
Francois Romieu15ecd032011-04-27 13:52:22 -07003078 rtl_apply_firmware(tp);
3079
hayeswang01dc7fe2011-03-21 01:50:28 +00003080 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3081
3082 /* DCO enable for 10M IDLE Power */
3083 rtl_writephy(tp, 0x1f, 0x0007);
3084 rtl_writephy(tp, 0x1e, 0x0023);
3085 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3086 rtl_writephy(tp, 0x1f, 0x0000);
3087
3088 /* For impedance matching */
3089 rtl_writephy(tp, 0x1f, 0x0002);
3090 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003091 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003092
3093 /* PHY auto speed down */
3094 rtl_writephy(tp, 0x1f, 0x0007);
3095 rtl_writephy(tp, 0x1e, 0x002d);
3096 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3097 rtl_writephy(tp, 0x1f, 0x0000);
3098 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3099
3100 rtl_writephy(tp, 0x1f, 0x0005);
3101 rtl_writephy(tp, 0x05, 0x8b86);
3102 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3103 rtl_writephy(tp, 0x1f, 0x0000);
3104
3105 rtl_writephy(tp, 0x1f, 0x0005);
3106 rtl_writephy(tp, 0x05, 0x8b85);
3107 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3108 rtl_writephy(tp, 0x1f, 0x0007);
3109 rtl_writephy(tp, 0x1e, 0x0020);
3110 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3111 rtl_writephy(tp, 0x1f, 0x0006);
3112 rtl_writephy(tp, 0x00, 0x5a00);
3113 rtl_writephy(tp, 0x1f, 0x0000);
3114 rtl_writephy(tp, 0x0d, 0x0007);
3115 rtl_writephy(tp, 0x0e, 0x003c);
3116 rtl_writephy(tp, 0x0d, 0x4007);
3117 rtl_writephy(tp, 0x0e, 0x0000);
3118 rtl_writephy(tp, 0x0d, 0x0000);
3119}
3120
françois romieu9ecb9aa2012-12-07 11:20:21 +00003121static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3122{
3123 const u16 w[] = {
3124 addr[0] | (addr[1] << 8),
3125 addr[2] | (addr[3] << 8),
3126 addr[4] | (addr[5] << 8)
3127 };
3128 const struct exgmac_reg e[] = {
3129 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3130 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3131 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3132 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3133 };
3134
3135 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3136}
3137
Hayes Wang70090422011-07-06 15:58:06 +08003138static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3139{
3140 static const struct phy_reg phy_reg_init[] = {
3141 /* Enable Delay cap */
3142 { 0x1f, 0x0004 },
3143 { 0x1f, 0x0007 },
3144 { 0x1e, 0x00ac },
3145 { 0x18, 0x0006 },
3146 { 0x1f, 0x0002 },
3147 { 0x1f, 0x0000 },
3148 { 0x1f, 0x0000 },
3149
3150 /* Channel estimation fine tune */
3151 { 0x1f, 0x0003 },
3152 { 0x09, 0xa20f },
3153 { 0x1f, 0x0000 },
3154 { 0x1f, 0x0000 },
3155
3156 /* Green Setting */
3157 { 0x1f, 0x0005 },
3158 { 0x05, 0x8b5b },
3159 { 0x06, 0x9222 },
3160 { 0x05, 0x8b6d },
3161 { 0x06, 0x8000 },
3162 { 0x05, 0x8b76 },
3163 { 0x06, 0x8000 },
3164 { 0x1f, 0x0000 }
3165 };
3166
3167 rtl_apply_firmware(tp);
3168
3169 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3170
3171 /* For 4-corner performance improve */
3172 rtl_writephy(tp, 0x1f, 0x0005);
3173 rtl_writephy(tp, 0x05, 0x8b80);
3174 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3175 rtl_writephy(tp, 0x1f, 0x0000);
3176
3177 /* PHY auto speed down */
3178 rtl_writephy(tp, 0x1f, 0x0004);
3179 rtl_writephy(tp, 0x1f, 0x0007);
3180 rtl_writephy(tp, 0x1e, 0x002d);
3181 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3182 rtl_writephy(tp, 0x1f, 0x0002);
3183 rtl_writephy(tp, 0x1f, 0x0000);
3184 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3185
3186 /* improve 10M EEE waveform */
3187 rtl_writephy(tp, 0x1f, 0x0005);
3188 rtl_writephy(tp, 0x05, 0x8b86);
3189 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3190 rtl_writephy(tp, 0x1f, 0x0000);
3191
3192 /* Improve 2-pair detection performance */
3193 rtl_writephy(tp, 0x1f, 0x0005);
3194 rtl_writephy(tp, 0x05, 0x8b85);
3195 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3196 rtl_writephy(tp, 0x1f, 0x0000);
3197
3198 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003199 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003200 rtl_writephy(tp, 0x1f, 0x0005);
3201 rtl_writephy(tp, 0x05, 0x8b85);
3202 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3203 rtl_writephy(tp, 0x1f, 0x0004);
3204 rtl_writephy(tp, 0x1f, 0x0007);
3205 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003206 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003207 rtl_writephy(tp, 0x1f, 0x0002);
3208 rtl_writephy(tp, 0x1f, 0x0000);
3209 rtl_writephy(tp, 0x0d, 0x0007);
3210 rtl_writephy(tp, 0x0e, 0x003c);
3211 rtl_writephy(tp, 0x0d, 0x4007);
3212 rtl_writephy(tp, 0x0e, 0x0000);
3213 rtl_writephy(tp, 0x0d, 0x0000);
3214
3215 /* Green feature */
3216 rtl_writephy(tp, 0x1f, 0x0003);
3217 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3218 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3219 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003220
3221 r8168_aldps_enable_1(tp);
françois romieu9ecb9aa2012-12-07 11:20:21 +00003222
3223 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3224 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003225}
3226
Hayes Wang5f886e02012-03-30 14:33:03 +08003227static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3228{
3229 /* For 4-corner performance improve */
3230 rtl_writephy(tp, 0x1f, 0x0005);
3231 rtl_writephy(tp, 0x05, 0x8b80);
3232 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3233 rtl_writephy(tp, 0x1f, 0x0000);
3234
3235 /* PHY auto speed down */
3236 rtl_writephy(tp, 0x1f, 0x0007);
3237 rtl_writephy(tp, 0x1e, 0x002d);
3238 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3239 rtl_writephy(tp, 0x1f, 0x0000);
3240 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3241
3242 /* Improve 10M EEE waveform */
3243 rtl_writephy(tp, 0x1f, 0x0005);
3244 rtl_writephy(tp, 0x05, 0x8b86);
3245 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3246 rtl_writephy(tp, 0x1f, 0x0000);
3247}
3248
Hayes Wangc2218922011-09-06 16:55:18 +08003249static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3250{
3251 static const struct phy_reg phy_reg_init[] = {
3252 /* Channel estimation fine tune */
3253 { 0x1f, 0x0003 },
3254 { 0x09, 0xa20f },
3255 { 0x1f, 0x0000 },
3256
3257 /* Modify green table for giga & fnet */
3258 { 0x1f, 0x0005 },
3259 { 0x05, 0x8b55 },
3260 { 0x06, 0x0000 },
3261 { 0x05, 0x8b5e },
3262 { 0x06, 0x0000 },
3263 { 0x05, 0x8b67 },
3264 { 0x06, 0x0000 },
3265 { 0x05, 0x8b70 },
3266 { 0x06, 0x0000 },
3267 { 0x1f, 0x0000 },
3268 { 0x1f, 0x0007 },
3269 { 0x1e, 0x0078 },
3270 { 0x17, 0x0000 },
3271 { 0x19, 0x00fb },
3272 { 0x1f, 0x0000 },
3273
3274 /* Modify green table for 10M */
3275 { 0x1f, 0x0005 },
3276 { 0x05, 0x8b79 },
3277 { 0x06, 0xaa00 },
3278 { 0x1f, 0x0000 },
3279
3280 /* Disable hiimpedance detection (RTCT) */
3281 { 0x1f, 0x0003 },
3282 { 0x01, 0x328a },
3283 { 0x1f, 0x0000 }
3284 };
3285
3286 rtl_apply_firmware(tp);
3287
3288 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3289
Hayes Wang5f886e02012-03-30 14:33:03 +08003290 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003291
3292 /* Improve 2-pair detection performance */
3293 rtl_writephy(tp, 0x1f, 0x0005);
3294 rtl_writephy(tp, 0x05, 0x8b85);
3295 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3296 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003297
3298 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003299}
3300
3301static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3302{
3303 rtl_apply_firmware(tp);
3304
Hayes Wang5f886e02012-03-30 14:33:03 +08003305 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003306
3307 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003308}
3309
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003310static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3311{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003312 static const struct phy_reg phy_reg_init[] = {
3313 /* Channel estimation fine tune */
3314 { 0x1f, 0x0003 },
3315 { 0x09, 0xa20f },
3316 { 0x1f, 0x0000 },
3317
3318 /* Modify green table for giga & fnet */
3319 { 0x1f, 0x0005 },
3320 { 0x05, 0x8b55 },
3321 { 0x06, 0x0000 },
3322 { 0x05, 0x8b5e },
3323 { 0x06, 0x0000 },
3324 { 0x05, 0x8b67 },
3325 { 0x06, 0x0000 },
3326 { 0x05, 0x8b70 },
3327 { 0x06, 0x0000 },
3328 { 0x1f, 0x0000 },
3329 { 0x1f, 0x0007 },
3330 { 0x1e, 0x0078 },
3331 { 0x17, 0x0000 },
3332 { 0x19, 0x00aa },
3333 { 0x1f, 0x0000 },
3334
3335 /* Modify green table for 10M */
3336 { 0x1f, 0x0005 },
3337 { 0x05, 0x8b79 },
3338 { 0x06, 0xaa00 },
3339 { 0x1f, 0x0000 },
3340
3341 /* Disable hiimpedance detection (RTCT) */
3342 { 0x1f, 0x0003 },
3343 { 0x01, 0x328a },
3344 { 0x1f, 0x0000 }
3345 };
3346
3347
3348 rtl_apply_firmware(tp);
3349
3350 rtl8168f_hw_phy_config(tp);
3351
3352 /* Improve 2-pair detection performance */
3353 rtl_writephy(tp, 0x1f, 0x0005);
3354 rtl_writephy(tp, 0x05, 0x8b85);
3355 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3356 rtl_writephy(tp, 0x1f, 0x0000);
3357
3358 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3359
3360 /* Modify green table for giga */
3361 rtl_writephy(tp, 0x1f, 0x0005);
3362 rtl_writephy(tp, 0x05, 0x8b54);
3363 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3364 rtl_writephy(tp, 0x05, 0x8b5d);
3365 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3366 rtl_writephy(tp, 0x05, 0x8a7c);
3367 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3368 rtl_writephy(tp, 0x05, 0x8a7f);
3369 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3370 rtl_writephy(tp, 0x05, 0x8a82);
3371 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3372 rtl_writephy(tp, 0x05, 0x8a85);
3373 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3374 rtl_writephy(tp, 0x05, 0x8a88);
3375 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3376 rtl_writephy(tp, 0x1f, 0x0000);
3377
3378 /* uc same-seed solution */
3379 rtl_writephy(tp, 0x1f, 0x0005);
3380 rtl_writephy(tp, 0x05, 0x8b85);
3381 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3382 rtl_writephy(tp, 0x1f, 0x0000);
3383
3384 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003385 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003386 rtl_writephy(tp, 0x1f, 0x0005);
3387 rtl_writephy(tp, 0x05, 0x8b85);
3388 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3389 rtl_writephy(tp, 0x1f, 0x0004);
3390 rtl_writephy(tp, 0x1f, 0x0007);
3391 rtl_writephy(tp, 0x1e, 0x0020);
3392 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3393 rtl_writephy(tp, 0x1f, 0x0000);
3394 rtl_writephy(tp, 0x0d, 0x0007);
3395 rtl_writephy(tp, 0x0e, 0x003c);
3396 rtl_writephy(tp, 0x0d, 0x4007);
3397 rtl_writephy(tp, 0x0e, 0x0000);
3398 rtl_writephy(tp, 0x0d, 0x0000);
3399
3400 /* Green feature */
3401 rtl_writephy(tp, 0x1f, 0x0003);
3402 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3403 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3404 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003405
3406 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003407}
3408
Hayes Wangc5583862012-07-02 17:23:22 +08003409static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3410{
3411 static const u16 mac_ocp_patch[] = {
3412 0xe008, 0xe01b, 0xe01d, 0xe01f,
3413 0xe021, 0xe023, 0xe025, 0xe027,
3414 0x49d2, 0xf10d, 0x766c, 0x49e2,
3415 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3416
3417 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3418 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3419 0xbe00, 0xb416, 0x0076, 0xe86c,
3420 0xc602, 0xbe00, 0x0000, 0xc602,
3421
3422 0xbe00, 0x0000, 0xc602, 0xbe00,
3423 0x0000, 0xc602, 0xbe00, 0x0000,
3424 0xc602, 0xbe00, 0x0000, 0xc602,
3425 0xbe00, 0x0000, 0xc602, 0xbe00,
3426
3427 0x0000, 0x0000, 0x0000, 0x0000
3428 };
3429 u32 i;
3430
3431 /* Patch code for GPHY reset */
3432 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3433 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3434 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3435 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3436
3437 rtl_apply_firmware(tp);
3438
3439 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3440 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3441 else
3442 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3443
3444 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3445 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3446 else
3447 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3448
3449 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3450 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3451
3452 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3453 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3454
3455 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3456}
3457
françois romieu4da19632011-01-03 15:07:55 +00003458static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003459{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003460 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003461 { 0x1f, 0x0003 },
3462 { 0x08, 0x441d },
3463 { 0x01, 0x9100 },
3464 { 0x1f, 0x0000 }
3465 };
3466
françois romieu4da19632011-01-03 15:07:55 +00003467 rtl_writephy(tp, 0x1f, 0x0000);
3468 rtl_patchphy(tp, 0x11, 1 << 12);
3469 rtl_patchphy(tp, 0x19, 1 << 13);
3470 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003471
françois romieu4da19632011-01-03 15:07:55 +00003472 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003473}
3474
Hayes Wang5a5e4442011-02-22 17:26:21 +08003475static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3476{
3477 static const struct phy_reg phy_reg_init[] = {
3478 { 0x1f, 0x0005 },
3479 { 0x1a, 0x0000 },
3480 { 0x1f, 0x0000 },
3481
3482 { 0x1f, 0x0004 },
3483 { 0x1c, 0x0000 },
3484 { 0x1f, 0x0000 },
3485
3486 { 0x1f, 0x0001 },
3487 { 0x15, 0x7701 },
3488 { 0x1f, 0x0000 }
3489 };
3490
3491 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003492 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003493
François Romieu953a12c2011-04-24 17:38:48 +02003494 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003495
3496 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003497
3498 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003499}
3500
Hayes Wang7e18dca2012-03-30 14:33:02 +08003501static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3502{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003503 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003504 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003505
3506 rtl_apply_firmware(tp);
3507
3508 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003509 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003510 rtl_writephy(tp, 0x1f, 0x0004);
3511 rtl_writephy(tp, 0x10, 0x401f);
3512 rtl_writephy(tp, 0x19, 0x7030);
3513 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003514
3515 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003516}
3517
Hayes Wang5598bfe2012-07-02 17:23:21 +08003518static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3519{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003520 static const struct phy_reg phy_reg_init[] = {
3521 { 0x1f, 0x0004 },
3522 { 0x10, 0xc07f },
3523 { 0x19, 0x7030 },
3524 { 0x1f, 0x0000 }
3525 };
3526
3527 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003528 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003529
3530 rtl_apply_firmware(tp);
3531
Francois Romieufdf6fc02012-07-06 22:40:38 +02003532 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003533 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3534
Francois Romieufdf6fc02012-07-06 22:40:38 +02003535 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003536
3537 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003538}
3539
Francois Romieu5615d9f2007-08-17 17:50:46 +02003540static void rtl_hw_phy_config(struct net_device *dev)
3541{
3542 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003543
3544 rtl8169_print_mac_version(tp);
3545
3546 switch (tp->mac_version) {
3547 case RTL_GIGA_MAC_VER_01:
3548 break;
3549 case RTL_GIGA_MAC_VER_02:
3550 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003551 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003552 break;
3553 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003554 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003555 break;
françois romieu2e9558562009-08-10 19:44:19 +00003556 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003557 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003558 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003559 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003560 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003561 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003562 case RTL_GIGA_MAC_VER_07:
3563 case RTL_GIGA_MAC_VER_08:
3564 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003565 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003566 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003567 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003568 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003569 break;
3570 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003571 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003572 break;
3573 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003574 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003575 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003576 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003577 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003578 break;
3579 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003580 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003581 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003582 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003583 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003584 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003585 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003586 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003587 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003588 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003589 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003590 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003591 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003592 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003593 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003594 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003595 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003596 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003597 break;
3598 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003599 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003600 break;
3601 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003602 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003603 break;
françois romieue6de30d2011-01-03 15:08:37 +00003604 case RTL_GIGA_MAC_VER_28:
3605 rtl8168d_4_hw_phy_config(tp);
3606 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003607 case RTL_GIGA_MAC_VER_29:
3608 case RTL_GIGA_MAC_VER_30:
3609 rtl8105e_hw_phy_config(tp);
3610 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003611 case RTL_GIGA_MAC_VER_31:
3612 /* None. */
3613 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003614 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003615 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003616 rtl8168e_1_hw_phy_config(tp);
3617 break;
3618 case RTL_GIGA_MAC_VER_34:
3619 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003620 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003621 case RTL_GIGA_MAC_VER_35:
3622 rtl8168f_1_hw_phy_config(tp);
3623 break;
3624 case RTL_GIGA_MAC_VER_36:
3625 rtl8168f_2_hw_phy_config(tp);
3626 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003627
Hayes Wang7e18dca2012-03-30 14:33:02 +08003628 case RTL_GIGA_MAC_VER_37:
3629 rtl8402_hw_phy_config(tp);
3630 break;
3631
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003632 case RTL_GIGA_MAC_VER_38:
3633 rtl8411_hw_phy_config(tp);
3634 break;
3635
Hayes Wang5598bfe2012-07-02 17:23:21 +08003636 case RTL_GIGA_MAC_VER_39:
3637 rtl8106e_hw_phy_config(tp);
3638 break;
3639
Hayes Wangc5583862012-07-02 17:23:22 +08003640 case RTL_GIGA_MAC_VER_40:
3641 rtl8168g_1_hw_phy_config(tp);
3642 break;
3643
3644 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003645 default:
3646 break;
3647 }
3648}
3649
Francois Romieuda78dbf2012-01-26 14:18:23 +01003650static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 struct timer_list *timer = &tp->timer;
3653 void __iomem *ioaddr = tp->mmio_addr;
3654 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3655
Francois Romieubcf0bf92006-07-26 23:14:13 +02003656 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
françois romieu4da19632011-01-03 15:07:55 +00003658 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003659 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 * A busy loop could burn quite a few cycles on nowadays CPU.
3661 * Let's delay the execution of the timer for a few ticks.
3662 */
3663 timeout = HZ/10;
3664 goto out_mod_timer;
3665 }
3666
3667 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003668 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669
Francois Romieuda78dbf2012-01-26 14:18:23 +01003670 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671
françois romieu4da19632011-01-03 15:07:55 +00003672 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673
3674out_mod_timer:
3675 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003676}
3677
3678static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3679{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003680 if (!test_and_set_bit(flag, tp->wk.flags))
3681 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003682}
3683
3684static void rtl8169_phy_timer(unsigned long __opaque)
3685{
3686 struct net_device *dev = (struct net_device *)__opaque;
3687 struct rtl8169_private *tp = netdev_priv(dev);
3688
Francois Romieu98ddf982012-01-31 10:47:34 +01003689 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690}
3691
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3693 void __iomem *ioaddr)
3694{
3695 iounmap(ioaddr);
3696 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003697 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 pci_disable_device(pdev);
3699 free_netdev(dev);
3700}
3701
Francois Romieuffc46952012-07-06 14:19:23 +02003702DECLARE_RTL_COND(rtl_phy_reset_cond)
3703{
3704 return tp->phy_reset_pending(tp);
3705}
3706
Francois Romieubf793292006-11-01 00:53:05 +01003707static void rtl8169_phy_reset(struct net_device *dev,
3708 struct rtl8169_private *tp)
3709{
françois romieu4da19632011-01-03 15:07:55 +00003710 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003711 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003712}
3713
David S. Miller8decf862011-09-22 03:23:13 -04003714static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3715{
3716 void __iomem *ioaddr = tp->mmio_addr;
3717
3718 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3719 (RTL_R8(PHYstatus) & TBI_Enable);
3720}
3721
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003722static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003724 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003725
Francois Romieu5615d9f2007-08-17 17:50:46 +02003726 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003727
Marcus Sundberg773328942008-07-10 21:28:08 +02003728 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3729 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3730 RTL_W8(0x82, 0x01);
3731 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003732
Francois Romieu6dccd162007-02-13 23:38:05 +01003733 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3734
3735 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3736 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003737
Francois Romieubcf0bf92006-07-26 23:14:13 +02003738 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003739 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3740 RTL_W8(0x82, 0x01);
3741 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003742 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003743 }
3744
Francois Romieubf793292006-11-01 00:53:05 +01003745 rtl8169_phy_reset(dev, tp);
3746
Oliver Neukum54405cd2011-01-06 21:55:13 +01003747 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003748 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3749 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3750 (tp->mii.supports_gmii ?
3751 ADVERTISED_1000baseT_Half |
3752 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003753
David S. Miller8decf862011-09-22 03:23:13 -04003754 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003755 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003756}
3757
Francois Romieu773d2022007-01-31 23:47:43 +01003758static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3759{
3760 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003761
Francois Romieuda78dbf2012-01-26 14:18:23 +01003762 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003763
3764 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003765
françois romieu9ecb9aa2012-12-07 11:20:21 +00003766 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2b2010-04-26 11:42:58 +00003767 RTL_R32(MAC4);
3768
françois romieu9ecb9aa2012-12-07 11:20:21 +00003769 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2b2010-04-26 11:42:58 +00003770 RTL_R32(MAC0);
3771
françois romieu9ecb9aa2012-12-07 11:20:21 +00003772 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3773 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003774
Francois Romieu773d2022007-01-31 23:47:43 +01003775 RTL_W8(Cfg9346, Cfg9346_Lock);
3776
Francois Romieuda78dbf2012-01-26 14:18:23 +01003777 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003778}
3779
3780static int rtl_set_mac_address(struct net_device *dev, void *p)
3781{
3782 struct rtl8169_private *tp = netdev_priv(dev);
3783 struct sockaddr *addr = p;
3784
3785 if (!is_valid_ether_addr(addr->sa_data))
3786 return -EADDRNOTAVAIL;
3787
3788 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3789
3790 rtl_rar_set(tp, dev->dev_addr);
3791
3792 return 0;
3793}
3794
Francois Romieu5f787a12006-08-17 13:02:36 +02003795static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3796{
3797 struct rtl8169_private *tp = netdev_priv(dev);
3798 struct mii_ioctl_data *data = if_mii(ifr);
3799
Francois Romieu8b4ab282008-11-19 22:05:25 -08003800 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3801}
Francois Romieu5f787a12006-08-17 13:02:36 +02003802
Francois Romieucecb5fd2011-04-01 10:21:07 +02003803static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3804 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003805{
Francois Romieu5f787a12006-08-17 13:02:36 +02003806 switch (cmd) {
3807 case SIOCGMIIPHY:
3808 data->phy_id = 32; /* Internal PHY */
3809 return 0;
3810
3811 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003812 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003813 return 0;
3814
3815 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003816 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003817 return 0;
3818 }
3819 return -EOPNOTSUPP;
3820}
3821
Francois Romieu8b4ab282008-11-19 22:05:25 -08003822static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3823{
3824 return -EOPNOTSUPP;
3825}
3826
Francois Romieufbac58f2007-10-04 22:51:38 +02003827static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3828{
3829 if (tp->features & RTL_FEATURE_MSI) {
3830 pci_disable_msi(pdev);
3831 tp->features &= ~RTL_FEATURE_MSI;
3832 }
3833}
3834
Bill Pembertonbaf63292012-12-03 09:23:28 -05003835static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003836{
3837 struct mdio_ops *ops = &tp->mdio_ops;
3838
3839 switch (tp->mac_version) {
3840 case RTL_GIGA_MAC_VER_27:
3841 ops->write = r8168dp_1_mdio_write;
3842 ops->read = r8168dp_1_mdio_read;
3843 break;
françois romieue6de30d2011-01-03 15:08:37 +00003844 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003845 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003846 ops->write = r8168dp_2_mdio_write;
3847 ops->read = r8168dp_2_mdio_read;
3848 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003849 case RTL_GIGA_MAC_VER_40:
3850 case RTL_GIGA_MAC_VER_41:
3851 ops->write = r8168g_mdio_write;
3852 ops->read = r8168g_mdio_read;
3853 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003854 default:
3855 ops->write = r8169_mdio_write;
3856 ops->read = r8169_mdio_read;
3857 break;
3858 }
3859}
3860
David S. Miller1805b2f2011-10-24 18:18:09 -04003861static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3862{
3863 void __iomem *ioaddr = tp->mmio_addr;
3864
3865 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003866 case RTL_GIGA_MAC_VER_25:
3867 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003868 case RTL_GIGA_MAC_VER_29:
3869 case RTL_GIGA_MAC_VER_30:
3870 case RTL_GIGA_MAC_VER_32:
3871 case RTL_GIGA_MAC_VER_33:
3872 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003873 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003874 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003875 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003876 case RTL_GIGA_MAC_VER_40:
3877 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003878 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3879 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3880 break;
3881 default:
3882 break;
3883 }
3884}
3885
3886static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3887{
3888 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3889 return false;
3890
3891 rtl_writephy(tp, 0x1f, 0x0000);
3892 rtl_writephy(tp, MII_BMCR, 0x0000);
3893
3894 rtl_wol_suspend_quirk(tp);
3895
3896 return true;
3897}
3898
françois romieu065c27c2011-01-03 15:08:12 +00003899static void r810x_phy_power_down(struct rtl8169_private *tp)
3900{
3901 rtl_writephy(tp, 0x1f, 0x0000);
3902 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3903}
3904
3905static void r810x_phy_power_up(struct rtl8169_private *tp)
3906{
3907 rtl_writephy(tp, 0x1f, 0x0000);
3908 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3909}
3910
3911static void r810x_pll_power_down(struct rtl8169_private *tp)
3912{
Hayes Wang00042992012-03-30 14:33:00 +08003913 void __iomem *ioaddr = tp->mmio_addr;
3914
David S. Miller1805b2f2011-10-24 18:18:09 -04003915 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003916 return;
françois romieu065c27c2011-01-03 15:08:12 +00003917
3918 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003919
3920 switch (tp->mac_version) {
3921 case RTL_GIGA_MAC_VER_07:
3922 case RTL_GIGA_MAC_VER_08:
3923 case RTL_GIGA_MAC_VER_09:
3924 case RTL_GIGA_MAC_VER_10:
3925 case RTL_GIGA_MAC_VER_13:
3926 case RTL_GIGA_MAC_VER_16:
3927 break;
3928 default:
3929 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3930 break;
3931 }
françois romieu065c27c2011-01-03 15:08:12 +00003932}
3933
3934static void r810x_pll_power_up(struct rtl8169_private *tp)
3935{
Hayes Wang00042992012-03-30 14:33:00 +08003936 void __iomem *ioaddr = tp->mmio_addr;
3937
françois romieu065c27c2011-01-03 15:08:12 +00003938 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003939
3940 switch (tp->mac_version) {
3941 case RTL_GIGA_MAC_VER_07:
3942 case RTL_GIGA_MAC_VER_08:
3943 case RTL_GIGA_MAC_VER_09:
3944 case RTL_GIGA_MAC_VER_10:
3945 case RTL_GIGA_MAC_VER_13:
3946 case RTL_GIGA_MAC_VER_16:
3947 break;
3948 default:
3949 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3950 break;
3951 }
françois romieu065c27c2011-01-03 15:08:12 +00003952}
3953
3954static void r8168_phy_power_up(struct rtl8169_private *tp)
3955{
3956 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003957 switch (tp->mac_version) {
3958 case RTL_GIGA_MAC_VER_11:
3959 case RTL_GIGA_MAC_VER_12:
3960 case RTL_GIGA_MAC_VER_17:
3961 case RTL_GIGA_MAC_VER_18:
3962 case RTL_GIGA_MAC_VER_19:
3963 case RTL_GIGA_MAC_VER_20:
3964 case RTL_GIGA_MAC_VER_21:
3965 case RTL_GIGA_MAC_VER_22:
3966 case RTL_GIGA_MAC_VER_23:
3967 case RTL_GIGA_MAC_VER_24:
3968 case RTL_GIGA_MAC_VER_25:
3969 case RTL_GIGA_MAC_VER_26:
3970 case RTL_GIGA_MAC_VER_27:
3971 case RTL_GIGA_MAC_VER_28:
3972 case RTL_GIGA_MAC_VER_31:
3973 rtl_writephy(tp, 0x0e, 0x0000);
3974 break;
3975 default:
3976 break;
3977 }
françois romieu065c27c2011-01-03 15:08:12 +00003978 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3979}
3980
3981static void r8168_phy_power_down(struct rtl8169_private *tp)
3982{
3983 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003984 switch (tp->mac_version) {
3985 case RTL_GIGA_MAC_VER_32:
3986 case RTL_GIGA_MAC_VER_33:
3987 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3988 break;
3989
3990 case RTL_GIGA_MAC_VER_11:
3991 case RTL_GIGA_MAC_VER_12:
3992 case RTL_GIGA_MAC_VER_17:
3993 case RTL_GIGA_MAC_VER_18:
3994 case RTL_GIGA_MAC_VER_19:
3995 case RTL_GIGA_MAC_VER_20:
3996 case RTL_GIGA_MAC_VER_21:
3997 case RTL_GIGA_MAC_VER_22:
3998 case RTL_GIGA_MAC_VER_23:
3999 case RTL_GIGA_MAC_VER_24:
4000 case RTL_GIGA_MAC_VER_25:
4001 case RTL_GIGA_MAC_VER_26:
4002 case RTL_GIGA_MAC_VER_27:
4003 case RTL_GIGA_MAC_VER_28:
4004 case RTL_GIGA_MAC_VER_31:
4005 rtl_writephy(tp, 0x0e, 0x0200);
4006 default:
4007 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4008 break;
4009 }
françois romieu065c27c2011-01-03 15:08:12 +00004010}
4011
4012static void r8168_pll_power_down(struct rtl8169_private *tp)
4013{
4014 void __iomem *ioaddr = tp->mmio_addr;
4015
Francois Romieucecb5fd2011-04-01 10:21:07 +02004016 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4017 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4018 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004019 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004020 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004021 }
françois romieu065c27c2011-01-03 15:08:12 +00004022
Francois Romieucecb5fd2011-04-01 10:21:07 +02004023 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4024 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004025 (RTL_R16(CPlusCmd) & ASF)) {
4026 return;
4027 }
4028
hayeswang01dc7fe2011-03-21 01:50:28 +00004029 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4030 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004031 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004032
David S. Miller1805b2f2011-10-24 18:18:09 -04004033 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004034 return;
françois romieu065c27c2011-01-03 15:08:12 +00004035
4036 r8168_phy_power_down(tp);
4037
4038 switch (tp->mac_version) {
4039 case RTL_GIGA_MAC_VER_25:
4040 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004041 case RTL_GIGA_MAC_VER_27:
4042 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004043 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004044 case RTL_GIGA_MAC_VER_32:
4045 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004046 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4047 break;
4048 }
4049}
4050
4051static void r8168_pll_power_up(struct rtl8169_private *tp)
4052{
4053 void __iomem *ioaddr = tp->mmio_addr;
4054
françois romieu065c27c2011-01-03 15:08:12 +00004055 switch (tp->mac_version) {
4056 case RTL_GIGA_MAC_VER_25:
4057 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004058 case RTL_GIGA_MAC_VER_27:
4059 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004060 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004061 case RTL_GIGA_MAC_VER_32:
4062 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004063 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4064 break;
4065 }
4066
4067 r8168_phy_power_up(tp);
4068}
4069
Francois Romieud58d46b2011-05-03 16:38:29 +02004070static void rtl_generic_op(struct rtl8169_private *tp,
4071 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004072{
4073 if (op)
4074 op(tp);
4075}
4076
4077static void rtl_pll_power_down(struct rtl8169_private *tp)
4078{
Francois Romieud58d46b2011-05-03 16:38:29 +02004079 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004080}
4081
4082static void rtl_pll_power_up(struct rtl8169_private *tp)
4083{
Francois Romieud58d46b2011-05-03 16:38:29 +02004084 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004085}
4086
Bill Pembertonbaf63292012-12-03 09:23:28 -05004087static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004088{
4089 struct pll_power_ops *ops = &tp->pll_power_ops;
4090
4091 switch (tp->mac_version) {
4092 case RTL_GIGA_MAC_VER_07:
4093 case RTL_GIGA_MAC_VER_08:
4094 case RTL_GIGA_MAC_VER_09:
4095 case RTL_GIGA_MAC_VER_10:
4096 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004097 case RTL_GIGA_MAC_VER_29:
4098 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004099 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004100 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004101 ops->down = r810x_pll_power_down;
4102 ops->up = r810x_pll_power_up;
4103 break;
4104
4105 case RTL_GIGA_MAC_VER_11:
4106 case RTL_GIGA_MAC_VER_12:
4107 case RTL_GIGA_MAC_VER_17:
4108 case RTL_GIGA_MAC_VER_18:
4109 case RTL_GIGA_MAC_VER_19:
4110 case RTL_GIGA_MAC_VER_20:
4111 case RTL_GIGA_MAC_VER_21:
4112 case RTL_GIGA_MAC_VER_22:
4113 case RTL_GIGA_MAC_VER_23:
4114 case RTL_GIGA_MAC_VER_24:
4115 case RTL_GIGA_MAC_VER_25:
4116 case RTL_GIGA_MAC_VER_26:
4117 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004118 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004119 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004120 case RTL_GIGA_MAC_VER_32:
4121 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004122 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004123 case RTL_GIGA_MAC_VER_35:
4124 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004125 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004126 case RTL_GIGA_MAC_VER_40:
4127 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004128 ops->down = r8168_pll_power_down;
4129 ops->up = r8168_pll_power_up;
4130 break;
4131
4132 default:
4133 ops->down = NULL;
4134 ops->up = NULL;
4135 break;
4136 }
4137}
4138
Hayes Wange542a222011-07-06 15:58:04 +08004139static void rtl_init_rxcfg(struct rtl8169_private *tp)
4140{
4141 void __iomem *ioaddr = tp->mmio_addr;
4142
4143 switch (tp->mac_version) {
4144 case RTL_GIGA_MAC_VER_01:
4145 case RTL_GIGA_MAC_VER_02:
4146 case RTL_GIGA_MAC_VER_03:
4147 case RTL_GIGA_MAC_VER_04:
4148 case RTL_GIGA_MAC_VER_05:
4149 case RTL_GIGA_MAC_VER_06:
4150 case RTL_GIGA_MAC_VER_10:
4151 case RTL_GIGA_MAC_VER_11:
4152 case RTL_GIGA_MAC_VER_12:
4153 case RTL_GIGA_MAC_VER_13:
4154 case RTL_GIGA_MAC_VER_14:
4155 case RTL_GIGA_MAC_VER_15:
4156 case RTL_GIGA_MAC_VER_16:
4157 case RTL_GIGA_MAC_VER_17:
4158 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4159 break;
4160 case RTL_GIGA_MAC_VER_18:
4161 case RTL_GIGA_MAC_VER_19:
4162 case RTL_GIGA_MAC_VER_20:
4163 case RTL_GIGA_MAC_VER_21:
4164 case RTL_GIGA_MAC_VER_22:
4165 case RTL_GIGA_MAC_VER_23:
4166 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004167 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004168 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4169 break;
4170 default:
4171 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4172 break;
4173 }
4174}
4175
Hayes Wang92fc43b2011-07-06 15:58:03 +08004176static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4177{
4178 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4179}
4180
Francois Romieud58d46b2011-05-03 16:38:29 +02004181static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4182{
françois romieu9c5028e2012-03-02 04:43:14 +00004183 void __iomem *ioaddr = tp->mmio_addr;
4184
4185 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004186 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004187 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004188}
4189
4190static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4191{
françois romieu9c5028e2012-03-02 04:43:14 +00004192 void __iomem *ioaddr = tp->mmio_addr;
4193
4194 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004195 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004196 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004197}
4198
4199static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4200{
4201 void __iomem *ioaddr = tp->mmio_addr;
4202
4203 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4204 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4205 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4206}
4207
4208static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4209{
4210 void __iomem *ioaddr = tp->mmio_addr;
4211
4212 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4213 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4214 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4215}
4216
4217static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4218{
4219 void __iomem *ioaddr = tp->mmio_addr;
4220
4221 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4222}
4223
4224static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4225{
4226 void __iomem *ioaddr = tp->mmio_addr;
4227
4228 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4229}
4230
4231static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4232{
4233 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004234
4235 RTL_W8(MaxTxPacketSize, 0x3f);
4236 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4237 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004238 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004239}
4240
4241static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4242{
4243 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004244
4245 RTL_W8(MaxTxPacketSize, 0x0c);
4246 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4247 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004248 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004249}
4250
4251static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4252{
4253 rtl_tx_performance_tweak(tp->pci_dev,
4254 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4255}
4256
4257static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4258{
4259 rtl_tx_performance_tweak(tp->pci_dev,
4260 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4261}
4262
4263static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4264{
4265 void __iomem *ioaddr = tp->mmio_addr;
4266
4267 r8168b_0_hw_jumbo_enable(tp);
4268
4269 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4270}
4271
4272static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4273{
4274 void __iomem *ioaddr = tp->mmio_addr;
4275
4276 r8168b_0_hw_jumbo_disable(tp);
4277
4278 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4279}
4280
Bill Pembertonbaf63292012-12-03 09:23:28 -05004281static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004282{
4283 struct jumbo_ops *ops = &tp->jumbo_ops;
4284
4285 switch (tp->mac_version) {
4286 case RTL_GIGA_MAC_VER_11:
4287 ops->disable = r8168b_0_hw_jumbo_disable;
4288 ops->enable = r8168b_0_hw_jumbo_enable;
4289 break;
4290 case RTL_GIGA_MAC_VER_12:
4291 case RTL_GIGA_MAC_VER_17:
4292 ops->disable = r8168b_1_hw_jumbo_disable;
4293 ops->enable = r8168b_1_hw_jumbo_enable;
4294 break;
4295 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4296 case RTL_GIGA_MAC_VER_19:
4297 case RTL_GIGA_MAC_VER_20:
4298 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4299 case RTL_GIGA_MAC_VER_22:
4300 case RTL_GIGA_MAC_VER_23:
4301 case RTL_GIGA_MAC_VER_24:
4302 case RTL_GIGA_MAC_VER_25:
4303 case RTL_GIGA_MAC_VER_26:
4304 ops->disable = r8168c_hw_jumbo_disable;
4305 ops->enable = r8168c_hw_jumbo_enable;
4306 break;
4307 case RTL_GIGA_MAC_VER_27:
4308 case RTL_GIGA_MAC_VER_28:
4309 ops->disable = r8168dp_hw_jumbo_disable;
4310 ops->enable = r8168dp_hw_jumbo_enable;
4311 break;
4312 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4313 case RTL_GIGA_MAC_VER_32:
4314 case RTL_GIGA_MAC_VER_33:
4315 case RTL_GIGA_MAC_VER_34:
4316 ops->disable = r8168e_hw_jumbo_disable;
4317 ops->enable = r8168e_hw_jumbo_enable;
4318 break;
4319
4320 /*
4321 * No action needed for jumbo frames with 8169.
4322 * No jumbo for 810x at all.
4323 */
Hayes Wangc5583862012-07-02 17:23:22 +08004324 case RTL_GIGA_MAC_VER_40:
4325 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004326 default:
4327 ops->disable = NULL;
4328 ops->enable = NULL;
4329 break;
4330 }
4331}
4332
Francois Romieuffc46952012-07-06 14:19:23 +02004333DECLARE_RTL_COND(rtl_chipcmd_cond)
4334{
4335 void __iomem *ioaddr = tp->mmio_addr;
4336
4337 return RTL_R8(ChipCmd) & CmdReset;
4338}
4339
Francois Romieu6f43adc2011-04-29 15:05:51 +02004340static void rtl_hw_reset(struct rtl8169_private *tp)
4341{
4342 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004343
Francois Romieu6f43adc2011-04-29 15:05:51 +02004344 RTL_W8(ChipCmd, CmdReset);
4345
Francois Romieuffc46952012-07-06 14:19:23 +02004346 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004347}
4348
Francois Romieub6ffd972011-06-17 17:00:05 +02004349static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4350{
4351 struct rtl_fw *rtl_fw;
4352 const char *name;
4353 int rc = -ENOMEM;
4354
4355 name = rtl_lookup_firmware_name(tp);
4356 if (!name)
4357 goto out_no_firmware;
4358
4359 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4360 if (!rtl_fw)
4361 goto err_warn;
4362
4363 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4364 if (rc < 0)
4365 goto err_free;
4366
Francois Romieufd112f22011-06-18 00:10:29 +02004367 rc = rtl_check_firmware(tp, rtl_fw);
4368 if (rc < 0)
4369 goto err_release_firmware;
4370
Francois Romieub6ffd972011-06-17 17:00:05 +02004371 tp->rtl_fw = rtl_fw;
4372out:
4373 return;
4374
Francois Romieufd112f22011-06-18 00:10:29 +02004375err_release_firmware:
4376 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004377err_free:
4378 kfree(rtl_fw);
4379err_warn:
4380 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4381 name, rc);
4382out_no_firmware:
4383 tp->rtl_fw = NULL;
4384 goto out;
4385}
4386
François Romieu953a12c2011-04-24 17:38:48 +02004387static void rtl_request_firmware(struct rtl8169_private *tp)
4388{
Francois Romieub6ffd972011-06-17 17:00:05 +02004389 if (IS_ERR(tp->rtl_fw))
4390 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004391}
4392
Hayes Wang92fc43b2011-07-06 15:58:03 +08004393static void rtl_rx_close(struct rtl8169_private *tp)
4394{
4395 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004396
Francois Romieu1687b562011-07-19 17:21:29 +02004397 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004398}
4399
Francois Romieuffc46952012-07-06 14:19:23 +02004400DECLARE_RTL_COND(rtl_npq_cond)
4401{
4402 void __iomem *ioaddr = tp->mmio_addr;
4403
4404 return RTL_R8(TxPoll) & NPQ;
4405}
4406
4407DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4408{
4409 void __iomem *ioaddr = tp->mmio_addr;
4410
4411 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4412}
4413
françois romieue6de30d2011-01-03 15:08:37 +00004414static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
françois romieue6de30d2011-01-03 15:08:37 +00004416 void __iomem *ioaddr = tp->mmio_addr;
4417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004419 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Hayes Wang92fc43b2011-07-06 15:58:03 +08004421 rtl_rx_close(tp);
4422
Hayes Wang5d2e1952011-02-22 17:26:22 +08004423 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004424 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4425 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004426 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004427 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4428 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004429 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004430 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004431 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4432 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004433 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004434 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004435 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004436 } else {
4437 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4438 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004439 }
4440
Hayes Wang92fc43b2011-07-06 15:58:03 +08004441 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442}
4443
Francois Romieu7f796d832007-06-11 23:04:41 +02004444static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004445{
4446 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004447
4448 /* Set DMA burst size and Interframe Gap Time */
4449 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4450 (InterFrameGap << TxInterFrameGapShift));
4451}
4452
Francois Romieu07ce4062007-02-23 23:36:39 +01004453static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454{
4455 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
Francois Romieu07ce4062007-02-23 23:36:39 +01004457 tp->hw_start(dev);
4458
Francois Romieuda78dbf2012-01-26 14:18:23 +01004459 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004460}
4461
Francois Romieu7f796d832007-06-11 23:04:41 +02004462static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4463 void __iomem *ioaddr)
4464{
4465 /*
4466 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4467 * register to be written before TxDescAddrLow to work.
4468 * Switching from MMIO to I/O access fixes the issue as well.
4469 */
4470 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004471 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004472 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004473 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004474}
4475
4476static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4477{
4478 u16 cmd;
4479
4480 cmd = RTL_R16(CPlusCmd);
4481 RTL_W16(CPlusCmd, cmd);
4482 return cmd;
4483}
4484
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004485static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004486{
4487 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004488 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004489}
4490
Francois Romieu6dccd162007-02-13 23:38:05 +01004491static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4492{
Francois Romieu37441002011-06-17 22:58:54 +02004493 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004494 u32 mac_version;
4495 u32 clk;
4496 u32 val;
4497 } cfg2_info [] = {
4498 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4499 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4500 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4501 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004502 };
4503 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004504 unsigned int i;
4505 u32 clk;
4506
4507 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004508 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004509 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4510 RTL_W32(0x7c, p->val);
4511 break;
4512 }
4513 }
4514}
4515
Francois Romieue6b763e2012-03-08 09:35:39 +01004516static void rtl_set_rx_mode(struct net_device *dev)
4517{
4518 struct rtl8169_private *tp = netdev_priv(dev);
4519 void __iomem *ioaddr = tp->mmio_addr;
4520 u32 mc_filter[2]; /* Multicast hash filter */
4521 int rx_mode;
4522 u32 tmp = 0;
4523
4524 if (dev->flags & IFF_PROMISC) {
4525 /* Unconditionally log net taps. */
4526 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4527 rx_mode =
4528 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4529 AcceptAllPhys;
4530 mc_filter[1] = mc_filter[0] = 0xffffffff;
4531 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4532 (dev->flags & IFF_ALLMULTI)) {
4533 /* Too many to filter perfectly -- accept all multicasts. */
4534 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4535 mc_filter[1] = mc_filter[0] = 0xffffffff;
4536 } else {
4537 struct netdev_hw_addr *ha;
4538
4539 rx_mode = AcceptBroadcast | AcceptMyPhys;
4540 mc_filter[1] = mc_filter[0] = 0;
4541 netdev_for_each_mc_addr(ha, dev) {
4542 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4543 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4544 rx_mode |= AcceptMulticast;
4545 }
4546 }
4547
4548 if (dev->features & NETIF_F_RXALL)
4549 rx_mode |= (AcceptErr | AcceptRunt);
4550
4551 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4552
4553 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4554 u32 data = mc_filter[0];
4555
4556 mc_filter[0] = swab32(mc_filter[1]);
4557 mc_filter[1] = swab32(data);
4558 }
4559
Nathan Walp04817762012-11-01 12:08:47 +00004560 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4561 mc_filter[1] = mc_filter[0] = 0xffffffff;
4562
Francois Romieue6b763e2012-03-08 09:35:39 +01004563 RTL_W32(MAR0 + 4, mc_filter[1]);
4564 RTL_W32(MAR0 + 0, mc_filter[0]);
4565
4566 RTL_W32(RxConfig, tmp);
4567}
4568
Francois Romieu07ce4062007-02-23 23:36:39 +01004569static void rtl_hw_start_8169(struct net_device *dev)
4570{
4571 struct rtl8169_private *tp = netdev_priv(dev);
4572 void __iomem *ioaddr = tp->mmio_addr;
4573 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004574
Francois Romieu9cb427b2006-11-02 00:10:16 +01004575 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4576 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4577 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4578 }
4579
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004581 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4582 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4583 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4584 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004585 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4586
Hayes Wange542a222011-07-06 15:58:04 +08004587 rtl_init_rxcfg(tp);
4588
françois romieuf0298f82011-01-03 15:07:42 +00004589 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004591 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Francois Romieucecb5fd2011-04-01 10:21:07 +02004593 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4594 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4595 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4596 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004597 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598
Francois Romieu7f796d832007-06-11 23:04:41 +02004599 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004600
Francois Romieucecb5fd2011-04-01 10:21:07 +02004601 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4602 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004603 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004605 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 }
4607
Francois Romieubcf0bf92006-07-26 23:14:13 +02004608 RTL_W16(CPlusCmd, tp->cp_cmd);
4609
Francois Romieu6dccd162007-02-13 23:38:05 +01004610 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4611
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 /*
4613 * Undocumented corner. Supposedly:
4614 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4615 */
4616 RTL_W16(IntrMitigate, 0x0000);
4617
Francois Romieu7f796d832007-06-11 23:04:41 +02004618 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004619
Francois Romieucecb5fd2011-04-01 10:21:07 +02004620 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4621 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4622 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4623 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004624 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4625 rtl_set_rx_tx_config_registers(tp);
4626 }
4627
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004629
4630 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4631 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632
4633 RTL_W32(RxMissed, 0);
4634
Francois Romieu07ce4062007-02-23 23:36:39 +01004635 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
4637 /* no early-rx interrupts */
4638 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004639}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004640
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004641static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4642{
4643 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004644 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004645}
4646
4647static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4648{
Francois Romieu52989f02012-07-06 13:37:00 +02004649 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004650}
4651
4652static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004653{
4654 u32 csi;
4655
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004656 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4657 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004658}
4659
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004660static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004661{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004662 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004663}
4664
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004665static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004666{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004667 rtl_csi_access_enable(tp, 0x27000000);
4668}
4669
Francois Romieuffc46952012-07-06 14:19:23 +02004670DECLARE_RTL_COND(rtl_csiar_cond)
4671{
4672 void __iomem *ioaddr = tp->mmio_addr;
4673
4674 return RTL_R32(CSIAR) & CSIAR_FLAG;
4675}
4676
Francois Romieu52989f02012-07-06 13:37:00 +02004677static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004678{
Francois Romieu52989f02012-07-06 13:37:00 +02004679 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004680
4681 RTL_W32(CSIDR, value);
4682 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4683 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4684
Francois Romieuffc46952012-07-06 14:19:23 +02004685 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004686}
4687
Francois Romieu52989f02012-07-06 13:37:00 +02004688static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004689{
Francois Romieu52989f02012-07-06 13:37:00 +02004690 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004691
4692 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4693 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4694
Francois Romieuffc46952012-07-06 14:19:23 +02004695 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4696 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004697}
4698
Francois Romieu52989f02012-07-06 13:37:00 +02004699static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004700{
Francois Romieu52989f02012-07-06 13:37:00 +02004701 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004702
4703 RTL_W32(CSIDR, value);
4704 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4705 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4706 CSIAR_FUNC_NIC);
4707
Francois Romieuffc46952012-07-06 14:19:23 +02004708 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004709}
4710
Francois Romieu52989f02012-07-06 13:37:00 +02004711static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004712{
Francois Romieu52989f02012-07-06 13:37:00 +02004713 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004714
4715 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4716 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4717
Francois Romieuffc46952012-07-06 14:19:23 +02004718 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4719 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004720}
4721
Bill Pembertonbaf63292012-12-03 09:23:28 -05004722static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004723{
4724 struct csi_ops *ops = &tp->csi_ops;
4725
4726 switch (tp->mac_version) {
4727 case RTL_GIGA_MAC_VER_01:
4728 case RTL_GIGA_MAC_VER_02:
4729 case RTL_GIGA_MAC_VER_03:
4730 case RTL_GIGA_MAC_VER_04:
4731 case RTL_GIGA_MAC_VER_05:
4732 case RTL_GIGA_MAC_VER_06:
4733 case RTL_GIGA_MAC_VER_10:
4734 case RTL_GIGA_MAC_VER_11:
4735 case RTL_GIGA_MAC_VER_12:
4736 case RTL_GIGA_MAC_VER_13:
4737 case RTL_GIGA_MAC_VER_14:
4738 case RTL_GIGA_MAC_VER_15:
4739 case RTL_GIGA_MAC_VER_16:
4740 case RTL_GIGA_MAC_VER_17:
4741 ops->write = NULL;
4742 ops->read = NULL;
4743 break;
4744
Hayes Wang7e18dca2012-03-30 14:33:02 +08004745 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004746 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004747 ops->write = r8402_csi_write;
4748 ops->read = r8402_csi_read;
4749 break;
4750
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004751 default:
4752 ops->write = r8169_csi_write;
4753 ops->read = r8169_csi_read;
4754 break;
4755 }
Francois Romieudacf8152008-08-02 20:44:13 +02004756}
4757
4758struct ephy_info {
4759 unsigned int offset;
4760 u16 mask;
4761 u16 bits;
4762};
4763
Francois Romieufdf6fc02012-07-06 22:40:38 +02004764static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4765 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004766{
4767 u16 w;
4768
4769 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004770 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4771 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004772 e++;
4773 }
4774}
4775
Francois Romieub726e492008-06-28 12:22:59 +02004776static void rtl_disable_clock_request(struct pci_dev *pdev)
4777{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004778 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4779 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004780}
4781
françois romieue6de30d2011-01-03 15:08:37 +00004782static void rtl_enable_clock_request(struct pci_dev *pdev)
4783{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004784 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4785 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004786}
4787
Francois Romieub726e492008-06-28 12:22:59 +02004788#define R8168_CPCMD_QUIRK_MASK (\
4789 EnableBist | \
4790 Mac_dbgo_oe | \
4791 Force_half_dup | \
4792 Force_rxflow_en | \
4793 Force_txflow_en | \
4794 Cxpl_dbg_sel | \
4795 ASF | \
4796 PktCntrDisable | \
4797 Mac_dbgo_sel)
4798
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004799static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004800{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004801 void __iomem *ioaddr = tp->mmio_addr;
4802 struct pci_dev *pdev = tp->pci_dev;
4803
Francois Romieub726e492008-06-28 12:22:59 +02004804 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4805
4806 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4807
Francois Romieu2e68ae42008-06-28 12:00:55 +02004808 rtl_tx_performance_tweak(pdev,
4809 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004810}
4811
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004812static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004813{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004814 void __iomem *ioaddr = tp->mmio_addr;
4815
4816 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004817
françois romieuf0298f82011-01-03 15:07:42 +00004818 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004819
4820 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004821}
4822
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004823static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004824{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004825 void __iomem *ioaddr = tp->mmio_addr;
4826 struct pci_dev *pdev = tp->pci_dev;
4827
Francois Romieub726e492008-06-28 12:22:59 +02004828 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4829
4830 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4831
Francois Romieu219a1e92008-06-28 11:58:39 +02004832 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004833
4834 rtl_disable_clock_request(pdev);
4835
4836 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004837}
4838
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004839static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004840{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004841 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004842 { 0x01, 0, 0x0001 },
4843 { 0x02, 0x0800, 0x1000 },
4844 { 0x03, 0, 0x0042 },
4845 { 0x06, 0x0080, 0x0000 },
4846 { 0x07, 0, 0x2000 }
4847 };
4848
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004849 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004850
Francois Romieufdf6fc02012-07-06 22:40:38 +02004851 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004852
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004853 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004854}
4855
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004856static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004857{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004858 void __iomem *ioaddr = tp->mmio_addr;
4859 struct pci_dev *pdev = tp->pci_dev;
4860
4861 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004862
4863 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4864
4865 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4866
4867 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4868}
4869
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004870static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004871{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004872 void __iomem *ioaddr = tp->mmio_addr;
4873 struct pci_dev *pdev = tp->pci_dev;
4874
4875 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004876
4877 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4878
4879 /* Magic. */
4880 RTL_W8(DBG_REG, 0x20);
4881
françois romieuf0298f82011-01-03 15:07:42 +00004882 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004883
4884 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4885
4886 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4887}
4888
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004889static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004890{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004891 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004892 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004893 { 0x02, 0x0800, 0x1000 },
4894 { 0x03, 0, 0x0002 },
4895 { 0x06, 0x0080, 0x0000 }
4896 };
4897
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004898 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004899
4900 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4901
Francois Romieufdf6fc02012-07-06 22:40:38 +02004902 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004903
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004904 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004905}
4906
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004907static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004908{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004909 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004910 { 0x01, 0, 0x0001 },
4911 { 0x03, 0x0400, 0x0220 }
4912 };
4913
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004914 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004915
Francois Romieufdf6fc02012-07-06 22:40:38 +02004916 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004917
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004918 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004919}
4920
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004921static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004922{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004923 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004924}
4925
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004926static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004927{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004928 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004929
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004930 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004931}
4932
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004933static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004934{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004935 void __iomem *ioaddr = tp->mmio_addr;
4936 struct pci_dev *pdev = tp->pci_dev;
4937
4938 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004939
4940 rtl_disable_clock_request(pdev);
4941
françois romieuf0298f82011-01-03 15:07:42 +00004942 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004943
4944 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4945
4946 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4947}
4948
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004949static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004950{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004951 void __iomem *ioaddr = tp->mmio_addr;
4952 struct pci_dev *pdev = tp->pci_dev;
4953
4954 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004955
4956 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4957
4958 RTL_W8(MaxTxPacketSize, TxPacketMax);
4959
4960 rtl_disable_clock_request(pdev);
4961}
4962
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004963static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004964{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004965 void __iomem *ioaddr = tp->mmio_addr;
4966 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004967 static const struct ephy_info e_info_8168d_4[] = {
4968 { 0x0b, ~0, 0x48 },
4969 { 0x19, 0x20, 0x50 },
4970 { 0x0c, ~0, 0x20 }
4971 };
4972 int i;
4973
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004974 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004975
4976 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4977
4978 RTL_W8(MaxTxPacketSize, TxPacketMax);
4979
4980 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4981 const struct ephy_info *e = e_info_8168d_4 + i;
4982 u16 w;
4983
Francois Romieufdf6fc02012-07-06 22:40:38 +02004984 w = rtl_ephy_read(tp, e->offset);
4985 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004986 }
4987
4988 rtl_enable_clock_request(pdev);
4989}
4990
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004991static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004992{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004993 void __iomem *ioaddr = tp->mmio_addr;
4994 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004995 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004996 { 0x00, 0x0200, 0x0100 },
4997 { 0x00, 0x0000, 0x0004 },
4998 { 0x06, 0x0002, 0x0001 },
4999 { 0x06, 0x0000, 0x0030 },
5000 { 0x07, 0x0000, 0x2000 },
5001 { 0x00, 0x0000, 0x0020 },
5002 { 0x03, 0x5800, 0x2000 },
5003 { 0x03, 0x0000, 0x0001 },
5004 { 0x01, 0x0800, 0x1000 },
5005 { 0x07, 0x0000, 0x4000 },
5006 { 0x1e, 0x0000, 0x2000 },
5007 { 0x19, 0xffff, 0xfe6c },
5008 { 0x0a, 0x0000, 0x0040 }
5009 };
5010
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005011 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005012
Francois Romieufdf6fc02012-07-06 22:40:38 +02005013 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005014
5015 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5016
5017 RTL_W8(MaxTxPacketSize, TxPacketMax);
5018
5019 rtl_disable_clock_request(pdev);
5020
5021 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005022 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5023 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005024
Francois Romieucecb5fd2011-04-01 10:21:07 +02005025 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005026}
5027
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005028static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005029{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005030 void __iomem *ioaddr = tp->mmio_addr;
5031 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005032 static const struct ephy_info e_info_8168e_2[] = {
5033 { 0x09, 0x0000, 0x0080 },
5034 { 0x19, 0x0000, 0x0224 }
5035 };
5036
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005037 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005038
Francois Romieufdf6fc02012-07-06 22:40:38 +02005039 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005040
5041 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5042
Francois Romieufdf6fc02012-07-06 22:40:38 +02005043 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5044 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5045 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5046 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5047 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5048 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5049 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5050 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005051
Hayes Wang3090bd92011-09-06 16:55:15 +08005052 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005053
Hayes Wang70090422011-07-06 15:58:06 +08005054 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5055 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5056
5057 /* Adjust EEE LED frequency */
5058 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5059
5060 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5061 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005062 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5063 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005064}
5065
Hayes Wang5f886e02012-03-30 14:33:03 +08005066static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005067{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005068 void __iomem *ioaddr = tp->mmio_addr;
5069 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005070
Hayes Wang5f886e02012-03-30 14:33:03 +08005071 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005072
5073 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5074
Francois Romieufdf6fc02012-07-06 22:40:38 +02005075 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5076 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5077 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5078 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5079 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5080 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5081 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5082 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5083 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5084 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005085
5086 RTL_W8(MaxTxPacketSize, EarlySize);
5087
Hayes Wangc2218922011-09-06 16:55:18 +08005088 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5089 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005090 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005091 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5092 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5093 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005094}
5095
Hayes Wang5f886e02012-03-30 14:33:03 +08005096static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5097{
5098 void __iomem *ioaddr = tp->mmio_addr;
5099 static const struct ephy_info e_info_8168f_1[] = {
5100 { 0x06, 0x00c0, 0x0020 },
5101 { 0x08, 0x0001, 0x0002 },
5102 { 0x09, 0x0000, 0x0080 },
5103 { 0x19, 0x0000, 0x0224 }
5104 };
5105
5106 rtl_hw_start_8168f(tp);
5107
Francois Romieufdf6fc02012-07-06 22:40:38 +02005108 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005109
Francois Romieufdf6fc02012-07-06 22:40:38 +02005110 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005111
5112 /* Adjust EEE LED frequency */
5113 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5114}
5115
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005116static void rtl_hw_start_8411(struct rtl8169_private *tp)
5117{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005118 static const struct ephy_info e_info_8168f_1[] = {
5119 { 0x06, 0x00c0, 0x0020 },
5120 { 0x0f, 0xffff, 0x5200 },
5121 { 0x1e, 0x0000, 0x4000 },
5122 { 0x19, 0x0000, 0x0224 }
5123 };
5124
5125 rtl_hw_start_8168f(tp);
5126
Francois Romieufdf6fc02012-07-06 22:40:38 +02005127 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005128
Francois Romieufdf6fc02012-07-06 22:40:38 +02005129 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005130}
5131
Hayes Wangc5583862012-07-02 17:23:22 +08005132static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5133{
5134 void __iomem *ioaddr = tp->mmio_addr;
5135 struct pci_dev *pdev = tp->pci_dev;
5136
5137 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5138 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5139 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5140 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5141
5142 rtl_csi_access_enable_1(tp);
5143
5144 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5145
5146 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5147 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5148
5149 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005150 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005151 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005152 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5153 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005154
5155 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5156 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5157
5158 /* Adjust EEE LED frequency */
5159 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5160
5161 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5162}
5163
Francois Romieu07ce4062007-02-23 23:36:39 +01005164static void rtl_hw_start_8168(struct net_device *dev)
5165{
Francois Romieu2dd99532007-06-11 23:22:52 +02005166 struct rtl8169_private *tp = netdev_priv(dev);
5167 void __iomem *ioaddr = tp->mmio_addr;
5168
5169 RTL_W8(Cfg9346, Cfg9346_Unlock);
5170
françois romieuf0298f82011-01-03 15:07:42 +00005171 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005172
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005173 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005174
Francois Romieu0e485152007-02-20 00:00:26 +01005175 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005176
5177 RTL_W16(CPlusCmd, tp->cp_cmd);
5178
Francois Romieu0e485152007-02-20 00:00:26 +01005179 RTL_W16(IntrMitigate, 0x5151);
5180
5181 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005182 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005183 tp->event_slow |= RxFIFOOver | PCSTimeout;
5184 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005185 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005186
5187 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5188
Francois Romieub8363902008-06-01 12:31:57 +02005189 rtl_set_rx_mode(dev);
5190
5191 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5192 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005193
5194 RTL_R8(IntrMask);
5195
Francois Romieu219a1e92008-06-28 11:58:39 +02005196 switch (tp->mac_version) {
5197 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005198 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005199 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005200
5201 case RTL_GIGA_MAC_VER_12:
5202 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005203 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005204 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005205
5206 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005207 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005208 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005209
5210 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005211 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005212 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005213
5214 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005215 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005216 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005217
Francois Romieu197ff762008-06-28 13:16:02 +02005218 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005219 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005220 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005221
Francois Romieu6fb07052008-06-29 11:54:28 +02005222 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005223 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005224 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005225
Francois Romieuef3386f2008-06-29 12:24:30 +02005226 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005227 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005228 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005229
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005230 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005231 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005232 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005233
Francois Romieu5b538df2008-07-20 16:22:45 +02005234 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005235 case RTL_GIGA_MAC_VER_26:
5236 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005237 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005238 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005239
françois romieue6de30d2011-01-03 15:08:37 +00005240 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005241 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005242 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005243
hayeswang4804b3b2011-03-21 01:50:29 +00005244 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005245 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005246 break;
5247
hayeswang01dc7fe2011-03-21 01:50:28 +00005248 case RTL_GIGA_MAC_VER_32:
5249 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005250 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005251 break;
5252 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005253 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005254 break;
françois romieue6de30d2011-01-03 15:08:37 +00005255
Hayes Wangc2218922011-09-06 16:55:18 +08005256 case RTL_GIGA_MAC_VER_35:
5257 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005258 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005259 break;
5260
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005261 case RTL_GIGA_MAC_VER_38:
5262 rtl_hw_start_8411(tp);
5263 break;
5264
Hayes Wangc5583862012-07-02 17:23:22 +08005265 case RTL_GIGA_MAC_VER_40:
5266 case RTL_GIGA_MAC_VER_41:
5267 rtl_hw_start_8168g_1(tp);
5268 break;
5269
Francois Romieu219a1e92008-06-28 11:58:39 +02005270 default:
5271 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5272 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005273 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005274 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005275
Francois Romieu0e485152007-02-20 00:00:26 +01005276 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5277
Francois Romieub8363902008-06-01 12:31:57 +02005278 RTL_W8(Cfg9346, Cfg9346_Lock);
5279
Francois Romieu2dd99532007-06-11 23:22:52 +02005280 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005281}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282
Francois Romieu2857ffb2008-08-02 21:08:49 +02005283#define R810X_CPCMD_QUIRK_MASK (\
5284 EnableBist | \
5285 Mac_dbgo_oe | \
5286 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005287 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005288 Force_txflow_en | \
5289 Cxpl_dbg_sel | \
5290 ASF | \
5291 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005292 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005293
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005294static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005295{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005296 void __iomem *ioaddr = tp->mmio_addr;
5297 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005298 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005299 { 0x01, 0, 0x6e65 },
5300 { 0x02, 0, 0x091f },
5301 { 0x03, 0, 0xc2f9 },
5302 { 0x06, 0, 0xafb5 },
5303 { 0x07, 0, 0x0e00 },
5304 { 0x19, 0, 0xec80 },
5305 { 0x01, 0, 0x2e65 },
5306 { 0x01, 0, 0x6e65 }
5307 };
5308 u8 cfg1;
5309
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005310 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005311
5312 RTL_W8(DBG_REG, FIX_NAK_1);
5313
5314 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5315
5316 RTL_W8(Config1,
5317 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5318 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5319
5320 cfg1 = RTL_R8(Config1);
5321 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5322 RTL_W8(Config1, cfg1 & ~LEDS0);
5323
Francois Romieufdf6fc02012-07-06 22:40:38 +02005324 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005325}
5326
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005327static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005328{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005329 void __iomem *ioaddr = tp->mmio_addr;
5330 struct pci_dev *pdev = tp->pci_dev;
5331
5332 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005333
5334 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5335
5336 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5337 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005338}
5339
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005340static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005341{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005342 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005343
Francois Romieufdf6fc02012-07-06 22:40:38 +02005344 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005345}
5346
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005347static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005348{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005349 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005350 static const struct ephy_info e_info_8105e_1[] = {
5351 { 0x07, 0, 0x4000 },
5352 { 0x19, 0, 0x0200 },
5353 { 0x19, 0, 0x0020 },
5354 { 0x1e, 0, 0x2000 },
5355 { 0x03, 0, 0x0001 },
5356 { 0x19, 0, 0x0100 },
5357 { 0x19, 0, 0x0004 },
5358 { 0x0a, 0, 0x0020 }
5359 };
5360
Francois Romieucecb5fd2011-04-01 10:21:07 +02005361 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005362 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5363
Francois Romieucecb5fd2011-04-01 10:21:07 +02005364 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005365 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5366
5367 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005368 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005369 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5370 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5371 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005372
Francois Romieufdf6fc02012-07-06 22:40:38 +02005373 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005374}
5375
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005376static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005377{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005378 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005379 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005380}
5381
Hayes Wang7e18dca2012-03-30 14:33:02 +08005382static void rtl_hw_start_8402(struct rtl8169_private *tp)
5383{
5384 void __iomem *ioaddr = tp->mmio_addr;
5385 static const struct ephy_info e_info_8402[] = {
5386 { 0x19, 0xffff, 0xff64 },
5387 { 0x1e, 0, 0x4000 }
5388 };
5389
5390 rtl_csi_access_enable_2(tp);
5391
5392 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5393 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5394
5395 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5396 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005397 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5398 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5399 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005400
Francois Romieufdf6fc02012-07-06 22:40:38 +02005401 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005402
5403 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5404
Francois Romieufdf6fc02012-07-06 22:40:38 +02005405 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5406 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5407 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5408 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5409 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5410 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5411 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005412}
5413
Hayes Wang5598bfe2012-07-02 17:23:21 +08005414static void rtl_hw_start_8106(struct rtl8169_private *tp)
5415{
5416 void __iomem *ioaddr = tp->mmio_addr;
5417
5418 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5419 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5420
hayeswangd64ec842012-11-01 16:46:28 +00005421 RTL_W32(MISC,
5422 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5423 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5424 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005425 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5426 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5427}
5428
Francois Romieu07ce4062007-02-23 23:36:39 +01005429static void rtl_hw_start_8101(struct net_device *dev)
5430{
Francois Romieucdf1a602007-06-11 23:29:50 +02005431 struct rtl8169_private *tp = netdev_priv(dev);
5432 void __iomem *ioaddr = tp->mmio_addr;
5433 struct pci_dev *pdev = tp->pci_dev;
5434
Francois Romieuda78dbf2012-01-26 14:18:23 +01005435 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5436 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005437
Francois Romieucecb5fd2011-04-01 10:21:07 +02005438 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005439 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005440 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5441 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005442
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005443 RTL_W8(Cfg9346, Cfg9346_Unlock);
5444
Francois Romieu2857ffb2008-08-02 21:08:49 +02005445 switch (tp->mac_version) {
5446 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005447 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005448 break;
5449
5450 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005451 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005452 break;
5453
5454 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005455 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005456 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005457
5458 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005459 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005460 break;
5461 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005462 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005463 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005464
5465 case RTL_GIGA_MAC_VER_37:
5466 rtl_hw_start_8402(tp);
5467 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005468
5469 case RTL_GIGA_MAC_VER_39:
5470 rtl_hw_start_8106(tp);
5471 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005472 }
5473
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005474 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005475
françois romieuf0298f82011-01-03 15:07:42 +00005476 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005477
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005478 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005479
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005480 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005481 RTL_W16(CPlusCmd, tp->cp_cmd);
5482
5483 RTL_W16(IntrMitigate, 0x0000);
5484
5485 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5486
5487 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5488 rtl_set_rx_tx_config_registers(tp);
5489
Francois Romieucdf1a602007-06-11 23:29:50 +02005490 RTL_R8(IntrMask);
5491
Francois Romieucdf1a602007-06-11 23:29:50 +02005492 rtl_set_rx_mode(dev);
5493
5494 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495}
5496
5497static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5498{
Francois Romieud58d46b2011-05-03 16:38:29 +02005499 struct rtl8169_private *tp = netdev_priv(dev);
5500
5501 if (new_mtu < ETH_ZLEN ||
5502 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 return -EINVAL;
5504
Francois Romieud58d46b2011-05-03 16:38:29 +02005505 if (new_mtu > ETH_DATA_LEN)
5506 rtl_hw_jumbo_enable(tp);
5507 else
5508 rtl_hw_jumbo_disable(tp);
5509
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005511 netdev_update_features(dev);
5512
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005513 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514}
5515
5516static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5517{
Al Viro95e09182007-12-22 18:55:39 +00005518 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5520}
5521
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005522static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5523 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005524{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005525 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005526 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005527
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005528 kfree(*data_buff);
5529 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530 rtl8169_make_unusable_by_asic(desc);
5531}
5532
5533static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5534{
5535 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5536
5537 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5538}
5539
5540static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5541 u32 rx_buf_sz)
5542{
5543 desc->addr = cpu_to_le64(mapping);
5544 wmb();
5545 rtl8169_mark_to_asic(desc, rx_buf_sz);
5546}
5547
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005548static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005550 return (void *)ALIGN((long)data, 16);
5551}
5552
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005553static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5554 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005555{
5556 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005558 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005559 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005560 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005562 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5563 if (!data)
5564 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005565
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005566 if (rtl8169_align(data) != data) {
5567 kfree(data);
5568 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5569 if (!data)
5570 return NULL;
5571 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005572
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005573 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005574 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005575 if (unlikely(dma_mapping_error(d, mapping))) {
5576 if (net_ratelimit())
5577 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005578 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
5581 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005582 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005583
5584err_out:
5585 kfree(data);
5586 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587}
5588
5589static void rtl8169_rx_clear(struct rtl8169_private *tp)
5590{
Francois Romieu07d3f512007-02-21 22:40:46 +01005591 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
5593 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005594 if (tp->Rx_databuff[i]) {
5595 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 tp->RxDescArray + i);
5597 }
5598 }
5599}
5600
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005601static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005603 desc->opts1 |= cpu_to_le32(RingEnd);
5604}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005605
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005606static int rtl8169_rx_fill(struct rtl8169_private *tp)
5607{
5608 unsigned int i;
5609
5610 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005611 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005612
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005613 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005615
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005616 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005617 if (!data) {
5618 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005619 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005620 }
5621 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005624 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5625 return 0;
5626
5627err_out:
5628 rtl8169_rx_clear(tp);
5629 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630}
5631
Linus Torvalds1da177e2005-04-16 15:20:36 -07005632static int rtl8169_init_ring(struct net_device *dev)
5633{
5634 struct rtl8169_private *tp = netdev_priv(dev);
5635
5636 rtl8169_init_ring_indexes(tp);
5637
5638 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005639 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005641 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642}
5643
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005644static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645 struct TxDesc *desc)
5646{
5647 unsigned int len = tx_skb->len;
5648
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005649 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5650
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651 desc->opts1 = 0x00;
5652 desc->opts2 = 0x00;
5653 desc->addr = 0x00;
5654 tx_skb->len = 0;
5655}
5656
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005657static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5658 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659{
5660 unsigned int i;
5661
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005662 for (i = 0; i < n; i++) {
5663 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664 struct ring_info *tx_skb = tp->tx_skb + entry;
5665 unsigned int len = tx_skb->len;
5666
5667 if (len) {
5668 struct sk_buff *skb = tx_skb->skb;
5669
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005670 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671 tp->TxDescArray + entry);
5672 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005673 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 dev_kfree_skb(skb);
5675 tx_skb->skb = NULL;
5676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677 }
5678 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005679}
5680
5681static void rtl8169_tx_clear(struct rtl8169_private *tp)
5682{
5683 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684 tp->cur_tx = tp->dirty_tx = 0;
5685}
5686
Francois Romieu4422bcd2012-01-26 11:23:32 +01005687static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688{
David Howellsc4028952006-11-22 14:57:56 +00005689 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005690 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691
Francois Romieuda78dbf2012-01-26 14:18:23 +01005692 napi_disable(&tp->napi);
5693 netif_stop_queue(dev);
5694 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695
françois romieuc7c2c392011-12-04 20:30:52 +00005696 rtl8169_hw_reset(tp);
5697
Francois Romieu56de4142011-03-15 17:29:31 +01005698 for (i = 0; i < NUM_RX_DESC; i++)
5699 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5700
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005702 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703
Francois Romieuda78dbf2012-01-26 14:18:23 +01005704 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005705 rtl_hw_start(dev);
5706 netif_wake_queue(dev);
5707 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708}
5709
5710static void rtl8169_tx_timeout(struct net_device *dev)
5711{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005712 struct rtl8169_private *tp = netdev_priv(dev);
5713
5714 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715}
5716
5717static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005718 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719{
5720 struct skb_shared_info *info = skb_shinfo(skb);
5721 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005722 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005723 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724
5725 entry = tp->cur_tx;
5726 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005727 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005728 dma_addr_t mapping;
5729 u32 status, len;
5730 void *addr;
5731
5732 entry = (entry + 1) % NUM_TX_DESC;
5733
5734 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005735 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005736 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005737 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005738 if (unlikely(dma_mapping_error(d, mapping))) {
5739 if (net_ratelimit())
5740 netif_err(tp, drv, tp->dev,
5741 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005742 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
Francois Romieucecb5fd2011-04-01 10:21:07 +02005745 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005746 status = opts[0] | len |
5747 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748
5749 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005750 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 txd->addr = cpu_to_le64(mapping);
5752
5753 tp->tx_skb[entry].len = len;
5754 }
5755
5756 if (cur_frag) {
5757 tp->tx_skb[entry].skb = skb;
5758 txd->opts1 |= cpu_to_le32(LastFrag);
5759 }
5760
5761 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005762
5763err_out:
5764 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5765 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766}
5767
Francois Romieu2b7b4312011-04-18 22:53:24 -07005768static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5769 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005771 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005772 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005773 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005774
Francois Romieu2b7b4312011-04-18 22:53:24 -07005775 if (mss) {
5776 opts[0] |= TD_LSO;
5777 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5778 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005779 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780
5781 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005782 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005784 opts[offset] |= info->checksum.udp;
5785 else
5786 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788}
5789
Stephen Hemminger613573252009-08-31 19:50:58 +00005790static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5791 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792{
5793 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005794 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795 struct TxDesc *txd = tp->TxDescArray + entry;
5796 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005797 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798 dma_addr_t mapping;
5799 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005800 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005801 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005802
Julien Ducourthial477206a2012-05-09 00:00:06 +02005803 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005804 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005805 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806 }
5807
5808 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005809 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005811 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005812 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005813 if (unlikely(dma_mapping_error(d, mapping))) {
5814 if (net_ratelimit())
5815 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005816 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
5819 tp->tx_skb[entry].len = len;
5820 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
Kirill Smelkov810f4892012-11-10 21:11:02 +04005822 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005823 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005824
Francois Romieu2b7b4312011-04-18 22:53:24 -07005825 rtl8169_tso_csum(tp, skb, opts);
5826
5827 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005828 if (frags < 0)
5829 goto err_dma_1;
5830 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005831 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005832 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005833 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005834 tp->tx_skb[entry].skb = skb;
5835 }
5836
Francois Romieu2b7b4312011-04-18 22:53:24 -07005837 txd->opts2 = cpu_to_le32(opts[1]);
5838
Richard Cochran5047fb52012-03-10 07:29:42 +00005839 skb_tx_timestamp(skb);
5840
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841 wmb();
5842
Francois Romieucecb5fd2011-04-01 10:21:07 +02005843 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005844 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845 txd->opts1 = cpu_to_le32(status);
5846
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847 tp->cur_tx += frags + 1;
5848
David Dillow4c020a92010-03-03 16:33:10 +00005849 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850
Francois Romieucecb5fd2011-04-01 10:21:07 +02005851 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852
Francois Romieuda78dbf2012-01-26 14:18:23 +01005853 mmiowb();
5854
Julien Ducourthial477206a2012-05-09 00:00:06 +02005855 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005856 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5857 * not miss a ring update when it notices a stopped queue.
5858 */
5859 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005861 /* Sync with rtl_tx:
5862 * - publish queue status and cur_tx ring index (write barrier)
5863 * - refresh dirty_tx ring index (read barrier).
5864 * May the current thread have a pessimistic view of the ring
5865 * status and forget to wake up queue, a racing rtl_tx thread
5866 * can't.
5867 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005868 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005869 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870 netif_wake_queue(dev);
5871 }
5872
Stephen Hemminger613573252009-08-31 19:50:58 +00005873 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005875err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005876 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005877err_dma_0:
5878 dev_kfree_skb(skb);
5879 dev->stats.tx_dropped++;
5880 return NETDEV_TX_OK;
5881
5882err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005884 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005885 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005886}
5887
5888static void rtl8169_pcierr_interrupt(struct net_device *dev)
5889{
5890 struct rtl8169_private *tp = netdev_priv(dev);
5891 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892 u16 pci_status, pci_cmd;
5893
5894 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5895 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5896
Joe Perchesbf82c182010-02-09 11:49:50 +00005897 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5898 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
5900 /*
5901 * The recovery sequence below admits a very elaborated explanation:
5902 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005903 * - I did not see what else could be done;
5904 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905 *
5906 * Feel free to adjust to your needs.
5907 */
Francois Romieua27993f2006-12-18 00:04:19 +01005908 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005909 pci_cmd &= ~PCI_COMMAND_PARITY;
5910 else
5911 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5912
5913 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914
5915 pci_write_config_word(pdev, PCI_STATUS,
5916 pci_status & (PCI_STATUS_DETECTED_PARITY |
5917 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5918 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5919
5920 /* The infamous DAC f*ckup only happens at boot time */
5921 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005922 void __iomem *ioaddr = tp->mmio_addr;
5923
Joe Perchesbf82c182010-02-09 11:49:50 +00005924 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 tp->cp_cmd &= ~PCIDAC;
5926 RTL_W16(CPlusCmd, tp->cp_cmd);
5927 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928 }
5929
françois romieue6de30d2011-01-03 15:08:37 +00005930 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005931
Francois Romieu98ddf982012-01-31 10:47:34 +01005932 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933}
5934
Francois Romieuda78dbf2012-01-26 14:18:23 +01005935static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936{
5937 unsigned int dirty_tx, tx_left;
5938
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939 dirty_tx = tp->dirty_tx;
5940 smp_rmb();
5941 tx_left = tp->cur_tx - dirty_tx;
5942
5943 while (tx_left > 0) {
5944 unsigned int entry = dirty_tx % NUM_TX_DESC;
5945 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946 u32 status;
5947
5948 rmb();
5949 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5950 if (status & DescOwn)
5951 break;
5952
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005953 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5954 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005956 u64_stats_update_begin(&tp->tx_stats.syncp);
5957 tp->tx_stats.packets++;
5958 tp->tx_stats.bytes += tx_skb->skb->len;
5959 u64_stats_update_end(&tp->tx_stats.syncp);
5960 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961 tx_skb->skb = NULL;
5962 }
5963 dirty_tx++;
5964 tx_left--;
5965 }
5966
5967 if (tp->dirty_tx != dirty_tx) {
5968 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005969 /* Sync with rtl8169_start_xmit:
5970 * - publish dirty_tx ring index (write barrier)
5971 * - refresh cur_tx ring index and queue status (read barrier)
5972 * May the current thread miss the stopped queue condition,
5973 * a racing xmit thread can only have a right view of the
5974 * ring status.
5975 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005976 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005978 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979 netif_wake_queue(dev);
5980 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005981 /*
5982 * 8168 hack: TxPoll requests are lost when the Tx packets are
5983 * too close. Let's kick an extra TxPoll request when a burst
5984 * of start_xmit activity is detected (if it is not detected,
5985 * it is slow enough). -- FR
5986 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005987 if (tp->cur_tx != dirty_tx) {
5988 void __iomem *ioaddr = tp->mmio_addr;
5989
Francois Romieud78ae2d2007-08-26 20:08:19 +02005990 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992 }
5993}
5994
Francois Romieu126fa4b2005-05-12 20:09:17 -04005995static inline int rtl8169_fragmented_frame(u32 status)
5996{
5997 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5998}
5999
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006000static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002 u32 status = opts1 & RxProtoMask;
6003
6004 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006005 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006 skb->ip_summed = CHECKSUM_UNNECESSARY;
6007 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006008 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009}
6010
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006011static struct sk_buff *rtl8169_try_rx_copy(void *data,
6012 struct rtl8169_private *tp,
6013 int pkt_size,
6014 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006016 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006017 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006019 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006020 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006021 prefetch(data);
6022 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6023 if (skb)
6024 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006025 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6026
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006027 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028}
6029
Francois Romieuda78dbf2012-01-26 14:18:23 +01006030static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031{
6032 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006033 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035 cur_rx = tp->cur_rx;
6036 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006037 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006039 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006041 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042 u32 status;
6043
6044 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006045 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
6047 if (status & DescOwn)
6048 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006049 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006050 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6051 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006052 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006054 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006056 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006057 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006058 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006059 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006060 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006061 if ((status & (RxRUNT | RxCRC)) &&
6062 !(status & (RxRWT | RxFOVF)) &&
6063 (dev->features & NETIF_F_RXALL))
6064 goto process_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006066 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006067 dma_addr_t addr;
6068 int pkt_size;
6069
6070process_pkt:
6071 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006072 if (likely(!(dev->features & NETIF_F_RXFCS)))
6073 pkt_size = (status & 0x00003fff) - 4;
6074 else
6075 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076
Francois Romieu126fa4b2005-05-12 20:09:17 -04006077 /*
6078 * The driver does not support incoming fragmented
6079 * frames. They are seen as a symptom of over-mtu
6080 * sized frames.
6081 */
6082 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006083 dev->stats.rx_dropped++;
6084 dev->stats.rx_length_errors++;
françois romieuce11ff52013-01-24 13:30:06 +00006085 goto release_descriptor;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006086 }
6087
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006088 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6089 tp, pkt_size, addr);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006090 if (!skb) {
6091 dev->stats.rx_dropped++;
françois romieuce11ff52013-01-24 13:30:06 +00006092 goto release_descriptor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093 }
6094
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006095 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 skb_put(skb, pkt_size);
6097 skb->protocol = eth_type_trans(skb, dev);
6098
Francois Romieu7a8fc772011-03-01 17:18:33 +01006099 rtl8169_rx_vlan_tag(desc, skb);
6100
Francois Romieu56de4142011-03-15 17:29:31 +01006101 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102
Junchang Wang8027aa22012-03-04 23:30:32 +01006103 u64_stats_update_begin(&tp->rx_stats.syncp);
6104 tp->rx_stats.packets++;
6105 tp->rx_stats.bytes += pkt_size;
6106 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107 }
françois romieuce11ff52013-01-24 13:30:06 +00006108release_descriptor:
6109 desc->opts2 = 0;
6110 wmb();
6111 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112 }
6113
6114 count = cur_rx - tp->cur_rx;
6115 tp->cur_rx = cur_rx;
6116
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006117 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
6119 return count;
6120}
6121
Francois Romieu07d3f512007-02-21 22:40:46 +01006122static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123{
Francois Romieu07d3f512007-02-21 22:40:46 +01006124 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006125 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006127 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006129 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006130 if (status && status != 0xffff) {
6131 status &= RTL_EVENT_NAPI | tp->event_slow;
6132 if (status) {
6133 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006134
Francois Romieuda78dbf2012-01-26 14:18:23 +01006135 rtl_irq_disable(tp);
6136 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139 return IRQ_RETVAL(handled);
6140}
6141
Francois Romieuda78dbf2012-01-26 14:18:23 +01006142/*
6143 * Workqueue context.
6144 */
6145static void rtl_slow_event_work(struct rtl8169_private *tp)
6146{
6147 struct net_device *dev = tp->dev;
6148 u16 status;
6149
6150 status = rtl_get_events(tp) & tp->event_slow;
6151 rtl_ack_events(tp, status);
6152
6153 if (unlikely(status & RxFIFOOver)) {
6154 switch (tp->mac_version) {
6155 /* Work around for rx fifo overflow */
6156 case RTL_GIGA_MAC_VER_11:
6157 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006158 /* XXX - Hack alert. See rtl_task(). */
6159 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006160 default:
6161 break;
6162 }
6163 }
6164
6165 if (unlikely(status & SYSErr))
6166 rtl8169_pcierr_interrupt(dev);
6167
6168 if (status & LinkChg)
6169 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6170
françois romieu7dbb4912012-06-09 10:53:16 +00006171 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006172}
6173
Francois Romieu4422bcd2012-01-26 11:23:32 +01006174static void rtl_task(struct work_struct *work)
6175{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006176 static const struct {
6177 int bitnr;
6178 void (*action)(struct rtl8169_private *);
6179 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006180 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006181 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6182 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6183 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6184 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006185 struct rtl8169_private *tp =
6186 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006187 struct net_device *dev = tp->dev;
6188 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006189
Francois Romieuda78dbf2012-01-26 14:18:23 +01006190 rtl_lock_work(tp);
6191
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006192 if (!netif_running(dev) ||
6193 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006194 goto out_unlock;
6195
6196 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6197 bool pending;
6198
Francois Romieuda78dbf2012-01-26 14:18:23 +01006199 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006200 if (pending)
6201 rtl_work[i].action(tp);
6202 }
6203
6204out_unlock:
6205 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006206}
6207
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006208static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006210 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6211 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006212 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6213 int work_done= 0;
6214 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215
Francois Romieuda78dbf2012-01-26 14:18:23 +01006216 status = rtl_get_events(tp);
6217 rtl_ack_events(tp, status & ~tp->event_slow);
6218
6219 if (status & RTL_EVENT_NAPI_RX)
6220 work_done = rtl_rx(dev, tp, (u32) budget);
6221
6222 if (status & RTL_EVENT_NAPI_TX)
6223 rtl_tx(dev, tp);
6224
6225 if (status & tp->event_slow) {
6226 enable_mask &= ~tp->event_slow;
6227
6228 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006230
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006231 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006232 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006233
Francois Romieuda78dbf2012-01-26 14:18:23 +01006234 rtl_irq_enable(tp, enable_mask);
6235 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006236 }
6237
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006238 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006239}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006240
Francois Romieu523a6092008-09-10 22:28:56 +02006241static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6242{
6243 struct rtl8169_private *tp = netdev_priv(dev);
6244
6245 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6246 return;
6247
6248 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6249 RTL_W32(RxMissed, 0);
6250}
6251
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252static void rtl8169_down(struct net_device *dev)
6253{
6254 struct rtl8169_private *tp = netdev_priv(dev);
6255 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006256
Francois Romieu4876cc12011-03-11 21:07:11 +01006257 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006259 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006260 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
Hayes Wang92fc43b2011-07-06 15:58:03 +08006262 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006263 /*
6264 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006265 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6266 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006267 */
Francois Romieu523a6092008-09-10 22:28:56 +02006268 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006271 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273 rtl8169_tx_clear(tp);
6274
6275 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006276
6277 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278}
6279
6280static int rtl8169_close(struct net_device *dev)
6281{
6282 struct rtl8169_private *tp = netdev_priv(dev);
6283 struct pci_dev *pdev = tp->pci_dev;
6284
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006285 pm_runtime_get_sync(&pdev->dev);
6286
Francois Romieucecb5fd2011-04-01 10:21:07 +02006287 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006288 rtl8169_update_counters(dev);
6289
Francois Romieuda78dbf2012-01-26 14:18:23 +01006290 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006291 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006292
Linus Torvalds1da177e2005-04-16 15:20:36 -07006293 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006294 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006295
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006296 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006297
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006298 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6299 tp->RxPhyAddr);
6300 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6301 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302 tp->TxDescArray = NULL;
6303 tp->RxDescArray = NULL;
6304
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006305 pm_runtime_put_sync(&pdev->dev);
6306
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307 return 0;
6308}
6309
Francois Romieudc1c00c2012-03-08 10:06:18 +01006310#ifdef CONFIG_NET_POLL_CONTROLLER
6311static void rtl8169_netpoll(struct net_device *dev)
6312{
6313 struct rtl8169_private *tp = netdev_priv(dev);
6314
6315 rtl8169_interrupt(tp->pci_dev->irq, dev);
6316}
6317#endif
6318
Francois Romieudf43ac72012-03-08 09:48:40 +01006319static int rtl_open(struct net_device *dev)
6320{
6321 struct rtl8169_private *tp = netdev_priv(dev);
6322 void __iomem *ioaddr = tp->mmio_addr;
6323 struct pci_dev *pdev = tp->pci_dev;
6324 int retval = -ENOMEM;
6325
6326 pm_runtime_get_sync(&pdev->dev);
6327
6328 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006329 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006330 * dma_alloc_coherent provides more.
6331 */
6332 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6333 &tp->TxPhyAddr, GFP_KERNEL);
6334 if (!tp->TxDescArray)
6335 goto err_pm_runtime_put;
6336
6337 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6338 &tp->RxPhyAddr, GFP_KERNEL);
6339 if (!tp->RxDescArray)
6340 goto err_free_tx_0;
6341
6342 retval = rtl8169_init_ring(dev);
6343 if (retval < 0)
6344 goto err_free_rx_1;
6345
6346 INIT_WORK(&tp->wk.work, rtl_task);
6347
6348 smp_mb();
6349
6350 rtl_request_firmware(tp);
6351
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006352 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006353 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6354 dev->name, dev);
6355 if (retval < 0)
6356 goto err_release_fw_2;
6357
6358 rtl_lock_work(tp);
6359
6360 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6361
6362 napi_enable(&tp->napi);
6363
6364 rtl8169_init_phy(dev, tp);
6365
6366 __rtl8169_set_features(dev, dev->features);
6367
6368 rtl_pll_power_up(tp);
6369
6370 rtl_hw_start(dev);
6371
6372 netif_start_queue(dev);
6373
6374 rtl_unlock_work(tp);
6375
6376 tp->saved_wolopts = 0;
6377 pm_runtime_put_noidle(&pdev->dev);
6378
6379 rtl8169_check_link_status(dev, tp, ioaddr);
6380out:
6381 return retval;
6382
6383err_release_fw_2:
6384 rtl_release_firmware(tp);
6385 rtl8169_rx_clear(tp);
6386err_free_rx_1:
6387 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6388 tp->RxPhyAddr);
6389 tp->RxDescArray = NULL;
6390err_free_tx_0:
6391 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6392 tp->TxPhyAddr);
6393 tp->TxDescArray = NULL;
6394err_pm_runtime_put:
6395 pm_runtime_put_noidle(&pdev->dev);
6396 goto out;
6397}
6398
Junchang Wang8027aa22012-03-04 23:30:32 +01006399static struct rtnl_link_stats64 *
6400rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006401{
6402 struct rtl8169_private *tp = netdev_priv(dev);
6403 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006404 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006405
Francois Romieuda78dbf2012-01-26 14:18:23 +01006406 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006407 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006408
Junchang Wang8027aa22012-03-04 23:30:32 +01006409 do {
6410 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6411 stats->rx_packets = tp->rx_stats.packets;
6412 stats->rx_bytes = tp->rx_stats.bytes;
6413 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6414
6415
6416 do {
6417 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6418 stats->tx_packets = tp->tx_stats.packets;
6419 stats->tx_bytes = tp->tx_stats.bytes;
6420 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6421
6422 stats->rx_dropped = dev->stats.rx_dropped;
6423 stats->tx_dropped = dev->stats.tx_dropped;
6424 stats->rx_length_errors = dev->stats.rx_length_errors;
6425 stats->rx_errors = dev->stats.rx_errors;
6426 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6427 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6428 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6429
6430 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431}
6432
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006433static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006434{
françois romieu065c27c2011-01-03 15:08:12 +00006435 struct rtl8169_private *tp = netdev_priv(dev);
6436
Francois Romieu5d06a992006-02-23 00:47:58 +01006437 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006438 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006439
6440 netif_device_detach(dev);
6441 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006442
6443 rtl_lock_work(tp);
6444 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006445 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006446 rtl_unlock_work(tp);
6447
6448 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006449}
Francois Romieu5d06a992006-02-23 00:47:58 +01006450
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006451#ifdef CONFIG_PM
6452
6453static int rtl8169_suspend(struct device *device)
6454{
6455 struct pci_dev *pdev = to_pci_dev(device);
6456 struct net_device *dev = pci_get_drvdata(pdev);
6457
6458 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006459
Francois Romieu5d06a992006-02-23 00:47:58 +01006460 return 0;
6461}
6462
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006463static void __rtl8169_resume(struct net_device *dev)
6464{
françois romieu065c27c2011-01-03 15:08:12 +00006465 struct rtl8169_private *tp = netdev_priv(dev);
6466
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006467 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006468
6469 rtl_pll_power_up(tp);
6470
Artem Savkovcff4c162012-04-03 10:29:11 +00006471 rtl_lock_work(tp);
6472 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006473 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006474 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006475
Francois Romieu98ddf982012-01-31 10:47:34 +01006476 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006477}
6478
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006479static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006480{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006481 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006482 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006483 struct rtl8169_private *tp = netdev_priv(dev);
6484
6485 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006486
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006487 if (netif_running(dev))
6488 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006489
Francois Romieu5d06a992006-02-23 00:47:58 +01006490 return 0;
6491}
6492
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006493static int rtl8169_runtime_suspend(struct device *device)
6494{
6495 struct pci_dev *pdev = to_pci_dev(device);
6496 struct net_device *dev = pci_get_drvdata(pdev);
6497 struct rtl8169_private *tp = netdev_priv(dev);
6498
6499 if (!tp->TxDescArray)
6500 return 0;
6501
Francois Romieuda78dbf2012-01-26 14:18:23 +01006502 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006503 tp->saved_wolopts = __rtl8169_get_wol(tp);
6504 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006505 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006506
6507 rtl8169_net_suspend(dev);
6508
6509 return 0;
6510}
6511
6512static int rtl8169_runtime_resume(struct device *device)
6513{
6514 struct pci_dev *pdev = to_pci_dev(device);
6515 struct net_device *dev = pci_get_drvdata(pdev);
6516 struct rtl8169_private *tp = netdev_priv(dev);
6517
6518 if (!tp->TxDescArray)
6519 return 0;
6520
Francois Romieuda78dbf2012-01-26 14:18:23 +01006521 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006522 __rtl8169_set_wol(tp, tp->saved_wolopts);
6523 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006524 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006525
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006526 rtl8169_init_phy(dev, tp);
6527
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006528 __rtl8169_resume(dev);
6529
6530 return 0;
6531}
6532
6533static int rtl8169_runtime_idle(struct device *device)
6534{
6535 struct pci_dev *pdev = to_pci_dev(device);
6536 struct net_device *dev = pci_get_drvdata(pdev);
6537 struct rtl8169_private *tp = netdev_priv(dev);
6538
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006539 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006540}
6541
Alexey Dobriyan47145212009-12-14 18:00:08 -08006542static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006543 .suspend = rtl8169_suspend,
6544 .resume = rtl8169_resume,
6545 .freeze = rtl8169_suspend,
6546 .thaw = rtl8169_resume,
6547 .poweroff = rtl8169_suspend,
6548 .restore = rtl8169_resume,
6549 .runtime_suspend = rtl8169_runtime_suspend,
6550 .runtime_resume = rtl8169_runtime_resume,
6551 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006552};
6553
6554#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6555
6556#else /* !CONFIG_PM */
6557
6558#define RTL8169_PM_OPS NULL
6559
6560#endif /* !CONFIG_PM */
6561
David S. Miller1805b2f2011-10-24 18:18:09 -04006562static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6563{
6564 void __iomem *ioaddr = tp->mmio_addr;
6565
6566 /* WoL fails with 8168b when the receiver is disabled. */
6567 switch (tp->mac_version) {
6568 case RTL_GIGA_MAC_VER_11:
6569 case RTL_GIGA_MAC_VER_12:
6570 case RTL_GIGA_MAC_VER_17:
6571 pci_clear_master(tp->pci_dev);
6572
6573 RTL_W8(ChipCmd, CmdRxEnb);
6574 /* PCI commit */
6575 RTL_R8(ChipCmd);
6576 break;
6577 default:
6578 break;
6579 }
6580}
6581
Francois Romieu1765f952008-09-13 17:21:40 +02006582static void rtl_shutdown(struct pci_dev *pdev)
6583{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006584 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006585 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006586 struct device *d = &pdev->dev;
6587
6588 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006589
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006590 rtl8169_net_suspend(dev);
6591
Francois Romieucecb5fd2011-04-01 10:21:07 +02006592 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006593 rtl_rar_set(tp, dev->perm_addr);
6594
Hayes Wang92fc43b2011-07-06 15:58:03 +08006595 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006596
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006597 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006598 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6599 rtl_wol_suspend_quirk(tp);
6600 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006601 }
6602
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006603 pci_wake_from_d3(pdev, true);
6604 pci_set_power_state(pdev, PCI_D3hot);
6605 }
françois romieu2a15cd22012-03-06 01:14:12 +00006606
6607 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006608}
Francois Romieu5d06a992006-02-23 00:47:58 +01006609
Bill Pembertonbaf63292012-12-03 09:23:28 -05006610static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006611{
6612 struct net_device *dev = pci_get_drvdata(pdev);
6613 struct rtl8169_private *tp = netdev_priv(dev);
6614
6615 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6616 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6617 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6618 rtl8168_driver_stop(tp);
6619 }
6620
6621 cancel_work_sync(&tp->wk.work);
6622
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006623 netif_napi_del(&tp->napi);
6624
Francois Romieue27566e2012-03-08 09:54:01 +01006625 unregister_netdev(dev);
6626
6627 rtl_release_firmware(tp);
6628
6629 if (pci_dev_run_wake(pdev))
6630 pm_runtime_get_noresume(&pdev->dev);
6631
6632 /* restore original MAC address */
6633 rtl_rar_set(tp, dev->perm_addr);
6634
6635 rtl_disable_msi(pdev, tp);
6636 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6637 pci_set_drvdata(pdev, NULL);
6638}
6639
Francois Romieufa9c3852012-03-08 10:01:50 +01006640static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006641 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006642 .ndo_stop = rtl8169_close,
6643 .ndo_get_stats64 = rtl8169_get_stats64,
6644 .ndo_start_xmit = rtl8169_start_xmit,
6645 .ndo_tx_timeout = rtl8169_tx_timeout,
6646 .ndo_validate_addr = eth_validate_addr,
6647 .ndo_change_mtu = rtl8169_change_mtu,
6648 .ndo_fix_features = rtl8169_fix_features,
6649 .ndo_set_features = rtl8169_set_features,
6650 .ndo_set_mac_address = rtl_set_mac_address,
6651 .ndo_do_ioctl = rtl8169_ioctl,
6652 .ndo_set_rx_mode = rtl_set_rx_mode,
6653#ifdef CONFIG_NET_POLL_CONTROLLER
6654 .ndo_poll_controller = rtl8169_netpoll,
6655#endif
6656
6657};
6658
Francois Romieu31fa8b12012-03-08 10:09:40 +01006659static const struct rtl_cfg_info {
6660 void (*hw_start)(struct net_device *);
6661 unsigned int region;
6662 unsigned int align;
6663 u16 event_slow;
6664 unsigned features;
6665 u8 default_ver;
6666} rtl_cfg_infos [] = {
6667 [RTL_CFG_0] = {
6668 .hw_start = rtl_hw_start_8169,
6669 .region = 1,
6670 .align = 0,
6671 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6672 .features = RTL_FEATURE_GMII,
6673 .default_ver = RTL_GIGA_MAC_VER_01,
6674 },
6675 [RTL_CFG_1] = {
6676 .hw_start = rtl_hw_start_8168,
6677 .region = 2,
6678 .align = 8,
6679 .event_slow = SYSErr | LinkChg | RxOverflow,
6680 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6681 .default_ver = RTL_GIGA_MAC_VER_11,
6682 },
6683 [RTL_CFG_2] = {
6684 .hw_start = rtl_hw_start_8101,
6685 .region = 2,
6686 .align = 8,
6687 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6688 PCSTimeout,
6689 .features = RTL_FEATURE_MSI,
6690 .default_ver = RTL_GIGA_MAC_VER_13,
6691 }
6692};
6693
6694/* Cfg9346_Unlock assumed. */
6695static unsigned rtl_try_msi(struct rtl8169_private *tp,
6696 const struct rtl_cfg_info *cfg)
6697{
6698 void __iomem *ioaddr = tp->mmio_addr;
6699 unsigned msi = 0;
6700 u8 cfg2;
6701
6702 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6703 if (cfg->features & RTL_FEATURE_MSI) {
6704 if (pci_enable_msi(tp->pci_dev)) {
6705 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6706 } else {
6707 cfg2 |= MSIEnable;
6708 msi = RTL_FEATURE_MSI;
6709 }
6710 }
6711 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6712 RTL_W8(Config2, cfg2);
6713 return msi;
6714}
6715
Hayes Wangc5583862012-07-02 17:23:22 +08006716DECLARE_RTL_COND(rtl_link_list_ready_cond)
6717{
6718 void __iomem *ioaddr = tp->mmio_addr;
6719
6720 return RTL_R8(MCU) & LINK_LIST_RDY;
6721}
6722
6723DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6724{
6725 void __iomem *ioaddr = tp->mmio_addr;
6726
6727 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6728}
6729
Bill Pembertonbaf63292012-12-03 09:23:28 -05006730static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006731{
6732 void __iomem *ioaddr = tp->mmio_addr;
6733 u32 data;
6734
6735 tp->ocp_base = OCP_STD_PHY_BASE;
6736
6737 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6738
6739 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6740 return;
6741
6742 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6743 return;
6744
6745 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6746 msleep(1);
6747 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6748
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006749 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006750 data &= ~(1 << 14);
6751 r8168_mac_ocp_write(tp, 0xe8de, data);
6752
6753 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6754 return;
6755
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006756 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006757 data |= (1 << 15);
6758 r8168_mac_ocp_write(tp, 0xe8de, data);
6759
6760 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6761 return;
6762}
6763
Bill Pembertonbaf63292012-12-03 09:23:28 -05006764static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006765{
6766 switch (tp->mac_version) {
6767 case RTL_GIGA_MAC_VER_40:
6768 case RTL_GIGA_MAC_VER_41:
6769 rtl_hw_init_8168g(tp);
6770 break;
6771
6772 default:
6773 break;
6774 }
6775}
6776
Bill Pembertonbaf63292012-12-03 09:23:28 -05006777static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006778rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6779{
6780 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6781 const unsigned int region = cfg->region;
6782 struct rtl8169_private *tp;
6783 struct mii_if_info *mii;
6784 struct net_device *dev;
6785 void __iomem *ioaddr;
6786 int chipset, i;
6787 int rc;
6788
6789 if (netif_msg_drv(&debug)) {
6790 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6791 MODULENAME, RTL8169_VERSION);
6792 }
6793
6794 dev = alloc_etherdev(sizeof (*tp));
6795 if (!dev) {
6796 rc = -ENOMEM;
6797 goto out;
6798 }
6799
6800 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006801 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006802 tp = netdev_priv(dev);
6803 tp->dev = dev;
6804 tp->pci_dev = pdev;
6805 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6806
6807 mii = &tp->mii;
6808 mii->dev = dev;
6809 mii->mdio_read = rtl_mdio_read;
6810 mii->mdio_write = rtl_mdio_write;
6811 mii->phy_id_mask = 0x1f;
6812 mii->reg_num_mask = 0x1f;
6813 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6814
6815 /* disable ASPM completely as that cause random device stop working
6816 * problems as well as full system hangs for some PCIe devices users */
6817 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6818 PCIE_LINK_STATE_CLKPM);
6819
6820 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6821 rc = pci_enable_device(pdev);
6822 if (rc < 0) {
6823 netif_err(tp, probe, dev, "enable failure\n");
6824 goto err_out_free_dev_1;
6825 }
6826
6827 if (pci_set_mwi(pdev) < 0)
6828 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6829
6830 /* make sure PCI base addr 1 is MMIO */
6831 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6832 netif_err(tp, probe, dev,
6833 "region #%d not an MMIO resource, aborting\n",
6834 region);
6835 rc = -ENODEV;
6836 goto err_out_mwi_2;
6837 }
6838
6839 /* check for weird/broken PCI region reporting */
6840 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6841 netif_err(tp, probe, dev,
6842 "Invalid PCI region size(s), aborting\n");
6843 rc = -ENODEV;
6844 goto err_out_mwi_2;
6845 }
6846
6847 rc = pci_request_regions(pdev, MODULENAME);
6848 if (rc < 0) {
6849 netif_err(tp, probe, dev, "could not request regions\n");
6850 goto err_out_mwi_2;
6851 }
6852
6853 tp->cp_cmd = RxChkSum;
6854
6855 if ((sizeof(dma_addr_t) > 4) &&
6856 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6857 tp->cp_cmd |= PCIDAC;
6858 dev->features |= NETIF_F_HIGHDMA;
6859 } else {
6860 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6861 if (rc < 0) {
6862 netif_err(tp, probe, dev, "DMA configuration failed\n");
6863 goto err_out_free_res_3;
6864 }
6865 }
6866
6867 /* ioremap MMIO region */
6868 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6869 if (!ioaddr) {
6870 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6871 rc = -EIO;
6872 goto err_out_free_res_3;
6873 }
6874 tp->mmio_addr = ioaddr;
6875
6876 if (!pci_is_pcie(pdev))
6877 netif_info(tp, probe, dev, "not PCI Express\n");
6878
6879 /* Identify chip attached to board */
6880 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6881
6882 rtl_init_rxcfg(tp);
6883
6884 rtl_irq_disable(tp);
6885
Hayes Wangc5583862012-07-02 17:23:22 +08006886 rtl_hw_initialize(tp);
6887
Francois Romieu3b6cf252012-03-08 09:59:04 +01006888 rtl_hw_reset(tp);
6889
6890 rtl_ack_events(tp, 0xffff);
6891
6892 pci_set_master(pdev);
6893
6894 /*
6895 * Pretend we are using VLANs; This bypasses a nasty bug where
6896 * Interrupts stop flowing on high load on 8110SCd controllers.
6897 */
6898 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6899 tp->cp_cmd |= RxVlan;
6900
6901 rtl_init_mdio_ops(tp);
6902 rtl_init_pll_power_ops(tp);
6903 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006904 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006905
6906 rtl8169_print_mac_version(tp);
6907
6908 chipset = tp->mac_version;
6909 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6910
6911 RTL_W8(Cfg9346, Cfg9346_Unlock);
6912 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6913 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6914 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6915 tp->features |= RTL_FEATURE_WOL;
6916 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6917 tp->features |= RTL_FEATURE_WOL;
6918 tp->features |= rtl_try_msi(tp, cfg);
6919 RTL_W8(Cfg9346, Cfg9346_Lock);
6920
6921 if (rtl_tbi_enabled(tp)) {
6922 tp->set_speed = rtl8169_set_speed_tbi;
6923 tp->get_settings = rtl8169_gset_tbi;
6924 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6925 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6926 tp->link_ok = rtl8169_tbi_link_ok;
6927 tp->do_ioctl = rtl_tbi_ioctl;
6928 } else {
6929 tp->set_speed = rtl8169_set_speed_xmii;
6930 tp->get_settings = rtl8169_gset_xmii;
6931 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6932 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6933 tp->link_ok = rtl8169_xmii_link_ok;
6934 tp->do_ioctl = rtl_xmii_ioctl;
6935 }
6936
6937 mutex_init(&tp->wk.mutex);
6938
6939 /* Get MAC address */
6940 for (i = 0; i < ETH_ALEN; i++)
6941 dev->dev_addr[i] = RTL_R8(MAC0 + i);
6942 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6943
6944 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6945 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006946
6947 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6948
6949 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6950 * properly for all devices */
6951 dev->features |= NETIF_F_RXCSUM |
6952 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6953
6954 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6955 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6956 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6957 NETIF_F_HIGHDMA;
6958
6959 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6960 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6961 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6962
6963 dev->hw_features |= NETIF_F_RXALL;
6964 dev->hw_features |= NETIF_F_RXFCS;
6965
6966 tp->hw_start = cfg->hw_start;
6967 tp->event_slow = cfg->event_slow;
6968
6969 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6970 ~(RxBOVF | RxFOVF) : ~0;
6971
6972 init_timer(&tp->timer);
6973 tp->timer.data = (unsigned long) dev;
6974 tp->timer.function = rtl8169_phy_timer;
6975
6976 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6977
6978 rc = register_netdev(dev);
6979 if (rc < 0)
6980 goto err_out_msi_4;
6981
6982 pci_set_drvdata(pdev, dev);
6983
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006984 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6985 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6986 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006987 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6988 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6989 "tx checksumming: %s]\n",
6990 rtl_chip_infos[chipset].jumbo_max,
6991 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6992 }
6993
6994 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6995 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6996 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6997 rtl8168_driver_start(tp);
6998 }
6999
7000 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
7001
7002 if (pci_dev_run_wake(pdev))
7003 pm_runtime_put_noidle(&pdev->dev);
7004
7005 netif_carrier_off(dev);
7006
7007out:
7008 return rc;
7009
7010err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007011 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007012 rtl_disable_msi(pdev, tp);
7013 iounmap(ioaddr);
7014err_out_free_res_3:
7015 pci_release_regions(pdev);
7016err_out_mwi_2:
7017 pci_clear_mwi(pdev);
7018 pci_disable_device(pdev);
7019err_out_free_dev_1:
7020 free_netdev(dev);
7021 goto out;
7022}
7023
Linus Torvalds1da177e2005-04-16 15:20:36 -07007024static struct pci_driver rtl8169_pci_driver = {
7025 .name = MODULENAME,
7026 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007027 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05007028 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02007029 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007030 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031};
7032
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007033module_pci_driver(rtl8169_pci_driver);